Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
2af0403
refactor(lib): change how manim API is imported
jeertmans Oct 13, 2023
e0fdac9
chore(lib): delete old files
jeertmans Oct 13, 2023
01aca2f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 13, 2023
5ebb61c
Merge remote-tracking branch 'origin/refactor-manim' into refactor-manim
jeertmans Oct 13, 2023
f3ff76e
wip: moving all commands
jeertmans Oct 13, 2023
06ff18f
adding animations
jeertmans Oct 13, 2023
9355e3d
fix tests
jeertmans Oct 13, 2023
2211ac6
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 13, 2023
dd57527
fix mypy
jeertmans Oct 13, 2023
effcc75
fixes
jeertmans Oct 13, 2023
418f1f7
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 13, 2023
f5f60e7
trying to fix docs
jeertmans Oct 14, 2023
d4a6148
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 14, 2023
1b1d6c5
wip: docs
jeertmans Oct 16, 2023
c803d67
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 16, 2023
bccff71
make it work
jeertmans Oct 16, 2023
036a796
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 16, 2023
2c3e5cc
wip test
jeertmans Oct 16, 2023
927a489
Merge remote-tracking branch 'origin/refactor-manim' into refactor-manim
jeertmans Oct 16, 2023
fb97409
tests are working
jeertmans Oct 16, 2023
946cb11
improving docs
jeertmans Oct 16, 2023
aa8205a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 16, 2023
85ff07e
fix index
jeertmans Oct 16, 2023
b79da53
docs: nicer shift
jeertmans Oct 16, 2023
6c14ee2
docs: nicer quickstart example
jeertmans Oct 16, 2023
95f84ef
fix tests
jeertmans Oct 17, 2023
353a7f4
change tests
jeertmans Oct 17, 2023
7b37c2d
move coverage to test workflow
jeertmans Oct 17, 2023
b182e72
fix(tests): remove resolve
jeertmans Oct 17, 2023
ffe8322
strict resolve
jeertmans Oct 17, 2023
90a2909
change local path test
jeertmans Oct 17, 2023
4c1df69
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 17, 2023
f8978c2
documented changes
jeertmans Oct 17, 2023
489ea5b
Merge remote-tracking branch 'origin/refactor-manim' into refactor-manim
jeertmans Oct 17, 2023
c010971
cleanup docs
jeertmans Oct 17, 2023
4d166d5
cleanup files
jeertmans Oct 17, 2023
a767aef
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 17, 2023
9300811
fix(ci): set type
jeertmans Oct 17, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
wip: moving all commands
  • Loading branch information
jeertmans committed Oct 13, 2023
commit f3ff76e02aa783458bba206c49f770578afcc877
4 changes: 2 additions & 2 deletions docs/source/reference/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Therefore, we only document here the methods we think the end-user will ever
use, not the methods used internally when rendering.

```{eval-rst}
.. autoclass:: manim_slides.Slide
.. autoclass:: manim_slides.slide.Slide
:members:
add_to_canvas,
canvas,
Expand All @@ -22,6 +22,6 @@ use, not the methods used internally when rendering.
wipe,
zoom,

.. autoclass:: manim_slides.ThreeDSlide
.. autoclass:: manim_slides.slide.ThreeDSlide
:members:
```
31 changes: 17 additions & 14 deletions manim_slides/slide/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
__all__ = [
"MANIM",
"MANIMGL",
"API_NAME",
"Slide",
"ThreeDSlide",
]


import os
import sys

Expand All @@ -14,7 +23,7 @@ def __init__(self):
API_NAMES = {
"manim": "manim",
"manimce": "manim",
"manimlib": "manim",
"manimlib": "manimlib",
"manimgl": "manimlib",
}

Expand All @@ -31,28 +40,22 @@ def __init__(self):

API_NAME = API_NAMES[API]

MANIM = True
MANIMGL = False


if not os.environ.get(FORCE_MANIM_API):
if "manim" in sys.modules:
API_NAME = "manim"
elif "manimlib" in sys.modules:
API_NAME = "manimgl"
API_NAME = "manimlib"

MANIM = API_NAME == "manim"
MANIMGL = API_NAME == "manimlib"

if MANIM:
try:
from .manim import Slide, ThreeDSlide
except ImportError:
raise ManimApiNotFoundError from None
else:
os.environ[MANIM_API] = "manim"
except ImportError as e:
raise ManimApiNotFoundError from e
elif MANIMGL:
try:
from .manimgl import Slide, ThreeDSlide
except ImportError:
raise ManimApiNotFoundError from None
else:
os.environ[MANIM_API] = "manimgl"
except ImportError as e:
raise ManimApiNotFoundError from e
13 changes: 2 additions & 11 deletions manim_slides/slide/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ class Base(ABC):
_wait_time_between_slides = 0.0

