manim 0.17.0__py3-none-any.whl → 0.19.1__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.
Files changed (163) hide show
  1. manim/__init__.py +11 -6
  2. manim/__main__.py +62 -19
  3. manim/_config/__init__.py +10 -9
  4. manim/_config/cli_colors.py +26 -9
  5. manim/_config/default.cfg +1 -3
  6. manim/_config/logger_utils.py +23 -13
  7. manim/_config/utils.py +662 -468
  8. manim/animation/animation.py +164 -18
  9. manim/animation/changing.py +34 -23
  10. manim/animation/composition.py +265 -67
  11. manim/animation/creation.py +208 -26
  12. manim/animation/fading.py +16 -18
  13. manim/animation/growing.py +35 -15
  14. manim/animation/indication.py +150 -76
  15. manim/animation/movement.py +56 -22
  16. manim/animation/numbers.py +64 -6
  17. manim/animation/rotation.py +78 -7
  18. manim/animation/specialized.py +6 -7
  19. manim/animation/speedmodifier.py +13 -10
  20. manim/animation/transform.py +14 -11
  21. manim/animation/transform_matching_parts.py +3 -4
  22. manim/animation/updaters/mobject_update_utils.py +152 -30
  23. manim/animation/updaters/update.py +10 -7
  24. manim/camera/camera.py +182 -118
  25. manim/camera/mapping_camera.py +34 -3
  26. manim/camera/moving_camera.py +95 -74
  27. manim/camera/multi_camera.py +23 -15
  28. manim/camera/three_d_camera.py +70 -52
  29. manim/cli/__init__.py +17 -0
  30. manim/cli/cfg/group.py +76 -44
  31. manim/cli/checkhealth/checks.py +192 -0
  32. manim/cli/checkhealth/commands.py +90 -0
  33. manim/cli/default_group.py +158 -25
  34. manim/cli/init/commands.py +33 -25
  35. manim/cli/plugins/commands.py +16 -3
  36. manim/cli/render/commands.py +72 -60
  37. manim/cli/render/ease_of_access_options.py +4 -3
  38. manim/cli/render/global_options.py +59 -17
  39. manim/cli/render/output_options.py +6 -5
  40. manim/cli/render/render_options.py +98 -33
  41. manim/constants.py +109 -59
  42. manim/data_structures.py +31 -0
  43. manim/mobject/frame.py +8 -5
  44. manim/mobject/geometry/__init__.py +1 -0
  45. manim/mobject/geometry/arc.py +277 -135
  46. manim/mobject/geometry/boolean_ops.py +32 -31
  47. manim/mobject/geometry/labeled.py +376 -0
  48. manim/mobject/geometry/line.py +192 -87
  49. manim/mobject/geometry/polygram.py +224 -58
  50. manim/mobject/geometry/shape_matchers.py +61 -25
  51. manim/mobject/geometry/tips.py +122 -48
  52. manim/mobject/graph.py +1027 -419
  53. manim/mobject/graphing/coordinate_systems.py +533 -278
  54. manim/mobject/graphing/functions.py +53 -32
  55. manim/mobject/graphing/number_line.py +123 -65
  56. manim/mobject/graphing/probability.py +88 -62
  57. manim/mobject/graphing/scale.py +33 -19
  58. manim/mobject/logo.py +118 -28
  59. manim/mobject/matrix.py +87 -83
  60. manim/mobject/mobject.py +912 -442
  61. manim/mobject/opengl/dot_cloud.py +16 -5
  62. manim/mobject/opengl/opengl_compatibility.py +4 -2
  63. manim/mobject/opengl/opengl_geometry.py +254 -153
  64. manim/mobject/opengl/opengl_image_mobject.py +3 -1
  65. manim/mobject/opengl/opengl_mobject.py +779 -482
  66. manim/mobject/opengl/opengl_point_cloud_mobject.py +41 -14
  67. manim/mobject/opengl/opengl_surface.py +14 -92
  68. manim/mobject/opengl/opengl_three_dimensions.py +12 -8
  69. manim/mobject/opengl/opengl_vectorized_mobject.py +98 -100
  70. manim/mobject/svg/brace.py +173 -41
  71. manim/mobject/svg/svg_mobject.py +139 -53
  72. manim/mobject/table.py +61 -68
  73. manim/mobject/text/code_mobject.py +193 -539
  74. manim/mobject/text/numbers.py +81 -34
  75. manim/mobject/text/tex_mobject.py +130 -78
  76. manim/mobject/text/text_mobject.py +288 -164
  77. manim/mobject/three_d/polyhedra.py +111 -13
  78. manim/mobject/three_d/three_d_utils.py +17 -8
  79. manim/mobject/three_d/three_dimensions.py +239 -106
  80. manim/mobject/types/image_mobject.py +50 -30
  81. manim/mobject/types/point_cloud_mobject.py +120 -75
  82. manim/mobject/types/vectorized_mobject.py +841 -408
  83. manim/mobject/value_tracker.py +105 -38
  84. manim/mobject/vector_field.py +50 -31
  85. manim/opengl/__init__.py +3 -3
  86. manim/plugins/__init__.py +14 -1
  87. manim/plugins/plugins_flags.py +10 -14
  88. manim/renderer/cairo_renderer.py +65 -50
  89. manim/renderer/opengl_renderer.py +89 -69
  90. manim/renderer/opengl_renderer_window.py +39 -18
  91. manim/renderer/shader.py +123 -87
  92. manim/renderer/shader_wrapper.py +44 -28
  93. manim/renderer/vectorized_mobject_rendering.py +38 -10
  94. manim/scene/moving_camera_scene.py +32 -3
  95. manim/scene/scene.py +507 -242
  96. manim/scene/scene_file_writer.py +371 -220
  97. manim/scene/section.py +20 -16
  98. manim/scene/three_d_scene.py +14 -22
  99. manim/scene/vector_space_scene.py +223 -129
  100. manim/scene/zoomed_scene.py +46 -41
  101. manim/typing.py +990 -0
  102. manim/utils/bezier.py +1823 -371
  103. manim/utils/caching.py +12 -5
  104. manim/utils/color/AS2700.py +236 -0
  105. manim/utils/color/BS381.py +318 -0
  106. manim/utils/color/DVIPSNAMES.py +96 -0
  107. manim/utils/color/SVGNAMES.py +179 -0
  108. manim/utils/color/X11.py +533 -0
  109. manim/utils/color/XKCD.py +952 -0
  110. manim/utils/color/__init__.py +61 -0
  111. manim/utils/color/core.py +1667 -0
  112. manim/utils/color/manim_colors.py +218 -0
  113. manim/utils/commands.py +48 -20
  114. manim/utils/config_ops.py +39 -19
  115. manim/utils/debug.py +8 -7
  116. manim/utils/deprecation.py +86 -39
  117. manim/utils/docbuild/__init__.py +17 -0
  118. manim/utils/docbuild/autoaliasattr_directive.py +236 -0
  119. manim/utils/docbuild/autocolor_directive.py +99 -0
  120. manim/utils/docbuild/manim_directive.py +94 -41
  121. manim/utils/docbuild/module_parsing.py +245 -0
  122. manim/utils/exceptions.py +6 -0
  123. manim/utils/family.py +5 -3
  124. manim/utils/family_ops.py +17 -4
  125. manim/utils/file_ops.py +27 -17
  126. manim/utils/hashing.py +55 -45
  127. manim/utils/images.py +13 -7
  128. manim/utils/ipython_magic.py +13 -7
  129. manim/utils/iterables.py +163 -120
  130. manim/utils/module_ops.py +66 -24
  131. manim/utils/opengl.py +77 -24
  132. manim/utils/parameter_parsing.py +32 -0
  133. manim/utils/paths.py +30 -33
  134. manim/utils/polylabel.py +235 -0
  135. manim/utils/qhull.py +218 -0
  136. manim/utils/rate_functions.py +98 -32
  137. manim/utils/simple_functions.py +25 -33
  138. manim/utils/sounds.py +7 -1
  139. manim/utils/space_ops.py +188 -115
  140. manim/utils/testing/__init__.py +17 -0
  141. manim/utils/testing/_frames_testers.py +13 -8
  142. manim/utils/testing/_show_diff.py +5 -3
  143. manim/utils/testing/_test_class_makers.py +34 -18
  144. manim/utils/testing/frames_comparison.py +37 -19
  145. manim/utils/tex.py +130 -198
  146. manim/utils/tex_file_writing.py +77 -47
  147. manim/utils/tex_templates.py +2 -1
  148. manim/utils/unit.py +6 -5
  149. {manim-0.17.0.dist-info → manim-0.19.1.dist-info}/METADATA +64 -65
  150. manim-0.19.1.dist-info/RECORD +220 -0
  151. {manim-0.17.0.dist-info → manim-0.19.1.dist-info}/WHEEL +1 -1
  152. manim-0.19.1.dist-info/entry_points.txt +3 -0
  153. {manim-0.17.0.dist-info → manim-0.19.1.dist-info/licenses}/LICENSE.community +1 -1
  154. manim/cli/new/group.py +0 -189
  155. manim/communitycolors.py +0 -9
  156. manim/gui/__init__.py +0 -0
  157. manim/gui/gui.py +0 -82
  158. manim/plugins/import_plugins.py +0 -43
  159. manim/utils/color.py +0 -552
  160. manim-0.17.0.dist-info/RECORD +0 -206
  161. manim-0.17.0.dist-info/entry_points.txt +0 -4
  162. /manim/cli/{new → checkhealth}/__init__.py +0 -0
  163. {manim-0.17.0.dist-info → manim-0.19.1.dist-info/licenses}/LICENSE +0 -0
