typed-ffmpeg-compatible 2.6.2__py3-none-any.whl → 2.6.4__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 (36) hide show
  1. typed_ffmpeg/__init__.py +26 -1
  2. typed_ffmpeg/base.py +87 -29
  3. typed_ffmpeg/common/schema.py +281 -3
  4. typed_ffmpeg/common/serialize.py +118 -21
  5. typed_ffmpeg/dag/__init__.py +13 -0
  6. typed_ffmpeg/dag/compile.py +39 -4
  7. typed_ffmpeg/dag/context.py +137 -29
  8. typed_ffmpeg/dag/factory.py +27 -0
  9. typed_ffmpeg/dag/global_runnable/global_args.py +11 -0
  10. typed_ffmpeg/dag/global_runnable/runnable.py +143 -34
  11. typed_ffmpeg/dag/io/_input.py +2 -1
  12. typed_ffmpeg/dag/io/_output.py +2 -1
  13. typed_ffmpeg/dag/nodes.py +402 -67
  14. typed_ffmpeg/dag/schema.py +3 -1
  15. typed_ffmpeg/dag/utils.py +29 -8
  16. typed_ffmpeg/dag/validate.py +83 -20
  17. typed_ffmpeg/exceptions.py +42 -9
  18. typed_ffmpeg/info.py +137 -16
  19. typed_ffmpeg/probe.py +31 -6
  20. typed_ffmpeg/schema.py +32 -5
  21. typed_ffmpeg/sources.py +2825 -0
  22. typed_ffmpeg/streams/channel_layout.py +13 -0
  23. typed_ffmpeg/utils/escaping.py +47 -7
  24. typed_ffmpeg/utils/forzendict.py +108 -0
  25. typed_ffmpeg/utils/lazy_eval/operator.py +43 -1
  26. typed_ffmpeg/utils/lazy_eval/schema.py +122 -6
  27. typed_ffmpeg/utils/run.py +44 -7
  28. typed_ffmpeg/utils/snapshot.py +36 -1
  29. typed_ffmpeg/utils/typing.py +29 -4
  30. typed_ffmpeg/utils/view.py +46 -4
  31. {typed_ffmpeg_compatible-2.6.2.dist-info → typed_ffmpeg_compatible-2.6.4.dist-info}/METADATA +1 -1
  32. typed_ffmpeg_compatible-2.6.4.dist-info/RECORD +48 -0
  33. typed_ffmpeg_compatible-2.6.2.dist-info/RECORD +0 -46
  34. {typed_ffmpeg_compatible-2.6.2.dist-info → typed_ffmpeg_compatible-2.6.4.dist-info}/LICENSE +0 -0
  35. {typed_ffmpeg_compatible-2.6.2.dist-info → typed_ffmpeg_compatible-2.6.4.dist-info}/WHEEL +0 -0
  36. {typed_ffmpeg_compatible-2.6.2.dist-info → typed_ffmpeg_compatible-2.6.4.dist-info}/entry_points.txt +0 -0
