From 8721bf8cb889911bf2d7ff031f239529f02ed9fd Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Tue, 18 Jul 2023 15:58:29 -0700 Subject: [PATCH 01/25] added new checkhealth subcommand --- manim/__main__.py | 2 + manim/cli/checkhealth/__init__.py | 0 manim/cli/checkhealth/checks.py | 126 ++++++++++++++++++++++++++++++ manim/cli/checkhealth/commands.py | 72 +++++++++++++++++ 4 files changed, 200 insertions(+) create mode 100644 manim/cli/checkhealth/__init__.py create mode 100644 manim/cli/checkhealth/checks.py create mode 100644 manim/cli/checkhealth/commands.py diff --git a/manim/__main__.py b/manim/__main__.py index d1b0fff204..c90d24bfac 100644 --- a/manim/__main__.py +++ b/manim/__main__.py @@ -7,6 +7,7 @@ from . import __version__, cli_ctx_settings, console from .cli.cfg.group import cfg +from .cli.checkhealth.commands import checkhealth from .cli.default_group import DefaultGroup from .cli.init.commands import init from .cli.new.group import new @@ -48,6 +49,7 @@ def main(ctx): pass +main.add_command(checkhealth) main.add_command(cfg) main.add_command(plugins) main.add_command(init) diff --git a/manim/cli/checkhealth/__init__.py b/manim/cli/checkhealth/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/manim/cli/checkhealth/checks.py b/manim/cli/checkhealth/checks.py new file mode 100644 index 0000000000..00875eb65f --- /dev/null +++ b/manim/cli/checkhealth/checks.py @@ -0,0 +1,126 @@ +"""Auxiliary module for the checkhealth subcommand, contains +the actual check implementations.""" + +from __future__ import annotations + +from ..._config import config + +import os +import shutil +import subprocess + +HEALTH_CHECKS = [] + +def check( + description: str, + recommendation: str, + skip_on_failed: list[callable] | None = None, + post_fail_fix_hook: callable | None = None + ): + """Decorator used for declaring health checks. + + This decorator attaches some data to a function, + which is then added to a list containing all checks. + + Parameters + ---------- + description + A brief description of this check, displayed when + the checkhealth subcommand is run. + recommendation + Help text which is displayed in case the check fails. + skip_on_failed + A list of check functions which, if they fail, cause + the current check to be skipped. + post_fail_fix_hook + A function that is supposed to (interactively) help + to fix the detected problem, if possible. This is + only called upon explicit confirmation of the user. + + Returns + ------- + A check function, as required by the checkhealth subcommand. + """ + if skip_on_failed is None: + skip_on_failed = [] + skip_on_failed = [ + skip.__name__ if callable(skip) else skip + for skip in skip_on_failed + ] + def decorator(func): + func.description = description + func.recommendation = recommendation + func.skip_on_failed = skip_on_failed + func.post_fail_fix_hook = post_fail_fix_hook + HEALTH_CHECKS.append(func) + return func + return decorator + +@check( + description="Checking whether manim is on your PATH", + recommendation=( + "The command is currently not on your system's PATH.\n\n" + "You can work around this by calling the manim module directly " + "via instead of just .\n\n" + "To fix the PATH issue properly: " + "Usually, the Python package installer pip issues a warning " + "during the installation which contains more information. " + "Consider reinstalling manim via " + "followed by to see the warning again, " + "then consult the internet on how to modify your system's " + "PATH variable." + ), +) +def is_manim_on_path(): + path_to_manim = shutil.which("manim") + return path_to_manim is not None + +@check( + description="Checking whether the executable belongs to manim", + recommendation="TODO", + skip_on_failed=[is_manim_on_path], +) +def is_manim_executable_associated_to_this_library(): + path_to_manim = shutil.which("manim") + with open(path_to_manim, "r") as f: + manim_exec = f.read() + return "manim.__main__" in manim_exec + +@check( + description="Checking whether ffmpeg is available", + recommendation="TODO", +) +def is_ffmpeg_available(): + path_to_ffmpeg = shutil.which(config.ffmpeg_executable) + return path_to_ffmpeg is not None and os.access(path_to_ffmpeg, os.X_OK) + +@check( + description="Checking whether ffmpeg is working", + recommendation="TODO", + skip_on_failed=[is_ffmpeg_available], +) +def is_ffmpeg_working(): + ffmpeg_version = subprocess.run( + [config.ffmpeg_executable, "-version"], + stdout=subprocess.PIPE, + ).stdout.decode() + return ( + ffmpeg_version.startswith("ffmpeg version") and + "--enable-libx264" in ffmpeg_version + ) + +@check( + description="Checking whether latex is available", + recommendation="TODO", +) +def is_latex_available(): + path_to_latex = shutil.which("latex") + return path_to_latex is not None and os.access(path_to_latex, os.X_OK) + +@check( + description="Checking whether dvisvgm is available", + recommendation="TODO", +) +def is_dvisvgm_available(): + path_to_dvisvgm = shutil.which("dvisvgm") + return path_to_dvisvgm is not None and os.access(path_to_dvisvgm, os.X_OK) \ No newline at end of file diff --git a/manim/cli/checkhealth/commands.py b/manim/cli/checkhealth/commands.py new file mode 100644 index 0000000000..9268047f15 --- /dev/null +++ b/manim/cli/checkhealth/commands.py @@ -0,0 +1,72 @@ +"""A CLI utility helping to diagnose problems with +your Manim installation. + +""" + +from __future__ import annotations + +import click +import cloup + +from .checks import HEALTH_CHECKS + + +@cloup.command( + context_settings=None, +) +def checkhealth(): + """This subcommand checks whether Manim is installed correctly + and has access to its required (and optional) system dependencies. + """ + click.echo( + "Checking whether your installation of Manim Community " + "is healthy..." + ) + failed_checks = [] + + for check in HEALTH_CHECKS: + click.echo(f"- {check.description} ... ", nl=False) + if any( + failed_check.__name__ in check.skip_on_failed + for failed_check in failed_checks + ): + click.secho("SKIPPED", fg="blue") + continue + check_result = check() + if check_result: + click.secho("PASSED", fg="green") + else: + click.secho("FAILED", fg="red") + failed_checks.append(check) + + click.echo() + + if failed_checks: + click.echo( + "There are problems with your installation, " + "here are some recommendations to fix them:" + ) + for ind, failed_check in enumerate(failed_checks): + click.echo(failed_check.recommendation) + if ind + 1 < len(failed_checks): + click.confirm("Continue with next recommendation?") + + else: # no problems detected! + click.echo("No problems detected, your installation seems healthy!") + render_test_scene = click.confirm( + "Would you like to render and preview a test scene?" + ) + if render_test_scene: + from manim import tempconfig, Scene, ManimBanner, FadeOut, UP + + class CheckHealthDemo(Scene): + def construct(self): + banner = ManimBanner() + self.play(banner.create()) + self.wait() + self.play(banner.expand()) + self.wait() + self.play(FadeOut(banner, shift=UP)) + + with tempconfig({"preview": True, "disable_caching": True}): + CheckHealthDemo().render() From 4769f581239012ffd62ad7737add437720781be5 Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Tue, 18 Jul 2023 15:59:37 -0700 Subject: [PATCH 02/25] basic checkhealth tests --- tests/interface/test_commands.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tests/interface/test_commands.py b/tests/interface/test_commands.py index 5f6f0dcb75..5c99c0ee11 100644 --- a/tests/interface/test_commands.py +++ b/tests/interface/test_commands.py @@ -6,8 +6,9 @@ from click.testing import CliRunner -from manim import __version__, capture +from manim import __version__, capture, tempconfig from manim.__main__ import main +from manim.cli.checkhealth.checks import HEALTH_CHECKS def test_manim_version(): @@ -62,6 +63,26 @@ def test_manim_plugins_subcommand(): assert dedent(expected_output) == result.output +def test_manim_checkhealth_subcommand(): + command = ["checkhealth"] + runner = CliRunner() + result = runner.invoke(main, command) + output_lines = result.output.split("\n") + num_passed = len([line for line in output_lines if "PASSED" in line]) + assert num_passed == len(HEALTH_CHECKS) + assert "No problems detected, your installation seems healthy!" in output_lines + + +def test_manim_checkhealth_failing_subcommand(): + command = ["checkhealth"] + runner = CliRunner() + with tempconfig({"ffmpeg_executable": "/path/to/nowhere"}): + result = runner.invoke(main, command) + output_lines = result.output.split("\n") + assert "- Checking whether ffmpeg is available ... FAILED" in output_lines + assert "- Checking whether ffmpeg is working ... SKIPPED" in output_lines + + def test_manim_init_subcommand(): command = ["init"] runner = CliRunner() From 359905573ec6ca37c49fb6ba1ea5ef00f80a723e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 18 Jul 2023 23:22:26 +0000 Subject: [PATCH 03/25] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- manim/cli/checkhealth/checks.py | 34 +++++++++++++++++++------------ manim/cli/checkhealth/commands.py | 15 ++++++-------- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/manim/cli/checkhealth/checks.py b/manim/cli/checkhealth/checks.py index 00875eb65f..c1ee5e02f2 100644 --- a/manim/cli/checkhealth/checks.py +++ b/manim/cli/checkhealth/checks.py @@ -3,20 +3,21 @@ from __future__ import annotations -from ..._config import config - import os import shutil import subprocess +from ..._config import config + HEALTH_CHECKS = [] + def check( - description: str, - recommendation: str, - skip_on_failed: list[callable] | None = None, - post_fail_fix_hook: callable | None = None - ): + description: str, + recommendation: str, + skip_on_failed: list[callable] | None = None, + post_fail_fix_hook: callable | None = None, +): """Decorator used for declaring health checks. This decorator attaches some data to a function, @@ -44,9 +45,9 @@ def check( if skip_on_failed is None: skip_on_failed = [] skip_on_failed = [ - skip.__name__ if callable(skip) else skip - for skip in skip_on_failed + skip.__name__ if callable(skip) else skip for skip in skip_on_failed ] + def decorator(func): func.description = description func.recommendation = recommendation @@ -54,8 +55,10 @@ def decorator(func): func.post_fail_fix_hook = post_fail_fix_hook HEALTH_CHECKS.append(func) return func + return decorator + @check( description="Checking whether manim is on your PATH", recommendation=( @@ -75,6 +78,7 @@ def is_manim_on_path(): path_to_manim = shutil.which("manim") return path_to_manim is not None + @check( description="Checking whether the executable belongs to manim", recommendation="TODO", @@ -82,10 +86,11 @@ def is_manim_on_path(): ) def is_manim_executable_associated_to_this_library(): path_to_manim = shutil.which("manim") - with open(path_to_manim, "r") as f: + with open(path_to_manim) as f: manim_exec = f.read() return "manim.__main__" in manim_exec + @check( description="Checking whether ffmpeg is available", recommendation="TODO", @@ -94,6 +99,7 @@ def is_ffmpeg_available(): path_to_ffmpeg = shutil.which(config.ffmpeg_executable) return path_to_ffmpeg is not None and os.access(path_to_ffmpeg, os.X_OK) + @check( description="Checking whether ffmpeg is working", recommendation="TODO", @@ -105,10 +111,11 @@ def is_ffmpeg_working(): stdout=subprocess.PIPE, ).stdout.decode() return ( - ffmpeg_version.startswith("ffmpeg version") and - "--enable-libx264" in ffmpeg_version + ffmpeg_version.startswith("ffmpeg version") + and "--enable-libx264" in ffmpeg_version ) + @check( description="Checking whether latex is available", recommendation="TODO", @@ -117,10 +124,11 @@ def is_latex_available(): path_to_latex = shutil.which("latex") return path_to_latex is not None and os.access(path_to_latex, os.X_OK) + @check( description="Checking whether dvisvgm is available", recommendation="TODO", ) def is_dvisvgm_available(): path_to_dvisvgm = shutil.which("dvisvgm") - return path_to_dvisvgm is not None and os.access(path_to_dvisvgm, os.X_OK) \ No newline at end of file + return path_to_dvisvgm is not None and os.access(path_to_dvisvgm, os.X_OK) diff --git a/manim/cli/checkhealth/commands.py b/manim/cli/checkhealth/commands.py index 9268047f15..98455a323f 100644 --- a/manim/cli/checkhealth/commands.py +++ b/manim/cli/checkhealth/commands.py @@ -18,10 +18,7 @@ def checkhealth(): """This subcommand checks whether Manim is installed correctly and has access to its required (and optional) system dependencies. """ - click.echo( - "Checking whether your installation of Manim Community " - "is healthy..." - ) + click.echo("Checking whether your installation of Manim Community " "is healthy...") failed_checks = [] for check in HEALTH_CHECKS: @@ -38,9 +35,9 @@ def checkhealth(): else: click.secho("FAILED", fg="red") failed_checks.append(check) - + click.echo() - + if failed_checks: click.echo( "There are problems with your installation, " @@ -50,14 +47,14 @@ def checkhealth(): click.echo(failed_check.recommendation) if ind + 1 < len(failed_checks): click.confirm("Continue with next recommendation?") - + else: # no problems detected! click.echo("No problems detected, your installation seems healthy!") render_test_scene = click.confirm( "Would you like to render and preview a test scene?" ) if render_test_scene: - from manim import tempconfig, Scene, ManimBanner, FadeOut, UP + from manim import UP, FadeOut, ManimBanner, Scene, tempconfig class CheckHealthDemo(Scene): def construct(self): @@ -67,6 +64,6 @@ def construct(self): self.play(banner.expand()) self.wait() self.play(FadeOut(banner, shift=UP)) - + with tempconfig({"preview": True, "disable_caching": True}): CheckHealthDemo().render() From e1a888c889f9621987b64928a175ec2d72e1e0bc Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Tue, 18 Jul 2023 16:26:40 -0700 Subject: [PATCH 04/25] check -> healthcheck --- manim/cli/checkhealth/checks.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/manim/cli/checkhealth/checks.py b/manim/cli/checkhealth/checks.py index c1ee5e02f2..ccfbe3f739 100644 --- a/manim/cli/checkhealth/checks.py +++ b/manim/cli/checkhealth/checks.py @@ -12,7 +12,7 @@ HEALTH_CHECKS = [] -def check( +def healthcheck( description: str, recommendation: str, skip_on_failed: list[callable] | None = None, @@ -59,7 +59,7 @@ def decorator(func): return decorator -@check( +@healthcheck( description="Checking whether manim is on your PATH", recommendation=( "The command is currently not on your system's PATH.\n\n" @@ -79,7 +79,7 @@ def is_manim_on_path(): return path_to_manim is not None -@check( +@healthcheck( description="Checking whether the executable belongs to manim", recommendation="TODO", skip_on_failed=[is_manim_on_path], @@ -91,7 +91,7 @@ def is_manim_executable_associated_to_this_library(): return "manim.__main__" in manim_exec -@check( +@healthcheck( description="Checking whether ffmpeg is available", recommendation="TODO", ) @@ -100,7 +100,7 @@ def is_ffmpeg_available(): return path_to_ffmpeg is not None and os.access(path_to_ffmpeg, os.X_OK) -@check( +@healthcheck( description="Checking whether ffmpeg is working", recommendation="TODO", skip_on_failed=[is_ffmpeg_available], @@ -116,7 +116,7 @@ def is_ffmpeg_working(): ) -@check( +@healthcheck( description="Checking whether latex is available", recommendation="TODO", ) @@ -125,7 +125,7 @@ def is_latex_available(): return path_to_latex is not None and os.access(path_to_latex, os.X_OK) -@check( +@healthcheck( description="Checking whether dvisvgm is available", recommendation="TODO", ) From 5cc66efc7a2e1055d5d6b37f5e0dd3e3c4f78fb5 Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Tue, 18 Jul 2023 16:42:56 -0700 Subject: [PATCH 05/25] more helpful test output on checkhealth fail --- tests/interface/test_commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/interface/test_commands.py b/tests/interface/test_commands.py index 5c99c0ee11..3a8bfe3b91 100644 --- a/tests/interface/test_commands.py +++ b/tests/interface/test_commands.py @@ -69,7 +69,7 @@ def test_manim_checkhealth_subcommand(): result = runner.invoke(main, command) output_lines = result.output.split("\n") num_passed = len([line for line in output_lines if "PASSED" in line]) - assert num_passed == len(HEALTH_CHECKS) + assert num_passed == len(HEALTH_CHECKS), f"Some checks failed! Full output:\n{result.output}" assert "No problems detected, your installation seems healthy!" in output_lines From 47d7047a63fc7881ad891d869298201e81e6f060 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 18 Jul 2023 23:43:48 +0000 Subject: [PATCH 06/25] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/interface/test_commands.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/interface/test_commands.py b/tests/interface/test_commands.py index 3a8bfe3b91..318c9d70d2 100644 --- a/tests/interface/test_commands.py +++ b/tests/interface/test_commands.py @@ -69,7 +69,9 @@ def test_manim_checkhealth_subcommand(): result = runner.invoke(main, command) output_lines = result.output.split("\n") num_passed = len([line for line in output_lines if "PASSED" in line]) - assert num_passed == len(HEALTH_CHECKS), f"Some checks failed! Full output:\n{result.output}" + assert num_passed == len( + HEALTH_CHECKS + ), f"Some checks failed! Full output:\n{result.output}" assert "No problems detected, your installation seems healthy!" in output_lines From 61fdf056ac208e61135b2ff9f697832100a81819 Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Tue, 18 Jul 2023 16:45:41 -0700 Subject: [PATCH 07/25] callable -> Callable --- manim/cli/checkhealth/checks.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/manim/cli/checkhealth/checks.py b/manim/cli/checkhealth/checks.py index ccfbe3f739..65344a2e0e 100644 --- a/manim/cli/checkhealth/checks.py +++ b/manim/cli/checkhealth/checks.py @@ -6,6 +6,7 @@ import os import shutil import subprocess +from typing import Callable from ..._config import config @@ -15,8 +16,8 @@ def healthcheck( description: str, recommendation: str, - skip_on_failed: list[callable] | None = None, - post_fail_fix_hook: callable | None = None, + skip_on_failed: list[Callable] | None = None, + post_fail_fix_hook: Callable | None = None, ): """Decorator used for declaring health checks. From 814f7238e0ea044140f9eb733979ee500a9a8756 Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Tue, 18 Jul 2023 17:55:55 -0700 Subject: [PATCH 08/25] fix executable check for windows --- manim/cli/checkhealth/checks.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/manim/cli/checkhealth/checks.py b/manim/cli/checkhealth/checks.py index 65344a2e0e..7a2e70ca28 100644 --- a/manim/cli/checkhealth/checks.py +++ b/manim/cli/checkhealth/checks.py @@ -6,6 +6,7 @@ import os import shutil import subprocess +from pathlib import Path from typing import Callable from ..._config import config @@ -86,10 +87,12 @@ def is_manim_on_path(): skip_on_failed=[is_manim_on_path], ) def is_manim_executable_associated_to_this_library(): - path_to_manim = shutil.which("manim") - with open(path_to_manim) as f: + path_to_manim = Path(shutil.which("manim")) + if not path_to_manim.exists(): # windows has manim.exe instead of just manim + path_to_manim = path_to_manim.with_suffix(".exe") + with open(path_to_manim, "rb") as f: manim_exec = f.read() - return "manim.__main__" in manim_exec + return b"manim.__main__" in manim_exec @healthcheck( From 57af9dadfa9c119f2f89d044c635e61fa65ca08f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 19 Jul 2023 00:57:13 +0000 Subject: [PATCH 09/25] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- manim/cli/checkhealth/checks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manim/cli/checkhealth/checks.py b/manim/cli/checkhealth/checks.py index 7a2e70ca28..db645703a5 100644 --- a/manim/cli/checkhealth/checks.py +++ b/manim/cli/checkhealth/checks.py @@ -88,7 +88,7 @@ def is_manim_on_path(): ) def is_manim_executable_associated_to_this_library(): path_to_manim = Path(shutil.which("manim")) - if not path_to_manim.exists(): # windows has manim.exe instead of just manim + if not path_to_manim.exists(): # windows has manim.exe instead of just manim path_to_manim = path_to_manim.with_suffix(".exe") with open(path_to_manim, "rb") as f: manim_exec = f.read() From 1dd987f6e29273ec8bcb05a4fee399016a17ba1f Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Tue, 18 Jul 2023 18:01:10 -0700 Subject: [PATCH 10/25] fixed type --- manim/cli/checkhealth/checks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manim/cli/checkhealth/checks.py b/manim/cli/checkhealth/checks.py index 7a2e70ca28..1cdaac1dda 100644 --- a/manim/cli/checkhealth/checks.py +++ b/manim/cli/checkhealth/checks.py @@ -17,7 +17,7 @@ def healthcheck( description: str, recommendation: str, - skip_on_failed: list[Callable] | None = None, + skip_on_failed: list[Callable | str] | None = None, post_fail_fix_hook: Callable | None = None, ): """Decorator used for declaring health checks. From 9b2a5332152ee1be3e4a8f8b90c5f49fc0e3ed4d Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Tue, 18 Jul 2023 18:12:58 -0700 Subject: [PATCH 11/25] shutil already returns .exe in case it is there --- manim/cli/checkhealth/checks.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/manim/cli/checkhealth/checks.py b/manim/cli/checkhealth/checks.py index 1cdaac1dda..5ff7085287 100644 --- a/manim/cli/checkhealth/checks.py +++ b/manim/cli/checkhealth/checks.py @@ -87,9 +87,7 @@ def is_manim_on_path(): skip_on_failed=[is_manim_on_path], ) def is_manim_executable_associated_to_this_library(): - path_to_manim = Path(shutil.which("manim")) - if not path_to_manim.exists(): # windows has manim.exe instead of just manim - path_to_manim = path_to_manim.with_suffix(".exe") + path_to_manim = shutil.which("manim") with open(path_to_manim, "rb") as f: manim_exec = f.read() return b"manim.__main__" in manim_exec From f06d6b4438272a6aff7642a3b973aac1d764ce81 Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Tue, 18 Jul 2023 18:16:19 -0700 Subject: [PATCH 12/25] debug commit ... --- manim/cli/checkhealth/checks.py | 1 + 1 file changed, 1 insertion(+) diff --git a/manim/cli/checkhealth/checks.py b/manim/cli/checkhealth/checks.py index 5ff7085287..77bfe3981c 100644 --- a/manim/cli/checkhealth/checks.py +++ b/manim/cli/checkhealth/checks.py @@ -90,6 +90,7 @@ def is_manim_executable_associated_to_this_library(): path_to_manim = shutil.which("manim") with open(path_to_manim, "rb") as f: manim_exec = f.read() + assert False, str(manim_exec) return b"manim.__main__" in manim_exec From d3cad81c624be9846459aa3802b88783afd4cb49 Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Tue, 18 Jul 2023 19:11:46 -0700 Subject: [PATCH 13/25] do proper debug commit for windows ... --- manim/cli/checkhealth/checks.py | 2 -- tests/interface/test_commands.py | 7 +++++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/manim/cli/checkhealth/checks.py b/manim/cli/checkhealth/checks.py index 77bfe3981c..21b662569c 100644 --- a/manim/cli/checkhealth/checks.py +++ b/manim/cli/checkhealth/checks.py @@ -6,7 +6,6 @@ import os import shutil import subprocess -from pathlib import Path from typing import Callable from ..._config import config @@ -90,7 +89,6 @@ def is_manim_executable_associated_to_this_library(): path_to_manim = shutil.which("manim") with open(path_to_manim, "rb") as f: manim_exec = f.read() - assert False, str(manim_exec) return b"manim.__main__" in manim_exec diff --git a/tests/interface/test_commands.py b/tests/interface/test_commands.py index 318c9d70d2..9bbd5a7975 100644 --- a/tests/interface/test_commands.py +++ b/tests/interface/test_commands.py @@ -1,5 +1,6 @@ from __future__ import annotations +import shutil import sys from pathlib import Path from textwrap import dedent @@ -62,6 +63,12 @@ def test_manim_plugins_subcommand(): """ assert dedent(expected_output) == result.output +def test_executable_check(): + path_to_manim = shutil.which("manim") + with open(path_to_manim, "rb") as f: + manim_exec = f.read() + assert b"manim.__main__" in manim_exec, str(manim_exec) + def test_manim_checkhealth_subcommand(): command = ["checkhealth"] From c5996a03fe603c26c2006bf1c91b9f565de9da61 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 19 Jul 2023 02:12:38 +0000 Subject: [PATCH 14/25] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/interface/test_commands.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/interface/test_commands.py b/tests/interface/test_commands.py index 9bbd5a7975..003c5d2cce 100644 --- a/tests/interface/test_commands.py +++ b/tests/interface/test_commands.py @@ -63,6 +63,7 @@ def test_manim_plugins_subcommand(): """ assert dedent(expected_output) == result.output + def test_executable_check(): path_to_manim = shutil.which("manim") with open(path_to_manim, "rb") as f: From eeb1df3fe6ed95641cc37a1f5620811cc37dcc79 Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Fri, 28 Jul 2023 18:52:55 +0200 Subject: [PATCH 15/25] fix failing test if executable is batch file --- manim/cli/checkhealth/checks.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/manim/cli/checkhealth/checks.py b/manim/cli/checkhealth/checks.py index 21b662569c..767c7f75a1 100644 --- a/manim/cli/checkhealth/checks.py +++ b/manim/cli/checkhealth/checks.py @@ -89,7 +89,11 @@ def is_manim_executable_associated_to_this_library(): path_to_manim = shutil.which("manim") with open(path_to_manim, "rb") as f: manim_exec = f.read() - return b"manim.__main__" in manim_exec + + # first condition below corresponds to the executable being + # some sort of python script. second condition happens when + # the executable is actually a Windows batch file. + return b"manim.__main__" in manim_exec or b'"%~dp0\\manim"' in manim_exec @healthcheck( From 3f4c97bb6c62e0cde18b265a53858b556d049a06 Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Fri, 28 Jul 2023 18:53:10 +0200 Subject: [PATCH 16/25] added more helpful (?) recommendations on failed tests --- manim/cli/checkhealth/checks.py | 44 +++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/manim/cli/checkhealth/checks.py b/manim/cli/checkhealth/checks.py index 767c7f75a1..600784337b 100644 --- a/manim/cli/checkhealth/checks.py +++ b/manim/cli/checkhealth/checks.py @@ -82,7 +82,13 @@ def is_manim_on_path(): @healthcheck( description="Checking whether the executable belongs to manim", - recommendation="TODO", + recommendation=( + "The command does not belong to your installed version " + "of this library, it likely belongs to manimgl / manimlib.\n\n" + "Run manim via or via , or uninstall " + "and reinstall manim via to fix this." + ), skip_on_failed=[is_manim_on_path], ) def is_manim_executable_associated_to_this_library(): @@ -98,7 +104,16 @@ def is_manim_executable_associated_to_this_library(): @healthcheck( description="Checking whether ffmpeg is available", - recommendation="TODO", + recommendation=( + "Manim does not work without ffmpeg. Please follow our " + "installation instructions " + "at https://docs.manim.community/en/stable/installation.html " + "to download ffmpeg. Then, either ...\n\n" + "(a) ... make the ffmpeg executable available to your system's PATH,\n" + "(b) or, alternatively, use to create a " + "custom configuration and set the ffmpeg_executable variable to the " + "full absolute path to the ffmpeg executable." + ), ) def is_ffmpeg_available(): path_to_ffmpeg = shutil.which(config.ffmpeg_executable) @@ -107,7 +122,12 @@ def is_ffmpeg_available(): @healthcheck( description="Checking whether ffmpeg is working", - recommendation="TODO", + recommendation=( + "Your installed version of ffmpeg does not support x264 encoding, " + "which manim requires. Please follow our installation instructions " + "at https://docs.manim.community/en/stable/installation.html " + "to download and install a newer version of ffmpeg." + ), skip_on_failed=[is_ffmpeg_available], ) def is_ffmpeg_working(): @@ -123,7 +143,15 @@ def is_ffmpeg_working(): @healthcheck( description="Checking whether latex is available", - recommendation="TODO", + recommendation=( + "Manim cannot find on your system's PATH. " + "You will not be able to use Tex and MathTex mobjects " + "in your scenes.\n\n" + "Consult our installation instructions " + "at https://docs.manim.community/en/stable/installation.html " + "or search the web for instructions on how to install a " + "LaTeX distribution on your operating system." + ), ) def is_latex_available(): path_to_latex = shutil.which("latex") @@ -132,7 +160,13 @@ def is_latex_available(): @healthcheck( description="Checking whether dvisvgm is available", - recommendation="TODO", + recommendation=( + "Manim could find , but not on your system's " + "PATH. Make sure your installed LaTeX distribution comes with " + "dvisvgm and consider installing a larger distribution if it " + "does not." + ), + skip_on_failed=[is_latex_available], ) def is_dvisvgm_available(): path_to_dvisvgm = shutil.which("dvisvgm") From 4c3f5a472c31b793cfd573232e73b7ab6ff77363 Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Sat, 29 Jul 2023 03:19:22 +0200 Subject: [PATCH 17/25] allow rendering ManimBanner from prerendered SVG path --- manim/mobject/logo.py | 103 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 92 insertions(+), 11 deletions(-) diff --git a/manim/mobject/logo.py b/manim/mobject/logo.py index dcb87bde2e..d878cb6791 100644 --- a/manim/mobject/logo.py +++ b/manim/mobject/logo.py @@ -4,19 +4,101 @@ __all__ = ["ManimBanner"] +import svgelements as se + from manim.animation.updaters.update import UpdateFromAlphaFunc from manim.mobject.geometry.arc import Circle from manim.mobject.geometry.polygram import Square, Triangle -from manim.mobject.text.tex_mobject import MathTex, Tex from ..animation.animation import override_animation from ..animation.composition import AnimationGroup, Succession from ..animation.creation import Create, SpiralIn from ..animation.fading import FadeIn from ..constants import DOWN, LEFT, ORIGIN, RIGHT, TAU, UP +from ..mobject.svg.svg_mobject import VMobjectFromSVGPath from ..mobject.types.vectorized_mobject import VGroup from ..utils.rate_functions import ease_in_out_cubic, ease_out_sine, smooth -from ..utils.tex_templates import TexFontTemplates + + +MANIM_SVG_PATHS: list[se.Path] = [ + se.Path( # double stroke letter M + "M4.64259-2.092154L2.739726-6.625156C2.660025-6.824408 2.650062-6.824408 " + "2.381071-6.824408H.52802C.348692-6.824408 .199253-6.824408 .199253-6.645" + "081C.199253-6.475716 .37858-6.475716 .428394-6.475716C.547945-6.475716 ." + "816936-6.455791 1.036115-6.37609V-1.05604C1.036115-.846824 1.036115-.408" + "468 .358655-.348692C.169365-.328767 .169365-.18929 .169365-.179328C.1693" + "65 0 .328767 0 .508095 0H2.052304C2.231631 0 2.381071 0 2.381071-.179328" + "C2.381071-.268991 2.30137-.33873 2.221669-.348692C1.454545-.408468 1.454" + "545-.826899 1.454545-1.05604V-6.017435L1.464508-6.027397L3.895392-.20921" + "5C3.975093-.029888 4.044832 0 4.104608 0C4.224159 0 4.254047-.079701 4.3" + "03861-.199253L6.744707-6.027397L6.75467-6.017435V-1.05604C6.75467-.84682" + "4 6.75467-.408468 6.07721-.348692C5.88792-.328767 5.88792-.18929 5.88792" + "-.179328C5.88792 0 6.047323 0 6.22665 0H8.886675C9.066002 0 9.215442 0 9" + ".215442-.179328C9.215442-.268991 9.135741-.33873 9.05604-.348692C8.28891" + "7-.408468 8.288917-.826899 8.288917-1.05604V-5.768369C8.288917-5.977584 " + "8.288917-6.41594 8.966376-6.475716C9.066002-6.485679 9.155666-6.535492 9" + ".155666-6.645081C9.155666-6.824408 9.006227-6.824408 8.826899-6.824408H6" + ".90411C6.645081-6.824408 6.625156-6.824408 6.535492-6.615193L4.64259-2.0" + "92154ZM4.343711-1.912827C4.423412-1.743462 4.433375-1.733499 4.552927-1." + "693649L4.11457-.637609H4.094645L1.823163-6.057285C1.77335-6.1868 1.69364" + "9-6.356164 1.554172-6.475716H2.420922L4.343711-1.912827ZM1.334994-.34869" + "2H1.165629C1.185554-.37858 1.205479-.408468 1.225405-.428394C1.235367-.4" + "38356 1.235367-.448319 1.24533-.458281L1.334994-.348692ZM7.103362-6.4757" + "16H8.159402C7.940224-6.22665 7.940224-5.967621 7.940224-5.788294V-1.0361" + "15C7.940224-.856787 7.940224-.597758 8.169365-.348692H6.884184C7.103362-" + ".597758 7.103362-.856787 7.103362-1.036115V-6.475716Z" + ), + se.Path( # letter a + "M1.464508-4.024907C1.464508-4.234122 1.743462-4.393524 2.092154-4.393524" + "C2.669988-4.393524 2.929016-4.124533 2.929016-3.516812V-2.789539C1.77335" + "-2.440847 .249066-2.042341 .249066-.916563C.249066-.308842 .71731 .13947" + "7 1.354919 .139477C1.92279 .139477 2.381071-.059776 2.929016-.557908C3.0" + "38605-.049813 3.257783 .139477 3.745953 .139477C4.174346 .139477 4.48318" + "8-.019925 4.861768-.428394L4.712329-.637609L4.612702-.537983C4.582814-.5" + "08095 4.552927-.498132 4.503113-.498132C4.363636-.498132 4.293898-.58779" + "6 4.293898-.747198V-3.347447C4.293898-4.184309 3.536737-4.712329 2.32129" + "5-4.712329C1.195517-4.712329 .438356-4.204234 .438356-3.457036C.438356-3" + ".048568 .67746-2.799502 1.085928-2.799502C1.484433-2.799502 1.763387-3.0" + "38605 1.763387-3.377335C1.763387-3.676214 1.464508-3.88543 1.464508-4.02" + "4907ZM2.919054-.996264C2.650062-.687422 2.450809-.56787 2.211706-.56787C" + "1.912827-.56787 1.703611-.836862 1.703611-1.235367C1.703611-1.8132 2.122" + "042-2.231631 2.919054-2.440847V-.996264Z" + ), + se.Path( # letter n + "M2.948941-4.044832C3.297634-4.044832 3.466999-3.775841 3.466999-3.217933" + "V-.806974C3.466999-.438356 3.337484-.278954 2.998755-.239103V0H5.339975V" + "-.239103C4.951432-.268991 4.851806-.388543 4.851806-.806974V-3.307597C4." + "851806-4.164384 4.323786-4.712329 3.506849-4.712329C2.909091-4.712329 2." + "450809-4.433375 2.082192-3.845579V-4.592777H.179328V-4.353674C.617684-4." + "283935 .707347-4.184309 .707347-3.765878V-.836862C.707347-.418431 .62764" + "6-.328767 .179328-.239103V0H2.580324V-.239103C2.211706-.288917 2.092154-" + ".438356 2.092154-.806974V-3.466999C2.092154-3.576588 2.530511-4.044832 2" + ".948941-4.044832Z" + ), + se.Path( # letter i + "M2.15193-4.592777H.239103V-4.353674C.67746-4.26401 .767123-4.174346 .767" + "123-3.765878V-.836862C.767123-.428394 .697385-.348692 .239103-.239103V0H" + "2.6401V-.239103C2.291407-.288917 2.15193-.428394 2.15193-.806974V-4.5927" + "77ZM1.454545-6.884184C1.026152-6.884184 .67746-6.535492 .67746-6.117061C" + ".67746-5.668742 1.006227-5.339975 1.444583-5.339975S2.221669-5.668742 2." + "221669-6.107098C2.221669-6.535492 1.882939-6.884184 1.454545-6.884184Z" + ), + se.Path( # letter m + "M2.929016-4.044832C3.317559-4.044832 3.466999-3.815691 3.466999-3.217933" + "V-.806974C3.466999-.398506 3.35741-.268991 2.988792-.239103V0H5.32005V-." + "239103C4.971357-.278954 4.851806-.428394 4.851806-.806974V-3.466999C4.85" + "1806-3.576588 5.310087-4.044832 5.69863-4.044832C6.07721-4.044832 6.2266" + "5-3.805729 6.22665-3.217933V-.806974C6.22665-.388543 6.117061-.268991 5." + "738481-.239103V0H8.109589V-.239103C7.721046-.259029 7.611457-.37858 7.61" + "1457-.806974V-3.307597C7.611457-4.164384 7.083437-4.712329 6.266501-4.71" + "2329C5.69863-4.712329 5.32005-4.483188 4.801993-3.845579C4.503113-4.4732" + "25 4.154421-4.712329 3.526775-4.712329S2.440847-4.443337 2.062267-3.8455" + "79V-4.592777H.179328V-4.353674C.617684-4.293898 .707347-4.174346 .707347" + "-3.765878V-.836862C.707347-.428394 .617684-.318804 .179328-.239103V0H2.5" + "50436V-.239103C2.201743-.288917 2.092154-.428394 2.092154-.806974V-3.466" + "999C2.092154-3.58655 2.530511-4.044832 2.929016-4.044832Z" + ), +] class ManimBanner(VGroup): @@ -67,8 +149,9 @@ def __init__(self, dark_theme: bool = True): self.font_color = "#ece6e2" if dark_theme else "#343434" self.scale_factor = 1 - self.M = MathTex(r"\mathbb{M}").scale(7).set_color(self.font_color) - self.M.shift(2.25 * LEFT + 1.5 * UP) + self.M = VMobjectFromSVGPath(MANIM_SVG_PATHS[0]).flip(RIGHT).center() + self.M.set(stroke_width=0).scale(7 * 48 / 960) + self.M.set_fill(color=self.font_color, opacity=1).shift(2.25 * LEFT + 1.5 * UP) self.circle = Circle(color=logo_green, fill_opacity=1).shift(LEFT) self.square = Square(color=logo_blue, fill_opacity=1).shift(UP) @@ -78,16 +161,14 @@ def __init__(self, dark_theme: bool = True): self.move_to(ORIGIN) anim = VGroup() - for i, ch in enumerate("anim"): - tex = Tex( - "\\textbf{" + ch + "}", - tex_template=TexFontTemplates.gnu_freeserif_freesans, - ) - if i != 0: + for ind, path in enumerate(MANIM_SVG_PATHS[1:]): + tex = VMobjectFromSVGPath(path).flip(RIGHT).center() + tex.set(stroke_width=0).scale(48 / 960) + if ind > 0: tex.next_to(anim, buff=0.01) tex.align_to(self.M, DOWN) anim.add(tex) - anim.set_color(self.font_color) + anim.set_fill(color=self.font_color, opacity=1) anim.height = m_height_over_anim_height * self.M.height # Note: "anim" is only shown in the expanded state From 85ab0dd08a814d6225f9cd08853f10f8f1796ca9 Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Sat, 29 Jul 2023 03:38:17 +0200 Subject: [PATCH 18/25] improved test scene, actually test text / latex --- manim/cli/checkhealth/commands.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/manim/cli/checkhealth/commands.py b/manim/cli/checkhealth/commands.py index 98455a323f..1ebec0c505 100644 --- a/manim/cli/checkhealth/commands.py +++ b/manim/cli/checkhealth/commands.py @@ -54,16 +54,25 @@ def checkhealth(): "Would you like to render and preview a test scene?" ) if render_test_scene: - from manim import UP, FadeOut, ManimBanner, Scene, tempconfig + import manim as mn - class CheckHealthDemo(Scene): + class CheckHealthDemo(mn.Scene): def construct(self): - banner = ManimBanner() + banner = mn.ManimBanner().shift(mn.UP * 0.5) self.play(banner.create()) - self.wait() + self.wait(0.5) self.play(banner.expand()) - self.wait() - self.play(FadeOut(banner, shift=UP)) + self.wait(0.5) + text_left = mn.Text("All systems operational!") + formula_right = mn.MathTex(r"\oint_{\gamma} f(z)~dz = 0") + text_tex_group = mn.VGroup(text_left, formula_right) + text_tex_group.arrange(mn.RIGHT, buff=1).next_to(banner, mn.DOWN) + self.play(mn.Write(text_tex_group)) + self.wait(0.5) + self.play( + mn.FadeOut(banner, shift=mn.UP), + mn.FadeOut(text_tex_group, shift=mn.DOWN), + ) - with tempconfig({"preview": True, "disable_caching": True}): + with mn.tempconfig({"preview": True, "disable_caching": True}): CheckHealthDemo().render() From 2af2fb8a369f0d9d755e56a4c32667df8e3af654 Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Sat, 29 Jul 2023 04:09:41 +0200 Subject: [PATCH 19/25] added debug info on python executable --- manim/cli/checkhealth/commands.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/manim/cli/checkhealth/commands.py b/manim/cli/checkhealth/commands.py index 1ebec0c505..8d80582588 100644 --- a/manim/cli/checkhealth/commands.py +++ b/manim/cli/checkhealth/commands.py @@ -7,6 +7,7 @@ import click import cloup +import sys from .checks import HEALTH_CHECKS @@ -18,7 +19,8 @@ def checkhealth(): """This subcommand checks whether Manim is installed correctly and has access to its required (and optional) system dependencies. """ - click.echo("Checking whether your installation of Manim Community " "is healthy...") + click.echo(f"Python executable: {sys.executable}\n") + click.echo("Checking whether your installation of Manim Community is healthy...") failed_checks = [] for check in HEALTH_CHECKS: From fc7b76e8d70bb121d02b697a4f22839e7fee76af Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 29 Jul 2023 02:12:18 +0000 Subject: [PATCH 20/25] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- manim/cli/checkhealth/commands.py | 3 ++- manim/mobject/logo.py | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/manim/cli/checkhealth/commands.py b/manim/cli/checkhealth/commands.py index 8d80582588..5386f5e7e7 100644 --- a/manim/cli/checkhealth/commands.py +++ b/manim/cli/checkhealth/commands.py @@ -5,9 +5,10 @@ from __future__ import annotations +import sys + import click import cloup -import sys from .checks import HEALTH_CHECKS diff --git a/manim/mobject/logo.py b/manim/mobject/logo.py index d878cb6791..ad5fd5d663 100644 --- a/manim/mobject/logo.py +++ b/manim/mobject/logo.py @@ -19,7 +19,6 @@ from ..mobject.types.vectorized_mobject import VGroup from ..utils.rate_functions import ease_in_out_cubic, ease_out_sine, smooth - MANIM_SVG_PATHS: list[se.Path] = [ se.Path( # double stroke letter M "M4.64259-2.092154L2.739726-6.625156C2.660025-6.824408 2.650062-6.824408 " From eafc57cc99b0e3ddab2a5ef2702f7f715d951a0f Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Sat, 29 Jul 2023 04:30:20 +0200 Subject: [PATCH 21/25] remove debug test again --- tests/interface/test_commands.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/interface/test_commands.py b/tests/interface/test_commands.py index 003c5d2cce..995daf2c37 100644 --- a/tests/interface/test_commands.py +++ b/tests/interface/test_commands.py @@ -64,13 +64,6 @@ def test_manim_plugins_subcommand(): assert dedent(expected_output) == result.output -def test_executable_check(): - path_to_manim = shutil.which("manim") - with open(path_to_manim, "rb") as f: - manim_exec = f.read() - assert b"manim.__main__" in manim_exec, str(manim_exec) - - def test_manim_checkhealth_subcommand(): command = ["checkhealth"] runner = CliRunner() From 027a7564e219fd2843511f7116725acf525a8520 Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Sat, 5 Aug 2023 02:20:58 +0200 Subject: [PATCH 22/25] move SCALE_FACTOR_PER_FONT_POINT to constants --- manim/constants.py | 2 ++ manim/mobject/text/tex_mobject.py | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/manim/constants.py b/manim/constants.py index d81d85902c..1f6a8684e6 100644 --- a/manim/constants.py +++ b/manim/constants.py @@ -62,6 +62,7 @@ "DEFAULT_POINT_DENSITY_1D", "DEFAULT_STROKE_WIDTH", "DEFAULT_FONT_SIZE", + "SCALE_FACTOR_PER_FONT_POINT", "PI", "TAU", "DEGREES", @@ -183,6 +184,7 @@ DEFAULT_POINT_DENSITY_1D: int = 10 DEFAULT_STROKE_WIDTH: int = 4 DEFAULT_FONT_SIZE: float = 48 +SCALE_FACTOR_PER_FONT_POINT: float = 1 / 960 # Mathematical constants PI: float = np.pi diff --git a/manim/mobject/text/tex_mobject.py b/manim/mobject/text/tex_mobject.py index b92b5459e5..e265642ff0 100644 --- a/manim/mobject/text/tex_mobject.py +++ b/manim/mobject/text/tex_mobject.py @@ -38,8 +38,6 @@ from manim.utils.tex import TexTemplate from manim.utils.tex_file_writing import tex_to_svg_file -SCALE_FACTOR_PER_FONT_POINT = 1 / 960 - tex_string_to_mob_map = {} From 238746d72f1d52c717f961a43d16d05189c683ef Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Sat, 5 Aug 2023 02:22:06 +0200 Subject: [PATCH 23/25] access constants via module in logo.py --- manim/mobject/logo.py | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/manim/mobject/logo.py b/manim/mobject/logo.py index ad5fd5d663..6473e7c009 100644 --- a/manim/mobject/logo.py +++ b/manim/mobject/logo.py @@ -10,14 +10,15 @@ from manim.mobject.geometry.arc import Circle from manim.mobject.geometry.polygram import Square, Triangle +from .. import constants as cst + from ..animation.animation import override_animation from ..animation.composition import AnimationGroup, Succession from ..animation.creation import Create, SpiralIn from ..animation.fading import FadeIn -from ..constants import DOWN, LEFT, ORIGIN, RIGHT, TAU, UP from ..mobject.svg.svg_mobject import VMobjectFromSVGPath from ..mobject.types.vectorized_mobject import VGroup -from ..utils.rate_functions import ease_in_out_cubic, ease_out_sine, smooth +from ..utils.rate_functions import ease_in_out_cubic, smooth MANIM_SVG_PATHS: list[se.Path] = [ se.Path( # double stroke letter M @@ -148,24 +149,26 @@ def __init__(self, dark_theme: bool = True): self.font_color = "#ece6e2" if dark_theme else "#343434" self.scale_factor = 1 - self.M = VMobjectFromSVGPath(MANIM_SVG_PATHS[0]).flip(RIGHT).center() - self.M.set(stroke_width=0).scale(7 * 48 / 960) - self.M.set_fill(color=self.font_color, opacity=1).shift(2.25 * LEFT + 1.5 * UP) + self.M = VMobjectFromSVGPath(MANIM_SVG_PATHS[0]).flip(cst.RIGHT).center() + self.M.set(stroke_width=0).scale( + 7 * cst.DEFAULT_FONT_SIZE * cst.SCALE_FACTOR_PER_FONT_POINT + ) + self.M.set_fill(color=self.font_color, opacity=1).shift(2.25 * cst.LEFT + 1.5 * cst.UP) - self.circle = Circle(color=logo_green, fill_opacity=1).shift(LEFT) - self.square = Square(color=logo_blue, fill_opacity=1).shift(UP) - self.triangle = Triangle(color=logo_red, fill_opacity=1).shift(RIGHT) + self.circle = Circle(color=logo_green, fill_opacity=1).shift(cst.LEFT) + self.square = Square(color=logo_blue, fill_opacity=1).shift(cst.UP) + self.triangle = Triangle(color=logo_red, fill_opacity=1).shift(cst.RIGHT) self.shapes = VGroup(self.triangle, self.square, self.circle) self.add(self.shapes, self.M) - self.move_to(ORIGIN) + self.move_to(cst.ORIGIN) anim = VGroup() for ind, path in enumerate(MANIM_SVG_PATHS[1:]): - tex = VMobjectFromSVGPath(path).flip(RIGHT).center() + tex = VMobjectFromSVGPath(path).flip(cst.RIGHT).center() tex.set(stroke_width=0).scale(48 / 960) if ind > 0: tex.next_to(anim, buff=0.01) - tex.align_to(self.M, DOWN) + tex.align_to(self.M, cst.DOWN) anim.add(tex) anim.set_fill(color=self.font_color, opacity=1) anim.height = m_height_over_anim_height * self.M.height @@ -261,7 +264,7 @@ def construct(self): m_shape_offset = 6.25 * self.scale_factor shape_sliding_overshoot = self.scale_factor * 0.8 m_anim_buff = 0.06 - self.anim.next_to(self.M, buff=m_anim_buff).align_to(self.M, DOWN) + self.anim.next_to(self.M, buff=m_anim_buff).align_to(self.M, cst.DOWN) self.anim.set_opacity(0) self.shapes.save_state() m_clone = self.anim[-1].copy() @@ -273,7 +276,7 @@ def construct(self): def shift(vector): self.shapes.restore() - left_group.align_to(self.M.saved_state, LEFT) + left_group.align_to(self.M.saved_state, cst.LEFT) if direction == "right": self.shapes.shift(vector) elif direction == "center": @@ -283,7 +286,7 @@ def shift(vector): left_group.shift(-vector) def slide_and_uncover(mob, alpha): - shift(alpha * (m_shape_offset + shape_sliding_overshoot) * RIGHT) + shift(alpha * (m_shape_offset + shape_sliding_overshoot) * cst.RIGHT) # Add letters when they are covered for letter in mob.anim: @@ -305,7 +308,7 @@ def slide_back(mob, alpha): m_clone.move_to(mob.anim[-1]) mob.anim.set_opacity(1) - shift(alpha * shape_sliding_overshoot * LEFT) + shift(alpha * shape_sliding_overshoot * cst.LEFT) if alpha == 1: mob.remove(m_clone) From 08ed37ca6c0839f88bf1285d6176de64b7483538 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 5 Aug 2023 00:22:46 +0000 Subject: [PATCH 24/25] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- manim/mobject/logo.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/manim/mobject/logo.py b/manim/mobject/logo.py index 6473e7c009..b1579d1791 100644 --- a/manim/mobject/logo.py +++ b/manim/mobject/logo.py @@ -11,7 +11,6 @@ from manim.mobject.geometry.polygram import Square, Triangle from .. import constants as cst - from ..animation.animation import override_animation from ..animation.composition import AnimationGroup, Succession from ..animation.creation import Create, SpiralIn @@ -153,7 +152,9 @@ def __init__(self, dark_theme: bool = True): self.M.set(stroke_width=0).scale( 7 * cst.DEFAULT_FONT_SIZE * cst.SCALE_FACTOR_PER_FONT_POINT ) - self.M.set_fill(color=self.font_color, opacity=1).shift(2.25 * cst.LEFT + 1.5 * cst.UP) + self.M.set_fill(color=self.font_color, opacity=1).shift( + 2.25 * cst.LEFT + 1.5 * cst.UP + ) self.circle = Circle(color=logo_green, fill_opacity=1).shift(cst.LEFT) self.square = Square(color=logo_blue, fill_opacity=1).shift(cst.UP) From 558dfd8fb94d43f2a8e911adae1eeaf55e80ffe1 Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Sat, 5 Aug 2023 02:25:14 +0200 Subject: [PATCH 25/25] replaced other occurrence of 48 / 960 --- manim/mobject/logo.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/manim/mobject/logo.py b/manim/mobject/logo.py index b1579d1791..6242a4c645 100644 --- a/manim/mobject/logo.py +++ b/manim/mobject/logo.py @@ -166,7 +166,9 @@ def __init__(self, dark_theme: bool = True): anim = VGroup() for ind, path in enumerate(MANIM_SVG_PATHS[1:]): tex = VMobjectFromSVGPath(path).flip(cst.RIGHT).center() - tex.set(stroke_width=0).scale(48 / 960) + tex.set(stroke_width=0).scale( + cst.DEFAULT_FONT_SIZE * cst.SCALE_FACTOR_PER_FONT_POINT + ) if ind > 0: tex.next_to(anim, buff=0.01) tex.align_to(self.M, cst.DOWN)