@@ -5,7 +5,8 @@ from __future__ import annotations
5
5
  __all__ = ["ThreeDCamera"]
6
6
 
7
7
 
8
- from typing import Callable
8
+ from collections.abc import Callable, Iterable
9
+ from typing import Any
9
10
 
10
11
  import numpy as np
11
12
 
@@ -16,7 +17,15 @@ from manim.mobject.three_d.three_d_utils import (
16
17
  get_3d_vmob_start_corner,
17
18
  get_3d_vmob_start_corner_unit_normal,
18
19
  )
20
+ from manim.mobject.types.vectorized_mobject import VMobject
19
21
  from manim.mobject.value_tracker import ValueTracker
22
+ from manim.typing import (
23
+ FloatRGBA_Array,
24
+ MatrixMN,
25
+ Point3D,
26
+ Point3D_Array,
27
+ Point3DLike,
28
+ )
20
29
 
21
30
  from .. import config
22
31
  from ..camera.camera import Camera
@@ -30,17 +39,17 @@ from ..utils.space_ops import rotation_about_z, rotation_matrix
30
39
  class ThreeDCamera(Camera):
31
40
  def __init__(
32
41
  self,
33
- focal_distance=20.0,
34
- shading_factor=0.2,
35
- default_distance=5.0,
36
- light_source_start_point=9 * DOWN + 7 * LEFT + 10 * OUT,
37
- should_apply_shading=True,
38
- exponential_projection=False,
39
- phi=0,
40
- theta=-90 * DEGREES,
41
- gamma=0,
42
- zoom=1,
43
- **kwargs,
42
+ focal_distance: float = 20.0,
43
+ shading_factor: float = 0.2,
44
+ default_distance: float = 5.0,
45
+ light_source_start_point: Point3DLike = 9 * DOWN + 7 * LEFT + 10 * OUT,
46
+ should_apply_shading: bool = True,
47
+ exponential_projection: bool = False,
48
+ phi: float = 0,
49
+ theta: float = -90 * DEGREES,
50
+ gamma: float = 0,
51
+ zoom: float = 1,
52
+ **kwargs: Any,
44
53
  ):
