Package devstatusdecos
devstatusdecos
Decorators, warnings, and exceptions related to documentation of the development statuses of classes, functions, and other objects.
Sub-modules
devstatusdecos.devstatusdecos-
devstatusdecos …
devstatusdecos.tests-
init …
Classes
class ExperimentalWarning (*args, **kwargs)-
Expand source code
class ExperimentalWarning(Warning): """A warning used to indicate that a function or class is experimental and may change at any time."""A warning used to indicate that a function or class is experimental and may change at any time.
Ancestors
- builtins.Warning
- builtins.Exception
- builtins.BaseException
Subclasses
class FatallyInsecureError (*args: object, code: int = 1)-
Expand source code
class FatallyInsecureError(InsecureError, SystemExit): """ An extention of `InsecureError`, raised in conditions where a function or class should raise an error that attempts to force termination of execution via an exception. """ def __init__(self, *args: object, code:int = 1) -> None: super(InsecureError, self).__init__(*args) self.code = codeAn extention of
InsecureError, raised in conditions where a function or class should raise an error that attempts to force termination of execution via an exception.Ancestors
- InsecureError
- builtins.RuntimeError
- builtins.Exception
- builtins.SystemExit
- builtins.BaseException
class InsecureError (*args, **kwargs)-
Expand source code
class InsecureError(RuntimeError): """ An exception raised when a `insecure` Callable is executed. This is a subclass of `RuntimeError` and is used to indicate that a function or class is in some way insecure and should not be allowed to execute further. This exception is used mainly by the `insecure` decorator. """An exception raised when a
insecureCallable is executed.This is a subclass of
RuntimeErrorand is used to indicate that a function or class is in some way insecure and should not be allowed to execute further. This exception is used mainly by theinsecuredecorator.Ancestors
- builtins.RuntimeError
- builtins.Exception
- builtins.BaseException
Subclasses
class TodoError (*args, **kwargs)-
Expand source code
class TodoError(NotImplementedError): """ An exception raised when a `todo` Callable is executed. This is a subclass of `NotImplementedError` and is used to indicate that a function or class contains a todo and is likely missing a key part of its functionality. This exception is used mainly by the `todo` decorator. """An exception raised when a
todoCallable is executed.This is a subclass of
NotImplementedErrorand is used to indicate that a function or class contains a todo and is likely missing a key part of its functionality. This exception is used mainly by thetododecorator.Ancestors
- builtins.NotImplementedError
- builtins.RuntimeError
- builtins.Exception
- builtins.BaseException
class TodoWarning (*args, **kwargs)-
Expand source code
class TodoWarning(ExperimentalWarning): """A warning used to indicate that a function or class contains something todo and likely is missing a key part of its functionality and may change at any time or even be removed. This will also always be raised as a error when a `todo` `Callable` is called."""A warning used to indicate that a function or class contains something todo and likely is missing a key part of its functionality and may change at any time or even be removed. This will also always be raised as a error when a
todoCallableis called.Ancestors
- ExperimentalWarning
- builtins.Warning
- builtins.Exception
- builtins.BaseException
class deprecated (message: str,
/,
*,
category: Type[Warning] | None = builtins.DeprecationWarning,
stacklevel: int = 1)-
Expand source code
class deprecated: """Indicate that a class, function or overload is deprecated. When this decorator is applied to an object, the type checker will generate a diagnostic on usage of the deprecated object. Usage: @deprecated("Use B instead") class A: pass @deprecated("Use g instead") def f(): pass @overload @deprecated("int support is deprecated") def g(x: int) -> int: ... @overload def g(x: str) -> int: ... The warning specified by *category* will be emitted at runtime on use of deprecated objects. For functions, that happens on calls; for classes, on instantiation and on creation of subclasses. If the *category* is ``None``, no warning is emitted at runtime. The *stacklevel* determines where the warning is emitted. If it is ``1`` (the default), the warning is emitted at the direct caller of the deprecated object; if it is higher, it is emitted further up the stack. Static type checker behavior is not affected by the *category* and *stacklevel* arguments. The deprecation message passed to the decorator is saved in the ``__deprecated__`` attribute on the decorated object. If applied to an overload, the decorator must be after the ``@overload`` decorator for the attribute to exist on the overload as returned by ``get_overloads()``. See PEP 702 for details. """ def __init__( self, message: str, /, *, category: typing.Optional[typing.Type[Warning]] = DeprecationWarning, stacklevel: int = 1, ) -> None: if not isinstance(message, str): raise TypeError( "Expected an object of type str for 'message', not " f"{type(message).__name__!r}" ) self.message = message self.category = category self.stacklevel = stacklevel def __call__(self, arg: _T, /) -> _T: # Make sure the inner functions created below don't # retain a reference to self. msg = self.message category = self.category stacklevel = self.stacklevel if category is None: arg.__deprecated__ = msg return arg elif isinstance(arg, type): import functools from types import MethodType original_new = arg.__new__ @functools.wraps(original_new) def __new__(cls, /, *args, **kwargs): if cls is arg: warnings.warn(msg, category=category, stacklevel=stacklevel + 1) if original_new is not object.__new__: return original_new(cls, *args, **kwargs) # Mirrors a similar check in object.__new__. elif cls.__init__ is object.__init__ and (args or kwargs): raise TypeError(f"{cls.__name__}() takes no arguments") else: return original_new(cls) arg.__new__ = staticmethod(__new__) original_init_subclass = arg.__init_subclass__ # We need slightly different behavior if __init_subclass__ # is a bound method (likely if it was implemented in Python) if isinstance(original_init_subclass, MethodType): original_init_subclass = original_init_subclass.__func__ @functools.wraps(original_init_subclass) def __init_subclass__(*args, **kwargs): warnings.warn(msg, category=category, stacklevel=stacklevel + 1) return original_init_subclass(*args, **kwargs) arg.__init_subclass__ = classmethod(__init_subclass__) # Or otherwise, which likely means it's a builtin such as # object's implementation of __init_subclass__. else: @functools.wraps(original_init_subclass) def __init_subclass__(*args, **kwargs): warnings.warn(msg, category=category, stacklevel=stacklevel + 1) return original_init_subclass(*args, **kwargs) arg.__init_subclass__ = __init_subclass__ arg.__deprecated__ = __new__.__deprecated__ = msg __init_subclass__.__deprecated__ = msg return arg elif callable(arg): import asyncio.coroutines import functools import inspect @functools.wraps(arg) def wrapper(*args, **kwargs): warnings.warn(msg, category=category, stacklevel=stacklevel + 1) return arg(*args, **kwargs) if asyncio.coroutines.iscoroutinefunction(arg): # Breakpoint: https://github.com/python/cpython/pull/99247 if sys.version_info >= (3, 12): wrapper = inspect.markcoroutinefunction(wrapper) else: wrapper._is_coroutine = asyncio.coroutines._is_coroutine arg.__deprecated__ = wrapper.__deprecated__ = msg return wrapper else: raise TypeError( "@deprecated decorator with non-None category must be applied to " f"a class or callable, not {arg!r}" )Indicate that a class, function or overload is deprecated.
When this decorator is applied to an object, the type checker will generate a diagnostic on usage of the deprecated object.
Usage
@deprecated("Use B instead") class A: pass
@deprecated("Use g instead") def f(): pass
@overload @deprecated("int support is deprecated") def g(x: int) -> int: … @overload def g(x: str) -> int: …
The warning specified by category will be emitted at runtime on use of deprecated objects. For functions, that happens on calls; for classes, on instantiation and on creation of subclasses. If the category is
None, no warning is emitted at runtime. The stacklevel determines where the warning is emitted. If it is1(the default), the warning is emitted at the direct caller of the deprecated object; if it is higher, it is emitted further up the stack. Static type checker behavior is not affected by the category and stacklevel arguments.The deprecation message passed to the decorator is saved in the
__deprecated__attribute on the decorated object. If applied to an overload, the decorator must be after the@overloaddecorator for the attribute to exist on the overload as returned byget_overloads().See PEP 702 for details.
Subclasses
class superseded (message: str,
/,
*,
category: Type[Warning] | None = builtins.DeprecationWarning,
stacklevel: int = 1)-
Expand source code
class deprecated: """Indicate that a class, function or overload is deprecated. When this decorator is applied to an object, the type checker will generate a diagnostic on usage of the deprecated object. Usage: @deprecated("Use B instead") class A: pass @deprecated("Use g instead") def f(): pass @overload @deprecated("int support is deprecated") def g(x: int) -> int: ... @overload def g(x: str) -> int: ... The warning specified by *category* will be emitted at runtime on use of deprecated objects. For functions, that happens on calls; for classes, on instantiation and on creation of subclasses. If the *category* is ``None``, no warning is emitted at runtime. The *stacklevel* determines where the warning is emitted. If it is ``1`` (the default), the warning is emitted at the direct caller of the deprecated object; if it is higher, it is emitted further up the stack. Static type checker behavior is not affected by the *category* and *stacklevel* arguments. The deprecation message passed to the decorator is saved in the ``__deprecated__`` attribute on the decorated object. If applied to an overload, the decorator must be after the ``@overload`` decorator for the attribute to exist on the overload as returned by ``get_overloads()``. See PEP 702 for details. """ def __init__( self, message: str, /, *, category: typing.Optional[typing.Type[Warning]] = DeprecationWarning, stacklevel: int = 1, ) -> None: if not isinstance(message, str): raise TypeError( "Expected an object of type str for 'message', not " f"{type(message).__name__!r}" ) self.message = message self.category = category self.stacklevel = stacklevel def __call__(self, arg: _T, /) -> _T: # Make sure the inner functions created below don't # retain a reference to self. msg = self.message category = self.category stacklevel = self.stacklevel if category is None: arg.__deprecated__ = msg return arg elif isinstance(arg, type): import functools from types import MethodType original_new = arg.__new__ @functools.wraps(original_new) def __new__(cls, /, *args, **kwargs): if cls is arg: warnings.warn(msg, category=category, stacklevel=stacklevel + 1) if original_new is not object.__new__: return original_new(cls, *args, **kwargs) # Mirrors a similar check in object.__new__. elif cls.__init__ is object.__init__ and (args or kwargs): raise TypeError(f"{cls.__name__}() takes no arguments") else: return original_new(cls) arg.__new__ = staticmethod(__new__) original_init_subclass = arg.__init_subclass__ # We need slightly different behavior if __init_subclass__ # is a bound method (likely if it was implemented in Python) if isinstance(original_init_subclass, MethodType): original_init_subclass = original_init_subclass.__func__ @functools.wraps(original_init_subclass) def __init_subclass__(*args, **kwargs): warnings.warn(msg, category=category, stacklevel=stacklevel + 1) return original_init_subclass(*args, **kwargs) arg.__init_subclass__ = classmethod(__init_subclass__) # Or otherwise, which likely means it's a builtin such as # object's implementation of __init_subclass__. else: @functools.wraps(original_init_subclass) def __init_subclass__(*args, **kwargs): warnings.warn(msg, category=category, stacklevel=stacklevel + 1) return original_init_subclass(*args, **kwargs) arg.__init_subclass__ = __init_subclass__ arg.__deprecated__ = __new__.__deprecated__ = msg __init_subclass__.__deprecated__ = msg return arg elif callable(arg): import asyncio.coroutines import functools import inspect @functools.wraps(arg) def wrapper(*args, **kwargs): warnings.warn(msg, category=category, stacklevel=stacklevel + 1) return arg(*args, **kwargs) if asyncio.coroutines.iscoroutinefunction(arg): # Breakpoint: https://github.com/python/cpython/pull/99247 if sys.version_info >= (3, 12): wrapper = inspect.markcoroutinefunction(wrapper) else: wrapper._is_coroutine = asyncio.coroutines._is_coroutine arg.__deprecated__ = wrapper.__deprecated__ = msg return wrapper else: raise TypeError( "@deprecated decorator with non-None category must be applied to " f"a class or callable, not {arg!r}" )Indicate that a class, function or overload is deprecated.
When this decorator is applied to an object, the type checker will generate a diagnostic on usage of the deprecated object.
Usage
@deprecated("Use B instead") class A: pass
@deprecated("Use g instead") def f(): pass
@overload @deprecated("int support is deprecated") def g(x: int) -> int: … @overload def g(x: str) -> int: …
The warning specified by category will be emitted at runtime on use of deprecated objects. For functions, that happens on calls; for classes, on instantiation and on creation of subclasses. If the category is
None, no warning is emitted at runtime. The stacklevel determines where the warning is emitted. If it is1(the default), the warning is emitted at the direct caller of the deprecated object; if it is higher, it is emitted further up the stack. Static type checker behavior is not affected by the category and stacklevel arguments.The deprecation message passed to the decorator is saved in the
__deprecated__attribute on the decorated object. If applied to an overload, the decorator must be after the@overloaddecorator for the attribute to exist on the overload as returned byget_overloads().See PEP 702 for details.
Subclasses
class experimental (message: LiteralString,
/,
*,
category: Type[Warning] | None = devstatusdecos.devstatusdecos.ExperimentalWarning,
stacklevel: int = 1)-
Expand source code
class experimental(deprecated): # pylint:disable=invalid-name """A decorator that marks a class, function or method as experimental and should be used with caution. Note that this inherits the native `deprecated` decorator, so some introspective tools might falsely flag this as a deprecated function instead.""" def __init__(self, message:LiteralString, /, *, category:Type[Warning]|None = ExperimentalWarning, stacklevel:int = 1): super().__init__(message, category=category, stacklevel=stacklevel)A decorator that marks a class, function or method as experimental and should be used with caution. Note that this inherits the native
deprecateddecorator, so some introspective tools might falsely flag this as a deprecated function instead.Ancestors
- typing_extensions.deprecated
Subclasses
class insecure (message: str, fatal: bool, code: int = 1)-
Expand source code
class insecure(): # pylint:disable=invalid-name """A decorator that marks a class, function or method as insecure, indicating that it should not be allowed to execute further. Unlike other dev stats decorators, this replaces the a decorated callable or type entirely with a callable that raises an error, which may confuse some type checkers. While not intended for use on things besides types or callables, the exception will be raised immediately in cases there the decorated object is not callable. """ def __init__(self, message:str, fatal:bool, code:int = 1, ): self.exc = FatallyInsecureError(message, code = code) if not fatal: self.exc = InsecureError(message) self.code = code def __call__(self, arg:Any) -> Callable[..., NoReturn]: # noqa:F811, E301 if not callable(arg): # its already possibly to late, but lets stop anyway raise self.exc def __wrapper(*_, **__): raise self.exc return __wrapperA decorator that marks a class, function or method as insecure, indicating that it should not be allowed to execute further. Unlike other dev stats decorators, this replaces the a decorated callable or type entirely with a callable that raises an error, which may confuse some type checkers.
While not intended for use on things besides types or callables, the exception will be raised immediately in cases there the decorated object is not callable.
class pending_deprecation (message: LiteralString,
/,
*,
pending_category: Type[DeprecationWarning | PendingDeprecationWarning] | None = builtins.PendingDeprecationWarning,
deprecated_category: Any = Ellipsis,
stacklevel: int = 1,
deprecate_py_ver: Any = Ellipsis)-
Expand source code
class pending_deprecation(deprecated, Generic[VersionInfoTupleT]): # pylint:disable=invalid-name """A decorator that indicates that the decorated class, function, or method is pending deprecation. Note that this inherits the native `deprecated` decorator, so some introspective tools might falsely flag this as a deprecated function instead.""" def __init__(self, message:LiteralString, /, *, pending_category:Type[DeprecationWarning | PendingDeprecationWarning ]|None = PendingDeprecationWarning, deprecated_category:Any = ..., # pylint:disable=unused-argument stacklevel:int = 1, deprecate_py_ver:Any = ... # pylint:disable=unused-argument ): super().__init__(message, category=pending_category, stacklevel=stacklevel) def __new__(cls, message:LiteralString, /, *, pending_category:Type[DeprecationWarning | PendingDeprecationWarning ]|None = PendingDeprecationWarning, deprecated_category:Type[DeprecationWarning ]|None = DeprecationWarning, stacklevel:int = 1, deprecate_py_ver:VersionInfoTupleT = None ): if deprecate_py_ver is not None and version_info >= deprecate_py_ver: return deprecated(message, category=deprecated_category, stacklevel=stacklevel) return super().__new__(cls)A decorator that indicates that the decorated class, function, or method is pending deprecation.
Note that this inherits the native
deprecateddecorator, so some introspective tools might falsely flag this as a deprecated function instead.Ancestors
- typing_extensions.deprecated
- typing.Generic
class todo (message: LiteralString,
error_condition: Callable[[Any], bool] | None = None,
/,
*,
category: Type[Warning] | None = devstatusdecos.devstatusdecos.TodoWarning,
stacklevel: int = 1)-
Expand source code
class todo(experimental): # pylint:disable=invalid-name """ A decorator that marks a class, function, or method as todo and is presumed to be missing a key part of it's functionality. It may change at any time or even removed. This will always raise a `TodoError` when a `todo` Callable is called (or Type is initalized), unless `error_condition` is truthy or a callable that will return `True`. `error_condition` will always be checked when the wrapped function is called. The constructor matches the same parameters as `deprecated`, in exception for the fact that the default warning type is a `TodoWarning` and that 'TODO:' is always appended to the message. """ # Sadly there is not way to easily make type checkers # recognise this besides making a plugin for this, # so we have to piggyback off of the deprecation # detection in all the type checkers for now. TODO_PREFIX:LiteralString = "TODO: " def __init__(self, message:LiteralString, error_condition:Callable[[Any], bool] | None = None, /, *, category:Type[Warning] | None = TodoWarning, stacklevel:int = 1 ): if not message.startswith(self.TODO_PREFIX): message = self.TODO_PREFIX + message super().__init__(message, category=category, stacklevel=stacklevel ) self.error_condition = error_condition @overload def __call__(self, # noqa:F811, E302 arg:Callable[PS, RT], /, ) -> Callable[PS, RT|Never]: ... @overload # noqa:E301 def __call__(self, arg:T, /) -> T: # noqa:F811, E302 ... def __call__(self, arg:Any, /) -> Any: # noqa:F811, E301 arg = super().__call__(arg) d = f"{self.message}\n{getattr(arg, '__doc__', '')}".strip() setattr(arg, "__doc__", d) if callable(arg): @wraps(arg, assigned=("__module__", "__name__", "__qualname__", "__doc__")) def __wrapper(*args, **kwargs): if self.error_condition is not None and self.error_condition(arg): raise TodoError(self.message) return arg(*args, **kwargs) return __wrapper return argA decorator that marks a class, function, or method as todo and is presumed to be missing a key part of it's functionality. It may change at any time or even removed.
This will always raise a
TodoErrorwhen atodoCallable is called (or Type is initalized), unlesserror_conditionis truthy or a callable that will returnTrue.error_conditionwill always be checked when the wrapped function is called.The constructor matches the same parameters as
deprecated, in exception for the fact that the default warning type is aTodoWarningand that 'TODO:' is always appended to the message.Ancestors
- experimental
- typing_extensions.deprecated
Class variables
var TODO_PREFIX : LiteralString
class TODO (message: LiteralString,
error_condition: Callable[[Any], bool] | None = None,
/,
*,
category: Type[Warning] | None = devstatusdecos.devstatusdecos.TodoWarning,
stacklevel: int = 1)-
Expand source code
class todo(experimental): # pylint:disable=invalid-name """ A decorator that marks a class, function, or method as todo and is presumed to be missing a key part of it's functionality. It may change at any time or even removed. This will always raise a `TodoError` when a `todo` Callable is called (or Type is initalized), unless `error_condition` is truthy or a callable that will return `True`. `error_condition` will always be checked when the wrapped function is called. The constructor matches the same parameters as `deprecated`, in exception for the fact that the default warning type is a `TodoWarning` and that 'TODO:' is always appended to the message. """ # Sadly there is not way to easily make type checkers # recognise this besides making a plugin for this, # so we have to piggyback off of the deprecation # detection in all the type checkers for now. TODO_PREFIX:LiteralString = "TODO: " def __init__(self, message:LiteralString, error_condition:Callable[[Any], bool] | None = None, /, *, category:Type[Warning] | None = TodoWarning, stacklevel:int = 1 ): if not message.startswith(self.TODO_PREFIX): message = self.TODO_PREFIX + message super().__init__(message, category=category, stacklevel=stacklevel ) self.error_condition = error_condition @overload def __call__(self, # noqa:F811, E302 arg:Callable[PS, RT], /, ) -> Callable[PS, RT|Never]: ... @overload # noqa:E301 def __call__(self, arg:T, /) -> T: # noqa:F811, E302 ... def __call__(self, arg:Any, /) -> Any: # noqa:F811, E301 arg = super().__call__(arg) d = f"{self.message}\n{getattr(arg, '__doc__', '')}".strip() setattr(arg, "__doc__", d) if callable(arg): @wraps(arg, assigned=("__module__", "__name__", "__qualname__", "__doc__")) def __wrapper(*args, **kwargs): if self.error_condition is not None and self.error_condition(arg): raise TodoError(self.message) return arg(*args, **kwargs) return __wrapper return argA decorator that marks a class, function, or method as todo and is presumed to be missing a key part of it's functionality. It may change at any time or even removed.
This will always raise a
TodoErrorwhen atodoCallable is called (or Type is initalized), unlesserror_conditionis truthy or a callable that will returnTrue.error_conditionwill always be checked when the wrapped function is called.The constructor matches the same parameters as
deprecated, in exception for the fact that the default warning type is aTodoWarningand that 'TODO:' is always appended to the message.Ancestors
- experimental
- typing_extensions.deprecated
Class variables
var TODO_PREFIX : LiteralString
class fixme (message: LiteralString,
error_condition: Callable[[Any], bool] | None = None,
/,
*,
category: Type[Warning] | None = devstatusdecos.devstatusdecos.TodoWarning,
stacklevel: int = 1)-
Expand source code
class todo(experimental): # pylint:disable=invalid-name """ A decorator that marks a class, function, or method as todo and is presumed to be missing a key part of it's functionality. It may change at any time or even removed. This will always raise a `TodoError` when a `todo` Callable is called (or Type is initalized), unless `error_condition` is truthy or a callable that will return `True`. `error_condition` will always be checked when the wrapped function is called. The constructor matches the same parameters as `deprecated`, in exception for the fact that the default warning type is a `TodoWarning` and that 'TODO:' is always appended to the message. """ # Sadly there is not way to easily make type checkers # recognise this besides making a plugin for this, # so we have to piggyback off of the deprecation # detection in all the type checkers for now. TODO_PREFIX:LiteralString = "TODO: " def __init__(self, message:LiteralString, error_condition:Callable[[Any], bool] | None = None, /, *, category:Type[Warning] | None = TodoWarning, stacklevel:int = 1 ): if not message.startswith(self.TODO_PREFIX): message = self.TODO_PREFIX + message super().__init__(message, category=category, stacklevel=stacklevel ) self.error_condition = error_condition @overload def __call__(self, # noqa:F811, E302 arg:Callable[PS, RT], /, ) -> Callable[PS, RT|Never]: ... @overload # noqa:E301 def __call__(self, arg:T, /) -> T: # noqa:F811, E302 ... def __call__(self, arg:Any, /) -> Any: # noqa:F811, E301 arg = super().__call__(arg) d = f"{self.message}\n{getattr(arg, '__doc__', '')}".strip() setattr(arg, "__doc__", d) if callable(arg): @wraps(arg, assigned=("__module__", "__name__", "__qualname__", "__doc__")) def __wrapper(*args, **kwargs): if self.error_condition is not None and self.error_condition(arg): raise TodoError(self.message) return arg(*args, **kwargs) return __wrapper return argA decorator that marks a class, function, or method as todo and is presumed to be missing a key part of it's functionality. It may change at any time or even removed.
This will always raise a
TodoErrorwhen atodoCallable is called (or Type is initalized), unlesserror_conditionis truthy or a callable that will returnTrue.error_conditionwill always be checked when the wrapped function is called.The constructor matches the same parameters as
deprecated, in exception for the fact that the default warning type is aTodoWarningand that 'TODO:' is always appended to the message.Ancestors
- experimental
- typing_extensions.deprecated
Class variables
var TODO_PREFIX : LiteralString
class FIXME (message: LiteralString,
error_condition: Callable[[Any], bool] | None = None,
/,
*,
category: Type[Warning] | None = devstatusdecos.devstatusdecos.TodoWarning,
stacklevel: int = 1)-
Expand source code
class todo(experimental): # pylint:disable=invalid-name """ A decorator that marks a class, function, or method as todo and is presumed to be missing a key part of it's functionality. It may change at any time or even removed. This will always raise a `TodoError` when a `todo` Callable is called (or Type is initalized), unless `error_condition` is truthy or a callable that will return `True`. `error_condition` will always be checked when the wrapped function is called. The constructor matches the same parameters as `deprecated`, in exception for the fact that the default warning type is a `TodoWarning` and that 'TODO:' is always appended to the message. """ # Sadly there is not way to easily make type checkers # recognise this besides making a plugin for this, # so we have to piggyback off of the deprecation # detection in all the type checkers for now. TODO_PREFIX:LiteralString = "TODO: " def __init__(self, message:LiteralString, error_condition:Callable[[Any], bool] | None = None, /, *, category:Type[Warning] | None = TodoWarning, stacklevel:int = 1 ): if not message.startswith(self.TODO_PREFIX): message = self.TODO_PREFIX + message super().__init__(message, category=category, stacklevel=stacklevel ) self.error_condition = error_condition @overload def __call__(self, # noqa:F811, E302 arg:Callable[PS, RT], /, ) -> Callable[PS, RT|Never]: ... @overload # noqa:E301 def __call__(self, arg:T, /) -> T: # noqa:F811, E302 ... def __call__(self, arg:Any, /) -> Any: # noqa:F811, E301 arg = super().__call__(arg) d = f"{self.message}\n{getattr(arg, '__doc__', '')}".strip() setattr(arg, "__doc__", d) if callable(arg): @wraps(arg, assigned=("__module__", "__name__", "__qualname__", "__doc__")) def __wrapper(*args, **kwargs): if self.error_condition is not None and self.error_condition(arg): raise TodoError(self.message) return arg(*args, **kwargs) return __wrapper return argA decorator that marks a class, function, or method as todo and is presumed to be missing a key part of it's functionality. It may change at any time or even removed.
This will always raise a
TodoErrorwhen atodoCallable is called (or Type is initalized), unlesserror_conditionis truthy or a callable that will returnTrue.error_conditionwill always be checked when the wrapped function is called.The constructor matches the same parameters as
deprecated, in exception for the fact that the default warning type is aTodoWarningand that 'TODO:' is always appended to the message.Ancestors
- experimental
- typing_extensions.deprecated
Class variables
var TODO_PREFIX : LiteralString