Skip to content

Commit 3136a18

Browse files
committed
POC: Implement Plugin using Hooks (with pluggy)
This uses pluggy to manage plugins, by implementing hooks, which the plugins can implement to modify the default behaviour in Manim. For now, there's only one hook `default_font()`, which plugins or even the users can define. REF: #1133
1 parent cddd47c commit 3136a18

File tree

8 files changed

+217
-4
lines changed

8 files changed

+217
-4
lines changed

manim/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@
1010

1111
import sys
1212

13+
import pluggy
14+
15+
# This should be created before anything else.
16+
pluggy_hookimpl = pluggy.HookimplMarker("manim")
17+
1318
# Importing the config module should be the first thing we do, since other
1419
# modules depend on the global config dict for initialization.
1520
from ._config import *

manim/_config/utils.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import colour
2727
import numpy as np
28+
import pluggy
2829

2930
from .. import constants
3031
from ..utils.tex import TexTemplate, TexTemplateFromFile
@@ -300,6 +301,7 @@ class MyScene(Scene):
300301

301302
def __init__(self) -> None:
302303
self._d = {k: None for k in self._OPTS}
304+
self._plugin_manager = None
303305

304306
# behave like a dict
305307
def __iter__(self) -> typing.Iterator[str]:
@@ -1570,6 +1572,19 @@ def plugins(self):
15701572
def plugins(self, value):
15711573
self._d["plugins"] = value
15721574

1575+
@property
1576+
def plugin_manager(self):
1577+
if self._plugin_manager:
1578+
return self._plugin_manager
1579+
from manim.plugins import hooksimpl, hookspecs
1580+
1581+
pm = pluggy.PluginManager("manim")
1582+
pm.add_hookspecs(hookspecs)
1583+
pm.load_setuptools_entrypoints("manim")
1584+
pm.register(hooksimpl)
1585+
self._plugin_manager = pm
1586+
return pm
1587+
15731588

15741589
class ManimFrame(Mapping):
15751590
_OPTS: set[str] = {

manim/cli/render/commands.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
from ... import __version__, config, console, error_console, logger
1919
from ...constants import EPILOG
20-
from ...utils.module_ops import scene_classes_from_file
20+
from ...utils.module_ops import get_module, scene_classes_from_file
2121
from .ease_of_access_options import ease_of_access_options
2222
from .global_options import global_options
2323
from .output_options import output_options
@@ -88,6 +88,9 @@ def __repr__(self):
8888

8989
config.digest_args(click_args)
9090
file = Path(config.input_file)
91+
# Register the input file with Pluggy
92+
# This is done so that user's implementation of hooks takes precedence.
93+
config.plugin_manager.register(get_module(file))
9194
if config.renderer == "opengl":
9295
from manim.renderer.opengl_renderer import OpenGLRenderer
9396

manim/mobject/text/text_mobject.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ def __init__(
409409
color: Color | str | None = None,
410410
font_size: float = DEFAULT_FONT_SIZE,
411411
line_spacing: float = -1,
412-
font: str = "",
412+
font: str | None = None,
413413
slant: str = NORMAL,
414414
weight: str = NORMAL,
415415
t2c: dict[str, str] = None,
@@ -429,6 +429,8 @@ def __init__(
429429
):
430430

431431
self.line_spacing = line_spacing
432+
if not font:
433+
font = config.plugin_manager.hook.default_font(requestor=Text.__name__)[0]
432434
self.font = font
433435
self._font_size = float(font_size)
434436
# needs to be a float or else size is inflated when font_size = 24

manim/plugins/hooksimpl.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from __future__ import annotations
2+
3+
from manim import pluggy_hookimpl
4+
5+
6+
@pluggy_hookimpl
7+
def default_font() -> str:
8+
# Returning empty string, just uses the default font.
9+
return ""

manim/plugins/hookspecs.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from __future__ import annotations
2+
3+
import pluggy
4+
5+
hookspec = pluggy.HookspecMarker("manim")
6+
7+
8+
@hookspec
9+
def default_font(requestor: str) -> str:
10+
"""Look who's requesting and return the default font to be used by
11+
them.
12+
13+
Parameters
14+
----------
15+
requestor:
16+
The ``__name__`` of the requesting class. This can be one of
17+
['Text', 'MarkupText', 'Paragraph', 'Code']
18+
19+
Returns
20+
-------
21+
str:
22+
Can be empty string to use the default font as defined by the system.
23+
"""

poetry.lock

Lines changed: 157 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ srt = "^3.5.0"
5555
screeninfo = "^0.8"
5656
Pygments = "^2.10.0"
5757
"backports.cached-property" = "^1.0.1"
58+
pluggy = "^1"
5859

5960
[tool.poetry.extras]
6061
jupyterlab = ["jupyterlab"]

0 commit comments

Comments
 (0)