@@ -1,3 +1,16 @@
1
+ """
2
+ Audio channel layout definitions for FFmpeg.
3
+
4
+ This module defines a mapping between FFmpeg's channel layout names and
5
+ the corresponding number of audio channels. This information is used for
6
+ audio stream processing, filtering, and conversion operations.
7
+
8
+ Channel layouts in FFmpeg represent different speaker configurations,
9
+ such as mono (1 channel), stereo (2 channels), 5.1 (6 channels), etc.
10
+ The names used in this dictionary match the standard names used by FFmpeg's
11
+ channel layout API.
12
+ """
13
+
1
14
  CHANNEL_LAYOUT = {
2
15
  "mono": 1,
3
16
  "stereo": 2,
@@ -1,17 +1,39 @@
1
+ """
2
+ Utilities for escaping special characters in FFmpeg command arguments.
3
+
4
+ This module provides functions for properly escaping special characters in
5
+ FFmpeg command-line arguments and converting Python dictionaries to FFmpeg
6
+ command-line parameter formats.
7
+ """
8
+
1
9
  from collections.abc import Iterable
2
10
  from typing import Any
3
11
 
4
12
 
5
13
  def escape(text: str | int | float, chars: str = "\\'=:") -> str:
6
14
  """
7
- Helper function to escape uncomfortable characters.
15
+ Escape special characters in a string for use in FFmpeg commands.
16
+
17
+ This function adds backslash escaping to specified characters in a string,
18
+ making it safe to use in FFmpeg filter strings and command-line arguments
19
+ where certain characters have special meaning.
8
20
 
9
21
  Args:
10
- text: The text to escape.
11
- chars: The characters to escape.
22
+ text: The text to escape (will be converted to string if not already)
23
+ chars: A string containing all characters that should be escaped
24
+ (default: "\\'=:" which handles most common special chars in FFmpeg)
12
25
 
13
26
  Returns:
14
- The escaped text.
27
+ The input text with all specified characters escaped with backslashes
28
+
29
+ Example:
30
+ ```python
31
+ # Escape a filename with spaces for FFmpeg
32
+ safe_filename = escape("input file.mp4") # "input\\ file.mp4"
33
+
34
+ # Escape a filter parameter value
35
+ safe_value = escape("key=value", "=:") # "key\\=value"
36
+ ```
15
37
  """
16
38
  text = str(text)
17
39
  _chars = list(set(chars))
@@ -27,13 +49,31 @@ def escape(text: str | int | float, chars: str = "\\'=:") -> str:
27
49
 
28
50
  def convert_kwargs_to_cmd_line_args(kwargs: dict[str, Any]) -> list[str]:
29
51
  """
30
- Helper function to build command line arguments out of dict.
52
+ Convert a Python dictionary to FFmpeg command-line arguments.
53
+
54
+ This function takes a dictionary of parameter names and values and converts
55
+ them to a list of strings in the format expected by FFmpeg command-line tools.
56
+ Each key becomes a parameter prefixed with '-', and its value follows as a
57
+ separate argument.
31
58
 
32
59
  Args:
33
- kwargs: The dict to convert.
60
+ kwargs: Dictionary mapping parameter names to their values
34
61
 
35
62
  Returns:
36
- The command line arguments.
63
+ A list of strings representing FFmpeg command-line arguments
64
+
65
+ Example:
66
+ ```python
67
+ args = convert_kwargs_to_cmd_line_args(
68
+ {"c:v": "libx264", "crf": 23, "preset": "medium"}
69
+ )
70
+ # Returns ['-c:v', 'libx264', '-crf', '23', '-preset', 'medium']
71
+ ```
72
+
73
+ Note:
74
+ If a value is None, only the parameter name is included.
75
+ If a value is an iterable (but not a string), the parameter is repeated
76
+ for each value in the iterable.
37
77
  """
38
78
  args = []
39
79
  for k in sorted(kwargs.keys()):
@@ -0,0 +1,108 @@
1
+ """
2
+ Provides an immutable dictionary implementation.
3
+
4
+ This module implements a frozen (immutable) dictionary class that can be used
5
+ where hashable dictionaries are needed, such as in sets or as keys in other
6
+ dictionaries. Once created, a FrozenDict cannot be modified.
7
+ """
8
+
9
+ from collections.abc import Iterator, Mapping
10
+ from typing import Any, Generic, TypeVar
11
+
12
+ K = TypeVar("K")
13
+ V = TypeVar("V")
14
+
15
+
16
+ class FrozenDict(Mapping[K, V], Generic[K, V]):
17
+ """
18
+ An immutable dictionary implementation.
19
+
20
+ FrozenDict provides a hashable, immutable view of a dictionary. It implements
21
+ the Mapping interface but does not allow modification after creation.
22
+ This makes it suitable for use as dictionary keys or in sets where
23
+ mutability would cause issues.
24
+ """
25
+
26
+ def __init__(self, data: dict[K, V]):
27
+ """
28
+ Initialize a FrozenDict with the provided dictionary data.
29
+
30
+ Args:
31
+ data: Dictionary to create a frozen copy of
32
+ """
33
+ self._data = dict(data)
34
+ self._hash: int | None = None # lazy computed
35
+
36
+ def __getitem__(self, key: K) -> V:
37
+ """
38
+ Retrieve a value from the dictionary by key.
39
+
40
+ Args:
41
+ key: The key to look up
42
+
43
+ Returns:
44
+ The value associated with the key
45
+
46
+ Raises:
47
+ KeyError: If the key is not found
48
+ """
49
+ return self._data[key]
50
+
51
+ def __iter__(self) -> Iterator[K]:
52
+ """
53
+ Return an iterator over the dictionary keys.
54
+
55
+ Returns:
56
+ An iterator yielding the dictionary keys
57
+ """
58
+ return iter(self._data)
59
+
60
+ def __len__(self) -> int:
61
+ """
62
+ Return the number of items in the dictionary.
63
+
64
+ Returns:
65
+ The number of key-value pairs in the dictionary
66
+ """
67
+ return len(self._data)
68
+
69
+ def __repr__(self) -> str:
70
+ """
71
+ Return a string representation of the FrozenDict.
72
+
73
+ Returns:
74
+ A string representation showing the dictionary contents
75
+ """
76
+ return f"FrozenDict({self._data})"
77
+
78
+ def __eq__(self, other: Any) -> bool:
79
+ """
80
+ Compare this FrozenDict with another object for equality.
81
+
82
+ Two FrozenDicts are equal if they contain the same key-value pairs.
83
+ A FrozenDict can also be equal to other Mapping objects with the same contents.
84
+
85
+ Args:
86
+ other: Object to compare with
87
+
88
+ Returns:
89
+ True if the objects are equal, False otherwise
90
+ """
91
+ if isinstance(other, Mapping):
92
+ return dict(self._data) == dict(other)
93
+ return NotImplemented
94
+
95
+ def __hash__(self) -> int:
96
+ """
97
+ Compute a hash value for this FrozenDict.
98
+
99
+ The hash is lazily computed the first time it's needed and then cached.
100
+ This makes FrozenDict usable as a dictionary key or in sets.
101
+
102
+ Returns:
103
+ An integer hash value
104
+ """
105
+ if self._hash is None:
106
+ # Create a stable hash based on sorted key-value pairs
107
+ self._hash = hash(frozenset(self._data.items()))
108
+ return self._hash
@@ -1,3 +1,12 @@
1
+ """
2
+ Concrete operator implementations for lazy evaluation expressions.
3
+
4
+ This module defines the specific operator classes that implement the LazyOperator
5
+ abstract base class. Each class represents a mathematical operation like addition,
6
+ subtraction, multiplication, etc., and provides the implementation for evaluating
7
+ that operation when all required values are available.
8
+ """
9
+
1
10
  from dataclasses import dataclass
2
11
  from typing import Any
3
12
 
@@ -7,13 +16,46 @@ from .schema import LazyOperator
7
16
  @dataclass(frozen=True, kw_only=True)
8
17
  class Add(LazyOperator):
9
18
  """
10
- A lazy operator for addition.
19
+ A lazy operator for addition operations.
20
+
21
+ This class implements the addition operation for lazy evaluation expressions.
22
+ It evaluates to the sum of its left and right operands when all required
23
+ values are available.
24
+
25
+ Example:
26
+ ```python
27
+ # Create an expression that adds width and height
28
+ from .schema import Symbol
29
+
30
+ width = Symbol("width")
31
+ height = Symbol("height")
32
+ expr = Add(left=width, right=height)
33
+
34
+ # Evaluate the expression with specific values
35
+ result = expr.eval(width=1280, height=720) # Returns 2000
36
+ ```
11
37
  """
12
38
 
13
39
  def _eval(self, left: Any, right: Any) -> Any:
40
+ """
41
+ Evaluate the addition operation with the given operands.
42
+
43
+ Args:
44
+ left: The left operand
45
+ right: The right operand
46
+
47
+ Returns:
48
+ The sum of the left and right operands
49
+ """
14
50
  return left + right
15
51
 
16
52
  def __str__(self) -> str:
53
+ """
54
+ Get a string representation of this addition operation.
55
+
56
+ Returns:
57
+ A string in the format "(left+right)"
58
+ """
17
59
  return f"({self.left}+{self.right})"
18
60
 
19
61
 
@@ -1,3 +1,13 @@
1
+ """
2
+ Schema for lazy evaluation of expressions in FFmpeg filter parameters.
3
+
4
+ This module defines the core classes for lazy evaluation of expressions in
5
+ FFmpeg filter parameters. It provides a way to represent expressions that
6
+ can be evaluated at a later time, when all required values are available.
7
+ This is particularly useful for parameters that depend on runtime information
8
+ or need to be computed based on other parameters.
9
+ """
10
+
1
11
  from __future__ import annotations
2
12
 
3
13
  from abc import ABC, abstractmethod
@@ -9,7 +19,15 @@ from ..typing import override
9
19
 
10
20
  class LazyValue(ABC):
11
21
  """
12
- A base class for lazy evaluation.
22
+ Abstract base class for lazy evaluation of expressions.
23
+
24
+ LazyValue represents an expression that can be evaluated at a later time,
25
+ when all required values are available. It supports various arithmetic
26
+ operations, allowing complex expressions to be built and evaluated lazily.
27
+
28
+ This class serves as the foundation for the lazy evaluation system, with
29
+ concrete implementations like Symbol and LazyOperator providing specific
30
+ functionality.
13
31
  """
14
32
 
15
33
  def __add__(self, v: Any) -> LazyValue:
@@ -132,6 +150,14 @@ class LazyValue(ABC):
132
150
  def ready(self) -> bool:
133
151
  """
134
152
  Check if the lazy value is ready to be evaluated.
153
+
154
+ A lazy value is considered ready for evaluation when it doesn't require
155
+ any additional values to be provided. This is determined by checking if
156
+ the set of required keys is empty.
157
+
158
+ Returns:
159
+ True if the lazy value can be evaluated without additional values,
160
+ False otherwise
135
161
  """
136
162
  return not self.keys()
137
163
 
@@ -139,6 +165,14 @@ class LazyValue(ABC):
139
165
  def keys(self) -> set[str]:
140
166
  """
141
167
  Get the keys that are required to evaluate the lazy value.
168
+
169
+ This method returns the set of symbol names that must be provided
170
+ as values for the lazy value to be fully evaluated. For example,
171
+ if the lazy value represents the expression 'width * height',
172
+ this method would return {'width', 'height'}.
173
+
174
+ Returns:
175
+ A set of strings representing the required symbol names
142
176
  """
143
177
  ...
144
178
 
@@ -146,33 +180,80 @@ class LazyValue(ABC):
146
180
  @dataclass(frozen=True)
147
181
  class Symbol(LazyValue):
148
182
  """
149
- A symbol that represents a variable in the lazy evaluation.
183
+ A symbol that represents a variable in lazy evaluation expressions.
184
+
185
+ Symbol is a concrete implementation of LazyValue that represents a named
186
+ variable in an expression. When evaluating the expression, the actual value
187
+ of the symbol is provided through a dictionary of values.
188
+
189
+ Examples of symbols include variable names like 'width', 'height', or any
190
+ other parameter that will be provided at evaluation time rather than at
191
+ expression creation time.
150
192
 
151
- Such as `x`, `y`, `z`, etc.
193
+ Attributes:
194
+ key: The name of the variable this symbol represents
152
195
  """
153
196
 
154
197
  key: str
155
198
 
156
199
  def __str__(self) -> str:
200
+ """
201
+ Get a string representation of this symbol.
202
+
203
+ Returns:
204
+ The symbol's key as a string
205
+ """
157
206
  return str(self.key)
158
207
 
159
208
  @override
160
209
  def partial(self, **values: Any) -> Any:
210
+ """
211
+ Partially evaluate this symbol with the given values.
212
+
213
+ If the symbol's key is present in the values dictionary, returns the
214
+ corresponding value. Otherwise, returns the symbol itself (unchanged).
215
+
216
+ Args:
217
+ **values: Dictionary mapping symbol names to their values
218
+
219
+ Returns:
220
+ The value for this symbol if available, otherwise the symbol itself
221
+ """
161
222
  if self.key in values:
162
223
  return values[self.key]
163
224
  return self
164
225
 
165
226
  @override
166
227
  def keys(self) -> set[str]:
228
+ """
229
+ Get the set of symbol names required to evaluate this symbol.
230
+
231
+ For a Symbol, this is simply a set containing its own key.
232
+
233
+ Returns:
234
+ A set containing the symbol's key
235
+ """
167
236
  return {self.key}
168
237
 
169
238
 
170
239
  @dataclass(frozen=True, kw_only=True)
171
240
  class LazyOperator(LazyValue):
172
241
  """
173
- A base class for lazy operators.
242
+ Abstract base class for operators in lazy evaluation expressions.
243
+
244
+ LazyOperator is an abstract implementation of LazyValue that represents
245
+ mathematical operations in an expression. Concrete subclasses implement
246
+ specific operations like addition, subtraction, multiplication, etc.
247
+
248
+ This class provides the common structure and behavior for all operators,
249
+ including handling of operands that may themselves be LazyValues.
174
250
 
175
- Such as `Add`, `Sub`, `Mul`, `TrueDiv`, `Pow`, `Neg`, `Pos`, `Abs`, `Mod`, `FloorDiv`.
251
+ Attributes:
252
+ left: The left operand of the operation (or the only operand for unary operations)
253
+ right: The right operand of the operation (None for unary operations)
254
+
255
+ Concrete implementations include:
256
+ Add, Sub, Mul, TrueDiv, Pow, Neg, Pos, Abs, Mod, FloorDiv
176
257
  """
177
258
 
178
259
  left: Any = None
@@ -181,12 +262,37 @@ class LazyOperator(LazyValue):
181
262
  @abstractmethod
182
263
  def _eval(self, left: Any, right: Any) -> Any:
183
264
  """
184
- Evaluate the operator with the given values.
265
+ Evaluate the operator with the given operand values.
266
+
267
+ This abstract method must be implemented by concrete operator subclasses
268
+ to define the specific operation to perform (e.g., addition, multiplication).
269
+
270
+ Args:
271
+ left: The evaluated left operand (or only operand for unary operations)
272
+ right: The evaluated right operand (may be None for unary operations)
273
+
274
+ Returns:
275
+ The result of applying the operation to the operands
185
276
  """
186
277
  ...
187
278
 
188
279
  @override
189
280
  def partial(self, **values: Any) -> Any:
281
+ """
282
+ Partially evaluate this operator with the given values.
283
+
284
+ This method recursively evaluates the operands (which may themselves be
285
+ LazyValues) with the provided values, then applies the operator's
286
+ specific operation to the results.
287
+
288
+ Args:
289
+ **values: Dictionary mapping symbol names to their values
290
+
291
+ Returns:
292
+ The result of applying the operation to the partially evaluated operands,
293
+ which may be a concrete value or another LazyValue if some symbols
294
+ remain unevaluated
295
+ """
190
296
  if isinstance(self.left, LazyValue):
191
297
  left = self.left.partial(**values)
192
298
  else:
@@ -201,6 +307,16 @@ class LazyOperator(LazyValue):
201
307
 
202
308
  @override
203
309
  def keys(self) -> set[str]:
310
+ """
311
+ Get the set of symbol names required to evaluate this operator.
312
+
313
+ This method collects the required symbol names from both operands
314
+ (if they are LazyValues) and returns their union.
315
+
316
+ Returns:
317
+ A set of strings representing all symbol names required to
318
+ fully evaluate this operator
319
+ """
204
320
  r = set()
205
321
  if isinstance(self.left, LazyValue):
206
322
  r |= self.left.keys()
typed_ffmpeg/utils/run.py CHANGED
@@ -1,27 +1,64 @@
1
+ """
2
+ Utilities for executing FFmpeg commands and handling command arguments.
3
+
4
+ This module provides helper functions for formatting command-line arguments,
5
+ filtering default values, and preparing options for command execution.
6
+ """
7
+
1
8
  import shlex
9
+ from collections.abc import Mapping
2
10
 
3
11
  from ..schema import Default
4
12
  from ..utils.lazy_eval.schema import LazyValue
13
+ from .forzendict import FrozenDict
5
14
 
6
15
 
7
16
  def command_line(args: list[str]) -> str:
8
17
  """
9
- Get the command line representation of the arguments.
18
+ Convert a list of command arguments to a properly escaped command-line string.
19
+
20
+ This function takes a list of command arguments and converts it to a single
21
+ string with proper shell escaping applied to each argument. This is useful
22
+ for logging commands or displaying them to users.
10
23
 
11
24
  Args:
12
- args: The arguments to convert.
25
+ args: The command arguments to convert to a string
13
26
 
14
27
  Returns:
15
- The command line representation of the arguments.
28
+ A properly escaped command-line string representation of the arguments
29
+
30
+ Example:
31
+ ```python
32
+ cmd = ["ffmpeg", "-i", "input file.mp4", "-c:v", "libx264"]
33
+ print(command_line(cmd)) # 'ffmpeg -i "input file.mp4" -c:v libx264'
34
+ ```
16
35
  """
17
36
  return " ".join(shlex.quote(arg) for arg in args)
18
37
 
19
38
 
20
39
  # Filter_Node_Option_Type
21
40
  def ignore_default(
22
- kwargs: dict[str, str | int | float | bool | Default],
23
- ) -> tuple[tuple[str, str | int | float | bool | LazyValue], ...]:
41
+ kwargs: Mapping[str, str | int | float | bool | Default],
42
+ ) -> FrozenDict[str, str | int | float | bool | LazyValue]:
24
43
  """
25
- Convert the values of the dictionary to strings.
44
+ Filter out Default values from a dictionary of options.
45
+
46
+ This function is used to process FFmpeg filter options and command arguments,
47
+ removing any values that are instances of the Default class. This ensures
48
+ that only explicitly set options are passed to FFmpeg, allowing default values
49
+ to be applied by FFmpeg itself.
50
+
51
+ Args:
52
+ kwargs: A mapping containing parameter names and values,
53
+ which may include Default instances
54
+
55
+ Returns:
56
+ An immutable FrozenDict containing only non-Default values
57
+
58
+ Example:
59
+ ```python
60
+ options = {"width": 1920, "height": 1080, "format": Default("yuv420p")}
61
+ filtered = ignore_default(options) # {"width": 1920, "height": 1080}
62
+ ```
26
63
  """
