diff --git a/manim/_config/utils.py b/manim/_config/utils.py index 8d1de7a9d4..897885ddb2 100644 --- a/manim/_config/utils.py +++ b/manim/_config/utils.py @@ -735,6 +735,9 @@ def digest_args(self, args: argparse.Namespace) -> Self: contents of said file with :meth:`~ManimConfig.digest_file` before digesting any other CLI arguments. + Otherwise, when rendering from a file, Manim looks for ``manim.cfg`` in + the input file's directory before digesting the CLI arguments. + """ # if the input file is a config file, parse it properly if args.file.suffix == ".cfg": @@ -749,6 +752,11 @@ def digest_args(self, args: argparse.Namespace) -> Self: # flags supersede it if args.config_file: self.digest_file(args.config_file) + elif str(args.file) != "-" and not getattr(args, "jupyter", False): + input_path = Path(args.file).absolute() + config_dir = input_path if input_path.is_dir() else input_path.parent + scene_config_file = config_dir / "manim.cfg" + self.digest_parser(make_config_parser(scene_config_file)) # read input_file from the args if it wasn't set by the config file if not self.input_file: diff --git a/tests/test_config.py b/tests/test_config.py index f80b5808ee..6bd3c75f84 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -6,8 +6,9 @@ import numpy as np import pytest -from manim import RIGHT, WHITE, Scene, Square, Tex, Text, Vector, tempconfig -from manim._config.utils import ManimConfig +from manim import BLUE, RED, RIGHT, WHITE, Scene, Square, Tex, Text, Vector, tempconfig +from manim._config.utils import ManimConfig, make_config_parser +from manim.cli.render.commands import ClickArgs, render from manim.constants import RendererType from manim.mobject.opengl.opengl_vectorized_mobject import OpenGLVMobject from manim.mobject.types.vectorized_mobject import VMobject @@ -133,6 +134,55 @@ def test_digest_file(tmp_path, config): ) +def test_digest_args_uses_config_next_to_input_file(tmp_path, monkeypatch): + working_dir = tmp_path / "working" + scene_dir = tmp_path / "scenes" + working_dir.mkdir() + scene_dir.mkdir() + + scene_file = scene_dir / "example.py" + scene_file.write_text("") + (working_dir / "manim.cfg").write_text( + "[CLI]\nbackground_color = BLUE\nframe_rate = 17\n" + ) + scene_config_file = scene_dir / "manim.cfg" + scene_config_file.write_text("[CLI]\nbackground_color = RED\n") + monkeypatch.chdir(working_dir) + + with render.make_context("manim render", [str(scene_file)]) as context: + args = ClickArgs(context.params) + + parsed_config = ManimConfig().digest_parser(make_config_parser()) + expected_config = ManimConfig().digest_parser(make_config_parser(scene_config_file)) + assert parsed_config.background_color == BLUE + assert parsed_config.frame_rate == 17 + + parsed_config.digest_args(args) + + assert parsed_config.background_color == RED + assert parsed_config.background_color == expected_config.background_color + assert parsed_config.frame_rate == expected_config.frame_rate + + +def test_digest_args_accepts_directory_with_input_file_config(tmp_path, monkeypatch): + working_dir = tmp_path / "working" + project_dir = tmp_path / "project" + working_dir.mkdir() + project_dir.mkdir() + scene_file = project_dir / "example.py" + scene_file.write_text("") + (project_dir / "manim.cfg").write_text(f"[CLI]\ninput_file = {scene_file}\n") + monkeypatch.chdir(working_dir) + + with render.make_context("manim render", [str(project_dir)]) as context: + args = ClickArgs(context.params) + + parsed_config = ManimConfig().digest_parser(make_config_parser()) + parsed_config.digest_args(args) + + assert Path(parsed_config.input_file) == scene_file + + def test_custom_dirs(tmp_path, config): config.media_dir = tmp_path config.save_sections = True