From 96f1a1df837855670d6eef076e27f46165efcb98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9rome=20Eertmans?= Date: Mon, 1 Jul 2024 19:24:12 +0200 Subject: [PATCH 1/6] feat(lib): use and add more config option Closes #441 --- manim_slides/slide/base.py | 16 ++++++++++++++-- manim_slides/slide/manim.py | 4 +++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/manim_slides/slide/base.py b/manim_slides/slide/base.py index 4c35b0d4..60ed89c5 100644 --- a/manim_slides/slide/base.py +++ b/manim_slides/slide/base.py @@ -3,6 +3,7 @@ __all__ = ["BaseSlide"] import platform +import shutil from abc import abstractmethod from collections.abc import MutableMapping, Sequence, ValuesView from pathlib import Path @@ -445,7 +446,12 @@ def _add_last_slide(self) -> None: ) ) - def _save_slides(self, use_cache: bool = True) -> None: + def _save_slides( + self, + use_cache: bool = True, + flush_cache: bool = False, + skip_reversing: bool = False, + ) -> None: """ Save slides, optionally using cached files. @@ -458,6 +464,9 @@ def _save_slides(self, use_cache: bool = True) -> None: scene_name = str(self) scene_files_folder = files_folder / scene_name + if flush_cache and scene_files_folder.exists(): + shutil.rmtree(scene_files_folder) + scene_files_folder.mkdir(parents=True, exist_ok=True) files: list[Path] = self._partial_movie_files @@ -492,7 +501,10 @@ def _save_slides(self, use_cache: bool = True) -> None: # 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) + if skip_reversing: + rev_file.symlink_to(dst_file) + else: + reverse_video_file(dst_file, rev_file) slides.append( SlideConfig.from_pre_slide_config_and_files( diff --git a/manim_slides/slide/manim.py b/manim_slides/slide/manim.py index d3db2355..cdc79dca 100644 --- a/manim_slides/slide/manim.py +++ b/manim_slides/slide/manim.py @@ -111,7 +111,9 @@ def render(self, *args: Any, **kwargs: Any) -> None: config["max_files_cached"] = max_files_cached - self._save_slides() + self._save_slides( + use_cache=not config["disable_caching"], flush_cache=config["flush_cache"] + ) class ThreeDSlide(Slide, ThreeDScene): # type: ignore[misc] From e5933ea917ecbdb94e3222e1fe4e5b365837c7cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9rome=20Eertmans?= Date: Thu, 5 Sep 2024 11:55:32 +0200 Subject: [PATCH 2/6] feat(lib): add support for more options and test them --- CHANGELOG.md | 3 + manim_slides/slide/base.py | 11 +++- manim_slides/slide/manim.py | 15 ++++- manim_slides/slide/manimlib.py | 6 +- requirements-dev.lock | 52 ++++++++++++++++- requirements.lock | 52 ++++++++++++++++- tests/data/slides.py | 4 ++ tests/test_slide.py | 102 +++++++++++++++++++++++++++++++++ 8 files changed, 235 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10d64fa9..a0b365d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `manim-slides checkhealth` command to easily obtain important information for debug purposes. [#458](https://github.com/jeertmans/manim-slides/pull/458) +- Added support for `disable_caching` and `flush_cache` options from Manim, and + also the possibility to configure them through class options. + [#452](https://github.com/jeertmans/manim-slides/pull/452) (unreleased-chore)= ### Chore diff --git a/manim_slides/slide/base.py b/manim_slides/slide/base.py index 60ed89c5..02e72cd6 100644 --- a/manim_slides/slide/base.py +++ b/manim_slides/slide/base.py @@ -33,6 +33,15 @@ class BaseSlide: + disable_caching = False + """Whether to disable the use of cached animation files.""" + flush_cache = False + """Whether to flush the cache. + + Unlike with Manim, flushing is performed before rendering.""" + skip_reversing: bool = False + """Whether to generate reversed animations.""" + def __init__( self, *args: Any, output_folder: Path = FOLDER_PATH, **kwargs: Any ) -> None: @@ -502,7 +511,7 @@ def _save_slides( # We only reverse video if it was not present if not use_cache or not rev_file.exists(): if skip_reversing: - rev_file.symlink_to(dst_file) + rev_file = dst_file else: reverse_video_file(dst_file, rev_file) diff --git a/manim_slides/slide/manim.py b/manim_slides/slide/manim.py index cdc79dca..f419d896 100644 --- a/manim_slides/slide/manim.py +++ b/manim_slides/slide/manim.py @@ -102,19 +102,30 @@ def next_slide( ) def render(self, *args: Any, **kwargs: Any) -> None: - """MANIM render.""" + """MANIM renderer.""" # We need to disable the caching limit since we rely on intermediate files max_files_cached = config["max_files_cached"] config["max_files_cached"] = float("inf") + flush_manim_cache = config["flush_cache"] + + if flush_manim_cache: + # We need to postpone flushing *after* we saved slides + config["flush_cache"] = False + super().render(*args, **kwargs) config["max_files_cached"] = max_files_cached self._save_slides( - use_cache=not config["disable_caching"], flush_cache=config["flush_cache"] + use_cache=not (config["disable_caching"] or self.disable_caching), + flush_cache=(config["flush_cache"] or self.flush_cache), + skip_reversing=self.skip_reversing, ) + if flush_manim_cache: + self.renderer.file_writer.flush_cache_directory() + class ThreeDSlide(Slide, ThreeDScene): # type: ignore[misc] """ diff --git a/manim_slides/slide/manimlib.py b/manim_slides/slide/manimlib.py index 0aba17e3..6b13344d 100644 --- a/manim_slides/slide/manimlib.py +++ b/manim_slides/slide/manimlib.py @@ -62,7 +62,11 @@ def _start_at_animation_number(self) -> Optional[int]: def run(self, *args: Any, **kwargs: Any) -> None: """MANIMGL renderer.""" super().run(*args, **kwargs) - self._save_slides(use_cache=False) + self._save_slides( + use_cache=False, + flush_cache=self.flush_cache, + skip_reversing=self.skip_reversing, + ) class ThreeDSlide(Slide): diff --git a/requirements-dev.lock b/requirements-dev.lock index 859eba85..f7c1f2a6 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -7,6 +7,7 @@ # all-features: true # with-sources: false # generate-hashes: false +# universal: false -e file:. alabaster==1.0.0 @@ -48,10 +49,16 @@ click-default-group==1.2.4 # via manim-slides cloup==3.0.5 # via manim +colour==0.1.5 + # via manimgl comm==0.2.2 # via ipykernel +contourpy==1.3.0 + # via matplotlib coverage==7.6.1 # via pytest-cov +cycler==0.12.1 + # via matplotlib debugpy==1.8.5 # via ipykernel decorator==5.1.1 @@ -73,6 +80,8 @@ fastjsonschema==2.20.0 # via nbformat filelock==3.15.4 # via virtualenv +fonttools==4.53.1 + # via matplotlib furo==2024.8.6 # via manim-slides glcontext==3.0.0 @@ -90,8 +99,10 @@ ipykernel==6.29.5 ipython==8.26.0 # via ipykernel # via manim-slides + # via manimgl isosurfaces==0.1.2 # via manim + # via manimgl jedi==0.19.1 # via ipython jinja2==3.1.4 @@ -115,16 +126,22 @@ jupyter-core==5.7.2 # via nbformat jupyterlab-pygments==0.3.0 # via nbconvert +kiwisolver==1.4.5 + # via matplotlib lxml==5.3.0 # via manim-slides # via python-pptx manim==0.18.1 # via manim-slides +manimgl==1.6.1 + # via manim-slides manimpango==0.5.0 # via --override (workspace) # via manim + # via manimgl mapbox-earcut==1.0.2 # via manim + # via manimgl markdown-it-py==3.0.0 # via mdit-py-plugins # via myst-parser @@ -132,6 +149,8 @@ markdown-it-py==3.0.0 markupsafe==2.1.5 # via jinja2 # via nbconvert +matplotlib==3.9.2 + # via manimgl matplotlib-inline==0.1.7 # via ipykernel # via ipython @@ -143,9 +162,13 @@ mistune==3.0.2 # via nbconvert moderngl==5.11.1 # via manim + # via manimgl # via moderngl-window moderngl-window==2.4.6 # via manim + # via manimgl +mpmath==1.3.0 + # via sympy multipledispatch==1.0.0 # via pyrr myst-parser==4.0.0 @@ -166,19 +189,21 @@ networkx==3.3 # via manim nodeenv==1.9.1 # via pre-commit -numpy==2.1.0 +numpy==1.24.0 # via --override (workspace) - # via ipython + # via contourpy # via isosurfaces # via manim # via manim-slides + # via manimgl # via mapbox-earcut + # via matplotlib # via moderngl-window - # via networkx # via pyrr # via scipy packaging==24.1 # via ipykernel + # via matplotlib # via nbconvert # via pytest # via qtpy @@ -194,6 +219,8 @@ pexpect==4.9.0 pillow==10.4.0 # via manim # via manim-slides + # via manimgl + # via matplotlib # via moderngl-window # via python-pptx platformdirs==4.2.2 @@ -231,15 +258,21 @@ pydantic-settings==2.4.0 # via bump-my-version pydub==0.25.1 # via manim + # via manimgl pyglet==2.0.17 # via moderngl-window pygments==2.18.0 # via furo # via ipython # via manim + # via manimgl # via nbconvert # via rich # via sphinx +pyopengl==3.1.7 + # via manimgl +pyparsing==3.1.4 + # via matplotlib pyqt6==6.7.1 # via manim-slides pyqt6-qt6==6.7.2 @@ -271,11 +304,13 @@ pytest-qt==4.4.0 # via manim-slides python-dateutil==2.9.0.post0 # via jupyter-client + # via matplotlib python-dotenv==1.0.1 # via pydantic-settings python-pptx==1.0.2 # via manim-slides pyyaml==6.0.2 + # via manimgl # via myst-parser # via pre-commit pyzmq==26.2.0 @@ -295,6 +330,7 @@ rich==13.7.1 # via bump-my-version # via manim # via manim-slides + # via manimgl # via rich-click rich-click==1.8.3 # via bump-my-version @@ -305,8 +341,10 @@ rtoml==0.11.0 # via manim-slides scipy==1.14.1 # via manim + # via manimgl screeninfo==0.8.1 # via manim + # via manimgl setuptools==73.0.1 shiboken6==6.7.2 # via pyside6 @@ -318,6 +356,7 @@ six==1.16.0 # via python-dateutil skia-pathops==0.8.0.post1 # via manim + # via manimgl snowballstemmer==2.2.0 # via sphinx soupsieve==2.6 @@ -357,6 +396,9 @@ stack-data==0.6.3 # via ipython svgelements==1.9.6 # via manim + # via manimgl +sympy==1.13.2 + # via manimgl tinycss2==1.3.0 # via nbconvert tomlkit==0.13.2 @@ -367,6 +409,7 @@ tornado==6.4.1 tqdm==4.66.5 # via manim # via manim-slides + # via manimgl traitlets==5.14.3 # via comm # via ipykernel @@ -379,6 +422,7 @@ traitlets==5.14.3 # via nbformat # via nbsphinx typing-extensions==4.12.2 + # via ipython # via manim # via pydantic # via pydantic-core @@ -386,6 +430,8 @@ typing-extensions==4.12.2 # via rich-click urllib3==2.2.2 # via requests +validators==0.33.0 + # via manimgl virtualenv==20.26.3 # via pre-commit watchdog==4.0.2 diff --git a/requirements.lock b/requirements.lock index a6f25ba1..986ac2f7 100644 --- a/requirements.lock +++ b/requirements.lock @@ -7,6 +7,7 @@ # all-features: true # with-sources: false # generate-hashes: false +# universal: false -e file:. alabaster==1.0.0 @@ -41,10 +42,16 @@ click-default-group==1.2.4 # via manim-slides cloup==3.0.5 # via manim +colour==0.1.5 + # via manimgl comm==0.2.2 # via ipykernel +contourpy==1.3.0 + # via matplotlib coverage==7.6.1 # via pytest-cov +cycler==0.12.1 + # via matplotlib debugpy==1.8.5 # via ipykernel decorator==5.1.1 @@ -62,6 +69,8 @@ executing==2.0.1 # via stack-data fastjsonschema==2.20.0 # via nbformat +fonttools==4.53.1 + # via matplotlib furo==2024.8.6 # via manim-slides glcontext==3.0.0 @@ -77,8 +86,10 @@ ipykernel==6.29.5 ipython==8.26.0 # via ipykernel # via manim-slides + # via manimgl isosurfaces==0.1.2 # via manim + # via manimgl jedi==0.19.1 # via ipython jinja2==3.1.4 @@ -102,16 +113,22 @@ jupyter-core==5.7.2 # via nbformat jupyterlab-pygments==0.3.0 # via nbconvert +kiwisolver==1.4.5 + # via matplotlib lxml==5.3.0 # via manim-slides # via python-pptx manim==0.18.1 # via manim-slides +manimgl==1.6.1 + # via manim-slides manimpango==0.5.0 # via --override (workspace) # via manim + # via manimgl mapbox-earcut==1.0.2 # via manim + # via manimgl markdown-it-py==3.0.0 # via mdit-py-plugins # via myst-parser @@ -119,6 +136,8 @@ markdown-it-py==3.0.0 markupsafe==2.1.5 # via jinja2 # via nbconvert +matplotlib==3.9.2 + # via manimgl matplotlib-inline==0.1.7 # via ipykernel # via ipython @@ -130,9 +149,13 @@ mistune==3.0.2 # via nbconvert moderngl==5.11.1 # via manim + # via manimgl # via moderngl-window moderngl-window==2.4.6 # via manim + # via manimgl +mpmath==1.3.0 + # via sympy multipledispatch==1.0.0 # via pyrr myst-parser==4.0.0 @@ -151,19 +174,21 @@ nest-asyncio==1.6.0 # via ipykernel networkx==3.3 # via manim -numpy==2.1.0 +numpy==1.24.0 # via --override (workspace) - # via ipython + # via contourpy # via isosurfaces # via manim # via manim-slides + # via manimgl # via mapbox-earcut + # via matplotlib # via moderngl-window - # via networkx # via pyrr # via scipy packaging==24.1 # via ipykernel + # via matplotlib # via nbconvert # via pytest # via qtpy @@ -179,6 +204,8 @@ pexpect==4.9.0 pillow==10.4.0 # via manim # via manim-slides + # via manimgl + # via matplotlib # via moderngl-window # via python-pptx platformdirs==4.2.2 @@ -209,15 +236,21 @@ pydantic-extra-types==2.9.0 # via manim-slides pydub==0.25.1 # via manim + # via manimgl pyglet==2.0.17 # via moderngl-window pygments==2.18.0 # via furo # via ipython # via manim + # via manimgl # via nbconvert # via rich # via sphinx +pyopengl==3.1.7 + # via manimgl +pyparsing==3.1.4 + # via matplotlib pyqt6==6.7.1 # via manim-slides pyqt6-qt6==6.7.2 @@ -249,9 +282,11 @@ pytest-qt==4.4.0 # via manim-slides python-dateutil==2.9.0.post0 # via jupyter-client + # via matplotlib python-pptx==1.0.2 # via manim-slides pyyaml==6.0.2 + # via manimgl # via myst-parser pyzmq==26.2.0 # via ipykernel @@ -267,6 +302,7 @@ requests==2.32.3 rich==13.7.1 # via manim # via manim-slides + # via manimgl rpds-py==0.20.0 # via jsonschema # via referencing @@ -274,8 +310,10 @@ rtoml==0.11.0 # via manim-slides scipy==1.14.1 # via manim + # via manimgl screeninfo==0.8.1 # via manim + # via manimgl shiboken6==6.7.2 # via pyside6 # via pyside6-addons @@ -286,6 +324,7 @@ six==1.16.0 # via python-dateutil skia-pathops==0.8.0.post1 # via manim + # via manimgl snowballstemmer==2.2.0 # via sphinx soupsieve==2.6 @@ -325,6 +364,9 @@ stack-data==0.6.3 # via ipython svgelements==1.9.6 # via manim + # via manimgl +sympy==1.13.2 + # via manimgl tinycss2==1.3.0 # via nbconvert tornado==6.4.1 @@ -333,6 +375,7 @@ tornado==6.4.1 tqdm==4.66.5 # via manim # via manim-slides + # via manimgl traitlets==5.14.3 # via comm # via ipykernel @@ -345,12 +388,15 @@ traitlets==5.14.3 # via nbformat # via nbsphinx typing-extensions==4.12.2 + # via ipython # via manim # via pydantic # via pydantic-core # via python-pptx urllib3==2.2.2 # via requests +validators==0.33.0 + # via manimgl watchdog==4.0.2 # via manim wcwidth==0.2.13 diff --git a/tests/data/slides.py b/tests/data/slides.py index 0aeebe27..4dc84ad9 100644 --- a/tests/data/slides.py +++ b/tests/data/slides.py @@ -38,3 +38,7 @@ def construct(self): self.next_slide() self.zoom(other_text, []) + + +class BasicSlideSkipReversing(BasicSlide): + skip_reversing = True diff --git a/tests/test_slide.py b/tests/test_slide.py index 10cbdcb4..10f80534 100644 --- a/tests/test_slide.py +++ b/tests/test_slide.py @@ -97,6 +97,108 @@ def test_render_basic_slide( assert local_presentation_config.resolution == presentation_config.resolution +def test_clear_cache( + slides_file: Path, +) -> None: + runner = CliRunner() + + with runner.isolated_filesystem() as tmp_dir: + local_media_folder = ( + Path(tmp_dir) + / "media" + / "videos" + / slides_file.stem + / "480p15" + / "partial_movie_files" + / "BasicSlide" + ) + local_slides_folder = Path(tmp_dir) / "slides" + + assert not local_media_folder.exists() + assert not local_slides_folder.exists() + results = runner.invoke(render, [str(slides_file), "BasicSlide", "-ql"]) + + assert results.exit_code == 0, results + assert local_media_folder.is_dir() and list(local_media_folder.iterdir()) + assert local_slides_folder.exists() + + results = runner.invoke( + render, [str(slides_file), "BasicSlide", "-ql", "--flush_cache"] + ) + + assert results.exit_code == 0, results + assert local_media_folder.is_dir() and not list(local_media_folder.iterdir()) + assert local_slides_folder.exists() + + results = runner.invoke( + render, [str(slides_file), "BasicSlide", "-ql", "--disable_caching"] + ) + + assert results.exit_code == 0, results + assert local_media_folder.is_dir() and list(local_media_folder.iterdir()) + assert local_slides_folder.exists() + + results = runner.invoke( + render, + [ + str(slides_file), + "BasicSlide", + "-ql", + "--disable_caching", + "--flush_cache", + ], + ) + + assert results.exit_code == 0, results + assert local_media_folder.is_dir() and not list(local_media_folder.iterdir()) + assert local_slides_folder.exists() + + +@pytest.mark.parametrize( + "renderer", + [ + "--CE", + pytest.param( + "--GL", + marks=pytest.mark.skipif( + sys.version_info >= (3, 12), + reason="ManimGL requires numpy<1.25, which is outdated and Python < 3.12", + ), + ), + ], +) +@pytest.mark.parametrize( + ("klass", "skip_reversing"), + [("BasicSlide", False), ("BasicSlideSkipReversing", True)], +) +def test_skip_reversing( + renderer: str, + slides_file: Path, + manimgl_config: Path, + klass: str, + skip_reversing: bool, +) -> None: + runner = CliRunner() + + with runner.isolated_filesystem() as tmp_dir: + shutil.copy(manimgl_config, tmp_dir) + results = runner.invoke(render, [renderer, str(slides_file), klass, "-ql"]) + + assert results.exit_code == 0, results + + local_slides_folder = (Path(tmp_dir) / "slides").resolve(strict=True) + + local_config_file = (local_slides_folder / f"{klass}.json").resolve(strict=True) + + local_presentation_config = PresentationConfig.from_file(local_config_file) + + for slide in local_presentation_config.slides: + if skip_reversing: + assert slide.file == slide.rev_file + else: + assert slide.file != slide.rev_file + + def init_slide(cls: SlideType) -> Slide: if issubclass(cls, CESlide): return cls() From f388512dd17eb40190eb53f3708f337992917cf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9rome=20Eertmans?= Date: Thu, 5 Sep 2024 12:13:20 +0200 Subject: [PATCH 3/6] chore(docs): add attributes to documentation --- docs/source/reference/api.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/source/reference/api.md b/docs/source/reference/api.md index 3a707933..7e80e036 100644 --- a/docs/source/reference/api.md +++ b/docs/source/reference/api.md @@ -11,6 +11,9 @@ use, not the methods used internally when rendering. ```{eval-rst} .. autoclass:: manim_slides.slide.Slide :members: + disable_caching, + flush_cache, + skip_reversing, add_to_canvas, canvas, canvas_mobjects, From e773f857f4fc25cdc1cc49273e7af861dc704bfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9rome=20Eertmans?= Date: Thu, 5 Sep 2024 12:32:45 +0200 Subject: [PATCH 4/6] chore(docs): sort members by member type --- docs/source/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/conf.py b/docs/source/conf.py index 66d53f41..d458c528 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -37,6 +37,7 @@ "manim_slides.docs.manim_slides_directive", ] +autodoc_member_order = "groupwise" autodoc_typehints = "both" myst_enable_extensions = [ From ecbf5bbe726339c06261a5f95bd062834bf3ce16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9rome=20Eertmans?= Date: Thu, 5 Sep 2024 12:55:21 +0200 Subject: [PATCH 5/6] chore(docs): small improvements --- manim_slides/slide/base.py | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/manim_slides/slide/base.py b/manim_slides/slide/base.py index 02e72cd6..465d96b0 100644 --- a/manim_slides/slide/base.py +++ b/manim_slides/slide/base.py @@ -294,23 +294,34 @@ def next_slide( If set, next slide will play immediately play the next slide upon terminating. - Note that this is only supported by ``manim-slides present`` - and ``manim-slides convert --to=html``. + .. attention:: + + Only supported by ``manim-slides present`` + and ``manim-slides convert --to=html``. :param playback_rate: Playback rate at which the video is played. - Note that this is only supported by ``manim-slides present``. + .. attention:: + + Only supported by ``manim-slides present``. :param reversed_playback_rate: Playback rate at which the reversed video is played. - Note that this is only supported by ``manim-slides present``. + .. attention:: + + Only supported by ``manim-slides present``. :param notes: Presenter notes, in Markdown format. - Note that PowerPoint does not support Markdown. + .. note:: + PowerPoint does not support Markdown formatting, + so the text will be displayed as is. + + .. attention:: - Note that this is only supported by ``manim-slides present`` - and ``manim-slides convert --to=html/pptx``. + Only supported by ``manim-slides present``, + ``manim-slides convert --to=html`` and + ``manim-slides convert --to=pptx``. :param dedent_notes: If set, apply :func:`textwrap.dedent` to notes. :param kwargs: @@ -464,7 +475,8 @@ def _save_slides( """ Save slides, optionally using cached files. - Note that cached files only work with Manim. + .. attention: + Caching files only work with Manim. """ self._add_last_slide() From 041759370f23755227d10d71ddeea30da898e450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9rome=20Eertmans?= Date: Thu, 5 Sep 2024 14:07:42 +0200 Subject: [PATCH 6/6] chore(docs): cleanup --- docs/source/conf.py | 1 - docs/source/reference/api.md | 3 -- manim_slides/docs/manim_slides_directive.py | 3 +- manim_slides/slide/base.py | 43 +++++++++++++-------- manim_slides/slide/manim.py | 16 ++++++++ 5 files changed, 44 insertions(+), 22 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index d458c528..66d53f41 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -37,7 +37,6 @@ "manim_slides.docs.manim_slides_directive", ] -autodoc_member_order = "groupwise" autodoc_typehints = "both" myst_enable_extensions = [ diff --git a/docs/source/reference/api.md b/docs/source/reference/api.md index 7e80e036..3a707933 100644 --- a/docs/source/reference/api.md +++ b/docs/source/reference/api.md @@ -11,9 +11,6 @@ use, not the methods used internally when rendering. ```{eval-rst} .. autoclass:: manim_slides.slide.Slide :members: - disable_caching, - flush_cache, - skip_reversing, add_to_canvas, canvas, canvas_mobjects, diff --git a/manim_slides/docs/manim_slides_directive.py b/manim_slides/docs/manim_slides_directive.py index a444f0b2..ce897fff 100644 --- a/manim_slides/docs/manim_slides_directive.py +++ b/manim_slides/docs/manim_slides_directive.py @@ -283,8 +283,7 @@ def run(self): # noqa: C901 # Rendering is skipped if the tag skip-manim is present, # or if we are making the pot-files should_skip = ( - "skip-manim-slides" - in self.state.document.settings.env.app.builder.tags.tags + self.state.document.settings.env.app.builder.tags.has("skip-manim-slides") or self.state.document.settings.env.app.builder.name == "gettext" or "SKIP_MANIM_SLIDES" in os.environ ) diff --git a/manim_slides/slide/base.py b/manim_slides/slide/base.py index 465d96b0..9f47635f 100644 --- a/manim_slides/slide/base.py +++ b/manim_slides/slide/base.py @@ -33,14 +33,9 @@ class BaseSlide: - disable_caching = False - """Whether to disable the use of cached animation files.""" - flush_cache = False - """Whether to flush the cache. - - Unlike with Manim, flushing is performed before rendering.""" + disable_caching: bool = False + flush_cache: bool = False skip_reversing: bool = False - """Whether to generate reversed animations.""" def __init__( self, *args: Any, output_folder: Path = FOLDER_PATH, **kwargs: Any @@ -180,11 +175,23 @@ def add_to_canvas(self, **objects: Mobject) -> None: animations. You must still call :code:`self.add` or play some animation that introduces each Mobject for it to appear. The same applies when removing objects. + + .. seealso:: + + :attr:`canvas` for usage examples. """ self._canvas.update(objects) def remove_from_canvas(self, *names: str) -> None: - """Remove objects from the canvas.""" + """ + Remove objects from the canvas. + + :param names: The names of objects to remove. + + .. seealso:: + + :attr:`canvas` for usage examples. + """ for name in names: self._canvas.pop(name) @@ -196,8 +203,12 @@ def canvas_mobjects(self) -> ValuesView[Mobject]: @property def mobjects_without_canvas(self) -> Sequence[Mobject]: """ - Return the list of objects contained in the scene, minus those present in + Return the list of Mobjects contained in the scene, minus those present in the canvas. + + .. seealso:: + + :attr:`canvas` for usage examples. """ return [ mobject @@ -285,7 +296,7 @@ def next_slide( next slide is played. By default, this is the right arrow key. :param args: - Positional arguments to be passed to + Positional arguments passed to :meth:`Scene.next_section`, or ignored if `manimlib` API is used. :param loop: @@ -294,20 +305,20 @@ def next_slide( If set, next slide will play immediately play the next slide upon terminating. - .. attention:: + .. warning:: Only supported by ``manim-slides present`` and ``manim-slides convert --to=html``. :param playback_rate: Playback rate at which the video is played. - .. attention:: + .. warning:: Only supported by ``manim-slides present``. :param reversed_playback_rate: Playback rate at which the reversed video is played. - .. attention:: + .. warning:: Only supported by ``manim-slides present``. :param notes: @@ -317,7 +328,7 @@ def next_slide( PowerPoint does not support Markdown formatting, so the text will be displayed as is. - .. attention:: + .. warning:: Only supported by ``manim-slides present``, ``manim-slides convert --to=html`` and @@ -325,7 +336,7 @@ def next_slide( :param dedent_notes: If set, apply :func:`textwrap.dedent` to notes. :param kwargs: - Keyword arguments to be passed to + Keyword arguments passed to :meth:`Scene.next_section`, or ignored if `manimlib` API is used. @@ -475,7 +486,7 @@ def _save_slides( """ Save slides, optionally using cached files. - .. attention: + .. warning: Caching files only work with Manim. """ self._add_last_slide() diff --git a/manim_slides/slide/manim.py b/manim_slides/slide/manim.py index f419d896..21e50831 100644 --- a/manim_slides/slide/manim.py +++ b/manim_slides/slide/manim.py @@ -13,6 +13,22 @@ class Slide(BaseSlide, Scene): # type: ignore[misc] """ Inherits from :class:`Scene` and provide necessary tools for slides rendering. + + :param args: Positional arguments passed to scene object. + :param output_folder: Where the slide animation files should be written. + :param kwargs: Keyword arguments passed to scene object. + :cvar bool disable_caching: :data:`False`: Whether to disable the use of + cached animation files. + :cvar bool flush_cache: :data:`False`: Whether to flush the cache. + + Unlike with Manim, flushing is performed before rendering. + :cvar bool skip_reversing: :data:`False`: Whether to generate reversed animations. + + If set to :data:`False`, and no cached reversed animation + exists (or caching is disabled) for a given slide, + then the reversed animation will be simply the same + as the original one, i.e., ``rev_file = file``, + for the current slide config. """ @property