Skip to content

pyDeprecate🔗

Author: Jiri Borovec · License: Apache 2.0 · Python: 3.9+ · Install: pip install pyDeprecate · Import: from deprecate import deprecated · PyPI: https://pypi.org/project/pyDeprecate/

Every time you rename a function or retire an argument, you end up writing the same boilerplate: a wrapper, a warnings.warn call with the right category and stacklevel, manual argument forwarding, and no way to enforce the removal deadline when it arrives. pyDeprecate replaces all of that with a single decorator and gives you CI tools to make sure deprecated code does not quietly outlive its deadline.

pyDeprecate has broad PyPI usage. For current download statistics, see pepy.tech.

Read: Mastering API Deprecation in Python — the pain points and how pyDeprecate can help — CodeX / Medium

from deprecate import deprecated


# New function which replaces `addition`
def compute_sum(x: int, y: int) -> int:
    return x + y


@deprecated(target=compute_sum, deprecated_in="1.0", remove_in="2.0")
def addition(x: int, y: int) -> int: ...


print(addition(1, 2))
Output: addition(1, 2)
3

Calling addition(1, 2) now emits a FutureWarning and transparently forwards to compute_sum.

Features🔗

  • Automatic call forwarding — the decorator routes every call to the replacement, including positional and keyword arguments. No manual *args/**kwargs plumbing.
  • Generator and async support — works natively with generator functions (def fn(): yield), async def coroutines, and async generators (async def fn(): yield). The deprecation warning fires at call time regardless of callable type; the async def wrapper preserves iscoroutinefunction introspection.
  • Argument mappingargs_mapping={"old": "new"} handles renames across the API boundary; map to None to drop an argument entirely.
  • Argument deprecationTargetMode.ARGS_REMAP warns only when the old argument name is actually passed; callers who have already migrated see no noise.
  • Class and Enum support@deprecated_class wraps entire classes, Enums, and dataclasses in a transparent proxy where isinstance and issubclass just work.
  • Instance / constant proxydeprecated_instance(obj, ...) wraps module-level objects (dicts, lists, custom objects) with optional read_only enforcement and transparent attribute/item access.
  • Configurable frequencynum_warns=1 (default) emits once per function, not on every call. Set -1 for always or N for exactly N times.
  • Docstring injectionupdate_docstring=True appends a Sphinx .. deprecated:: or MkDocs admonition notice automatically, keeping rendered API docs accurate.
  • Sphinx Plugin — ships deprecate.docstring.sphinx_ext so _DeprecatedProxy objects render with their injected deprecation notice in Sphinx autodoc.
  • MkDocs Plugin — ships deprecate.docstring.griffe_ext for mkdocstrings so runtime-injected !!! warning admonitions are visible in MkDocs-generated API docs.
  • Decorator stacking — stack @deprecated decorators for multi-version migrations: rename arguments across releases (ARGS_REMAP + ARGS_REMAP), then deprecate the whole function when a complete replacement arrives (ARGS_REMAP + NOTIFY). Unsupported combinations warn at decoration time, not at call time.
  • Custom streams — route warnings to logging, standard warnings, or any callable via the stream parameter; stream=None silences output while forwarding still occurs.
  • Custom message templatestemplate_mgs overrides the default message with %-style placeholders (source_name, target_path, deprecated_in, remove_in, argument_map).
  • Conditional skipskip_if=callable suppresses the deprecation notice when a runtime condition is met (e.g. caller has migrated to a newer dependency).
  • CI audit toolsvalidate_deprecation_expiry() catches zombie code past its deadline, validate_deprecation_chains() detects double-deprecation chains, and find_deprecation_wrappers() surfaces misconfigured args_mapping keys before they silently do nothing.
  • Static type-checker signals — native PEP 702 static diagnostics come from warnings.deprecated. For projects that need both static-checker hints and runtime call-forwarding, warnings.deprecated (for the static signal) and pyDeprecate's @deprecated (for forwarding) can be applied separately to the same function.
  • CLIpydeprecate check src/ / pydeprecate all src/ runs all audit checks from the command line. See CLI Reference.
  • Testing helpersassert_no_warnings() context manager asserts no warnings of a given type escape a block; no_warning_call retained as legacy alias.
  • Zero runtime dependencies — nothing added to install_requires.
  • Python 3.9+ supported.

Installation🔗

Choose the install that matches the workflow you need:

Workflow Command Includes
Runtime deprecation wrappers pip install pyDeprecate @deprecated, @deprecated_class, deprecated_instance, docstring helpers, and most audit metadata helpers
CI deadline checks pip install 'pyDeprecate[audit]' Adds packaging for PEP 440 version comparison in validate_deprecation_expiry()
Command-line audit workflows pip install 'pyDeprecate[audit,cli]' Adds CLI dependencies (fire, rich) plus expiry support for pydeprecate expiry and pydeprecate all
pip install pyDeprecate

For CI audit features that compare version strings:

pip install 'pyDeprecate[audit]'

The [audit] extra is only needed for validate_deprecation_expiry

The base install gives you @deprecated, @deprecated_class, deprecated_instance, and all other audit functions. Only validate_deprecation_expiry() needs the extra because it pulls in packaging for PEP 440 version comparison.

Use [audit,cli] for command-line audit workflows

The pydeprecate command itself lives in the [cli] extra, but pydeprecate expiry and the expiry phase of pydeprecate all also need [audit]. Start with pip install 'pyDeprecate[audit,cli]' unless you only need Python API calls.

Comparison with other tools🔗

The alternatives emit a deprecation notice but leave forwarding, argument mapping, and deadline enforcement to you. Here is what each tool covers:

Feature pyDeprecate warnings.warn deprecation Deprecated (wrapt) warnings.deprecated† (py3.13+)
Simple Warnings
Auto call forwarding
Generator / async
Argument mapping
Argument Deprecation ✍️
Class / Enum proxy
Docstring injection
Version Tracking ✍️
Prevent Log Spam ✍️
Zero runtime deps
Custom Streams ✍️
CI audit tools
Testing helpers
Static checker signal ✍️
Decorator Stacking
Sphinx Plugin
MkDocs Plugin

✍️ = possible but requires manual implementation
warnings.deprecated in the stdlib on Python 3.13+ (PEP 702); also available as the typing_extensions.deprecated backport for Python < 3.13

Positioning guide reviewed for pyDeprecate v0.11.0.dev0, July 2026. This is not a full cell-by-cell external audit; open an issue if you spot an inaccuracy.

When to prefer warnings.deprecated (PEP 702): If your project targets Python 3.13+ and you only need simple call-site warnings visible to static type-checkers (mypy, pyright, IDEs), the stdlib decorator is the right choice — zero extra dependency. Choose pyDeprecate when you need call-forwarding, argument remapping, proxy wrapping of module-level constants, or CI audit tools — none of those exist in PEP 702.

Fair strengths in alternative tools worth considering:

  • warnings.deprecated is the strongest choice for static-only IDE/type-checker visibility; it also adds no per-call runtime overhead when the warning category is suppressed.
  • deprecation includes @fail_if_not_removed, a focused test helper for direct test-failure enforcement when removal deadlines are reached.
  • Deprecated includes deprecated.sphinx.versionadded / deprecated.sphinx.versionchanged decorators that inject Sphinx directives into docstrings for lifecycle annotation in Sphinx-built API docs.
  • warnings.warn remains the simplest solution for one-off internal warnings without compatibility requirements.

Where to go next🔗

Compatibility and fit🔗

Recent PyPI download statistics show broad production use; see pepy.tech for current numbers.

Topic Status
Python versions Project metadata currently supports Python 3.9+; Borda-maintained development policy targets Python 3.10+ because Python 3.9 reached end of life in October 2025.
Runtime dependencies None.
Optional audit extra packaging (plus tomli on Python < 3.11 for pyproject.toml version detection).
Optional CLI extra fire, rich.
Docs engines Sphinx and MkDocs compatible.
Type checker static warnings Prefer warnings.deprecated for Python 3.13+ static-checker-only cases.

When not to use pyDeprecate🔗

Use warnings.warn for one-off internal warnings that do not need compatibility behavior. Use warnings.deprecated for static-checker-only visibility on Python 3.13+. Use pyDeprecate when callers need forwarding, argument mapping, class or object aliases, warning frequency control, or CI audit checks.