27
- return tuple((k, v) for k, v in kwargs.items() if not isinstance(v, Default))
64
+ return FrozenDict({k: v for k, v in kwargs.items() if not isinstance(v, Default)})
@@ -1,3 +1,12 @@
1
+ """
2
+ Snapshot testing utilities for FFmpeg DAG structures.
3
+
4
+ This module provides extensions for the syrupy snapshot testing library that
5
+ enable serialization and testing of FFmpeg's Directed Acyclic Graph (DAG)
6
+ structures. It helps in writing tests that verify the correct structure and
7
+ behavior of filter graphs.
8
+ """
9
+
1
10
  from dataclasses import asdict
2
11
  from typing import Optional
3
12
 
@@ -14,7 +23,16 @@ from ..dag.schema import Stream
14
23
 
15
24
  class DAGSnapshotExtenstion(JSONSnapshotExtension):
16
25
  """
17
- A snapshot extension for the DAG. This extension is used to serialize and match the DAG.
26
+ A snapshot extension for serializing and testing FFmpeg DAG structures.
27
+
28
+ This extension extends the JSON snapshot extension from syrupy to handle
29
+ the special case of FFmpeg DAG nodes. It converts DAG nodes into a serializable
30
+ form suitable for snapshot testing by wrapping them in a Stream object and
31
+ converting to a dictionary.
32
+
33
+ This allows for robust testing of filter graph structures and ensures that
34
+ changes to the graph structure are intentional and documented through
35
+ snapshot testing.
18
36
  """