45
54
  """Initializes the ThreeDCamera
46
55
 
@@ -68,24 +77,25 @@ class ThreeDCamera(Camera):
68
77
  self.focal_distance_tracker = ValueTracker(self.focal_distance)
69
78
  self.gamma_tracker = ValueTracker(self.gamma)
70
79
  self.zoom_tracker = ValueTracker(self.zoom)
71
- self.fixed_orientation_mobjects = {}
72
- self.fixed_in_frame_mobjects = set()
80
+ self.fixed_orientation_mobjects: dict[Mobject, Callable[[], Point3D]] = {}
81
+ self.fixed_in_frame_mobjects: set[Mobject] = set()
73
82
  self.reset_rotation_matrix()
74
83
 
75
84
  @property
76
- def frame_center(self):
85
+ def frame_center(self) -> Point3D:
77
86
  return self._frame_center.points[0]
78
87
 
79
88
  @frame_center.setter
80
- def frame_center(self, point):
89
+ def frame_center(self, point: Point3DLike) -> None:
81
90
  self._frame_center.move_to(point)
82
91
 
83
- def capture_mobjects(self, mobjects, **kwargs):
92
+ def capture_mobjects(self, mobjects: Iterable[Mobject], **kwargs: Any) -> None:
84
93
  self.reset_rotation_matrix()
85
94
  super().capture_mobjects(mobjects, **kwargs)
86
95
 
87
- def get_value_trackers(self):
88
- """Returns list of ValueTrackers of phi, theta, focal_distance and gamma
96
+ def get_value_trackers(self) -> list[ValueTracker]:
97
+ """A list of :class:`ValueTrackers <.ValueTracker>` of phi, theta, focal_distance,
98
+ gamma and zoom.
89
99
 
90
100
  Returns
91
101
  -------
@@ -100,7 +110,9 @@ class ThreeDCamera(Camera):
100
110
  self.zoom_tracker,
101
111
  ]
102
112
 
103
- def modified_rgbas(self, vmobject, rgbas):
113
+ def modified_rgbas(
114
+ self, vmobject: VMobject, rgbas: FloatRGBA_Array
115
+ ) -> FloatRGBA_Array:
104
116
  if not self.should_apply_shading:
105
117
  return rgbas
106
118
  if vmobject.shade_in_3d and (vmobject.get_num_points() > 0):
@@ -126,28 +138,33 @@ class ThreeDCamera(Camera):
126
138
 
127
139
  def get_stroke_rgbas(
128
140
  self,
129
- vmobject,
130
- background=False,
131
- ): # NOTE : DocStrings From parent
141
+ vmobject: VMobject,
142
+ background: bool = False,
143
+ ) -> FloatRGBA_Array: # NOTE : DocStrings From parent
132
144
  return self.modified_rgbas(vmobject, vmobject.get_stroke_rgbas(background))
133
145
 
134
- def get_fill_rgbas(self, vmobject): # NOTE : DocStrings From parent
146
+ def get_fill_rgbas(
147
+ self, vmobject: VMobject
148
+ ) -> FloatRGBA_Array: # NOTE : DocStrings From parent
135
149
  return self.modified_rgbas(vmobject, vmobject.get_fill_rgbas())
136
150
 
137
- def get_mobjects_to_display(self, *args, **kwargs): # NOTE : DocStrings From parent
151
+ def get_mobjects_to_display(
152
+ self, *args: Any, **kwargs: Any
153
+ ) -> list[Mobject]: # NOTE : DocStrings From parent
138
154
  mobjects = super().get_mobjects_to_display(*args, **kwargs)
139
155
  rot_matrix = self.get_rotation_matrix()
140
156
 
141
- def z_key(mob):
157
+ def z_key(mob: Mobject) -> float:
142
158
  if not (hasattr(mob, "shade_in_3d") and mob.shade_in_3d):
143
- return np.inf
159
+ return np.inf # type: ignore[no-any-return]
144
160
  # Assign a number to a three dimensional mobjects
145
161
  # based on how close it is to the camera
146
- return np.dot(mob.get_z_index_reference_point(), rot_matrix.T)[2]
162
+ distance: float = np.dot(mob.get_z_index_reference_point(), rot_matrix.T)[2]
163
+ return distance
147
164
 
148
165
  return sorted(mobjects, key=z_key)
149
166
 
150
- def get_phi(self):
167
+ def get_phi(self) -> float:
151
168
  """Returns the Polar angle (the angle off Z_AXIS) phi.
