import shutil import textwrap from pathlib import Path import pytest from ..utils.commands import capture plugin_pyproject_template = textwrap.dedent( """ [tool.poetry] name = "{plugin_name}" authors = ["ManimCE"] version = "0.1.0" description = "" [tool.poetry.dependencies] python = "^3.6" [tool.poetry.plugins."manim.plugins"] "{plugin_name}" = "{plugin_entrypoint}" [build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" """ ) plugin_init_template = textwrap.dedent( """ from manim import * class {class_name}(VMobject): def __init__(self): super().__init__() dot1 = Dot(fill_color=GREEN).shift(LEFT) dot2 = Dot(fill_color=BLUE) dot3 = Dot(fill_color=RED).shift(RIGHT) self.dotgrid = VGroup(dot1, dot2, dot3) self.add(self.dotgrid) def update_dot(self): self.dotgrid.become(self.dotgrid.shift(UP)) def {function_name}(): return [{class_name}] """ ) cfg_file_contents = textwrap.dedent( """ [CLI] plugins = test_plugin """ ) def simple_scenes_path(): return str(Path(__file__).parent / "simple_scenes.py") def cfg_file_create(cfg_file_contents, path): file_loc = (path / "manim.cfg").absolute() with open(file_loc, "w") as f: f.write(cfg_file_contents) return file_loc def test_plugin_warning(tmp_path, python_version): cfg_file_contents = textwrap.dedent( """ [CLI] plugins = DNEPlugin """ ) cfg_file = cfg_file_create(cfg_file_contents, tmp_path) scene_name = "SquareToCircle" command = [ python_version, "-m", "manim", "-ql", "--media_dir", str(cfg_file.parent), "--config_file", str(cfg_file), simple_scenes_path(), scene_name, ] out, err, exit_code = capture(command, cwd=str(cfg_file.parent)) assert exit_code == 0, err assert "Missing Plugins" in out, "Missing Plugins isn't in Output." @pytest.fixture def function_like_plugin(tmp_path, python_version): plugin_name = "test_plugin" entry_point = f"{plugin_name}.__init__:import_all" plugin_dir = tmp_path / "function_entrypoint" module_dir = plugin_dir / plugin_name module_dir.mkdir(parents=True) with open(module_dir / "__init__.py", "w") as f: f.write( plugin_init_template.format( class_name="FunctionLike", function_name="import_all", ) ) with open(plugin_dir / "pyproject.toml", "w") as f: f.write( plugin_pyproject_template.format( plugin_name=plugin_name, plugin_entrypoint=entry_point, ) ) command = [ python_version, "-m", "pip", "install", str(plugin_dir.absolute()), ] out, err, exit_code = capture(command, cwd=str(plugin_dir)) print(out) assert exit_code == 0, err yield module_dir shutil.rmtree(plugin_dir) command = [python_version, "-m", "pip", "uninstall", plugin_name, "-y"] out, err, exit_code = capture(command) print(out) assert exit_code == 0, err @pytest.mark.slow def test_plugin_function_like(tmp_path, function_like_plugin, python_version): cfg_file = cfg_file_create(cfg_file_contents, tmp_path) scene_name = "FunctionLikeTest" command = [ python_version, "-m", "manim", "-ql", "--media_dir", str(cfg_file.parent), "--config_file", str(cfg_file), simple_scenes_path(), scene_name, ] out, err, exit_code = capture(command, cwd=str(cfg_file.parent)) print(out) assert exit_code == 0, err @pytest.fixture def module_no_all_plugin(tmp_path, python_version): plugin_name = "test_plugin" entry_point = f"{plugin_name}" plugin_dir = tmp_path / "module_entrypoint_no_all" module_dir = plugin_dir / plugin_name module_dir.mkdir(parents=True) with open(module_dir / "__init__.py", "w") as f: f.write( plugin_init_template.format( class_name="NoAll", function_name="import_all", ) ) with open(plugin_dir / "pyproject.toml", "w") as f: f.write( plugin_pyproject_template.format( plugin_name=plugin_name, plugin_entrypoint=entry_point, ) ) command = [ python_version, "-m", "pip", "install", str(plugin_dir.absolute()), ] out, err, exit_code = capture(command, cwd=str(plugin_dir)) print(out) assert exit_code == 0, err yield module_dir shutil.rmtree(plugin_dir) command = [python_version, "-m", "pip", "uninstall", plugin_name, "-y"] out, err, exit_code = capture(command) print(out) assert exit_code == 0, err @pytest.mark.slow def test_plugin_no_all(tmp_path, module_no_all_plugin, python_version): cfg_file = cfg_file_create(cfg_file_contents, tmp_path) scene_name = "NoAllTest" command = [ python_version, "-m", "manim", "-ql", "--media_dir", str(cfg_file.parent), "--config_file", str(cfg_file), simple_scenes_path(), scene_name, ] out, err, exit_code = capture(command, cwd=str(cfg_file.parent)) print(out) print(err) assert exit_code == 0, err @pytest.fixture def module_with_all_plugin(tmp_path, python_version): plugin_name = "test_plugin" entry_point = f"{plugin_name}" plugin_dir = tmp_path / "module_entrypoint_with_all" module_dir = plugin_dir / plugin_name module_dir.mkdir(parents=True) with open(module_dir / "__init__.py", "w") as f: f.write("__all__=['WithAll']\n") f.write( plugin_init_template.format( class_name="WithAll", function_name="import_all", ) ) with open(plugin_dir / "pyproject.toml", "w") as f: f.write( plugin_pyproject_template.format( plugin_name=plugin_name, plugin_entrypoint=entry_point, ) ) command = [ python_version, "-m", "pip", "install", str(plugin_dir.absolute()), ] out, err, exit_code = capture(command, cwd=str(plugin_dir)) print(out) assert exit_code == 0, err yield module_dir shutil.rmtree(plugin_dir) command = [python_version, "-m", "pip", "uninstall", plugin_name, "-y"] out, err, exit_code = capture(command) print(out) assert exit_code == 0, err @pytest.mark.slow def test_plugin_with_all(tmp_path, module_with_all_plugin, python_version): cfg_file = cfg_file_create(cfg_file_contents, tmp_path) scene_name = "WithAllTest" command = [ python_version, "-m", "manim", "-ql", "--media_dir", str(cfg_file.parent), "--config_file", str(cfg_file), simple_scenes_path(), scene_name, ] out, err, exit_code = capture(command, cwd=str(cfg_file.parent)) print(out) print(err) assert exit_code == 0, err