API Reference🔗
Auto-generated from source docstrings. For usage examples see the User Guide.
Decorator🔗
deprecate.deprecation.deprecated(target=TargetMode.NOTIFY, deprecated_in='', remove_in='', stream=deprecation_warning, num_warns=1, template_mgs=None, args_mapping=None, args_extra=None, skip_if=False, update_docstring=False, docstring_style='auto')
🔗
Decorate a function/method with warning message and forward calls to target.
This decorator marks a function or method as deprecated and can automatically forward all calls to a replacement implementation. It supports argument mapping, custom warning messages, and flexible warning control.
For generator functions (def gen(): yield) and async generator functions (async def gen(): yield),
the deprecation warning fires at call time — when the (async) generator object is created — not at first
iteration. The generator body executes lazily as normal when iterated (next() / async for).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Union[bool, None, Callable, TargetMode]
|
How to handle the deprecation. Defaults to :attr:
Omitting |
NOTIFY
|
deprecated_in
|
str
|
Version when the function was deprecated (e.g., "1.0.0"). Default is empty string. |
''
|
remove_in
|
str
|
Version when the function will be removed (e.g., "2.0.0"). Default is empty string. |
''
|
stream
|
Optional[Callable]
|
Function to output warnings (default: :func: |
deprecation_warning
|
num_warns
|
int
|
Number of times to show warning per function or per deprecated argument:
- |
1
|
template_mgs
|
Optional[str]
|
Custom warning message template with format specifiers:
- |
None
|
args_mapping
|
Optional[ArgsMapping]
|
Map or skip arguments when forwarding:
- |
None
|
args_extra
|
Optional[dict[str, Any]]
|
Additional arguments merged into kwargs before the call. Used when target is a Callable or
:attr: |
None
|
skip_if
|
Union[bool, Callable]
|
Conditionally skip deprecation warning and forwarding:
- |
False
|
update_docstring
|
bool
|
If True, automatically inject a deprecation notice into the function's docstring (inserted before Google/NumPy-style sections when present, otherwise appended at the end). |
False
|
docstring_style
|
Literal['auto', 'rst', 'mkdocs', 'markdown']
|
Output style for injected deprecation notice when |
'auto'
|
Returns:
| Type | Description |
|---|---|
Callable[[Callable[..., Any]], Callable[..., Any]]
|
Decorator function that wraps the source function/method. |
Warns:
| Type | Description |
|---|---|
UserWarning
|
If applied directly to a class. The decorator delegates to
:func: |
UserWarning
|
If |
Raises:
| Type | Description |
|---|---|
TypeError
|
If the source is a class method and target is a method on a different class (cross-class
method forwarding detected at decoration time via |
TypeError
|
If skip_if is a callable that doesn't return a bool. |
TypeError
|
If arguments in args_mapping don't exist in target function and target doesn't accept **kwargs. |
Example
Basic forwarding🔗
def new_func(x: int) -> int: ... return x * 2 @deprecated(target=new_func, deprecated_in="1.0", remove_in="2.0") ... def old_func(x: int) -> int: ... pass
Argument mapping🔗
@deprecated( ... target=new_func, ... args_mapping={'old_name': 'new_name', 'unused': None} ... ) ... def old_func(old_name: int, unused: str) -> int: ... pass
Self-deprecation🔗
from deprecate import TargetMode @deprecated(target=TargetMode.ARGS_REMAP, args_mapping={'old_arg': 'new_arg'}) ... def my_func(old_arg: int = 0, new_arg: int = 0) -> int: ... return new_arg * 2
Warn-only (default — no target needed)🔗
@deprecated(deprecated_in="1.0", remove_in="2.0") ... def legacy_func(x: int) -> int: ... return x
Proxy🔗
deprecate.proxy.deprecated_class(target=None, *, deprecated_in='', remove_in='', num_warns=1, stream=deprecation_warning, template_mgs=None, args_mapping=None, args_extra=None, update_docstring=False, docstring_style='auto', _misconfigured_override=False)
🔗
Decorator factory for deprecating class definitions with optional target redirection.
Apply @deprecated_class(...) to an Enum or dataclass to wrap the class in a
:class:~deprecate.proxy._DeprecatedProxy. All attribute, item, and call access on the resulting object will
emit a deprecation warning and, if target is provided, will be forwarded to the replacement class.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Any
|
Optional replacement class to redirect all access to. |
None
|
deprecated_in
|
str
|
Version string when the class was deprecated. |
''
|
remove_in
|
str
|
Version string when the class will be removed. |
''
|
num_warns
|
int
|
Maximum number of warnings to emit per proxy instance. |
1
|
stream
|
Optional[Callable[..., None]]
|
Callable used to emit warnings. Defaults to :data: |
deprecation_warning
|
template_mgs
|
Optional[str]
|
Optional custom warning message template that overrides the built-in templates. When
Example: |
None
|
args_mapping
|
Optional[dict[str, Optional[str]]]
|
Optional dict remapping keyword argument names when the decorated class is called. Keys are
old argument names; values are new names, or |
None
|
args_extra
|
Optional[dict[str, Any]]
|
Optional dict of extra keyword arguments merged into the forwarded call after |
None
|
update_docstring
|
bool
|
If |
False
|
docstring_style
|
Literal['auto', 'rst', 'mkdocs', 'markdown']
|
Output style for the injected notice when |
'auto'
|
Returns:
| Type | Description |
|---|---|
Callable[[type], _DeprecatedProxy]
|
A decorator that wraps the class in a :class: |
Examples:
>>> from enum import Enum
>>> class NewColor(Enum):
... RED = 1
>>> @deprecated_class(target=NewColor, deprecated_in="1.0", remove_in="2.0", stream=None)
... class OldColor(Enum):
... RED = 1
>>> OldColor.RED is NewColor.RED
True
>>> OldColor(1) is NewColor.RED
True
When only argument names changed, omit target and supply args_mapping. The proxy auto-resolves to
:attr:~deprecate._types.TargetMode.ARGS_REMAP and warns only when the old argument name is passed:
>>> class Config:
... def __init__(self, timeout: int = 0) -> None:
... self.timeout = timeout
>>> LegacyConfig = deprecated_class(
... args_mapping={"time_limit": "timeout"},
... deprecated_in="1.5", remove_in="2.0", stream=None,
... )(Config)
>>> LegacyConfig(timeout=30).timeout # new name — no remap needed
30
>>> LegacyConfig(time_limit=30).timeout # old name — remapped to timeout
30
deprecate.proxy.deprecated_instance(obj, *, name='', deprecated_in='', remove_in='', num_warns=1, stream=deprecation_warning, template_mgs=None, read_only=False, args_extra=None)
🔗
Wrap any Python object with deprecation warnings.
Returns a :class:~deprecate.proxy._DeprecatedProxy that transparently forwards all read access to obj while
emitting a :class:FutureWarning. In read-only mode any write attempt through the proxy raises
:class:AttributeError.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
Any
|
The object to deprecate (dict, list, custom object, …). |
required |
name
|
str
|
Display name for obj used in the warning message. When omitted, the type name of obj is used
(e.g. |
''
|
deprecated_in
|
str
|
Version string when obj was deprecated. |
''
|
remove_in
|
str
|
Version string when obj will be removed. |
''
|
num_warns
|
int
|
Maximum number of warnings to emit. |
1
|
stream
|
Optional[Callable[..., None]]
|
Callable used to emit warnings. Defaults to :data: |
deprecation_warning
|
template_mgs
|
Optional[str]
|
Optional custom warning message template that overrides the built-in templates. When |
None
|
read_only
|
bool
|
If |
False
|
args_extra
|
Optional[dict[str, Any]]
|
Optional dict of extra keyword arguments merged into the forwarded call when the proxy is invoked. Caller-supplied values override entries with the same key. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
_DeprecatedProxy
|
|
Example
cfg = {"threshold": 0.5, "enabled": True} proxy = deprecated_instance( ... cfg, ... name="config_dict", ... deprecated_in="1.0", ... remove_in="2.0", ... stream=None, ... ) proxy["threshold"] 0.5 proxy.get("enabled") True
Audit🔗
deprecate.audit.find_deprecation_wrappers(module, recursive=True, include_members=True)
🔗
Scan a module or package for deprecated wrappers and validate them.
This is a development/CI tool to scan a codebase for all wrappers created with :func:~deprecate.deprecated,
:func:~deprecate.deprecated_class, or :func:~deprecate.deprecated_instance and validate that each wrapper
configuration is meaningful.
Returns comprehensive information about each deprecated wrapper including validation results that help identify
misconfigured wrappers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
module
|
Union[Any, str]
|
A Python module or package to scan for deprecated wrappers. Can be:
- Imported module object (e.g., |
required |
recursive
|
bool
|
If True (default), recursively scan submodules. If False, only scan the top-level module. |
True
|
include_members
|
bool
|
If True, also scan deprecated methods and constructors defined on classes. |
True
|
Returns:
| Type | Description |
|---|---|
list[DeprecationWrapperInfo]
|
List of :class: |
list[DeprecationWrapperInfo]
|
Each contains:
- module: Module name where the wrapper is defined
- function: Wrapper name
- deprecated_info: DeprecationConfig metadata from the decorator ( |
Example
from deprecate import find_deprecation_wrappers from tests import collection_deprecate as my_package
results = find_deprecation_wrappers(my_package) print(len(results) > 0) # Should find deprecated wrappers True
Also works with string module paths🔗
results = find_deprecation_wrappers("tests.collection_deprecate") print(len(results) > 0) True
Filter to find only problematic wrappers🔗
problematic = [r for r in results if r.invalid_args or r.no_effect] print(len(results) > 0) # May or may not have problematic ones True
Note
- Requires that the module be importable
- Inspects the
__deprecated__attribute set by the :func:~deprecate.deprecateddecorator - Skips private/magic attributes and imports from other modules
- Uses static member inspection to avoid scan-time side effects from dynamic attribute access
deprecate.audit.validate_deprecation_wrapper(func)
🔗
Validate if a deprecated wrapper configuration is effective.
This is a development tool to check if deprecated wrappers are configured correctly and will have the intended
effect. It examines the __deprecated__ attribute set by the :func:~deprecate.deprecated decorator and
identifies
configurations that would result in zero impact:
- args_mapping keys that don't exist in the function's signature
- Empty or None args_mapping (no argument remapping)
- Identity mappings where key equals value (e.g., {'arg': 'arg'})
- Target pointing to the same function (self-reference)
- target=None with no args_mapping (just warns, no forwarding)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
func
|
Callable
|
The decorated function to validate. Must have a |
required |
Returns:
| Type | Description |
|---|---|
DeprecationWrapperInfo
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If the wrapper has missing or invalid |
Example
from deprecate import deprecated, validate_deprecation_wrapper def new_implementation(value: int) -> int: ... return value * 2
@deprecated(target=new_implementation, deprecated_in="1.0", args_mapping={"old_val": "value"}) ... def old_func(old_val: int) -> int: ... pass
Valid mapping to different function - has effect🔗
result = validate_deprecation_wrapper(old_func) result.no_effect False result.invalid_args []
@deprecated(target=True, deprecated_in="1.0", args_mapping={"arg": "arg"}) ... def identity_func(arg: int) -> int: ... return arg
Identity mapping with self-deprecation - no effect🔗
result = validate_deprecation_wrapper(identity_func) result.identity_args_mapping ['arg'] result.no_effect True
Note
Use this function during development or in CI to ensure deprecation decorators are configured meaningfully. Invalid configurations won't cause runtime errors but will silently have no effect.
deprecate.audit.validate_deprecation_expiry(module, current_version=None, recursive=True, include_members=False)
🔗
Check all deprecated callables in a module/package for expired removal deadlines.
This enforcement tool scans an entire module or package for deprecated functions and checks if any have passed their scheduled removal version. It's designed for CI/CD pipelines to automatically detect and report zombie code across a codebase.
The function uses :func:~deprecate.audit.find_deprecation_wrappers to discover all deprecated wrappers,
then checks each one against
the current version. Any wrappers that have reached or passed their removal deadline are collected and reported.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
module
|
Union[Any, str]
|
A Python module or package to scan. Can be:
- Imported module object (e.g., |
required |
current_version
|
Optional[str]
|
The current version of your package to compare against removal deadlines (e.g., |
None
|
recursive
|
bool
|
If True (default), recursively scan submodules. If False, only scan the top-level module. |
True
|
include_members
|
bool
|
If True, also scan deprecated class members (methods, constructors). |
False
|
Returns:
| Type | Description |
|---|---|
list[str]
|
List of error messages for callables that have expired (past their removal deadline). |
list[str]
|
Empty list if all deprecated callables are still within their deprecation period. |
Example
Check a specific module with version before any deadlines🔗
from deprecate import validate_deprecation_expiry expired = validate_deprecation_expiry("tests.collection_deprecate", "0.1", recursive=False) len(expired) 0
Check with version past some removal deadlines🔗
expired = validate_deprecation_expiry("tests.collection_deprecate", "0.5", recursive=False) print(len(expired)) # Some functions have remove_in="0.5" 28
Note
- Skips callables without a
remove_infield (warnings only, no removal deadline) - Skips callables that cannot be imported or accessed
- Silently skips callables with invalid
remove_inversion formats - Uses semantic versioning comparison (e.g., "1.2.3" vs "2.0.0")
- Intended for automated checks in CI/CD pipelines
- Can be integrated into test suites or pre-commit hooks
deprecate.audit.validate_deprecation_chains(module, recursive=True)
🔗
Validate that deprecated functions don't form chains with other deprecated code.
This is a developer utility that scans a module or package for deprecated functions that form chains in two ways:
- TARGET chains: The
targetargument points to another deprecated callable instead of the final non-deprecated implementation. - STACKED chains: Multiple
@deprecated(True, ...)decorators are stacked on the same function with argument mappings that should be collapsed, or a callabletargetis itself a self-deprecation (target=True) requiring mapping composition.
Both types are wasteful: wrappers should point directly to the final (non-deprecated) implementation with composed argument mappings.
Detection is based purely on decorator metadata (__deprecated__ attributes) — no source-code or AST
inspection is performed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
module
|
Union[Any, str]
|
A Python module or package to scan for deprecation chains. Can be:
- Imported module object (e.g., |
required |
recursive
|
bool
|
If True (default), recursively scan submodules. If False, only scan the top-level module. |
True
|
Returns:
| Type | Description |
|---|---|
list[DeprecationWrapperInfo]
|
List of :class: |
list[DeprecationWrapperInfo]
|
deprecated wrapper that forms a chain ( |
Example
from deprecate import validate_deprecation_chains import tests.collection_chains as test_module
issues = validate_deprecation_chains(test_module, recursive=False) len(issues) > 0 # Should find chains True
Note
- Only flags callees using the :func:
~deprecate.deprecateddecorator - Uses :func:
~deprecate.audit.find_deprecation_wrappersand inspectschain_typeto detect chains
deprecate.audit.DeprecationWrapperInfo
dataclass
🔗
Information about a deprecated wrapper and its validation results.
This dataclass represents a deprecated wrapper (a :func:~deprecate.deprecated-decorated function or a
:func:~deprecate.proxy.deprecated_class/:func:~deprecate.proxy.deprecated_instance proxy), containing both
identification info and validation results from :func:~deprecate.audit.validate_deprecation_wrapper or
:func:~deprecate.audit.find_deprecation_wrappers.
Attributes:
| Name | Type | Description |
|---|---|---|
module |
str
|
Module name where the wrapper is defined (empty for direct validation). |
function |
str
|
Wrapper name. |
deprecated_info |
DeprecationConfig
|
The |
invalid_args |
list[str]
|
List of |
empty_args_mapping |
bool
|
True if |
identity_args_mapping |
list[str]
|
List of args where key equals value (e.g., |
self_reference |
bool
|
True if target points to the same wrapper. |
no_effect |
bool
|
True if wrapper has zero impact (combines all checks). |
all_identity |
bool
|
True when every configured mapping is an identity mapping (key == value, non-empty). |
chain_type |
Optional[ChainType]
|
The kind of deprecation chain detected, or |
misconfigured_target |
bool
|
True when the wrapper has an invalid target configuration:
|
empty_deprecated_in |
bool
|
True when |
api_type |
str
|
Inferred deprecated API type for report generation.
Possible values: |
Example
info = DeprecationWrapperInfo( ... module="my_package.module", ... function="old_function", ... deprecated_info=DeprecationConfig(deprecated_in="1.0", remove_in="2.0"), ... invalid_args=["nonexistent"], ... no_effect=True, ... ) info.function 'old_function' info.invalid_args ['nonexistent']
empty_mapping
property
🔗
Deprecated alias for :attr:~deprecate.audit.DeprecationWrapperInfo.empty_args_mapping.
Deprecated in 0.8
Renamed to :attr:~deprecate.audit.DeprecationWrapperInfo.empty_args_mapping.
Will be removed in v1.0.
Note
Python's default warning filter deduplicates per (message, category, module, lineno),
so accessing this property in a loop from the same call site emits at most one warning.
identity_mapping
property
🔗
Deprecated alias for :attr:~deprecate.audit.DeprecationWrapperInfo.identity_args_mapping.
Deprecated in 0.8
Renamed to :attr:~deprecate.audit.DeprecationWrapperInfo.identity_args_mapping.
Will be removed in v1.0.
Note
Python's default warning filter deduplicates per (message, category, module, lineno),
so accessing this property in a loop from the same call site emits at most one warning.
__post_init__()
🔗
Derive empty_deprecated_in from deprecated_info to keep them in sync.
deprecate.audit.ChainType
🔗
Bases: Enum
Type of deprecation chain detected by :func:~deprecate.audit.validate_deprecation_chains.
Attributes:
| Name | Type | Description |
|---|---|---|
TARGET |
The |
|
STACKED |
Arg mappings chain and must be composed/collapsed. Two sub-cases:
(a) Callable |
Types🔗
deprecate.TargetMode
🔗
Bases: Enum
Selects @deprecated behaviour when no callable replacement is provided.
Attributes:
| Name | Type | Description |
|---|---|---|
NOTIFY |
Notify-only deprecation -- warn on every call; original body executes unchanged. Replaces
|
|
ARGS_REMAP |
Deprecate argument names only -- warn only when deprecated argument names are passed; remaps
kwargs via |
Examples:
>>> from deprecate import TargetMode
>>> TargetMode.NOTIFY.value
'notify'
>>> TargetMode.ARGS_REMAP.value
'args_remap'
Utilities🔗
deprecate.utils.void(*args, **kwrgs)
🔗
Empty function that accepts any arguments and returns None.
This helper function is used to silence IDE warnings about unused parameters in deprecated functions where the body is never executed (calls are forwarded to a target function). It's purely a convenience for developers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*args
|
Any
|
Any positional arguments (ignored). |
()
|
**kwrgs
|
Any
|
Any keyword arguments (ignored). |
{}
|
Returns:
| Type | Description |
|---|---|
Any
|
None always. |
Example
from deprecate import deprecated, void
def new_func(x: int) -> int: ... return x * 2
@deprecated(target=new_func, deprecated_in="1.0", remove_in="2.0") ... def old_func(x: int) -> int: ... void(x) # Silences IDE warning about unused 'x' ... # This line is never reached - call forwarded to new_func
Note
This function has no runtime effect - it's purely for developer convenience. You can also use pass or
just a docstring instead of calling void().
deprecate.utils.assert_no_warnings(warning_type=None, match=None)
🔗
Context manager asserting that no warnings are raised — the inverse of pytest.warns().
Useful for testing that refactored code properly avoids deprecated functionality or that new implementations don't trigger warnings.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
warning_type
|
Optional[type[Warning]]
|
The warning type that must NOT be raised (e.g., :class: |
None
|
match
|
Optional[str]
|
If given, only fail if a warning message contains this string. If |
None
|
Raises:
| Type | Description |
|---|---|
AssertionError
|
If a warning of the specified type (and optionally matching the message pattern) was raised during the context. |
Example
Assert new function doesn't trigger FutureWarning🔗
import warnings def new_func(x: int) -> int: ... return x * 2 with assert_no_warnings(FutureWarning): ... result = new_func(42) result 84
Assert NO warnings at all are raised🔗
def clean_function(): ... pass with assert_no_warnings(): ... clean_function()
Only fail if warning message matches pattern🔗
def some_function(): ... warnings.warn("deprecated feature", FutureWarning)
Passes because warning contains "feature", not "other"🔗
with assert_no_warnings(FutureWarning, match="other"): ... some_function()
Note
This context manager is particularly useful in pytest for testing that refactored code properly uses new APIs without triggering deprecation warnings.