152
169
 
153
170
  Returns
@@ -157,7 +174,7 @@ class ThreeDCamera(Camera):
157
174
  """
158
175
  return self.phi_tracker.get_value()
159
176
 
160
- def get_theta(self):
177
+ def get_theta(self) -> float:
161
178
  """Returns the Azimuthal i.e the angle that spins the camera around the Z_AXIS.
162
179
 
163
180
  Returns
@@ -167,7 +184,7 @@ class ThreeDCamera(Camera):
167
184
  """
168
185
  return self.theta_tracker.get_value()
169
186
 
170
- def get_focal_distance(self):
187
+ def get_focal_distance(self) -> float:
171
188
  """Returns focal_distance of the Camera.
172
189
 
173
190
  Returns
@@ -177,7 +194,7 @@ class ThreeDCamera(Camera):
177
194
  """
178
195
  return self.focal_distance_tracker.get_value()
179
196
 
180
- def get_gamma(self):
197
+ def get_gamma(self) -> float:
181
198
  """Returns the rotation of the camera about the vector from the ORIGIN to the Camera.
182
199
 
183
200
  Returns
@@ -188,7 +205,7 @@ class ThreeDCamera(Camera):
188
205
  """
189
206
  return self.gamma_tracker.get_value()
190
207
 
191
- def get_zoom(self):
208
+ def get_zoom(self) -> float:
192
209
  """Returns the zoom amount of the camera.
