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
@@ -46,21 +46,22 @@ These colors form Manim's default color space.
46
46
  for line, char in zip(color_groups[0], "abcde"):
47
47
  color_groups.add(Text(char).scale(0.6).next_to(line, LEFT, buff=0.2))
48
48
 
49
- def named_lines_group(length, colors, names, text_colors, align_to_block):
49
+ def named_lines_group(length, color_names, labels, align_to_block):
50
+ colors = [getattr(Colors, color.upper()) for color in color_names]
50
51
  lines = VGroup(
51
52
  *[
52
53
  Line(
53
54
  ORIGIN,
54
55
  RIGHT * length,
55
56
  stroke_width=55,
56
- color=getattr(Colors, color.upper()),
57
+ color=color,
57
58
  )
58
59
  for color in colors
59
60
  ]
60
61
  ).arrange_submobjects(buff=0.6, direction=DOWN)
61
62
 
62
- for line, name, color in zip(lines, names, text_colors):
63
- line.add(Text(name, color=color).scale(0.6).move_to(line))
63
+ for line, name, color in zip(lines, labels, colors):
64
+ line.add(Text(name, color=color.contrasting()).scale(0.6).move_to(line))
64
65
  lines.next_to(color_groups, DOWN, buff=0.5).align_to(
65
66
  color_groups[align_to_block], LEFT
66
67
  )
@@ -79,7 +80,6 @@ These colors form Manim's default color space.
79
80
  3.2,
80
81
  other_colors,
81
82
  other_colors,
82
- [BLACK] * 4 + [WHITE] * 2,
83
83
  0,
84
84
  )
85
85
 
@@ -95,7 +95,6 @@ These colors form Manim's default color space.
95
95
  "darker_gray / gray_e",
96
96
  "black",
97
97
  ],
98
- [BLACK] * 3 + [WHITE] * 4,
99
98
  2,
100
99
  )
101
100
 
@@ -109,7 +108,6 @@ These colors form Manim's default color space.
109
108
  3.2,
110
109
  pure_colors,
111
110
  pure_colors,
112
- [BLACK, BLACK, WHITE],
113
111
  6,
114
112
  )
115
113
 
@@ -121,7 +119,7 @@ These colors form Manim's default color space.
121
119
 
