manim/tests/test_plugins/test_plugins.py
Jason Villanueva a87bb28484
Refactored the Command Line Interface to use Click + Cloup instead of Argparse (#1013)
* Added click dependency and command structure

* Refactored code for separation of concerns

* Shortened plugins command to plugin, added render options

* first draft for render -h

* First successful render using click

* Cleaned main

* Moved flush_cache to option, ran black

* Removed argparse logic, scattered print statements

* corrected tests, all passing

* merge upstream

* fixed test with click's clirunner

* Fixed doctest configuration.rst

* Temporarily add in main_utils

* Removed main_utils.parse_args, used ManimConfig.digest_args

* fixed progress bar

* Fix jupyter

* black

* Fixed incorrectly merged merge conflict

* updated README command.png image

* updated configuration.rst expected output

* Fixed test_plugins and config_file expected type

* Refixed the jupyter fix

* Apply 3/5 suggestions

Remove stray print

Improve readability of test code

Added module docs for the subcommands

* Updated `main` to `manim` for tests

* Forced `file` positional argument to be Path type

* Fixed main -> manim

* Added libpango to linux dependency

* Updated poetry.lock

* Changed configuration.rst test

* Fixed test_a_flag test

minor space issue

added media_width to configuration.rst

* Fixed fps flag in Cairo rendering

* Fixed more outdated rst in sphinx docs

Removed default for fps option, always overwrote quality

Fixed doctest control_data

* Fixed more incorrect rst orderings

* Update tests/test_commands.py

Co-authored-by: Naveen M K <naveen@syrusdark.website>

* Added suggestions

* Removed unused imports

* Reverted entry point back to main

* Update manim/_config/default.cfg

Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

* Adjusted ipython_magic's call to the entry_point

* Converted frame_rate to int if integer

* run black

* Fixed doctest

* Fixed issue with command name from CliRunner

* Fixed multiple video windows opening from upstream merge

* to black or not to black

* Added deprecation warning to render subcommand

* warning instead of warn

* Applied Naveen's suggestions

* Made `manim render` show the help page

* Update manim/cli/render/commands.py

Co-authored-by: Naveen M K <naveen@syrusdark.website>

* Update manim/cli/cfg/commands.py

Co-authored-by: Naveen M K <naveen@syrusdark.website>

* Update manim/cli/cfg/commands.py

Co-authored-by: Naveen M K <naveen@syrusdark.website>

* Update manim/cli/plugins/commands.py

Co-authored-by: Naveen M K <naveen@syrusdark.website>

* Addressed some style changes

* add back in write_to_movie temporarily for OpenGL support

* Removed sound flag, deprecated use_opengl_renderer, added renderer option

* revert webgl_renderer_path removal

* Fixed cfg export

Fixed readme usage of CLI

* Flake8/black

* Fixed bug in setting renderer choice

* Removed log message due to default option

Removed default option of background color

Fixed write_to_movie flag default

* Fix log_to_file tests

* Make '-c' option for config_file, not background_color

* print colored version always

* Remove -v = --version shorthand, conflicts with verbosity

* Use subprocess.run instead of Click's CliRunner for stdout

* Refactor cli/render to use Cloup instead of click-option-group

1) There's a new file for each option group
2) render is now a cloup.Command, not a Group

Fixed issue when an animation is cached, manim can't merge the partial movie files. (#1192)

* fixed issue

* fixed tests

* Update manim/renderer/cairo_renderer.py

Co-authored-by: Darylgolden <darylgolden@gmail.com>

* added tests

* imrpoved test

* fixed logic

* added new test

* check if the file has been outputed

* added test when caching is enabled

* fixed tests on windows

* black

* Update manim/renderer/cairo_renderer.py

Co-authored-by: Naveen M K <naveen@syrusdark.website>

* Update tests/assert_utils.py

Co-authored-by: Naveen M K <naveen@syrusdark.website>

Co-authored-by: KingWampy <9156604+WampyCakes@users.noreply.github.com>
Co-authored-by: Darylgolden <darylgolden@gmail.com>
Co-authored-by: Naveen M K <naveen@syrusdark.website>

Added :ref_methods: to the manim directive (#1209)

* fix manim_directive for methods

* added ref_methods to Angle example

* black

* added new ref_methods references

* sort out ref_functions vs ref_methods in examples.rst

Co-authored-by: Jason Villanueva <a@jsonvillanueva.com>
Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

Fixed issue when an animation is cached, manim can't merge the partial movie files. (#1192)

* fixed issue

* fixed tests

* Update manim/renderer/cairo_renderer.py

Co-authored-by: Darylgolden <darylgolden@gmail.com>

* added tests

* imrpoved test

* fixed logic

* added new test

* check if the file has been outputed

* added test when caching is enabled

* fixed tests on windows

* black

* Update manim/renderer/cairo_renderer.py

Co-authored-by: Naveen M K <naveen@syrusdark.website>

* Update tests/assert_utils.py

Co-authored-by: Naveen M K <naveen@syrusdark.website>

Co-authored-by: KingWampy <9156604+WampyCakes@users.noreply.github.com>
Co-authored-by: Darylgolden <darylgolden@gmail.com>
Co-authored-by: Naveen M K <naveen@syrusdark.website>

Added :ref_methods: to the manim directive (#1209)

* fix manim_directive for methods

* added ref_methods to Angle example

* black

* added new ref_methods references

* sort out ref_functions vs ref_methods in examples.rst

Co-authored-by: Jason Villanueva <a@jsonvillanueva.com>
Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>

Fixed unnecessary args dict

* Fixed bug that changed caching hashing result

* Revert doctest logic for fps filename output

Co-authored-by: Naveen M K <naveen@syrusdark.website>
Co-authored-by: Benjamin Hackl <devel@benjamin-hackl.at>
Co-authored-by: Gianluca Gippetto <gianluca.gippetto@gmail.com>
2021-04-01 23:53:07 -07:00

273 lines
7.3 KiB
Python

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