193
210
 
194
211
  Returns
@@ -198,7 +215,7 @@ class ThreeDCamera(Camera):
198
215
  """
199
216
  return self.zoom_tracker.get_value()
200
217
 
201
- def set_phi(self, value: float):
218
+ def set_phi(self, value: float) -> None:
202
219
  """Sets the polar angle i.e the angle between Z_AXIS and Camera through ORIGIN in radians.
203
220
 
204
221
  Parameters
@@ -208,7 +225,7 @@ class ThreeDCamera(Camera):
208
225
  """
209
226
  self.phi_tracker.set_value(value)
210
227
 
211
- def set_theta(self, value: float):
228
+ def set_theta(self, value: float) -> None:
212
229
  """Sets the azimuthal angle i.e the angle that spins the camera around Z_AXIS in radians.
213
230
 
214
231
  Parameters
@@ -218,7 +235,7 @@ class ThreeDCamera(Camera):
218
235
  """
219
236
  self.theta_tracker.set_value(value)
220
237
 
221
- def set_focal_distance(self, value: float):
238
+ def set_focal_distance(self, value: float) -> None:
222
239
  """Sets the focal_distance of the Camera.
223
240
 
224
241
  Parameters
@@ -228,7 +245,7 @@ class ThreeDCamera(Camera):
228
245
  """
229
246
  self.focal_distance_tracker.set_value(value)
230
247
 
231
- def set_gamma(self, value: float):
248
+ def set_gamma(self, value: float) -> None:
232
249
  """Sets the angle of rotation of the camera about the vector from the ORIGIN to the Camera.
233
250
 
234
251
  Parameters
@@ -238,7 +255,7 @@ class ThreeDCamera(Camera):
238
255
  """
239
256
  self.gamma_tracker.set_value(value)
240
257
 
241
- def set_zoom(self, value: float):
258
+ def set_zoom(self, value: float) -> None:
242
259
  """Sets the zoom amount of the camera.
243
260
 
244
261
  Parameters
@@ -248,13 +265,13 @@ class ThreeDCamera(Camera):
248
265
  """
249
266
  self.zoom_tracker.set_value(value)
250
267
 
251
- def reset_rotation_matrix(self):
268
+ def reset_rotation_matrix(self) -> None:
252
269
  """Sets the value of self.rotation_matrix to
253
270
  the matrix corresponding to the current position of the camera
254
271
  """
255
272
  self.rotation_matrix = self.generate_rotation_matrix()
256
273
 
257
- def get_rotation_matrix(self):
274
+ def get_rotation_matrix(self) -> MatrixMN:
258
275
  """Returns the matrix corresponding to the current position of the camera.
259
276
 
260
277
  Returns
@@ -264,7 +281,7 @@ class ThreeDCamera(Camera):
264
281
  """
265
282
  return self.rotation_matrix
266
283
 
267
- def generate_rotation_matrix(self):
284
+ def generate_rotation_matrix(self) -> MatrixMN:
268
285
  """Generates a rotation matrix based off the current position of the camera.
269
286
 
270
287
  Returns
@@ -285,7 +302,7 @@ class ThreeDCamera(Camera):
285
302
  result = np.dot(matrix, result)
286
303
  return result
287
304
 
288
- def project_points(self, points: np.ndarray | list):
305
+ def project_points(self, points: Point3D_Array) -> Point3D_Array:
289
306
  """Applies the current rotation_matrix as a projection
290
307
  matrix to the passed array of points.
291
308
 
@@ -322,7 +339,7 @@ class ThreeDCamera(Camera):
322
339
  points[:, i] *= factor * zoom
323
340
  return points
324
341
 
325
- def project_point(self, point: list | np.ndarray):
342
+ def project_point(self, point: Point3D) -> Point3D:
326
343
  """Applies the current rotation_matrix as a projection
327
344
  matrix to the passed point.
328
345
 
@@ -340,9 +357,9 @@ class ThreeDCamera(Camera):
340
357
 
341
358
  def transform_points_pre_display(
342
359
  self,
343
- mobject,
344
- points,
345
- ): # TODO: Write Docstrings for this Method.
360
+ mobject: Mobject,
361
+ points: Point3D_Array,
362
+ ) -> Point3D_Array: # TODO: Write Docstrings for this Method.
346
363
  points = super().transform_points_pre_display(mobject, points)
347
364
  fixed_orientation = mobject in self.fixed_orientation_mobjects