122
120
  """
123
121
 
124
- from typing import List
122
+ from __future__ import annotations
125
123
 
126
124
  from .core import ManimColor
127
125
 
@@ -215,6 +213,6 @@ LOGO_BLUE = ManimColor("#525893")
215
213
  LOGO_RED = ManimColor("#E07A5F")
216
214
  LOGO_BLACK = ManimColor("#343434")
217
215
 
218
- _all_manim_colors: List[ManimColor] = [
216
+ _all_manim_colors: list[ManimColor] = [
219
217
  x for x in globals().values() if isinstance(x, ManimColor)
220
218
  ]
manim/utils/commands.py CHANGED
@@ -1,10 +1,14 @@
1
1
  from __future__ import annotations
2
2
 
3
- import json
4
3
  import os
4
+ from collections.abc import Generator
5
5
  from pathlib import Path
6
6
  from subprocess import run
7
- from typing import Generator
7
+ from typing import TypedDict
8
+
9
+ import av
10
+
11
+ from manim.typing import StrOrBytesPath
8
12
 
9
13
  __all__ = [
10
14
  "capture",
@@ -13,7 +17,9 @@ __all__ = [
13
17
  ]
14
18
 
15
19
 
16
- def capture(command, cwd=None, command_input=None):
20
+ def capture(
21
+ command: str, cwd: StrOrBytesPath | None = None, command_input: str | None = None
22
+ ) -> tuple[str, str, int]:
17
23
  p = run(
18
24
  command,
19
25
  cwd=cwd,
@@ -26,22 +32,37 @@ def capture(command, cwd=None, command_input=None):
26
32
  return out, err, p.returncode
27
33
 
28
34
 
29
- def get_video_metadata(path_to_video: str | os.PathLike) -> dict[str]:
30
- command = [
31
- "ffprobe",
32
- "-v",
33
- "error",
34
- "-select_streams",
35
- "v:0",
36
- "-show_entries",
37
- "stream=width,height,nb_frames,duration,avg_frame_rate,codec_name",
38
- "-print_format",
39
- "json",
40
- str(path_to_video),
41
- ]
42
- config, err, exitcode = capture(command)
43
- assert exitcode == 0, f"FFprobe error: {err}"
44
- return json.loads(config)["streams"][0]
35
+ class VideoMetadata(TypedDict):
36
+ width: int
37
+ height: int
38
+ nb_frames: str
39
+ duration: str
40
+ avg_frame_rate: str
41
+ codec_name: str
42
+ pix_fmt: str
43
+
44
+
45
+ def get_video_metadata(path_to_video: str | os.PathLike) -> VideoMetadata:
46
+ with av.open(str(path_to_video)) as container:
47
+ stream = container.streams.video[0]
48
+ ctxt = stream.codec_context
49
+ rate = stream.average_rate
50
+ if stream.duration is not None:
51
+ duration = float(stream.duration * stream.time_base)
52
+ num_frames = stream.frames
53
+ else:
54
+ num_frames = sum(1 for _ in container.decode(video=0))
55
+ duration = float(num_frames / stream.base_rate)
56
+
57
+ return {
58
+ "width": ctxt.width,
59
+ "height": ctxt.height,
60
+ "nb_frames": str(num_frames),
61
+ "duration": f"{duration:.6f}",
62
+ "avg_frame_rate": f"{rate.numerator}/{rate.denominator}", # Can be a Fraction
63
+ "codec_name": stream.codec_context.name,
64
+ "pix_fmt": stream.codec_context.pix_fmt,
65
+ }
45
66
 
46
67
 
47
68
  def get_dir_layout(dirpath: Path) -> Generator[str, None, None]:
manim/utils/config_ops.py CHANGED
@@ -10,11 +10,12 @@ __all__ = [
10
10
 
11
11
 
12
12
  import itertools as it
13
+ from typing import Any
13
14
 
14
- import numpy as np
15
+ import numpy.typing as npt
15
16
 
16
17
 
17
- def merge_dicts_recursively(*dicts):
18
+ def merge_dicts_recursively(*dicts: dict[Any, Any]) -> dict[Any, Any]:
18
19
  """
19
20
  Creates a dict whose keyset is the union of all the
20
21
  input dictionaries. The value for each key is based
@@ -24,7 +25,7 @@ def merge_dicts_recursively(*dicts):
24
25
 
25
26
  When values are dictionaries, it is applied recursively
26
27
  """
27
- result = {}
28
+ result: dict = {}
28
29
  all_items = it.chain(*(d.items() for d in dicts))
29
30
  for key, value in all_items:
30
31
  if key in result and isinstance(result[key], dict) and isinstance(value, dict):
@@ -34,7 +35,9 @@ def merge_dicts_recursively(*dicts):
34
35
  return result
35
36
 
36
37
 
37
- def update_dict_recursively(current_dict, *others):
38
+ def update_dict_recursively(
39
+ current_dict: dict[Any, Any], *others: dict[Any, Any]
40
+ ) -> None:
38
41
  updated_dict = merge_dicts_recursively(current_dict, *others)
39
42
  current_dict.update(updated_dict)
40
43
 
@@ -44,7 +47,7 @@ def update_dict_recursively(current_dict, *others):
44
47
 
45
48
 
46
49
  class DictAsObject:
47
- def __init__(self, dictin):
50
+ def __init__(self, dictin: dict[str, Any]):
48
51
  self.__dict__ = dictin
49
52
 
50
53
 
@@ -53,13 +56,14 @@ class _Data:
53
56
  self.data attributes must be arrays.
54
57
  """
55
58
 
56
- def __set_name__(self, obj, name):
59
+ def __set_name__(self, obj: Any, name: str) -> None:
57
60
  self.name = name
58
61
 
59
- def __get__(self, obj, owner):
60
- return obj.data[self.name]
62
+ def __get__(self, obj: Any, owner: Any) -> npt.NDArray[Any]:
63
+ value: npt.NDArray[Any] = obj.data[self.name]
64
+ return value
61
65
 
