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.

Files changed (129) hide show
  1. manim/__main__.py +45 -12
  2. manim/_config/__init__.py +2 -2
  3. manim/_config/cli_colors.py +8 -4
  4. manim/_config/default.cfg +0 -2
  5. manim/_config/logger_utils.py +5 -0
  6. manim/_config/utils.py +29 -38
  7. manim/animation/animation.py +148 -8
  8. manim/animation/composition.py +16 -13
  9. manim/animation/creation.py +184 -8
  10. manim/animation/fading.py +5 -8
  11. manim/animation/indication.py +93 -26
  12. manim/animation/movement.py +21 -3
  13. manim/animation/rotation.py +2 -1
  14. manim/animation/specialized.py +3 -5
  15. manim/animation/speedmodifier.py +3 -3
  16. manim/animation/transform.py +4 -5
  17. manim/animation/updaters/mobject_update_utils.py +17 -14
  18. manim/camera/camera.py +2 -2
  19. manim/cli/__init__.py +17 -0
  20. manim/cli/cfg/group.py +52 -36
  21. manim/cli/checkhealth/checks.py +92 -76
  22. manim/cli/checkhealth/commands.py +12 -5
  23. manim/cli/default_group.py +148 -24
  24. manim/cli/init/commands.py +28 -23
  25. manim/cli/plugins/commands.py +13 -3
  26. manim/cli/render/commands.py +47 -42
  27. manim/cli/render/global_options.py +43 -9
  28. manim/cli/render/render_options.py +84 -19
  29. manim/constants.py +11 -4
  30. manim/mobject/frame.py +0 -1
  31. manim/mobject/geometry/arc.py +109 -75
  32. manim/mobject/geometry/boolean_ops.py +20 -17
  33. manim/mobject/geometry/labeled.py +300 -77
  34. manim/mobject/geometry/line.py +120 -60
  35. manim/mobject/geometry/polygram.py +109 -25
  36. manim/mobject/geometry/shape_matchers.py +35 -15
  37. manim/mobject/geometry/tips.py +36 -27
  38. manim/mobject/graph.py +48 -40
  39. manim/mobject/graphing/coordinate_systems.py +110 -45
  40. manim/mobject/graphing/functions.py +16 -10
  41. manim/mobject/graphing/number_line.py +23 -9
  42. manim/mobject/graphing/probability.py +2 -10
  43. manim/mobject/graphing/scale.py +6 -5
  44. manim/mobject/matrix.py +17 -19
  45. manim/mobject/mobject.py +149 -103
  46. manim/mobject/opengl/opengl_geometry.py +4 -8
  47. manim/mobject/opengl/opengl_mobject.py +506 -343
  48. manim/mobject/opengl/opengl_point_cloud_mobject.py +3 -7
  49. manim/mobject/opengl/opengl_surface.py +1 -2
  50. manim/mobject/opengl/opengl_vectorized_mobject.py +27 -65
  51. manim/mobject/svg/brace.py +61 -13
  52. manim/mobject/svg/svg_mobject.py +2 -1
  53. manim/mobject/table.py +11 -12
  54. manim/mobject/text/code_mobject.py +186 -550
  55. manim/mobject/text/numbers.py +7 -7
  56. manim/mobject/text/tex_mobject.py +22 -13
  57. manim/mobject/text/text_mobject.py +29 -20
  58. manim/mobject/three_d/polyhedra.py +98 -1
  59. manim/mobject/three_d/three_dimensions.py +59 -31
  60. manim/mobject/types/image_mobject.py +37 -23
  61. manim/mobject/types/point_cloud_mobject.py +103 -67
  62. manim/mobject/types/vectorized_mobject.py +387 -214
  63. manim/mobject/value_tracker.py +2 -1
  64. manim/mobject/vector_field.py +2 -4
  65. manim/opengl/__init__.py +3 -3
  66. manim/plugins/__init__.py +2 -3
  67. manim/plugins/plugins_flags.py +3 -3
  68. manim/renderer/cairo_renderer.py +11 -11
  69. manim/renderer/opengl_renderer.py +19 -20
  70. manim/renderer/shader.py +2 -3
  71. manim/renderer/shader_wrapper.py +3 -2
  72. manim/scene/moving_camera_scene.py +23 -0
  73. manim/scene/scene.py +72 -41
  74. manim/scene/scene_file_writer.py +313 -164
  75. manim/scene/section.py +15 -15
  76. manim/scene/three_d_scene.py +8 -15
  77. manim/scene/vector_space_scene.py +3 -6
  78. manim/typing.py +326 -66
  79. manim/utils/bezier.py +1658 -381
  80. manim/utils/caching.py +11 -5
  81. manim/utils/color/AS2700.py +2 -0
  82. manim/utils/color/BS381.py +2 -0
  83. manim/utils/color/DVIPSNAMES.py +96 -0
  84. manim/utils/color/SVGNAMES.py +179 -0
  85. manim/utils/color/X11.py +3 -0
  86. manim/utils/color/XKCD.py +2 -0
  87. manim/utils/color/__init__.py +8 -5
  88. manim/utils/color/core.py +818 -301
  89. manim/utils/color/manim_colors.py +7 -9
  90. manim/utils/commands.py +40 -19
  91. manim/utils/config_ops.py +18 -13
  92. manim/utils/debug.py +8 -6
  93. manim/utils/deprecation.py +92 -43
  94. manim/utils/docbuild/autoaliasattr_directive.py +45 -8
  95. manim/utils/docbuild/autocolor_directive.py +12 -13
  96. manim/utils/docbuild/manim_directive.py +35 -29
  97. manim/utils/docbuild/module_parsing.py +74 -27
  98. manim/utils/family.py +3 -3
  99. manim/utils/family_ops.py +12 -4
  100. manim/utils/file_ops.py +22 -16
  101. manim/utils/hashing.py +7 -7
  102. manim/utils/images.py +10 -4
  103. manim/utils/ipython_magic.py +12 -8
  104. manim/utils/iterables.py +161 -119
  105. manim/utils/module_ops.py +55 -19
  106. manim/utils/opengl.py +68 -23
  107. manim/utils/parameter_parsing.py +3 -2
  108. manim/utils/paths.py +11 -5
  109. manim/utils/polylabel.py +168 -0
  110. manim/utils/qhull.py +218 -0
  111. manim/utils/rate_functions.py +69 -32
  112. manim/utils/simple_functions.py +24 -15
  113. manim/utils/sounds.py +7 -1
  114. manim/utils/space_ops.py +48 -37
  115. manim/utils/testing/_frames_testers.py +13 -8
  116. manim/utils/testing/_show_diff.py +5 -3
  117. manim/utils/testing/_test_class_makers.py +33 -18
  118. manim/utils/testing/frames_comparison.py +20 -14
  119. manim/utils/tex.py +4 -2
  120. manim/utils/tex_file_writing.py +45 -45
  121. manim/utils/tex_templates.py +1 -1
  122. manim/utils/unit.py +6 -5
  123. {manim-0.18.1.dist-info → manim-0.19.0.dist-info}/METADATA +16 -9
  124. manim-0.19.0.dist-info/RECORD +221 -0
  125. {manim-0.18.1.dist-info → manim-0.19.0.dist-info}/WHEEL +1 -1
  126. manim-0.18.1.dist-info/RECORD +0 -217
  127. {manim-0.18.1.dist-info → manim-0.19.0.dist-info}/LICENSE +0 -0
  128. {manim-0.18.1.dist-info → manim-0.19.0.dist-info}/LICENSE.community +0 -0
  129. {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 config, console
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
- return config["format"] == "mp4"
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
- return config["format"] == "gif"
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
- return config["format"] == "webm"
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
- return config["format"] == "mov"
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
- return config["format"] == "png"
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: str, default_dir: Path, extensions: list[str]
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(file_path if not in_browser else file_path.parent)
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 is_gif_format():
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.animation.animation import Animation
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 = getattr(obj, "__dict__")
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:
@@ -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 Group, config, logger, tempconfig
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 is None:
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
- return config["scene_names"][0] + "@" + datetime.now().strftime("%Y-%m-%d@%H-%M-%S")
199
+ val: str = (
200
+ config["scene_names"][0] + "@" + datetime.now().strftime("%Y-%m-%d@%H-%M-%S")
201
+ )
202
+ return val