348
365
  fixed_in_frame = mobject in self.fixed_in_frame_mobjects
@@ -361,8 +378,8 @@ class ThreeDCamera(Camera):
361
378
  self,
362
379
  *mobjects: Mobject,
363
380
  use_static_center_func: bool = False,
364
- center_func: Callable[[], np.ndarray] | None = None,
365
- ):
381
+ center_func: Callable[[], Point3D] | None = None,
382
+ ) -> None:
366
383
  """This method allows the mobject to have a fixed orientation,
367
384
  even when the camera moves around.
368
385
  E.G If it was passed through this method, facing the camera, it
@@ -380,9 +397,10 @@ class ThreeDCamera(Camera):
380
397
  The function which returns the centerpoint
381
398
  with respect to which the mobject will be oriented, by default None
382
399
  """
400
+
383
401
  # This prevents the computation of mobject.get_center
384
402
  # every single time a projection happens
385
- def get_static_center_func(mobject):
403
+ def get_static_center_func(mobject: Mobject) -> Callable[[], Point3D]:
386
404
  point = mobject.get_center()
387
405
  return lambda: point
388
406
 
@@ -396,7 +414,7 @@ class ThreeDCamera(Camera):
396
414
  for submob in mobject.get_family():
397
415
  self.fixed_orientation_mobjects[submob] = func
398
416
 
399
- def add_fixed_in_frame_mobjects(self, *mobjects: Mobject):
417
+ def add_fixed_in_frame_mobjects(self, *mobjects: Mobject) -> None:
400
418
  """This method allows the mobject to have a fixed position,
401
419
  even when the camera moves around.
402
420
  E.G If it was passed through this method, at the top of the frame, it
@@ -412,7 +430,7 @@ class ThreeDCamera(Camera):
412
430
  for mobject in extract_mobject_family_members(mobjects):
413
431
  self.fixed_in_frame_mobjects.add(mobject)
414
432
 
415
- def remove_fixed_orientation_mobjects(self, *mobjects: Mobject):
433
+ def remove_fixed_orientation_mobjects(self, *mobjects: Mobject) -> None:
416
434
  """If a mobject was fixed in its orientation by passing it through
417
435
  :meth:`.add_fixed_orientation_mobjects`, then this undoes that fixing.
418
436
  The Mobject will no longer have a fixed orientation.
@@ -426,7 +444,7 @@ class ThreeDCamera(Camera):
426
444
  if mobject in self.fixed_orientation_mobjects:
427
445
  del self.fixed_orientation_mobjects[mobject]
428
446
 
429
- def remove_fixed_in_frame_mobjects(self, *mobjects: Mobject):
447
+ def remove_fixed_in_frame_mobjects(self, *mobjects: Mobject) -> None:
430
448
  """If a mobject was fixed in frame by passing it through
431
449
  :meth:`.add_fixed_in_frame_mobjects`, then this undoes that fixing.
432
450
  The Mobject will no longer be fixed in frame.
manim/cli/__init__.py CHANGED
@@ -0,0 +1,17 @@
1
+ """The Manim CLI, and the available commands for ``manim``.
2
+
3
+ This page is a work in progress. Please run ``manim`` or ``manim --help`` in
4
+ your terminal to find more information on the following commands.
5
+
6
+ Available commands
7
+ ------------------
8
+
9
+ .. autosummary::
10
+ :toctree: ../reference
11
+
12
+ cfg
13
+ checkhealth
14
+ init
15
+ plugins
16
+ render
17
+ """
manim/cli/cfg/group.py CHANGED
@@ -5,32 +5,45 @@ cfg``. Here you can specify options, subcommands, and subgroups for the cfg
5
5
  group.
6
6
 
7
7
  """
8
+
8
9
  from __future__ import annotations
9
10
 
10
- import os
11
+ import contextlib
11
12
  from ast import literal_eval
12
13
  from pathlib import Path
14
+ from typing import Any, cast
13
15
 
14
- import click
15
16
  import cloup
16
17
  from rich.errors import StyleSyntaxError
17
18
  from rich.style import Style
18
19
 
19
- from ... import cli_ctx_settings, console
20
- from ..._config.utils import config_file_paths, make_config_parser
21
- from ...constants import EPILOG
22
- from ...utils.file_ops import guarantee_existence, open_file
20
+ from manim._config import cli_ctx_settings, console
21
+ from manim._config.utils import config_file_paths, make_config_parser
22
+ from manim.constants import EPILOG
23
+ from manim.utils.file_ops import guarantee_existence, open_file
23
24
 