62
- def __set__(self, obj, array: np.ndarray):
66
+ def __set__(self, obj: Any, array: npt.NDArray[Any]) -> None:
63
67
  obj.data[self.name] = array
64
68
 
65
69
 
@@ -68,11 +72,12 @@ class _Uniforms:
68
72
  self.uniforms attributes must be floats.
69
73
  """
70
74
 
71
- def __set_name__(self, obj, name):
75
+ def __set_name__(self, obj: Any, name: str) -> None:
72
76
  self.name = name
73
77
 
74
- def __get__(self, obj, owner):
75
- return obj.__dict__["uniforms"][self.name]
78
+ def __get__(self, obj: Any, owner: Any) -> float:
79
+ val: float = obj.__dict__["uniforms"][self.name]
80
+ return val
76
81
 
77
- def __set__(self, obj, num: float):
82
+ def __set__(self, obj: Any, num: float) -> None:
78
83
  obj.__dict__["uniforms"][self.name] = num
manim/utils/debug.py CHANGED
@@ -5,14 +5,17 @@ from __future__ import annotations
5
5
  __all__ = ["print_family", "index_labels"]
6
6
 
7
7
 
8
+ from typing import Any
9
+
8
10
  from manim.mobject.mobject import Mobject
9
11
  from manim.mobject.text.numbers import Integer
12
+ from manim.utils.color import ManimColor
10
13
 
11
14
  from ..mobject.types.vectorized_mobject import VGroup
12
15
  from .color import BLACK
13
16
 
14
17
 
15
- def print_family(mobject, n_tabs=0):
18
+ def print_family(mobject: Mobject, n_tabs: int = 0) -> None:
16
19
  """For debugging purposes"""
17
20
  print("\t" * n_tabs, mobject, id(mobject))
18
21
  for submob in mobject.submobjects:
@@ -22,10 +25,10 @@ def print_family(mobject, n_tabs=0):
22
25
  def index_labels(
23
26
  mobject: Mobject,
24
27
  label_height: float = 0.15,
25
- background_stroke_width=5,
26
- background_stroke_color=BLACK,
27
- **kwargs,
28
- ):
28
+ background_stroke_width: float = 5,
29
+ background_stroke_color: ManimColor = BLACK,
30
+ **kwargs: Any,
31
+ ) -> VGroup:
29
32
  r"""Returns a :class:`~.VGroup` of :class:`~.Integer` mobjects
30
33
  that shows the index of each submobject.
31
34
 
@@ -67,7 +70,6 @@ def index_labels(
67
70
 
68
71
  self.add(text, indices)
69
72
  """
70
-
71
73
  labels = VGroup()
72
74
  for n, submob in enumerate(mobject):
73
75
  label = Integer(n, **kwargs)
@@ -6,15 +6,17 @@ __all__ = ["deprecated", "deprecated_params"]
6
6
 
7
7
 
8
8
  import inspect
9
+ import logging
9
10
  import re
10
- from typing import Any, Callable, Iterable
11
+ from collections.abc import Iterable
12
+ from typing import Any, Callable, TypeVar, overload
11
13
 
12
14
  from decorator import decorate, decorator
13
15
 
14
- from .. import logger
16
+ logger = logging.getLogger("manim")
15
17
 
16
18
 
17
- def _get_callable_info(callable: Callable) -> tuple[str, str]:
19
+ def _get_callable_info(callable_: Callable[..., Any], /) -> tuple[str, str]:
18
20
  """Returns type and name of a callable.
19
21
 
20
22
  Parameters
@@ -28,8 +30,8 @@ def _get_callable_info(callable: Callable) -> tuple[str, str]:
28
30
  The type and name of the callable. Type can can be one of "class", "method" (for
29
31
  functions defined in classes) or "function"). For methods, name is Class.method.