19
37
 
20
38
  def serialize(
@@ -25,6 +43,23 @@ class DAGSnapshotExtenstion(JSONSnapshotExtension):
25
43
  include: Optional["PropertyFilter"] = None,
26
44
  matcher: Optional["PropertyMatcher"] = None,
27
45
  ) -> "SerializedData":
46
+ """
47
+ Serialize a DAG node for snapshot testing.
48
+
49
+ This method converts a DAG node into a serializable format by wrapping
50
+ it in a Stream object and then converting that to a dictionary. This
51
+ approach ensures that all relevant properties of the node are captured
52
+ in the snapshot.
53
+
54
+ Args:
55
+ data: The DAG node to serialize
56
+ exclude: Optional filter specifying properties to exclude
57
+ include: Optional filter specifying properties to include
58
+ matcher: Optional property matcher
59
+
60
+ Returns:
61
+ The serialized representation of the DAG node
62
+ """
28
63
  stream = Stream(node=data)
29
64
 
30
65
  return super().serialize(asdict(stream))
@@ -1,3 +1,11 @@
1
+ """
2
+ Typing utilities for enhanced type annotations.
3
+
4
+ This module provides utilities for improving type annotations and enforcing
5
+ typing conventions within the codebase, offering better support for type checking
6
+ and documentation.
7
+ """
8
+
1
9
  from typing import TypeVar
2
10
 
3
11
  V = TypeVar("V")
@@ -5,13 +13,30 @@ V = TypeVar("V")
5
13
 
6
14
  def override(func: V) -> V:
7
15
  """
8
- Decorator to indicate overriding a method.
9
- the true override method is implemented until in python 3.12
16
+ Decorator to indicate a method that overrides a method in a superclass.
17
+
18
+ This decorator serves as a placeholder until Python 3.12, which introduces
19
+ a built-in @override decorator. Using this decorator helps with code clarity
20
+ and can catch errors where a method intended to override a parent class method
21
+ doesn't actually override anything (e.g., due to a typo in the method name).
10
22
 
11
23
  Args:
12
- func: The function to decorate.
24
+ func: The function to mark as an override of a superclass method
13
25
 
14
26
  Returns:
15
- The decorated function.
27
+ The original function, unchanged (the decorator is used only for documentation)
28
+
29
+ Example:
30
+ ```python
31
+ class Parent:
32
+ def method(self):
33
+ pass
34
+
35
+
36
+ class Child(Parent):
37
+ @override
38
+ def method(self): # Correctly overrides Parent.method
39
+ pass
40
+ ```
16
41
  """
17
42
  return func