24
25
  RICH_COLOUR_INSTRUCTIONS: str = """
25
26
  [red]The default colour is used by the input statement.
26
27
  If left empty, the default colour will be used.[/red]
27
28
  [magenta] For a full list of styles, visit[/magenta] [green]https://rich.readthedocs.io/en/latest/style.html[/green]
28
29
  """
29
- RICH_NON_STYLE_ENTRIES: str = ["log.width", "log.height", "log.timestamps"]
30
+ RICH_NON_STYLE_ENTRIES: list[str] = ["log.width", "log.height", "log.timestamps"]
31
+
32
+ __all__ = [
33
+ "value_from_string",
34
+ "value_from_string",
35
+ "is_valid_style",
36
+ "replace_keys",
37
+ "cfg",
38
+ "write",
39
+ "show",
40
+ "export",
41
+ ]
30
42
 
31
43
 
32
44
  def value_from_string(value: str) -> str | int | bool:
33
- """Extracts the literal of proper datatype from a string.
45
+ """Extract the literal of proper datatype from a ``value`` string.
46
+
34
47
  Parameters
35
48
  ----------
36
49
  value
@@ -38,51 +51,60 @@ def value_from_string(value: str) -> str | int | bool:
38
51
 
39
52
  Returns
40
53
  -------
41
- Union[:class:`str`, :class:`int`, :class:`bool`]
42
- Returns the literal of appropriate datatype.
54
+ :class:`str` | :class:`int` | :class:`bool`
55
+ The literal of appropriate datatype.
43
56
  """
44
- try:
57
+ with contextlib.suppress(SyntaxError, ValueError):
45
58
  value = literal_eval(value)
46
- except (SyntaxError, ValueError):
47
- pass
48
59
  return value
49
60
 
50
61
 
51
- def _is_expected_datatype(value: str, expected: str, style: bool = False) -> bool:
52
- """Checks whether `value` is the same datatype as `expected`,
53
- and checks if it is a valid `style` if `style` is true.
62
+ def _is_expected_datatype(
63
+ value: str, expected: str, validate_style: bool = False
64
+ ) -> bool:
65
+ """Check whether the literal from ``value`` is the same datatype as the
66
+ literal from ``expected``. If ``validate_style`` is ``True``, also check if
67
+ the style given by ``value`` is valid, according to ``rich``.
54
68
 
55
69
  Parameters
56
70
  ----------
57
71
  value
58
- The string of the value to check (obtained from reading the user input).
72
+ The string of the value to check, obtained from reading the user input.
59
73
  expected
60
- The string of the literal datatype must be matched by `value`. Obtained from
61
- reading the cfg file.
62
- style
63
- Whether or not to confirm if `value` is a style, by default False
74
+ The string of the literal datatype which must be matched by ``value``.
75
+ This is obtained from reading the ``cfg`` file.
76
+ validate_style
77
+ Whether or not to confirm if ``value`` is a valid style, according to
78
+ ``rich``. Default is ``False``.
64
79
 
65
80
  Returns
66
81
  -------
67
82
  :class:`bool`
68
- Whether or not `value` matches the datatype of `expected`.
83
+ Whether or not the literal from ``value`` matches the datatype of the
84
+ literal from ``expected``.
69
85
  """
70
- value = value_from_string(value)
71
- expected = type(value_from_string(expected))
86
+ value_literal = value_from_string(value)
87
+ ExpectedLiteralType = type(value_from_string(expected))
72
88
 
73
- return isinstance(value, expected) and (is_valid_style(value) if style else True)
89
+ return isinstance(value_literal, ExpectedLiteralType) and (
90
+ (isinstance(value_literal, str) and is_valid_style(value_literal))
91
+ if validate_style
92
+ else True
93
+ )
74
94
 
75
95
 
76
96
  def is_valid_style(style: str) -> bool:
77
- """Checks whether the entered color is a valid color according to rich
97
+ """Checks whether the entered color style is valid, according to ``rich``.
98
+
78
99
  Parameters
79
100
  ----------
80
101
  style
81
102
  The style to check whether it is valid.
103
+
82
104
  Returns
83
105
  -------