30
32
  """
31
- what = type(callable).__name__
32
- name = callable.__qualname__
33
+ what = type(callable_).__name__
34
+ name = callable_.__qualname__
33
35
  if what == "function" and "." in name:
34
36
  what = "method"
35
37
  elif what != "function":
@@ -38,9 +40,9 @@ def _get_callable_info(callable: Callable) -> tuple[str, str]:
38
40
 
39
41
 
40
42
  def _deprecation_text_component(
41
- since: str | None,
42
- until: str | None,
43
- message: str,
43
+ since: str | None = None,
44
+ until: str | None = None,
45
+ message: str | None = None,
44
46
  ) -> str:
45
47
  """Generates a text component used in deprecation messages.
46
48
 
@@ -68,13 +70,37 @@ def _deprecation_text_component(
68
70
  return f"deprecated {since}and {until}.{msg}"
69
71
 
70
72
 
73
+ # TODO: Use ParamSpec to type decorated functions when Python 3.9 is out of life
74
+ T = TypeVar("T")
75
+
76
+
77
+ @overload
78
+ def deprecated(
79
+ func: Callable[..., T],
80
+ since: str | None = None,
81
+ until: str | None = None,
82
+ replacement: str | None = None,
83
+ message: str | None = "",
84
+ ) -> Callable[..., T]: ...
85
+
86
+
87
+ @overload
88
+ def deprecated(
89
+ func: None = None,
90
+ since: str | None = None,
91
+ until: str | None = None,
92
+ replacement: str | None = None,
93
+ message: str | None = "",
94
+ ) -> Callable[[Callable[..., T]], Callable[..., T]]: ...
95
+
96
+
71
97
  def deprecated(
72
- func: Callable = None,
98
+ func: Callable[..., T] | None = None,
73
99
  since: str | None = None,
74
100
  until: str | None = None,
75
101
  replacement: str | None = None,
76
102
  message: str | None = "",
77
- ) -> Callable:
103
+ ) -> Callable[..., T] | Callable[[Callable[..., T]], Callable[..., T]]:
78
104
  """Decorator to mark a callable as deprecated.
79
105
 
80
106
  The decorated callable will cause a warning when used. The docstring of the
@@ -104,10 +130,12 @@ def deprecated(
104
130
 
105
131
  from manim.utils.deprecation import deprecated
106
132
 
133
+
107
134
  @deprecated
108
135
  def foo(**kwargs):
109
136
  pass
110
137
 
138
+
111
139
  @deprecated
112
140
  class Bar:
113
141
  def __init__(self):
@@ -117,6 +145,7 @@ def deprecated(
117
145
  def baz(self):
118
146
  pass
119
147
 
148
+
120
149
  foo()
121
150
  # WARNING The function foo has been deprecated and may be removed in a later version.
122
151
 
@@ -130,15 +159,14 @@ def deprecated(
130
159
 
131
160
  from manim.utils.deprecation import deprecated
132
161
 
162
+
133
163
  @deprecated(
134
- since="v0.2",
135
- until="v0.4",
136
- replacement="bar",
137
- message="It is cooler."
164
+ since="v0.2", until="v0.4", replacement="bar", message="It is cooler."
138
165
  )
139
166
  def foo():
140
167
  pass
141
168
 
169
+
142
170
  foo()
143
171
  # WARNING The function foo has been deprecated since v0.2 and is expected to be removed after v0.4. Use bar instead. It is cooler.
144
172
 
@@ -146,10 +174,12 @@ def deprecated(
146
174
 
147
175
  from manim.utils.deprecation import deprecated
148
176
 
177
+
149
178
  @deprecated(since="05/01/2021", until="06/01/2021")
150
179
  def foo():
151
180
  pass
152
181
 
182
+
153
183
  foo()
154
184
  # WARNING The function foo has been deprecated since 05/01/2021 and is expected to be removed after 06/01/2021.
155
185
 
@@ -183,7 +213,7 @@ def deprecated(
183
213
  deprecated = _deprecation_text_component(since, until, msg)
184
214
  return f"The {what} {name} has been {deprecated}"
185
215
 
186
- def deprecate_docs(func: Callable):
216
+ def deprecate_docs(func: Callable) -> None:
187
217
  """Adjust docstring to indicate the deprecation.
188
218
 
189
219
  Parameters
