From f162a23d1495f6c57ca91a677675d818b6d22cef Mon Sep 17 00:00:00 2001 From: Syrus Dark Date: Wed, 27 Jan 2021 01:22:05 +0530 Subject: [PATCH 01/13] Automatically import Plugins Specify plugins using CLI and config file Signed-off-by: Naveen M K --- docs/source/installation/plugins.rst | 29 +++++++++++++++++++- example_scenes/manim.cfg | 2 ++ manim/_config/default.cfg | 3 +++ manim/_config/main_utils.py | 11 ++++++++ manim/_config/utils.py | 15 ++++++++++- manim/plugins/.gitignore | 1 - manim/plugins/__init__.py | 1 + manim/plugins/import_plugins.py | 40 ++++++++++++++++++++++++++++ poetry.lock | 30 ++++++++++++--------- pyproject.toml | 4 ++- 10 files changed, 119 insertions(+), 17 deletions(-) delete mode 100644 manim/plugins/.gitignore create mode 100644 manim/plugins/__init__.py create mode 100644 manim/plugins/import_plugins.py diff --git a/docs/source/installation/plugins.rst b/docs/source/installation/plugins.rst index 27e447ff23..e84831081a 100644 --- a/docs/source/installation/plugins.rst +++ b/docs/source/installation/plugins.rst @@ -101,4 +101,31 @@ specified in poetry as: .. code-block:: toml [tool.poetry.plugins."manim.plugins"] - "name" = "object_reference" \ No newline at end of file + "name" = "object_reference" + +Here ``object_reference`` can point to either a function in a module or a module +itself. For example, + +.. code-block:: toml + + [tool.poetry.plugins."manim.plugins"] + "manim_plugintemplate" = "manim_plugintemplate" + +Here a module is used as ``object_reference``, and when this plugin is enabled, +Manim will look for ``__all__`` keyword defined in ``manim_plugintemplate`` and +everything as a global variable one by one. + +If ``object_reference`` is a function, Manim calls the function and expects the +function returns a list of modules or functions that needs to defined globally and +it defined it. + +For example, + +.. code-block:: toml + + [tool.poetry.plugins."manim.plugins"] + "manim_plugintemplate" = "manim_awesomeplugin.imports:setup_things" + +Here, Manim will call the function ``setup_things`` defined in +``manim_awesomeplugin.imports`` and calls that. It returns a list of function or +modules which will be imported globally. diff --git a/example_scenes/manim.cfg b/example_scenes/manim.cfg index a11d17e5bf..c3a76c9213 100644 --- a/example_scenes/manim.cfg +++ b/example_scenes/manim.cfg @@ -13,3 +13,5 @@ log_time = dim yellow log_message = green log_path = dim blue +[CLI] +plugins = manim_plugintemplate diff --git a/manim/_config/default.cfg b/manim/_config/default.cfg index 822bbea35f..da65017b14 100644 --- a/manim/_config/default.cfg +++ b/manim/_config/default.cfg @@ -112,6 +112,9 @@ disable_caching = False # --tex_template tex_template = +# specify the plugins as comma seperated values +# manim will load that plugin if it specified here. +plugins = # Overrides the default output folders, NOT the output file names. Note that # if the custom_folders flag is present, the Tex and text files will not be put diff --git a/manim/_config/main_utils.py b/manim/_config/main_utils.py index aee2ec76d5..0f61697a5f 100644 --- a/manim/_config/main_utils.py +++ b/manim/_config/main_utils.py @@ -84,6 +84,11 @@ def _str2bool(s: str) -> bool: raise argparse.ArgumentTypeError("True or False expected") +def _split(s: str) -> list: + """Helper function that handles list like CLI arguments.""" + return s.split(",") + + def parse_args(args: list) -> argparse.Namespace: """Parse CLI arguments. @@ -453,4 +458,10 @@ def _parse_args_no_subcmd(args: list) -> argparse.Namespace: metavar="True/False", ) + parser.add_argument( + "--plugins", + type=_split, + help="Enable plugins", + ) + return parser.parse_args(args[1:]) diff --git a/manim/_config/utils.py b/manim/_config/utils.py index 292f821841..0a176901e3 100644 --- a/manim/_config/utils.py +++ b/manim/_config/utils.py @@ -272,6 +272,7 @@ class MyScene(Scene): "partial_movie_dir", "pixel_height", "pixel_width", + "plugins", "png_mode", "preview", "progress_bar", @@ -551,7 +552,12 @@ def digest_parser(self, parser: configparser.ConfigParser) -> "ManimConfig": # "frame_height", ]: setattr(self, key, parser["CLI"].getfloat(key)) - + # plugins + setattr( + self, + "plugins", + parser["CLI"].get("plugins", fallback="", raw=True).split(","), + ) # the next two must be set AFTER digesting pixel_width and pixel_height self["frame_height"] = parser["CLI"].getfloat("frame_height", 8.0) width = parser["CLI"].getfloat("frame_width", None) @@ -622,6 +628,7 @@ def digest_args(self, args: argparse.Namespace) -> "ManimConfig": "verbosity", "background_color", "use_js_renderer", + "plugins", ]: if hasattr(args, key): attr = getattr(args, key) @@ -1304,6 +1311,12 @@ def tex_template_file(self, val: str) -> None: self._d["tex_template_file"] = val # actually set the falsy value self._tex_template = TexTemplate() # but don't use it + plugins = property( + lambda self: self._d["plugins"], + lambda self, val: self._d.__setitem__("plugins", val), + doc="List of Plugins to Enable.", + ) + class ManimFrame(Mapping): _OPTS: typing.Set[str] = { diff --git a/manim/plugins/.gitignore b/manim/plugins/.gitignore deleted file mode 100644 index 93f5256cda..0000000000 --- a/manim/plugins/.gitignore +++ /dev/null @@ -1 +0,0 @@ -__init__.py \ No newline at end of file diff --git a/manim/plugins/__init__.py b/manim/plugins/__init__.py new file mode 100644 index 0000000000..15c56a2b5e --- /dev/null +++ b/manim/plugins/__init__.py @@ -0,0 +1 @@ +from .import_plugins import * diff --git a/manim/plugins/import_plugins.py b/manim/plugins/import_plugins.py new file mode 100644 index 0000000000..6e8f71e10a --- /dev/null +++ b/manim/plugins/import_plugins.py @@ -0,0 +1,40 @@ +import pkg_resources +from importlib import import_module +from .. import config, logger + +__all__ = [] + +# don't know what is better to do here! +module_type = type(pkg_resources) +function_type = type(import_module) + +plugins_requested: list = config["plugins"] + +for plugin in pkg_resources.iter_entry_points("manim.plugins"): + if plugin.name in plugins_requested: + loaded_plugin = plugin.load() + if isinstance(loaded_plugin, module_type): + # it is a module so it can't be called + # see if __all__ is defined + # if it is defined use that to load all the modules necessary + # essentially this would be similar to `from plugin import *`` + # if not just import the module with the plugin name + if hasattr(loaded_plugin, "__all__"): + for thing in loaded_plugin.__all__: + exec(f"{thing}=loaded_plugin.{thing}") + __all__.append(thing) + else: + exec(plugin.name + "=loaded_plugin") + __all__.append(plugin.name) + elif isinstance(loaded_plugin, function_type): + # call the function first + # it will return a list of modules to add globally + # finally add it + lists = loaded_plugin() + for l in lists: + exec(l.__name__ + "=l") + __all__.append(l.__name__) + plugins_requested.remove(plugin.name) +else: + if plugins_requested != []: + logger.warning("Missing Plugins: %s", plugins_requested) diff --git a/poetry.lock b/poetry.lock index 7eaffdc711..b78e959fd0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -230,7 +230,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" name = "importlib-metadata" version = "3.4.0" description = "Read metadata from Python packages" -category = "dev" +category = "main" optional = false python-versions = ">=3.6" @@ -482,7 +482,7 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "pytest" -version = "6.2.1" +version = "6.2.2" description = "pytest: simple powerful testing with Python" category = "dev" optional = false @@ -599,8 +599,8 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "snowballstemmer" -version = "2.0.0" -description = "This package provides 26 stemmers for 25 languages generated from Snowball algorithms." +version = "2.1.0" +description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." category = "dev" optional = false python-versions = "*" @@ -745,7 +745,7 @@ python-versions = "*" [[package]] name = "urllib3" -version = "1.26.2" +version = "1.26.3" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "dev" optional = false @@ -779,7 +779,7 @@ python-versions = "*" name = "zipp" version = "3.4.0" description = "Backport of pathlib-compatible object wrapper for zip files" -category = "dev" +category = "main" optional = false python-versions = ">=3.6" @@ -793,7 +793,7 @@ js_renderer = ["grpcio", "grpcio-tools", "watchdog"] [metadata] lock-version = "1.1" python-versions = "^3.6" -content-hash = "5a0c8d8c8c581f09f6a663c3d793a85673d6897e4cd2778b42bd44ba6e65e189" +content-hash = "3fa4dae232b5896f924aea6535d9f8f6885b5431cb228d503518139a149c600b" [metadata.files] alabaster = [ @@ -1192,21 +1192,25 @@ pillow = [ {file = "Pillow-8.1.0-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:d355502dce85ade85a2511b40b4c61a128902f246504f7de29bbeec1ae27933a"}, {file = "Pillow-8.1.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:93a473b53cc6e0b3ce6bf51b1b95b7b1e7e6084be3a07e40f79b42e83503fbf2"}, {file = "Pillow-8.1.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:2353834b2c49b95e1313fb34edf18fca4d57446675d05298bb694bca4b194174"}, + {file = "Pillow-8.1.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:1d208e670abfeb41b6143537a681299ef86e92d2a3dac299d3cd6830d5c7bded"}, {file = "Pillow-8.1.0-cp36-cp36m-win32.whl", hash = "sha256:dd9eef866c70d2cbbea1ae58134eaffda0d4bfea403025f4db6859724b18ab3d"}, {file = "Pillow-8.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:b09e10ec453de97f9a23a5aa5e30b334195e8d2ddd1ce76cc32e52ba63c8b31d"}, {file = "Pillow-8.1.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:b02a0b9f332086657852b1f7cb380f6a42403a6d9c42a4c34a561aa4530d5234"}, {file = "Pillow-8.1.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:ca20739e303254287138234485579b28cb0d524401f83d5129b5ff9d606cb0a8"}, {file = "Pillow-8.1.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:604815c55fd92e735f9738f65dabf4edc3e79f88541c221d292faec1904a4b17"}, + {file = "Pillow-8.1.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:cf6e33d92b1526190a1de904df21663c46a456758c0424e4f947ae9aa6088bf7"}, {file = "Pillow-8.1.0-cp37-cp37m-win32.whl", hash = "sha256:47c0d93ee9c8b181f353dbead6530b26980fe4f5485aa18be8f1fd3c3cbc685e"}, {file = "Pillow-8.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:96d4dc103d1a0fa6d47c6c55a47de5f5dafd5ef0114fa10c85a1fd8e0216284b"}, {file = "Pillow-8.1.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:7916cbc94f1c6b1301ac04510d0881b9e9feb20ae34094d3615a8a7c3db0dcc0"}, {file = "Pillow-8.1.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:3de6b2ee4f78c6b3d89d184ade5d8fa68af0848f9b6b6da2b9ab7943ec46971a"}, {file = "Pillow-8.1.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:cdbbe7dff4a677fb555a54f9bc0450f2a21a93c5ba2b44e09e54fcb72d2bd13d"}, + {file = "Pillow-8.1.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:f50e7a98b0453f39000619d845be8b06e611e56ee6e8186f7f60c3b1e2f0feae"}, {file = "Pillow-8.1.0-cp38-cp38-win32.whl", hash = "sha256:cb192176b477d49b0a327b2a5a4979552b7a58cd42037034316b8018ac3ebb59"}, {file = "Pillow-8.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:6c5275bd82711cd3dcd0af8ce0bb99113ae8911fc2952805f1d012de7d600a4c"}, {file = "Pillow-8.1.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:165c88bc9d8dba670110c689e3cc5c71dbe4bfb984ffa7cbebf1fac9554071d6"}, {file = "Pillow-8.1.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:5e2fe3bb2363b862671eba632537cd3a823847db4d98be95690b7e382f3d6378"}, {file = "Pillow-8.1.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7612520e5e1a371d77e1d1ca3a3ee6227eef00d0a9cddb4ef7ecb0b7396eddf7"}, + {file = "Pillow-8.1.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d673c4990acd016229a5c1c4ee8a9e6d8f481b27ade5fc3d95938697fa443ce0"}, {file = "Pillow-8.1.0-cp39-cp39-win32.whl", hash = "sha256:dc577f4cfdda354db3ae37a572428a90ffdbe4e51eda7849bf442fb803f09c9b"}, {file = "Pillow-8.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:22d070ca2e60c99929ef274cfced04294d2368193e935c5d6febfd8b601bf865"}, {file = "Pillow-8.1.0-pp36-pypy36_pp73-macosx_10_10_x86_64.whl", hash = "sha256:a3d3e086474ef12ef13d42e5f9b7bbf09d39cf6bd4940f982263d6954b13f6a9"}, @@ -1274,8 +1278,8 @@ pyparsing = [ {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, ] pytest = [ - {file = "pytest-6.2.1-py3-none-any.whl", hash = "sha256:1969f797a1a0dbd8ccf0fecc80262312729afea9c17f1d70ebf85c5e76c6f7c8"}, - {file = "pytest-6.2.1.tar.gz", hash = "sha256:66e419b1899bc27346cb2c993e12c5e5e8daba9073c1fbce33b9807abc95c306"}, + {file = "pytest-6.2.2-py3-none-any.whl", hash = "sha256:b574b57423e818210672e07ca1fa90aaf194a4f63f3ab909a2c67ebb22913839"}, + {file = "pytest-6.2.2.tar.gz", hash = "sha256:9d1edf9e7d0b84d72ea3dbcdfd22b35fb543a5e8f2a60092dd578936bf63d7f9"}, ] python-dateutil = [ {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, @@ -1372,8 +1376,8 @@ six = [ {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, ] snowballstemmer = [ - {file = "snowballstemmer-2.0.0-py2.py3-none-any.whl", hash = "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0"}, - {file = "snowballstemmer-2.0.0.tar.gz", hash = "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52"}, + {file = "snowballstemmer-2.1.0-py2.py3-none-any.whl", hash = "sha256:b51b447bea85f9968c13b650126a888aabd4cb4463fca868ec596826325dedc2"}, + {file = "snowballstemmer-2.1.0.tar.gz", hash = "sha256:e997baa4f2e9139951b6f4c631bad912dfd3c792467e2f03d7239464af90e914"}, ] sphinx = [ {file = "Sphinx-3.4.3-py3-none-any.whl", hash = "sha256:c314c857e7cd47c856d2c5adff514ac2e6495f8b8e0f886a8a37e9305dfea0d8"}, @@ -1449,8 +1453,8 @@ typing-extensions = [ {file = "typing_extensions-3.7.4.3.tar.gz", hash = "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c"}, ] urllib3 = [ - {file = "urllib3-1.26.2-py2.py3-none-any.whl", hash = "sha256:d8ff90d979214d7b4f8ce956e80f4028fc6860e4431f731ea4a8c08f23f99473"}, - {file = "urllib3-1.26.2.tar.gz", hash = "sha256:19188f96923873c92ccb987120ec4acaa12f0461fa9ce5d3d0772bc965a39e08"}, + {file = "urllib3-1.26.3-py2.py3-none-any.whl", hash = "sha256:1b465e494e3e0d8939b50680403e3aedaa2bc434b7d5af64dfd3c958d7f5ae80"}, + {file = "urllib3-1.26.3.tar.gz", hash = "sha256:de3eedaad74a2683334e282005cd8d7f22f4d55fa690a2a1020a416cb0a47e73"}, ] watchdog = [ {file = "watchdog-1.0.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e2a531e71be7b5cc3499ae2d1494d51b6a26684bcc7c3146f63c810c00e8a3cc"}, diff --git a/pyproject.toml b/pyproject.toml index 01fc8dac6c..e24643fecd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,10 +35,12 @@ pygments = "*" rich = "^6.0" pycairo = "^1.19" manimpango = "^0.1.7" +networkx = "^2.5" +setuptools = "*" +importlib-metadata = {version="*", python = "<3.8"} grpcio = { version = "1.33.*", optional = true } grpcio-tools = { version = "1.33.*", optional = true } watchdog = { version = "*", optional = true } -networkx = "^2.5" [tool.poetry.extras] js_renderer = ["grpcio","grpcio-tools","watchdog"] From fa2f24ca3df21e92f89424d140278cd5b1204957 Mon Sep 17 00:00:00 2001 From: Syrus Dark Date: Wed, 27 Jan 2021 01:46:01 +0530 Subject: [PATCH 02/13] Fix Doc tests --- docs/source/tutorials/configuration.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/source/tutorials/configuration.rst b/docs/source/tutorials/configuration.rst index 219b981e70..dc0001dbfb 100644 --- a/docs/source/tutorials/configuration.rst +++ b/docs/source/tutorials/configuration.rst @@ -353,12 +353,12 @@ A list of all config options 'frame_y_radius', 'from_animation_number', 'images_dir', 'input_file', 'js_renderer_path', 'leave_progress_bars', 'left_side', 'log_dir', 'log_to_file', 'max_files_cached', 'media_dir', 'movie_file_extension', 'output_file', - 'partial_movie_dir', 'pixel_height', 'pixel_width', 'png_mode', 'preview', - 'progress_bar', 'quality', 'right_side', 'save_as_gif', 'save_last_frame', + 'partial_movie_dir', 'pixel_height', 'pixel_width', 'plugins', 'png_mode', + 'preview', 'progress_bar', 'quality', 'right_side', 'save_as_gif', 'save_last_frame', 'save_pngs', 'scene_names', 'show_in_file_browser', 'sound', 'tex_dir', 'tex_template', 'tex_template_file', 'text_dir', 'top', 'transparent', - 'upto_animation_number', 'use_js_renderer', 'verbosity', 'video_dir', 'write_all', - 'write_to_movie'] + 'upto_animation_number', 'use_js_renderer', 'verbosity', 'video_dir', + 'write_all', 'write_to_movie'] A list of all CLI flags @@ -439,5 +439,6 @@ A list of all CLI flags Verbosity level. Also changes the ffmpeg log level unless the latter is specified in the config --progress_bar True/False Display the progress bar + --plugins PLUGINS Enable plugins Made with <3 by the manim community devs From 61b5b5ec24d1b6a30c5c9febb28255d40a4aa60d Mon Sep 17 00:00:00 2001 From: Syrus Dark Date: Wed, 27 Jan 2021 01:51:42 +0530 Subject: [PATCH 03/13] clean manim.cfg --- example_scenes/manim.cfg | 2 -- manim/plugins/import_plugins.py | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/example_scenes/manim.cfg b/example_scenes/manim.cfg index c3a76c9213..a11d17e5bf 100644 --- a/example_scenes/manim.cfg +++ b/example_scenes/manim.cfg @@ -13,5 +13,3 @@ log_time = dim yellow log_message = green log_path = dim blue -[CLI] -plugins = manim_plugintemplate diff --git a/manim/plugins/import_plugins.py b/manim/plugins/import_plugins.py index 6e8f71e10a..6bd8c73eb9 100644 --- a/manim/plugins/import_plugins.py +++ b/manim/plugins/import_plugins.py @@ -9,7 +9,8 @@ function_type = type(import_module) plugins_requested: list = config["plugins"] - +if "" in plugins_requested: + plugins_requested.remove("") for plugin in pkg_resources.iter_entry_points("manim.plugins"): if plugin.name in plugins_requested: loaded_plugin = plugin.load() From a5e2f733b521b49bce770ff5fe48624aad9dc3b3 Mon Sep 17 00:00:00 2001 From: Syrus Dark Date: Wed, 27 Jan 2021 10:30:59 +0530 Subject: [PATCH 04/13] Add more explanatory docs --- docs/source/installation/plugins.rst | 42 ++++++++++++++++++---------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/docs/source/installation/plugins.rst b/docs/source/installation/plugins.rst index e84831081a..9d884c830e 100644 --- a/docs/source/installation/plugins.rst +++ b/docs/source/installation/plugins.rst @@ -55,27 +55,37 @@ You can list plugins as such: Using Plugins in Projects ************************* -Plugins specified in ``plugins/__init__.py`` are imported automatically by -manim's ``__init__.py``. As such, writing: +For enabling a plugin ``manim.cfg`` or command line parameters should be used. -.. code-block:: python +.. important:: - from manim import * + The plugins should be module name of the plugin and not PyPi name. -in your projects will import any of the plugins imported in -``plugins/__init__.py``. +Enabling plugins through ``manim.cfg`` -By default, ``plugins/__init__.py`` is not provided; although, there are -plans to support subcommands that would manage this file. It is especially -useful to create this file for projects that involve usage of the same -plugins. Alternatively, you may manually specify the plugins in your project -scripts. +.. code-block:: ini -.. code-block:: python + [CLI] + plugins = manim_rubikscube - import manim_cool_plugin - # or - from manim_cool_plugin import feature_x, feature_y, ... +For specifing multiple plugins, command separated values must be used. + +.. code-block:: ini + + [CLI] + plugins = manim_rubikscube, manim_plugintemplate + +Enabling Plugins through CLI + +.. code-block:: bash + + manim basic.py --plugins=manim_plugintemplate + +For multiple plugins + +.. code-block:: bash + + manim basic.py --plugins=manim_rubikscube,manim_plugintemplate Creating Plugins **************** @@ -103,6 +113,8 @@ specified in poetry as: [tool.poetry.plugins."manim.plugins"] "name" = "object_reference" +Here ``name`` is the name of the module of the plugin. + Here ``object_reference`` can point to either a function in a module or a module itself. For example, From 0477db0788cb4ecc01886604497baa3d77fcb426 Mon Sep 17 00:00:00 2001 From: Syrus Dark Date: Wed, 27 Jan 2021 10:32:32 +0530 Subject: [PATCH 05/13] add info about plugins site --- docs/source/installation/plugins.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/source/installation/plugins.rst b/docs/source/installation/plugins.rst index 9d884c830e..e85af462c4 100644 --- a/docs/source/installation/plugins.rst +++ b/docs/source/installation/plugins.rst @@ -20,6 +20,10 @@ install, use, and create your own plugins. for the best practices on installing, using, and creating plugins; as well as new subcommands/flags for ``manim plugins`` +.. tip:: + + See https://plugins.manim.community/ for the list of plugins available. + Installing Plugins ****************** Plugins can be easily installed via the ``pip`` From 1205f684bea149b5f9f71b59a494780769dd8f9d Mon Sep 17 00:00:00 2001 From: Naveen M K Date: Wed, 27 Jan 2021 19:22:14 +0530 Subject: [PATCH 06/13] use property method Co-authored-by: friedkeenan --- manim/_config/utils.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/manim/_config/utils.py b/manim/_config/utils.py index 0a176901e3..c22e0f6f2a 100644 --- a/manim/_config/utils.py +++ b/manim/_config/utils.py @@ -1311,11 +1311,15 @@ def tex_template_file(self, val: str) -> None: self._d["tex_template_file"] = val # actually set the falsy value self._tex_template = TexTemplate() # but don't use it - plugins = property( - lambda self: self._d["plugins"], - lambda self, val: self._d.__setitem__("plugins", val), - doc="List of Plugins to Enable.", - ) + @property + def plugins(self): + """List of plugins to enable.""" + + return self._d["plugins"] + + @plugins.setter + def plugins(self, value): + self._d["plugins"] = value class ManimFrame(Mapping): From c054c6f24b0f962e2807d8a6190498b89705aa94 Mon Sep 17 00:00:00 2001 From: Syrus Dark Date: Wed, 27 Jan 2021 19:28:33 +0530 Subject: [PATCH 07/13] use types module and f-strings --- manim/plugins/import_plugins.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/manim/plugins/import_plugins.py b/manim/plugins/import_plugins.py index 6bd8c73eb9..8332c7b218 100644 --- a/manim/plugins/import_plugins.py +++ b/manim/plugins/import_plugins.py @@ -1,12 +1,14 @@ -import pkg_resources +import types from importlib import import_module + +import pkg_resources + from .. import config, logger __all__ = [] -# don't know what is better to do here! -module_type = type(pkg_resources) -function_type = type(import_module) +module_type = types.ModuleType +function_type = types.FunctionType plugins_requested: list = config["plugins"] if "" in plugins_requested: @@ -25,7 +27,7 @@ exec(f"{thing}=loaded_plugin.{thing}") __all__.append(thing) else: - exec(plugin.name + "=loaded_plugin") + exec(f"{plugin.name}=loaded_plugin") __all__.append(plugin.name) elif isinstance(loaded_plugin, function_type): # call the function first @@ -33,7 +35,7 @@ # finally add it lists = loaded_plugin() for l in lists: - exec(l.__name__ + "=l") + exec(f"{l.__name__}=l") __all__.append(l.__name__) plugins_requested.remove(plugin.name) else: From e5e4463d9b43266d704b8a045bd0553198362b8d Mon Sep 17 00:00:00 2001 From: Syrus Dark Date: Thu, 28 Jan 2021 15:30:18 +0530 Subject: [PATCH 08/13] Add tests --- manim/plugins/import_plugins.py | 49 ++--- tests/conftest.py | 5 +- tests/test_plugins/__init__.py | 0 tests/test_plugins/simple_scenes.py | 26 +++ tests/test_plugins/test_plugins.py | 273 ++++++++++++++++++++++++++++ tests/utils/commands.py | 3 +- 6 files changed, 330 insertions(+), 26 deletions(-) create mode 100644 tests/test_plugins/__init__.py create mode 100644 tests/test_plugins/simple_scenes.py create mode 100644 tests/test_plugins/test_plugins.py diff --git a/manim/plugins/import_plugins.py b/manim/plugins/import_plugins.py index 8332c7b218..a11cfcc2cf 100644 --- a/manim/plugins/import_plugins.py +++ b/manim/plugins/import_plugins.py @@ -14,30 +14,31 @@ if "" in plugins_requested: plugins_requested.remove("") for plugin in pkg_resources.iter_entry_points("manim.plugins"): - if plugin.name in plugins_requested: - loaded_plugin = plugin.load() - if isinstance(loaded_plugin, module_type): - # it is a module so it can't be called - # see if __all__ is defined - # if it is defined use that to load all the modules necessary - # essentially this would be similar to `from plugin import *`` - # if not just import the module with the plugin name - if hasattr(loaded_plugin, "__all__"): - for thing in loaded_plugin.__all__: - exec(f"{thing}=loaded_plugin.{thing}") - __all__.append(thing) - else: - exec(f"{plugin.name}=loaded_plugin") - __all__.append(plugin.name) - elif isinstance(loaded_plugin, function_type): - # call the function first - # it will return a list of modules to add globally - # finally add it - lists = loaded_plugin() - for l in lists: - exec(f"{l.__name__}=l") - __all__.append(l.__name__) - plugins_requested.remove(plugin.name) + if plugin.name not in plugins_requested: + continue + loaded_plugin = plugin.load() + if isinstance(loaded_plugin, module_type): + # it is a module so it can't be called + # see if __all__ is defined + # if it is defined use that to load all the modules necessary + # essentially this would be similar to `from plugin import *`` + # if not just import the module with the plugin name + if hasattr(loaded_plugin, "__all__"): + for thing in loaded_plugin.__all__: + exec(f"{thing}=loaded_plugin.{thing}") + __all__.append(thing) + else: + exec(f"{plugin.name}=loaded_plugin") + __all__.append(plugin.name) + elif isinstance(loaded_plugin, function_type): + # call the function first + # it will return a list of modules to add globally + # finally add it + lists = loaded_plugin() + for l in lists: + exec(f"{l.__name__}=l") + __all__.append(l.__name__) + plugins_requested.remove(plugin.name) else: if plugins_requested != []: logger.warning("Missing Plugins: %s", plugins_requested) diff --git a/tests/conftest.py b/tests/conftest.py index abef7f47d2..fc68265763 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -39,7 +39,10 @@ def pytest_collection_modifyitems(config, items): @pytest.fixture(scope="session") def python_version(): - return "python3" if sys.platform == "darwin" else "python" + # use the same python executable as it is running currently + # rather than randomly calling using python or python3, which + # may create problems. + return sys.executable @pytest.fixture diff --git a/tests/test_plugins/__init__.py b/tests/test_plugins/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/test_plugins/simple_scenes.py b/tests/test_plugins/simple_scenes.py new file mode 100644 index 0000000000..82bb1d1ed4 --- /dev/null +++ b/tests/test_plugins/simple_scenes.py @@ -0,0 +1,26 @@ +from manim import * + + +class SquareToCircle(Scene): + def construct(self): + square = Square() + circle = Circle() + self.play(Transform(square, circle)) + +class FunctionLikeTest(Scene): + def contruct(self): + assert 'FunctionLike' in globals() + a=FunctionLike() + self.play(FadeIn(a)) + +class NoAllTest(Scene): + def construct(self): + assert 'test_plugin' in globals() + a=test_plugin.NoAll() + self.play(FadeIn(a)) + +class WithAllTest(Scene): + def construct(self): + assert 'WithAll' in globals() + a=WithAll() + self.play(FadeIn(a)) \ No newline at end of file diff --git a/tests/test_plugins/test_plugins.py b/tests/test_plugins/test_plugins.py new file mode 100644 index 0000000000..b1ac16d64b --- /dev/null +++ b/tests/test_plugins/test_plugins.py @@ -0,0 +1,273 @@ +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", + simple_scenes_path(), + scene_name, + "-ql", + "--media_dir", + str(cfg_file.parent), + "--config_file", + str(cfg_file), + ] + 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", + simple_scenes_path(), + scene_name, + "-ql", + "--media_dir", + str(cfg_file.parent), + "--config_file", + str(cfg_file), + ] + 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", + simple_scenes_path(), + scene_name, + "-ql", + "--media_dir", + str(cfg_file.parent), + "--config_file", + str(cfg_file), + ] + 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", + simple_scenes_path(), + scene_name, + "-ql", + "--media_dir", + str(cfg_file.parent), + "--config_file", + str(cfg_file), + ] + out, err, exit_code = capture(command, cwd=str(cfg_file.parent)) + print(out) + print(err) + assert exit_code == 0, err diff --git a/tests/utils/commands.py b/tests/utils/commands.py index 90c5d3caf1..46587aadbe 100644 --- a/tests/utils/commands.py +++ b/tests/utils/commands.py @@ -1,12 +1,13 @@ import subprocess -def capture(command): +def capture(command,cwd=None): proc = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf8", + cwd=cwd ) out, err = proc.communicate() return out, err, proc.returncode From 10c6f3f5bf746e037a2be682055136dbf0eb27e5 Mon Sep 17 00:00:00 2001 From: Syrus Dark Date: Thu, 28 Jan 2021 15:47:56 +0530 Subject: [PATCH 09/13] lint --- tests/test_plugins/simple_scenes.py | 17 ++++++++++------- tests/utils/commands.py | 4 ++-- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/tests/test_plugins/simple_scenes.py b/tests/test_plugins/simple_scenes.py index 82bb1d1ed4..41edca5f1b 100644 --- a/tests/test_plugins/simple_scenes.py +++ b/tests/test_plugins/simple_scenes.py @@ -7,20 +7,23 @@ def construct(self): circle = Circle() self.play(Transform(square, circle)) + class FunctionLikeTest(Scene): def contruct(self): - assert 'FunctionLike' in globals() - a=FunctionLike() + assert "FunctionLike" in globals() + a = FunctionLike() self.play(FadeIn(a)) + class NoAllTest(Scene): def construct(self): - assert 'test_plugin' in globals() - a=test_plugin.NoAll() + assert "test_plugin" in globals() + a = test_plugin.NoAll() self.play(FadeIn(a)) + class WithAllTest(Scene): def construct(self): - assert 'WithAll' in globals() - a=WithAll() - self.play(FadeIn(a)) \ No newline at end of file + assert "WithAll" in globals() + a = WithAll() + self.play(FadeIn(a)) diff --git a/tests/utils/commands.py b/tests/utils/commands.py index 46587aadbe..11316d6844 100644 --- a/tests/utils/commands.py +++ b/tests/utils/commands.py @@ -1,13 +1,13 @@ import subprocess -def capture(command,cwd=None): +def capture(command, cwd=None): proc = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf8", - cwd=cwd + cwd=cwd, ) out, err = proc.communicate() return out, err, proc.returncode From 75d341b88f6318fa2166213c2abd365ec98831f0 Mon Sep 17 00:00:00 2001 From: Syrus Dark Date: Thu, 28 Jan 2021 15:55:18 +0530 Subject: [PATCH 10/13] remove --plugins it seems it is not possible currently to implement that --- docs/source/tutorials/configuration.rst | 9 ++++----- manim/_config/main_utils.py | 11 ----------- manim/_config/utils.py | 1 - poetry.lock | 15 +++++++-------- pyproject.toml | 2 +- 5 files changed, 12 insertions(+), 26 deletions(-) diff --git a/docs/source/tutorials/configuration.rst b/docs/source/tutorials/configuration.rst index 6f57a5519b..0b2b7b7eaa 100644 --- a/docs/source/tutorials/configuration.rst +++ b/docs/source/tutorials/configuration.rst @@ -353,12 +353,12 @@ A list of all config options 'frame_y_radius', 'from_animation_number', 'images_dir', 'input_file', 'js_renderer_path', 'leave_progress_bars', 'left_side', 'log_dir', 'log_to_file', 'max_files_cached', 'media_dir', 'movie_file_extension', 'output_file', - 'partial_movie_dir', 'pixel_height', 'pixel_width', 'plugins', 'png_mode', - 'preview', 'progress_bar', 'quality', 'right_side', 'save_as_gif', 'save_last_frame', + 'partial_movie_dir', 'pixel_height', 'pixel_width', 'png_mode', 'preview', + 'progress_bar', 'quality', 'right_side', 'save_as_gif', 'save_last_frame', 'save_pngs', 'scene_names', 'show_in_file_browser', 'sound', 'tex_dir', 'tex_template', 'tex_template_file', 'text_dir', 'top', 'transparent', - 'upto_animation_number', 'use_js_renderer', 'verbosity', 'video_dir', - 'write_all', 'write_to_movie'] + 'upto_animation_number', 'use_js_renderer', 'verbosity', 'video_dir', 'write_all', + 'write_to_movie'] A list of all CLI flags @@ -440,6 +440,5 @@ A list of all CLI flags --version Print the current version of Manim you are using --progress_bar True/False Display the progress bar - --plugins PLUGINS Enable plugins Made with <3 by the ManimCommunity devs diff --git a/manim/_config/main_utils.py b/manim/_config/main_utils.py index 0ef6154cf6..858648783c 100644 --- a/manim/_config/main_utils.py +++ b/manim/_config/main_utils.py @@ -85,11 +85,6 @@ def _str2bool(s: str) -> bool: raise argparse.ArgumentTypeError("True or False expected") -def _split(s: str) -> list: - """Helper function that handles list like CLI arguments.""" - return s.split(",") - - def parse_args(args: list) -> argparse.Namespace: """Parse CLI arguments. @@ -468,10 +463,4 @@ def _parse_args_no_subcmd(args: list) -> argparse.Namespace: metavar="True/False", ) - parser.add_argument( - "--plugins", - type=_split, - help="Enable plugins", - ) - return parser.parse_args(args[1:]) diff --git a/manim/_config/utils.py b/manim/_config/utils.py index c22e0f6f2a..6479840788 100644 --- a/manim/_config/utils.py +++ b/manim/_config/utils.py @@ -628,7 +628,6 @@ def digest_args(self, args: argparse.Namespace) -> "ManimConfig": "verbosity", "background_color", "use_js_renderer", - "plugins", ]: if hasattr(args, key): attr = getattr(args, key) diff --git a/poetry.lock b/poetry.lock index 60ef75cf7b..90796c2be8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -228,19 +228,18 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "importlib-metadata" -version = "3.4.0" +version = "1.7.0" description = "Read metadata from Python packages" category = "main" optional = false -python-versions = ">=3.6" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [package.dependencies] -typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} zipp = ">=0.5" [package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "pytest-enabler", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] +docs = ["sphinx", "rst.linker"] +testing = ["packaging", "pep517", "importlib-resources (>=1.3)"] [[package]] name = "iniconfig" @@ -793,7 +792,7 @@ js_renderer = ["grpcio", "grpcio-tools", "watchdog"] [metadata] lock-version = "1.1" python-versions = "^3.6" -content-hash = "3fa4dae232b5896f924aea6535d9f8f6885b5431cb228d503518139a149c600b" +content-hash = "f17881f795acc10902e6592cb9fb8ad5d6a9d02bb837113b9d36c0b653ab2b03" [metadata.files] alabaster = [ @@ -971,8 +970,8 @@ imagesize = [ {file = "imagesize-1.2.0.tar.gz", hash = "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1"}, ] importlib-metadata = [ - {file = "importlib_metadata-3.4.0-py3-none-any.whl", hash = "sha256:ace61d5fc652dc280e7b6b4ff732a9c2d40db2c0f92bc6cb74e07b73d53a1771"}, - {file = "importlib_metadata-3.4.0.tar.gz", hash = "sha256:fa5daa4477a7414ae34e95942e4dd07f62adf589143c875c133c1e53c4eff38d"}, + {file = "importlib_metadata-1.7.0-py2.py3-none-any.whl", hash = "sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070"}, + {file = "importlib_metadata-1.7.0.tar.gz", hash = "sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83"}, ] iniconfig = [ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, diff --git a/pyproject.toml b/pyproject.toml index e24643fecd..eaadb3ea4a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,7 +37,7 @@ pycairo = "^1.19" manimpango = "^0.1.7" networkx = "^2.5" setuptools = "*" -importlib-metadata = {version="*", python = "<3.8"} +importlib-metadata = {version = "^1.0", python = "<3.8"} grpcio = { version = "1.33.*", optional = true } grpcio-tools = { version = "1.33.*", optional = true } watchdog = { version = "*", optional = true } From d536827f720873ef60ab2e4428fe4fb4aec40975 Mon Sep 17 00:00:00 2001 From: Syrus Dark Date: Thu, 28 Jan 2021 16:18:10 +0530 Subject: [PATCH 11/13] fix doc tests --- docs/source/tutorials/configuration.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/tutorials/configuration.rst b/docs/source/tutorials/configuration.rst index 0b2b7b7eaa..8de132014e 100644 --- a/docs/source/tutorials/configuration.rst +++ b/docs/source/tutorials/configuration.rst @@ -353,12 +353,12 @@ A list of all config options 'frame_y_radius', 'from_animation_number', 'images_dir', 'input_file', 'js_renderer_path', 'leave_progress_bars', 'left_side', 'log_dir', 'log_to_file', 'max_files_cached', 'media_dir', 'movie_file_extension', 'output_file', - 'partial_movie_dir', 'pixel_height', 'pixel_width', 'png_mode', 'preview', - 'progress_bar', 'quality', 'right_side', 'save_as_gif', 'save_last_frame', + 'partial_movie_dir', 'pixel_height', 'pixel_width', 'plugins', 'png_mode', + 'preview', 'progress_bar', 'quality', 'right_side', 'save_as_gif', 'save_last_frame', 'save_pngs', 'scene_names', 'show_in_file_browser', 'sound', 'tex_dir', 'tex_template', 'tex_template_file', 'text_dir', 'top', 'transparent', - 'upto_animation_number', 'use_js_renderer', 'verbosity', 'video_dir', 'write_all', - 'write_to_movie'] + 'upto_animation_number', 'use_js_renderer', 'verbosity', 'video_dir', + 'write_all', 'write_to_movie'] A list of all CLI flags From 4205490d835a99c752206eadc482edf7f0f4f44c Mon Sep 17 00:00:00 2001 From: Syrus Dark Date: Thu, 28 Jan 2021 17:12:55 +0530 Subject: [PATCH 12/13] don't define unnecessary variables --- manim/plugins/import_plugins.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/manim/plugins/import_plugins.py b/manim/plugins/import_plugins.py index a11cfcc2cf..2afdfee7bc 100644 --- a/manim/plugins/import_plugins.py +++ b/manim/plugins/import_plugins.py @@ -7,8 +7,6 @@ __all__ = [] -module_type = types.ModuleType -function_type = types.FunctionType plugins_requested: list = config["plugins"] if "" in plugins_requested: @@ -17,7 +15,7 @@ if plugin.name not in plugins_requested: continue loaded_plugin = plugin.load() - if isinstance(loaded_plugin, module_type): + if isinstance(loaded_plugin, types.ModuleType): # it is a module so it can't be called # see if __all__ is defined # if it is defined use that to load all the modules necessary @@ -30,7 +28,7 @@ else: exec(f"{plugin.name}=loaded_plugin") __all__.append(plugin.name) - elif isinstance(loaded_plugin, function_type): + elif isinstance(loaded_plugin, types.FunctionType): # call the function first # it will return a list of modules to add globally # finally add it From 05e92413991fe18aa504907b4c1ca62738121b5f Mon Sep 17 00:00:00 2001 From: Naveen M K Date: Thu, 28 Jan 2021 20:47:21 +0530 Subject: [PATCH 13/13] Apply suggestions from code review Co-authored-by: Leo Torres --- manim/_config/utils.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/manim/_config/utils.py b/manim/_config/utils.py index 6479840788..ed6b4daf76 100644 --- a/manim/_config/utils.py +++ b/manim/_config/utils.py @@ -553,11 +553,7 @@ def digest_parser(self, parser: configparser.ConfigParser) -> "ManimConfig": ]: setattr(self, key, parser["CLI"].getfloat(key)) # plugins - setattr( - self, - "plugins", - parser["CLI"].get("plugins", fallback="", raw=True).split(","), - ) + self.plugins = parser["CLI"].get("plugins", fallback="", raw=True).split(",") # the next two must be set AFTER digesting pixel_width and pixel_height self["frame_height"] = parser["CLI"].getfloat("frame_height", 8.0) width = parser["CLI"].getfloat("frame_width", None) @@ -1313,7 +1309,6 @@ def tex_template_file(self, val: str) -> None: @property def plugins(self): """List of plugins to enable.""" - return self._d["plugins"] @plugins.setter