84
- Boolean
85
- Returns whether it is valid style or not according to rich.
106
+ :class:`bool`
107
+ Whether the color style is valid or not, according to ``rich``.
86
108
  """
87
109
  try:
88
110
  Style.parse(style)
@@ -91,16 +113,20 @@ def is_valid_style(style: str) -> bool:
91
113
  return False
92
114
 
93
115
 
94
- def replace_keys(default: dict) -> dict:
95
- """Replaces _ to . and vice versa in a dictionary for rich
116
+ def replace_keys(default: dict[str, Any]) -> dict[str, Any]:
117
+ """Replace ``_`` with ``.`` and vice versa in a dictionary's keys for
118
+ ``rich``.
119
+
96
120
  Parameters
97
121
  ----------
98
122
  default
99
- The dictionary to check and replace
123
+ The dictionary whose keys will be checked and replaced.
124
+
100
125
  Returns
101
126
  -------
102
127
  :class:`dict`
103
- The dictionary which is modified by replacing _ with . and vice versa
128
+ The dictionary whose keys are modified by replacing ``_`` with ``.``
129
+ and vice versa.
104
130
  """
105
131
  for key in default:
106
132
  if "_" in key:
@@ -123,22 +149,22 @@ def replace_keys(default: dict) -> dict:
123
149
  epilog=EPILOG,
124
150
  help="Manages Manim configuration files.",
125
151
  )
126
- @click.pass_context
127
- def cfg(ctx):
152
+ @cloup.pass_context
153
+ def cfg(ctx: cloup.Context) -> None:
128
154
  """Responsible for the cfg subcommand."""
129
155
  pass
130
156
 
131
157
 
132
158
  @cfg.command(context_settings=cli_ctx_settings, no_args_is_help=True)
133
- @click.option(
159
+ @cloup.option(
134
160
  "-l",
135
161
  "--level",
136
- type=click.Choice(["user", "cwd"], case_sensitive=False),
162
+ type=cloup.Choice(["user", "cwd"], case_sensitive=False),
137
163
  default="cwd",
138
164
  help="Specify if this config is for user or the working directory.",
139
165
  )
140
- @click.option("-o", "--open", "openfile", is_flag=True)
141
- def write(level: str = None, openfile: bool = False) -> None:
166
+ @cloup.option("-o", "--open", "openfile", is_flag=True)
167
+ def write(level: str | None = None, openfile: bool = False) -> None:
142
168
  config_paths = config_file_paths()
143
169
  console.print(
144
170
  "[yellow bold]Manim Configuration File Writer[/yellow bold]",
@@ -157,7 +183,7 @@ To save your config please save that file and place it in your current working d
157
183
  action = "save this as"
158
184
  for category in parser:
159
185
  console.print(f"{category}", style="bold green underline")
160
- default = parser[category]
186
+ default = cast(dict[str, Any], parser[category])
161
187
  if category == "logger":
162
188
  console.print(RICH_COLOUR_INSTRUCTIONS)
163
189
  default = replace_keys(default)
@@ -187,7 +213,7 @@ To save your config please save that file and place it in your current working d
187
213
  """Not enough values in input.
188
214
  You may have added a new entry to default.cfg, in which case you will have to
189
215
  modify write_cfg_subcmd_input to account for it.""",
190
- )
216
+ ) from None
191
217
  if temp:
192
218
  while temp and not _is_expected_datatype(
193
219
  temp,
@@ -240,7 +266,13 @@ modify write_cfg_subcmd_input to account for it.""",
240
266
 
241
267
 
242
268
  @cfg.command(context_settings=cli_ctx_settings)
243
- def show():
269
+ def show() -> None:
270
+ console.print("CONFIG FILES READ", style="bold green underline")
271
+ for path in config_file_paths():
272
+ if path.exists():
273
+ console.print(f"{path}")
274
+ console.print()
275
+
244
276
  parser = make_config_parser()
245
277
  rich_non_style_entries = [a.replace(".", "_") for a in RICH_NON_STYLE_ENTRIES]
246
278
  for category in parser:
@@ -258,9 +290,9 @@ def show():
258
290
 
259
291
 
260
292
  @cfg.command(context_settings=cli_ctx_settings)
261
- @click.option("-d", "--directory", default=Path.cwd())
262
- @click.pass_context
263
- def export(ctx, directory):
293
+ @cloup.option("-d", "--directory", default=Path.cwd())
294
+ @cloup.pass_context
295
+ def export(ctx: cloup.Context, directory: str) -> None:
264
296
  directory_path = Path(directory)
265
297
  if directory_path.absolute == Path.cwd().absolute:
266
298
  console.print(