@@ -195,7 +225,7 @@ def deprecated(
195
225
  doc_string = func.__doc__ or ""
196
226
  func.__doc__ = f"{doc_string}\n\n.. attention:: Deprecated\n {warning}"
197
227
 
198
- def deprecate(func: Callable, *args, **kwargs):
228
+ def deprecate(func: Callable[..., T], *args: Any, **kwargs: Any) -> T:
199
229
  """The actual decorator used to extend the callables behavior.
200
230
 
201
231
  Logs a warning message.
@@ -220,7 +250,10 @@ def deprecated(
220
250
 
221
251
  if type(func).__name__ != "function":
222
252
  deprecate_docs(func)
223
- func.__init__ = decorate(func.__init__, deprecate)
253
+ # The following line raises this mypy error:
254
+ # Accessing "__init__" on an instance is unsound, since instance.__init__
255
+ # could be from an incompatible subclass [misc]</pre>
256
+ func.__init__ = decorate(func.__init__, deprecate) # type: ignore[misc]
224
257
  return func
225
258
 
226
259
  func = decorate(func, deprecate)
@@ -232,11 +265,10 @@ def deprecated_params(
232
265
  params: str | Iterable[str] | None = None,
233
266
  since: str | None = None,
234
267
  until: str | None = None,
235
- message: str | None = "",
236
- redirections: None | (
237
- Iterable[tuple[str, str] | Callable[..., dict[str, Any]]]
238
- ) = None,
239
- ) -> Callable:
268
+ message: str = "",
269
+ redirections: None
270
+ | (Iterable[tuple[str, str] | Callable[..., dict[str, Any]]]) = None,
271
+ ) -> Callable[..., T]:
240
272
  """Decorator to mark parameters of a callable as deprecated.
241
273
 
242
274
  It can also be used to automatically redirect deprecated parameter values to their
@@ -286,10 +318,12 @@ def deprecated_params(
286
318
 
287
319
  from manim.utils.deprecation import deprecated_params
288
320
 
321
+
289
322
  @deprecated_params(params="a, b, c")
290
323
  def foo(**kwargs):
291
324
  pass
292
325
 
326
+
293
327
  foo(x=2, y=3, z=4)
294
328
  # No warning
295
329
 
@@ -300,15 +334,17 @@ def deprecated_params(
300
334
 
301
335
  from manim.utils.deprecation import deprecated_params
302
336
 
337
+
303
338
  @deprecated_params(
304
339
  params="a, b, c",
305
340
  since="v0.2",
306
341
  until="v0.4",
307
- message="The letters x, y, z are cooler."
342
+ message="The letters x, y, z are cooler.",
308
343
  )
309
344
  def foo(**kwargs):
310
345
  pass
311
346
 
347
+
312
348
  foo(a=2)
313
349
  # WARNING The parameter a of method foo has been deprecated since v0.2 and is expected to be removed after v0.4. The letters x, y, z are cooler.
314
350
 
@@ -316,14 +352,18 @@ def deprecated_params(
316
352
 
317
353
  from manim.utils.deprecation import deprecated_params
318
354
 
319
- @deprecated_params(redirections=[
320
- # Two ways to redirect one parameter to another:
321
- ("old_param", "new_param"),
322
- lambda old_param2: {"new_param22": old_param2}
323
- ])
355
+
356
+ @deprecated_params(
357
+ redirections=[
358
+ # Two ways to redirect one parameter to another:
359
+ ("old_param", "new_param"),
360
+ lambda old_param2: {"new_param22": old_param2},
361
+ ]
362
+ )
324
363
  def foo(**kwargs):
325
364
  return kwargs
326
365
 
366
+
327
367
  foo(x=1, old_param=2)
328
368
  # WARNING The parameter old_param of method foo has been deprecated and may be removed in a later version.
329
369
  # returns {"x": 1, "new_param": 2}
@@ -332,12 +372,14 @@ def deprecated_params(
332
372
 
333
373
  from manim.utils.deprecation import deprecated_params
334
374
 
335
- @deprecated_params(redirections=[
336
- lambda runtime_in_ms: {"run_time": runtime_in_ms / 1000}
337
- ])
375
+
376
+ @deprecated_params(
377
+ redirections=[lambda runtime_in_ms: {"run_time": runtime_in_ms / 1000}]
378
+ )
338
379
  def foo(**kwargs):
339
380
  return kwargs
340
381
 
382
+
341
383
  foo(runtime_in_ms=500)
342
384
  # WARNING The parameter runtime_in_ms of method foo has been deprecated and may be removed in a later version.
343
385
  # returns {"run_time": 0.5}
@@ -346,12 +388,14 @@ def deprecated_params(
346
388
 
347
389
  from manim.utils.deprecation import deprecated_params
348
390
 
349
- @deprecated_params(redirections=[
350
- lambda buff_x=1, buff_y=1: {"buff": (buff_x, buff_y)}
351
- ])
391
+
392
+ @deprecated_params(
393
+ redirections=[lambda buff_x=1, buff_y=1: {"buff": (buff_x, buff_y)}]
394
+ )
352
395
  def foo(**kwargs):
353
396
  return kwargs
354
397
 
398
+
355
399
  foo(buff_x=2)
356
400
  # WARNING The parameter buff_x of method foo has been deprecated and may be removed in a later version.
357
401
  # returns {"buff": (2, 1)}
@@ -360,18 +404,23 @@ def deprecated_params(
360
404
 
361
405
  from manim.utils.deprecation import deprecated_params
362
406
 
363
- @deprecated_params(redirections=[
364
- lambda buff=1: {"buff_x": buff[0], "buff_y": buff[1]} if isinstance(buff, tuple)
365
- else {"buff_x": buff, "buff_y": buff}
366
- ])
407
+
408
+ @deprecated_params(
409
+ redirections=[
410
+ lambda buff=1: {"buff_x": buff[0], "buff_y": buff[1]}
411
+ if isinstance(buff, tuple)
412
+ else {"buff_x": buff, "buff_y": buff}
413
+ ]
414
+ )
367
415
  def foo(**kwargs):
368
416
  return kwargs
369
417
 
418
+
370
419
  foo(buff=0)
371
420
  # WARNING The parameter buff of method foo has been deprecated and may be removed in a later version.
372
421
  # returns {"buff_x": 0, buff_y: 0}
373
422
 
374
- foo(buff=(1,2))
423
+ foo(buff=(1, 2))
375
424
  # WARNING The parameter buff of method foo has been deprecated and may be removed in a later version.
376
425
  # returns {"buff_x": 1, buff_y: 2}
377
426
 
@@ -406,7 +455,7 @@ def deprecated_params(
406
455
 
407
456
  redirections = list(redirections)
408
457
 
409
- def warning_msg(func: Callable, used: list[str]):
458
+ def warning_msg(func: Callable[..., T], used: list[str]) -> str:
410
459
  """Generate the deprecation warning message.
411
460
 
412
461
  Parameters
@@ -429,7 +478,7 @@ def deprecated_params(
429
478
  deprecated = _deprecation_text_component(since, until, message)
430
479
  return f"The parameter{parameter_s} {used_} of {what} {name} {has_have_been} {deprecated}"
431
480
 
432
- def redirect_params(kwargs: dict, used: list[str]):
481
+ def redirect_params(kwargs: dict[str, Any], used: list[str]) -> None:
433
482
  """Adjust the keyword arguments as defined by the redirections.
434
483
 
435
484
  Parameters
@@ -453,7 +502,7 @@ def deprecated_params(
453
502
  if len(redirector_args) > 0:
454
503
  kwargs.update(redirector(**redirector_args))
455
504
 
456
- def deprecate_params(func, *args, **kwargs):
505
+ def deprecate_params(func: Callable[..., T], *args: Any, **kwargs: Any) -> T:
457
506
  """The actual decorator function used to extend the callables behavior.
458
507
 
459
508
  Logs a warning message when a deprecated parameter is used and redirects it if
@@ -485,4 +534,4 @@ def deprecated_params(
485
534
  redirect_params(kwargs, used)
486
535
  return func(*args, **kwargs)
487
536
 
488
- return decorator(deprecate_params)
537
+ return decorator(deprecate_params) # type: ignore[return-value]