Getting Started🔗
You renamed a function (or retired an argument) and now you need the old name to keep working, callers to see a clear deprecation notice, and a firm removal date you can enforce. pyDeprecate does all of that with a single decorator so you can focus on the new API instead of the plumbing.
Installation🔗
pyDeprecate requires Python 3.9 or later and has zero runtime dependencies.
Install from PyPI:
To install directly from source (for pre-release or development versions):
The audit extra adds packaging for version comparison, needed only by validate_deprecation_expiry. Install it when you want to enforce removal deadlines in CI:
Quick Start🔗
Here is the most common scenario: you renamed a function and need the old name to keep working during the transition. The decorator handles call forwarding automatically, so the deprecated wrapper needs no implementation.
from deprecate import deprecated
# NEW/FUTURE API — renamed to be more explicit about what it computes
def compute_sum(a: int = 0, b: int = 3) -> int:
return a + b
# DEPRECATED API — `addition` was the original name before the rename
@deprecated(target=compute_sum, deprecated_in="1.0", remove_in="2.0")
def addition(a: int, b: int = 5) -> int:
pass # body is not needed — calls are forwarded to compute_sum
# Using the original name still works but emits a deprecation notice
print(addition(1, 2))
All calls to addition() are automatically forwarded to compute_sum() with a FutureWarning. The old function's body is never executed.
Customizing deprecation messages
To customize the message template or redirect deprecation output to a logger, see Customization.
API at a Glance🔗
Not sure which API to reach for? This table maps common scenarios to the right tool. For worked examples of each, see Use Cases.
Pick the right decorator:
| Scenario | API to use |
|---|---|
| Renaming a function or method | @deprecated(target=new_func) |
| Renaming an argument within the same function | @deprecated(target=True, args_mapping={"old": "new"}) |
| Notice only — original body still runs | @deprecated(target=None) |
| Deprecating a class, Enum, or dataclass name | @deprecated_class(target=NewClass) |
| Deprecating a module-level constant or object | deprecated_instance(obj, ...) |
All @deprecated parameters:
| Param | Default | Purpose |
|---|---|---|
target |
— | Callable to forward to · True to remap args in-place · None notice-only |
deprecated_in |
"" |
Version when deprecated (e.g. "1.0") |
remove_in |
"" |
Version when removed (e.g. "2.0") |
stream |
deprecation_warning |
Output sink callable (set None to silence deprecation messages) |
num_warns |
1 |
1 once · -1 always · N exactly N times |
args_mapping |
None |
{"old": "new"} rename · {"old": None} drop |
template_mgs |
None |
Custom deprecation message template (%-style placeholders) |
args_extra |
None |
Fixed kwargs injected into the target call |
skip_if |
False |
bool or Callable → bool; skip deprecation when true |
update_docstring |
False |
Append Sphinx .. deprecated:: notice to docstring |
docstring_style |
"auto" |
Style of the injected notice: "auto", "rst", "mkdocs", "markdown" |
@deprecated_class() shares target, deprecated_in, remove_in, num_warns, stream, args_mapping, update_docstring, and docstring_style. deprecated_instance() shares deprecated_in, remove_in, num_warns, and stream; it requires obj and adds name (display name) and read_only.
Next: Use Cases — thirteen real-world deprecation patterns with full code examples. See also: Customization · Audit Tools · Troubleshooting