manim 0.18.1__py3-none-any.whl → 0.19.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of manim might be problematic. Click here for more details.
- manim/__main__.py +45 -12
- manim/_config/__init__.py +2 -2
- manim/_config/cli_colors.py +8 -4
- manim/_config/default.cfg +0 -2
- manim/_config/logger_utils.py +5 -0
- manim/_config/utils.py +29 -38
- manim/animation/animation.py +148 -8
- manim/animation/composition.py +16 -13
- manim/animation/creation.py +184 -8
- manim/animation/fading.py +5 -8
- manim/animation/indication.py +93 -26
- manim/animation/movement.py +21 -3
- manim/animation/rotation.py +2 -1
- manim/animation/specialized.py +3 -5
- manim/animation/speedmodifier.py +3 -3
- manim/animation/transform.py +4 -5
- manim/animation/updaters/mobject_update_utils.py +17 -14
- manim/camera/camera.py +2 -2
- manim/cli/__init__.py +17 -0
- manim/cli/cfg/group.py +52 -36
- manim/cli/checkhealth/checks.py +92 -76
- manim/cli/checkhealth/commands.py +12 -5
- manim/cli/default_group.py +148 -24
- manim/cli/init/commands.py +28 -23
- manim/cli/plugins/commands.py +13 -3
- manim/cli/render/commands.py +47 -42
- manim/cli/render/global_options.py +43 -9
- manim/cli/render/render_options.py +84 -19
- manim/constants.py +11 -4
- manim/mobject/frame.py +0 -1
- manim/mobject/geometry/arc.py +109 -75
- manim/mobject/geometry/boolean_ops.py +20 -17
- manim/mobject/geometry/labeled.py +300 -77
- manim/mobject/geometry/line.py +120 -60
- manim/mobject/geometry/polygram.py +109 -25
- manim/mobject/geometry/shape_matchers.py +35 -15
- manim/mobject/geometry/tips.py +36 -27
- manim/mobject/graph.py +48 -40
- manim/mobject/graphing/coordinate_systems.py +110 -45
- manim/mobject/graphing/functions.py +16 -10
- manim/mobject/graphing/number_line.py +23 -9
- manim/mobject/graphing/probability.py +2 -10
- manim/mobject/graphing/scale.py +6 -5
- manim/mobject/matrix.py +17 -19
- manim/mobject/mobject.py +149 -103
- manim/mobject/opengl/opengl_geometry.py +4 -8
- manim/mobject/opengl/opengl_mobject.py +506 -343
- manim/mobject/opengl/opengl_point_cloud_mobject.py +3 -7
- manim/mobject/opengl/opengl_surface.py +1 -2
- manim/mobject/opengl/opengl_vectorized_mobject.py +27 -65
- manim/mobject/svg/brace.py +61 -13
- manim/mobject/svg/svg_mobject.py +2 -1
- manim/mobject/table.py +11 -12
- manim/mobject/text/code_mobject.py +186 -550
- manim/mobject/text/numbers.py +7 -7
- manim/mobject/text/tex_mobject.py +22 -13
- manim/mobject/text/text_mobject.py +29 -20
- manim/mobject/three_d/polyhedra.py +98 -1
- manim/mobject/three_d/three_dimensions.py +59 -31
- manim/mobject/types/image_mobject.py +37 -23
- manim/mobject/types/point_cloud_mobject.py +103 -67
- manim/mobject/types/vectorized_mobject.py +387 -214
- manim/mobject/value_tracker.py +2 -1
- manim/mobject/vector_field.py +2 -4
- manim/opengl/__init__.py +3 -3
- manim/plugins/__init__.py +2 -3
- manim/plugins/plugins_flags.py +3 -3
- manim/renderer/cairo_renderer.py +11 -11
- manim/renderer/opengl_renderer.py +19 -20
- manim/renderer/shader.py +2 -3
- manim/renderer/shader_wrapper.py +3 -2
- manim/scene/moving_camera_scene.py +23 -0
- manim/scene/scene.py +72 -41
- manim/scene/scene_file_writer.py +313 -164
- manim/scene/section.py +15 -15
- manim/scene/three_d_scene.py +8 -15
- manim/scene/vector_space_scene.py +3 -6
- manim/typing.py +326 -66
- manim/utils/bezier.py +1658 -381
- manim/utils/caching.py +11 -5
- manim/utils/color/AS2700.py +2 -0
- manim/utils/color/BS381.py +2 -0
- manim/utils/color/DVIPSNAMES.py +96 -0
- manim/utils/color/SVGNAMES.py +179 -0
- manim/utils/color/X11.py +3 -0
- manim/utils/color/XKCD.py +2 -0
- manim/utils/color/__init__.py +8 -5
- manim/utils/color/core.py +818 -301
- manim/utils/color/manim_colors.py +7 -9
- manim/utils/commands.py +40 -19
- manim/utils/config_ops.py +18 -13
- manim/utils/debug.py +8 -6
- manim/utils/deprecation.py +92 -43
- manim/utils/docbuild/autoaliasattr_directive.py +45 -8
- manim/utils/docbuild/autocolor_directive.py +12 -13
- manim/utils/docbuild/manim_directive.py +35 -29
- manim/utils/docbuild/module_parsing.py +74 -27
- manim/utils/family.py +3 -3
- manim/utils/family_ops.py +12 -4
- manim/utils/file_ops.py +22 -16
- manim/utils/hashing.py +7 -7
- manim/utils/images.py +10 -4
- manim/utils/ipython_magic.py +12 -8
- manim/utils/iterables.py +161 -119
- manim/utils/module_ops.py +55 -19
- manim/utils/opengl.py +68 -23
- manim/utils/parameter_parsing.py +3 -2
- manim/utils/paths.py +11 -5
- manim/utils/polylabel.py +168 -0
- manim/utils/qhull.py +218 -0
- manim/utils/rate_functions.py +69 -32
- manim/utils/simple_functions.py +24 -15
- manim/utils/sounds.py +7 -1
- manim/utils/space_ops.py +48 -37
- manim/utils/testing/_frames_testers.py +13 -8
- manim/utils/testing/_show_diff.py +5 -3
- manim/utils/testing/_test_class_makers.py +33 -18
- manim/utils/testing/frames_comparison.py +20 -14
- manim/utils/tex.py +4 -2
- manim/utils/tex_file_writing.py +45 -45
- manim/utils/tex_templates.py +1 -1
- manim/utils/unit.py +6 -5
- {manim-0.18.1.dist-info → manim-0.19.0.dist-info}/METADATA +16 -9
- manim-0.19.0.dist-info/RECORD +221 -0
- {manim-0.18.1.dist-info → manim-0.19.0.dist-info}/WHEEL +1 -1
- manim-0.18.1.dist-info/RECORD +0 -217
- {manim-0.18.1.dist-info → manim-0.19.0.dist-info}/LICENSE +0 -0
- {manim-0.18.1.dist-info → manim-0.19.0.dist-info}/LICENSE.community +0 -0
- {manim-0.18.1.dist-info → manim-0.19.0.dist-info}/entry_points.txt +0 -0
manim/utils/file_ops.py
CHANGED
|
@@ -28,11 +28,13 @@ from shutil import copyfile
|
|
|
28
28
|
from typing import TYPE_CHECKING
|
|
29
29
|
|
|
30
30
|
if TYPE_CHECKING:
|
|
31
|
+
from manim.typing import StrPath
|
|
32
|
+
|
|
31
33
|
from ..scene.scene_file_writer import SceneFileWriter
|
|
32
34
|
|
|
33
35
|
from manim import __version__, config, logger
|
|
34
36
|
|
|
35
|
-
from .. import
|
|
37
|
+
from .. import console
|
|
36
38
|
|
|
37
39
|
|
|
38
40
|
def is_mp4_format() -> bool:
|
|
@@ -45,7 +47,8 @@ def is_mp4_format() -> bool:
|
|
|
45
47
|
``True`` if format is set as mp4
|
|
46
48
|
|
|
47
49
|
"""
|
|
48
|
-
|
|
50
|
+
val: bool = config["format"] == "mp4"
|
|
51
|
+
return val
|
|
49
52
|
|
|
50
53
|
|
|
51
54
|
def is_gif_format() -> bool:
|
|
@@ -58,7 +61,8 @@ def is_gif_format() -> bool:
|
|
|
58
61
|
``True`` if format is set as gif
|
|
59
62
|
|
|
60
63
|
"""
|
|
61
|
-
|
|
64
|
+
val: bool = config["format"] == "gif"
|
|
65
|
+
return val
|
|
62
66
|
|
|
63
67
|
|
|
64
68
|
def is_webm_format() -> bool:
|
|
@@ -71,7 +75,8 @@ def is_webm_format() -> bool:
|
|
|
71
75
|
``True`` if format is set as webm
|
|
72
76
|
|
|
73
77
|
"""
|
|
74
|
-
|
|
78
|
+
val: bool = config["format"] == "webm"
|
|
79
|
+
return val
|
|
75
80
|
|
|
76
81
|
|
|
77
82
|
def is_mov_format() -> bool:
|
|
@@ -84,7 +89,8 @@ def is_mov_format() -> bool:
|
|
|
84
89
|
``True`` if format is set as mov
|
|
85
90
|
|
|
86
91
|
"""
|
|
87
|
-
|
|
92
|
+
val: bool = config["format"] == "mov"
|
|
93
|
+
return val
|
|
88
94
|
|
|
89
95
|
|
|
90
96
|
def is_png_format() -> bool:
|
|
@@ -97,7 +103,8 @@ def is_png_format() -> bool:
|
|
|
97
103
|
``True`` if format is set as png
|
|
98
104
|
|
|
99
105
|
"""
|
|
100
|
-
|
|
106
|
+
val: bool = config["format"] == "png"
|
|
107
|
+
return val
|
|
101
108
|
|
|
102
109
|
|
|
103
110
|
def write_to_movie() -> bool:
|
|
@@ -124,7 +131,7 @@ def write_to_movie() -> bool:
|
|
|
124
131
|
|
|
125
132
|
def ensure_executable(path_to_exe: Path) -> bool:
|
|
126
133
|
if path_to_exe.parent == Path("."):
|
|
127
|
-
executable = shutil.which(path_to_exe.stem)
|
|
134
|
+
executable: StrPath | None = shutil.which(path_to_exe.stem)
|
|
128
135
|
if executable is None:
|
|
129
136
|
return False
|
|
130
137
|
else:
|
|
@@ -159,7 +166,7 @@ def guarantee_empty_existence(path: Path) -> Path:
|
|
|
159
166
|
|
|
160
167
|
|
|
161
168
|
def seek_full_path_from_defaults(
|
|
162
|
-
file_name:
|
|
169
|
+
file_name: StrPath, default_dir: Path, extensions: list[str]
|
|
163
170
|
) -> Path:
|
|
164
171
|
possible_paths = [Path(file_name).expanduser()]
|
|
165
172
|
possible_paths += [
|
|
@@ -186,10 +193,12 @@ def modify_atime(file_path: str) -> None:
|
|
|
186
193
|
os.utime(file_path, times=(time.time(), Path(file_path).stat().st_mtime))
|
|
187
194
|
|
|
188
195
|
|
|
189
|
-
def open_file(file_path, in_browser=False):
|
|
196
|
+
def open_file(file_path: Path, in_browser: bool = False) -> None:
|
|
190
197
|
current_os = platform.system()
|
|
191
198
|
if current_os == "Windows":
|
|
192
|
-
os.startfile
|
|
199
|
+
# The method os.startfile is only available in Windows,
|
|
200
|
+
# ignoring type error caused by this.
|
|
201
|
+
os.startfile(file_path if not in_browser else file_path.parent) # type: ignore[attr-defined]
|
|
193
202
|
else:
|
|
194
203
|
if current_os == "Linux":
|
|
195
204
|
commands = ["xdg-open"]
|
|
@@ -198,17 +207,14 @@ def open_file(file_path, in_browser=False):
|
|
|
198
207
|
commands = ["cygstart"]
|
|
199
208
|
file_path = file_path if not in_browser else file_path.parent
|
|
200
209
|
elif current_os == "Darwin":
|
|
201
|
-
if
|
|
202
|
-
commands = ["ffplay", "-loglevel", config["ffmpeg_loglevel"].lower()]
|
|
203
|
-
else:
|
|
204
|
-
commands = ["open"] if not in_browser else ["open", "-R"]
|
|
210
|
+
commands = ["open"] if not in_browser else ["open", "-R"]
|
|
205
211
|
else:
|
|
206
212
|
raise OSError("Unable to identify your operating system...")
|
|
207
213
|
|
|
208
214
|
# check after so that file path is set correctly
|
|
209
215
|
if config.preview_command:
|
|
210
216
|
commands = [config.preview_command]
|
|
211
|
-
commands.append(file_path)
|
|
217
|
+
commands.append(str(file_path))
|
|
212
218
|
sp.run(commands)
|
|
213
219
|
|
|
214
220
|
|
|
@@ -252,7 +258,7 @@ def get_template_path() -> Path:
|
|
|
252
258
|
return Path.resolve(Path(__file__).parent.parent / "templates")
|
|
253
259
|
|
|
254
260
|
|
|
255
|
-
def add_import_statement(file: Path):
|
|
261
|
+
def add_import_statement(file: Path) -> None:
|
|
256
262
|
"""Prepends an import statement in a file
|
|
257
263
|
|
|
258
264
|
Parameters
|
manim/utils/hashing.py
CHANGED
|
@@ -14,13 +14,13 @@ from typing import Any
|
|
|
14
14
|
|
|
15
15
|
import numpy as np
|
|
16
16
|
|
|
17
|
-
from manim.
|
|
18
|
-
from manim.camera.camera import Camera
|
|
19
|
-
from manim.mobject.mobject import Mobject
|
|
20
|
-
|
|
21
|
-
from .. import config, logger
|
|
17
|
+
from manim._config import config, logger
|
|
22
18
|
|
|
23
19
|
if typing.TYPE_CHECKING:
|
|
20
|
+
from manim.animation.animation import Animation
|
|
21
|
+
from manim.camera.camera import Camera
|
|
22
|
+
from manim.mobject.mobject import Mobject
|
|
23
|
+
from manim.opengl.opengl_renderer import OpenGLCamera
|
|
24
24
|
from manim.scene.scene import Scene
|
|
25
25
|
|
|
26
26
|
__all__ = ["KEYS_TO_FILTER_OUT", "get_hash_from_play_call", "get_json"]
|
|
@@ -223,7 +223,7 @@ class _CustomEncoder(json.JSONEncoder):
|
|
|
223
223
|
# We return the repr and not a list to avoid the JsonEncoder to iterate over it.
|
|
224
224
|
return repr(obj)
|
|
225
225
|
elif hasattr(obj, "__dict__"):
|
|
226
|
-
temp =
|
|
226
|
+
temp = obj.__dict__
|
|
227
227
|
# MappingProxy is scene-caching nightmare. It contains all of the object methods and attributes. We skip it as the mechanism will at some point process the object, but instantiated.
|
|
228
228
|
# Indeed, there is certainly no case where scene-caching will receive only a non instancied object, as this is never used in the library or encouraged to be used user-side.
|
|
229
229
|
if isinstance(temp, MappingProxyType):
|
|
@@ -324,7 +324,7 @@ def get_json(obj: dict):
|
|
|
324
324
|
|
|
325
325
|
def get_hash_from_play_call(
|
|
326
326
|
scene_object: Scene,
|
|
327
|
-
camera_object: Camera,
|
|
327
|
+
camera_object: Camera | OpenGLCamera,
|
|
328
328
|
animations_list: typing.Iterable[Animation],
|
|
329
329
|
current_mobjects_list: typing.Iterable[Mobject],
|
|
330
330
|
) -> str:
|
manim/utils/images.py
CHANGED
|
@@ -9,16 +9,22 @@ __all__ = [
|
|
|
9
9
|
"change_to_rgba_array",
|
|
10
10
|
]
|
|
11
11
|
|
|
12
|
-
from pathlib import Path
|
|
12
|
+
from pathlib import Path, PurePath
|
|
13
|
+
from typing import TYPE_CHECKING
|
|
13
14
|
|
|
14
15
|
import numpy as np
|
|
15
16
|
from PIL import Image
|
|
16
17
|
|
|
18
|
+
from manim.typing import RGBPixelArray
|
|
19
|
+
|
|
17
20
|
from .. import config
|
|
18
21
|
from ..utils.file_ops import seek_full_path_from_defaults
|
|
19
22
|
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
pass
|
|
25
|
+
|
|
20
26
|
|
|
21
|
-
def get_full_raster_image_path(image_file_name: str) -> Path:
|
|
27
|
+
def get_full_raster_image_path(image_file_name: str | PurePath) -> Path:
|
|
22
28
|
return seek_full_path_from_defaults(
|
|
23
29
|
image_file_name,
|
|
24
30
|
default_dir=config.get_dir("assets_dir"),
|
|
@@ -26,7 +32,7 @@ def get_full_raster_image_path(image_file_name: str) -> Path:
|
|
|
26
32
|
)
|
|
27
33
|
|
|
28
34
|
|
|
29
|
-
def get_full_vector_image_path(image_file_name: str) -> Path:
|
|
35
|
+
def get_full_vector_image_path(image_file_name: str | PurePath) -> Path:
|
|
30
36
|
return seek_full_path_from_defaults(
|
|
31
37
|
image_file_name,
|
|
32
38
|
default_dir=config.get_dir("assets_dir"),
|
|
@@ -49,7 +55,7 @@ def invert_image(image: np.array) -> Image:
|
|
|
49
55
|
return Image.fromarray(arr)
|
|
50
56
|
|
|
51
57
|
|
|
52
|
-
def change_to_rgba_array(image, dtype="uint8"):
|
|
58
|
+
def change_to_rgba_array(image: RGBPixelArray, dtype: str = "uint8") -> RGBPixelArray:
|
|
53
59
|
"""Converts an RGB array into RGBA with the alpha value opacity maxed."""
|
|
54
60
|
pa = image
|
|
55
61
|
if len(pa.shape) == 2:
|
manim/utils/ipython_magic.py
CHANGED
|
@@ -3,13 +3,12 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import mimetypes
|
|
6
|
-
import os
|
|
7
6
|
import shutil
|
|
8
7
|
from datetime import datetime
|
|
9
8
|
from pathlib import Path
|
|
10
9
|
from typing import Any
|
|
11
10
|
|
|
12
|
-
from manim import
|
|
11
|
+
from manim import config, logger, tempconfig
|
|
13
12
|
from manim.__main__ import main
|
|
14
13
|
from manim.renderer.shader import shader_program_cache
|
|
15
14
|
|
|
@@ -35,15 +34,15 @@ else:
|
|
|
35
34
|
class ManimMagic(Magics):
|
|
36
35
|
def __init__(self, shell: InteractiveShell) -> None:
|
|
37
36
|
super().__init__(shell)
|
|
38
|
-
self.rendered_files = {}
|
|
37
|
+
self.rendered_files: dict[Path, Path] = {}
|
|
39
38
|
|
|
40
39
|
@needs_local_scope
|
|
41
40
|
@line_cell_magic
|
|
42
41
|
def manim(
|
|
43
42
|
self,
|
|
44
43
|
line: str,
|
|
45
|
-
cell: str = None,
|
|
46
|
-
local_ns: dict[str, Any] = None,
|
|
44
|
+
cell: str | None = None,
|
|
45
|
+
local_ns: dict[str, Any] | None = None,
|
|
47
46
|
) -> None:
|
|
48
47
|
r"""Render Manim scenes contained in IPython cells.
|
|
49
48
|
Works as a line or cell magic.
|
|
@@ -128,8 +127,9 @@ else:
|
|
|
128
127
|
|
|
129
128
|
modified_args = self.add_additional_args(args)
|
|
130
129
|
args = main(modified_args, standalone_mode=False, prog_name="manim")
|
|
130
|
+
assert isinstance(local_ns, dict)
|
|
131
131
|
with tempconfig(local_ns.get("config", {})):
|
|
132
|
-
config.digest_args(args)
|
|
132
|
+
config.digest_args(args) # type: ignore[arg-type]
|
|
133
133
|
|
|
134
134
|
renderer = None
|
|
135
135
|
if config.renderer == RendererType.OPENGL:
|
|
@@ -168,8 +168,9 @@ else:
|
|
|
168
168
|
shutil.copy(local_path, tmpfile)
|
|
169
169
|
|
|
170
170
|
file_type = mimetypes.guess_type(config["output_file"])[0]
|
|
171
|
+
assert isinstance(file_type, str)
|
|
171
172
|
embed = config["media_embed"]
|
|
172
|
-
if embed
|
|
173
|
+
if not embed:
|
|
173
174
|
# videos need to be embedded when running in google colab.
|
|
174
175
|
# do this automatically in case config.media_embed has not been
|
|
175
176
|
# set explicitly.
|
|
@@ -195,4 +196,7 @@ else:
|
|
|
195
196
|
|
|
196
197
|
|
|
197
198
|
def _generate_file_name() -> str:
|
|
198
|
-
|
|
199
|
+
val: str = (
|
|
200
|
+
config["scene_names"][0] + "@" + datetime.now().strftime("%Y-%m-%d@%H-%M-%S")
|
|
201
|
+
)
|
|
202
|
+
return val
|