@property
@abstractmethod
def _ffmpeg_bin(self) -> Path:
"""Returns the path to the ffmpeg binaries."""
return FFMPEG_BIN
Expand All @@ -47,9 +46,6 @@ def _frame_height(self) -> float:
"""Returns the scene's frame height."""
...

def mdr(self):
...

@property
@abstractmethod
def _frame_width(self) -> float:
Expand Down Expand Up @@ -443,11 +439,11 @@ def _save_slides(self, use_cache: bool = True) -> None:

# We only concat animations if it was not present
if not use_cache or not dst_file.exists():
concatenate_video_files(slide_files, dst_file)
concatenate_video_files(self._ffmpeg_bin, slide_files, dst_file)

# We only reverse video if it was not present
if not use_cache or not rev_file.exists():
reverse_video_file(dst_file, rev_file)
reverse_video_file(self._ffmpeg_bin, dst_file, rev_file)

slides.append(
SlideConfig.from_pre_slide_config_and_files(
Expand All @@ -470,8 +466,3 @@ def _save_slides(self, use_cache: bool = True) -> None:
logger.info(
f"Slide '{scene_name}' configuration written in '{slide_path.absolute()}'"
)

def run(self, *args: Any, **kwargs: Any) -> None:
"""MANIMGL renderer"""
super().run(*args, **kwargs)
self._save_slides(use_cache=False)
3 changes: 1 addition & 2 deletions manim_slides/slide/manim.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

from manim import Scene, ThreeDScene, config

from ..defaults import FFMPEG_BIN
from .base import Base


Expand All @@ -19,7 +18,7 @@ def _ffmpeg_bin(self) -> Path:
try:
return Path(config.ffmpeg_executable)
except AttributeError:
return FFMPEG_BIN
return super()._ffmpeg_bin

@property
def _frame_height(self) -> float:
Expand Down
15 changes: 10 additions & 5 deletions manim_slides/slide/manimgl.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
class Slide(Base, Scene):
def __init__(self, *args: Any, **kwargs: Any) -> None:
Path("videos").mkdir(exist_ok=True)
kwargs["file_writer_config"] = {
"break_into_partial_movies": True,
"output_directory": "",
"write_to_movie": True,
}
kwargs["file_writer_config"].update(
break_into_partial_movies=True,
output_directory="",
write_to_movie=True,
)

kwargs.setdefault("preview", False) # Avoid opening a preview window

Expand Down Expand Up @@ -65,6 +65,11 @@ def _leave_progress_bar(self) -> bool:
def _start_at_animation_number(self) -> Optional[int]:
return getattr(self, "start_at_animation_number", None)

def run(self, *args: Any, **kwargs: Any) -> None:
"""MANIMGL renderer"""
super().run(*args, **kwargs)
self._save_slides(use_cache=False)


class ThreeDSlide(Slide):
CONFIG = {
Expand Down
10 changes: 5 additions & 5 deletions manim_slides/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
from pathlib import Path
from typing import List

from .manim import FFMPEG_BIN, logger
from .logger import logger


def concatenate_video_files(files: List[Path], dest: Path) -> None:
def concatenate_video_files(ffmpeg_bin: Path, files: List[Path], dest: Path) -> None:
"""
Concatenate multiple video files into one.
"""
Expand All @@ -17,7 +17,7 @@ def concatenate_video_files(files: List[Path], dest: Path) -> None:
f.close()

command: List[str] = [
str(FFMPEG_BIN),
ffmpeg_bin,
"-f",
"concat",
"-safe",
Expand Down Expand Up @@ -66,9 +66,9 @@ def merge_basenames(files: List[Path]) -> Path:
return dirname.joinpath(basename + ext)


def reverse_video_file(src: Path, dst: Path) -> None:
def reverse_video_file(ffmpeg_bin: Path, src: Path, dst: Path) -> None:
"""Reverses a video file, writting the result to `dst`."""
command = [str(FFMPEG_BIN), "-y", "-i", str(src), "-vf", "reverse", str(dst)]
command = [ffmpeg_bin, "-y", "-i", str(src), "-vf", "reverse", str(dst)]
logger.debug(" ".join(command))
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, error = process.communicate()
Expand Down
1 change: 0 additions & 1 deletion tests/data/slides.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,4 @@ def construct(self):

self.play(dot.animate.move_to(ORIGIN))
self.next_slide()

self.play(self.wipe(Group(dot, circle), []))
123 changes: 42 additions & 81 deletions tests/test_manim.py
Original file line number Diff line number Diff line change
@@ -1,62 +1,55 @@
import importlib
import os
import sys
from contextlib import contextmanager
from importlib.abc import MetaPathFinder
from importlib.machinery import ModuleSpec
from types import ModuleType
from typing import Iterator, Optional, Sequence

import pytest

import manim_slides.manim as msm
import manim_slides.slide as slide


@contextmanager
def suppress_module_finder() -> Iterator[None]:
meta_path = sys.meta_path
try:
def assert_import(
*,
api_name: str,
manim: bool,
manimgl: bool,
) -> None:
importlib.reload(slide)

class PathFinder(MetaPathFinder):
@classmethod
def find_spec(
cls,
fullname: str,
path: Optional[Sequence[str]],
target: Optional[ModuleType] = None,
) -> Optional[ModuleSpec]:
if fullname in ["manim", "manimlib"]:
return None
assert slide.API_NAME == api_name
assert slide.MANIM == manim
assert slide.MANIMGL == manimgl

for finder in meta_path:
spec = finder.find_spec(fullname, path, target=target)
if spec is not None:
return spec

return None
def test_force_api() -> None:
import manim # noqa: F401

sys.meta_path = [PathFinder]
yield
finally:
sys.meta_path = meta_path
if "manimlib" in sys.modules:
del sys.modules["manimlib"]

os.environ[slide.MANIM_API] = "manimlib"
os.environ[slide.FORCE_MANIM_API] = "1"

def assert_import(
*,
manim: bool,
manim_available: bool,
manim_imported: bool,
manimgl: bool,
manimgl_available: bool,
manimgl_imported: bool,
) -> None:
importlib.reload(msm)
assert_import(
api_name="manimlib",
manim=False,
manimgl=True,
)

del os.environ[slide.MANIM_API]
del os.environ[slide.FORCE_MANIM_API]

assert msm.MANIM == manim
assert msm.MANIM_AVAILABLE == manim_available
assert msm.MANIM_IMPORTED == manim_imported
assert msm.MANIMGL == manimgl
assert msm.MANIMGL_AVAILABLE == manim_available
assert msm.MANIMGL_IMPORTED == manimgl_imported

def test_invalid_api() -> None:
os.environ[slide.MANIM_API] = "manim_slides"

with pytest.raises(ImportError):
assert_import(
api_name="",
manim=False,
manimgl=False,
)

del os.environ[slide.MANIM_API]


@pytest.mark.filterwarnings("ignore:assert_import")
Expand All @@ -65,12 +58,9 @@ def test_manim_and_manimgl_imported() -> None:
import manimlib # noqa: F401

assert_import(
api_name="manim",
manim=True,
manim_available=True,
manim_imported=True,
manimgl=False,
manimgl_available=True,
manimgl_imported=True,
)


Expand All @@ -81,12 +71,9 @@ def test_manim_imported() -> None:
del sys.modules["manimlib"]

assert_import(
api_name="manim",
manim=True,
manim_available=True,
manim_imported=True,
manimgl=False,
manimgl_available=True,
manimgl_imported=False,
)


Expand All @@ -97,12 +84,9 @@ def test_manimgl_imported() -> None:
del sys.modules["manim"]

assert_import(
api_name="manimlib",
manim=False,
manim_available=True,
manim_imported=False,
manimgl=True,
manimgl_available=True,
manimgl_imported=True,
)


Expand All @@ -114,30 +98,7 @@ def test_nothing_imported() -> None:
del sys.modules["manimlib"]

assert_import(
api_name="manim",
manim=True,
manim_available=True,
manim_imported=False,
manimgl=False,
manimgl_available=True,
manimgl_imported=False,
)


def test_no_package_available() -> None:
with suppress_module_finder():
if "manim" in sys.modules:
del sys.modules["manim"]

if "manimlib" in sys.modules:
del sys.modules["manimlib"]

with pytest.raises(ModuleNotFoundError):
# Actual values are not important
assert_import(
manim=False,
manim_available=False,
manim_imported=False,
manimgl=False,
manimgl_available=False,
manimgl_imported=False,
)
2 changes: 1 addition & 1 deletion tests/test_slide.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from pydantic import ValidationError

from manim_slides.config import PresentationConfig
from manim_slides.slide import Slide
from manim_slides.slide.manim import Slide


@click.command(
Expand Down