v0.8.0: Default TargetMode enum & CLI audit tools
🎉 pyDeprecate 0.8.0
pyDeprecate 0.8.0 is the TargetMode enum & CLI tooling release — deprecation intent is now typed and explicit, warn-only deprecation is the default, and a new pydeprecate CLI lets you scan any package for misconfigured wrappers without writing a single audit script.
Summary
v0.8.0 centers on TargetMode: a proper enum (TargetMode.NOTIFY, TargetMode.ARGS_REMAP) replacing the target=None / target=True boolean sentinels. The old sentinels still work — they emit FutureWarning at decoration time — so you've got a full release cycle to migrate before they're removed in v1.0.
target now defaults to TargetMode.NOTIFY, so the most common pattern — warn callers and run the original body unchanged — needs nothing more than deprecated_in and remove_in:
@deprecated(deprecated_in="1.0", remove_in="2.0")
def old_fn(): ...A new pydeprecate CLI (four subcommands) rounds out the release. Run pydeprecate check path/to/mypackage to surface misconfigured wrappers across a whole codebase in seconds.
🚀 Spotlights
TargetMode enum
from deprecate import deprecated, TargetMode
# Warn-only: source body executes unchanged
@deprecated(target=TargetMode.NOTIFY, deprecated_in="0.8", remove_in="1.0")
def old_api(): ...
# Argument-rename: warns only when old arg name is passed
@deprecated(
target=TargetMode.ARGS_REMAP,
deprecated_in="0.8",
remove_in="1.0",
args_mapping={"old_param": "new_param"},
)
def new_api(new_param): ...TargetMode is exported from deprecate and works everywhere target= is accepted: @deprecated, deprecated_class(), and deprecated_instance().
Zero-boilerplate warn-only deprecation
target is now optional — TargetMode.NOTIFY is the default. Drop the target= entirely:
@deprecated(deprecated_in="0.8", remove_in="1.0")
def old_fn(): ...Omitting deprecated_in now surfaces a UserWarning at decoration time, not silently at call time, so misconfiguration is visible immediately.
pydeprecate CLI
pydeprecate check path/to/mypackage # validate wrapper configuration
pydeprecate expiry path/to/mypackage # find wrappers past remove_in date
pydeprecate chains path/to/mypackage # detect deprecated→deprecated chains
pydeprecate all path/to/mypackage # run all three in one passAlso available as python -m deprecate. Requires pip install 'pyDeprecate[cli]' for all subcommands (fire dependency). expiry additionally needs pip install 'pyDeprecate[audit]'. Or install both: pip install 'pyDeprecate[cli,audit]'.
Migration guide
No breaking changes. All v0.7.x code continues to run. The items below emit deprecation warnings now and will be removed in v1.0.
target=None → TargetMode.NOTIFY
# before — emits FutureWarning at decoration time
@deprecated(target=None, deprecated_in="0.8", remove_in="1.0")
def old_fn(): ...
# after — explicit or implicit (default)
@deprecated(target=TargetMode.NOTIFY, deprecated_in="0.8", remove_in="1.0")
def old_fn(): ...
# simplest form — NOTIFY is the default
@deprecated(deprecated_in="0.8", remove_in="1.0")
def old_fn(): ...target=True → TargetMode.ARGS_REMAP
# before — emits FutureWarning at decoration time
@deprecated(target=True, deprecated_in="0.8", remove_in="1.0", args_mapping={"old_arg": "new_arg"})
def new_fn(new_arg): ...
# after
@deprecated(target=TargetMode.ARGS_REMAP, deprecated_in="0.8", remove_in="1.0", args_mapping={"old_arg": "new_arg"})
def new_fn(new_arg): ...DeprecationWrapperInfo field renames
| Old name | New name | Removed in |
|---|---|---|
empty_mapping |
empty_args_mapping |
v1.0 |
identity_mapping |
identity_args_mapping |
v1.0 |
# before
if info.empty_mapping or info.identity_mapping:
...
# after
if info.empty_args_mapping or info.identity_args_mapping:
...DeprecationConfig.target no longer stores raw sentinels
Code that inspects wrapper.__deprecated__.target and compares against None or True must update:
# before
assert fn.__deprecated__.target is None
# after
from deprecate import TargetMode
assert fn.__deprecated__.target is TargetMode.NOTIFYNotable changes
Added
TargetModeenum (NOTIFY,ARGS_REMAP) exported fromdeprecate— typed replacement fortarget=None/target=Truesentinels. (#150)targetdefaults toTargetMode.NOTIFYon@deprecated— warn-only deprecation now requires onlydeprecated_inandremove_in. (#162)pydeprecateCLI —check,expiry,chains,allsubcommands.template_mgsandargs_extraondeprecated_class()anddeprecated_instance()— proxy factories now at full parity with@deprecated. (#150)DeprecationWrapperInfo.empty_deprecated_in—Truewhendeprecated_inis absent; for CI pipeline use. (#166)DeprecationConfig.misconfigured—Truewhen an invalid raw target sentinel (False) was passed at decoration time; surfaced viaDeprecationWrapperInfo.misconfigured_target. (#150)num_warns=0documented — equivalent tostream=None; suppresses all warnings. (#150)- Stacked-callable-target guard —
@deprecated(target=callable_a)stacked over another callable-target wrapper now emitsUserWarningat decoration time instead of crashing withTypeErrorat call time. (#169) template_mgsvalidated at decoration time — malformed%-style placeholders raiseValueErrorimmediately. (#169)
Changed
DeprecationConfig.targetnormalized at decoration time — storesTargetModeorCallable, never rawNone/True/False. (#150)- Misconfigured
TargetModecombos warn at construction time —ARGS_REMAPwithoutargs_mapping,NOTIFYwithargs_mappingorargs_extraall emitUserWarningimmediately. (#150) - Docs site URL layout versioned — content now at
https://borda.github.io/pyDeprecate/stable/(and/<tag>/); the bare root redirects tostable/. Existing bookmarks to flat paths will break on first deploy. (#148) - CLI chains reporting —
checksubcommand reports chains as warnings;chains/allsubcommands report chains as errors. (#149)
Deprecated
target=None— useTargetMode.NOTIFY. EmitsFutureWarning. Removed in v1.0. (#150)target=True— useTargetMode.ARGS_REMAP. EmitsFutureWarning. Removed in v1.0. (#150)target=False— never valid; now emitsUserWarning, treated asTargetMode.NOTIFY. RaisesTypeErrorin v1.0. (#150)DeprecationWrapperInfo.empty_mapping→empty_args_mapping. EmitsDeprecationWarning. Removed in v1.0. (#166)DeprecationWrapperInfo.identity_mapping→identity_args_mapping. EmitsDeprecationWarning. Removed in v1.0. (#166)
Fixed
- PEP 702 stacking crash —
@deprecatedstacked under@typing.deprecatedno longer raisesAttributeErroron__deprecated__lookup. (#169) - Double
FutureWarningondeprecated_class()in NOTIFY mode. (#162) - Cross-class guard false positives — metaclass/dynamic-class qualnames and pre-applied decorators that rewrite
__qualname__no longer trigger spuriousTypeErrorat decoration time; the guard still raises for genuine cross-class forwarding. (#169) args_mappingrename no longer clobbers source default when both old and new parameter names are supplied simultaneously. (#150)
🏆 Contributors
- Onuralp SEZER (@onuralpszr) — initial CLI scaffolding (#76)
- Jiri Borovec (@Borda) —
TargetModeenum, CLI subcommands, proxy parity, cross-class guard hardening, docs site restructure
Full changelog: v0.7.0...v0.8.0