Borda/pyDeprecate: v0.13.0: PEP 702 metadata and deprecation policy lint
Abstract
pyDeprecate v0.13.0 aligns __deprecated__ with PEP 702: it's now the plain conformant message string every PEP-702-aware tool expects, with pyDeprecate's own config moved to the new __deprecation_config__ attribute and read through the public get_deprecation_config(). Alongside the metadata split, a deprecation-governance lint (validate_deprecation_policy() / pydeprecate policy) checks that each deprecation gives callers a fair grace window before the removal PR lands, and every audit-scanning function gained an exclude= filter to keep frozen legacy trees out of package-wide scans. ✨ Spotlights __deprecated__ now follows PEP 702 from deprecate import deprecated, get_deprecation_config def new_func(): return "new behavior" @deprecated(target=new_func, deprecated_in="1.0", remove_in="2.0") def old_func(): return new_func() get_deprecation_config(old_func).target is new_func # True — replaces old_func.__deprecated__.target Deprecation policy lint pydeprecate policy path/to/your/package # exit 1 on a violation, e.g. too-short grace window or a message naming no replacement exclude= on every audit scan from deprecate import find_deprecation_wrappers find_deprecation_wrappers("my_package", recursive=True, exclude=["my_package.tests", "*._legacy*"]) 🔄 Migration guide __deprecated__ is now a plain PEP 702-conformant message string, not the DeprecationConfig object. The config object moved to __deprecation_config__. Code reading func.__deprecated__.target, .deprecated_in, .args_mapping, or any other config field, or checking isinstance(func.__deprecated__, DeprecationConfig), now gets a plain str and either raises AttributeError or evaluates False. Affects every wrapper kind — functions, methods, class proxies, instance proxies, and modules. # BEFORE (v0.12 and earlier) config = old_func.__deprecated__ target = config.target # AFTER (v0.13+) from deprecate import get_deprecation_config config = get_deprecation_config(old_func) target = config.target get_deprecation_config() also reads the pre-v0.13 layout, so it works unchanged against objects built by an older pyDeprecate release. 📝 Notable changes 🚀 Added Deprecation policy governance lint — validate_deprecation_policy() and the pydeprecate policy CLI subcommand check whether each deprecation was scheduled responsibly: a minimum grace window between deprecated_in/remove_in, and a warning message that names a replacement. Runs advisory-only inside pydeprecate all; the dedicated subcommand is the real gate. (#231) exclude on every audit scan — find_deprecation_wrappers(), validate_deprecation_expiry(), validate_deprecation_policy(), validate_deprecation_chains(), validate_mapping_compatibility(), and generate_deprecation_table() take a keyword-only exclude list of glob patterns over dotted module names; a matching module is never imported by the scan. (#231) Public get_deprecation_config(obj) metadata accessor — reads the v0.13 __deprecation_config__ and falls back to the pre-v0.13 __deprecated__ layout for mixed-version installs. (#230) pydeprecate coding-agent plugin for Codex and Claude Code — ships shared sunset and prune skills under plugins/pydeprecate/, packaged separately from the pip distribution. (#232) ⚠️ Breaking Changes __deprecated__ now stores a PEP 702 message string, not the DeprecationConfig object. See Migration guide above. (#230) 🌱 Changed Griffe's docstring-replacement guard now checks get_deprecation_config(obj) is not None instead of a bare __deprecated__ truthiness check — a foreign object decorated only with warnings.deprecated/typing_extensions.deprecated no longer gets mis-treated as a pyDeprecate wrapper. (#230) 🔧 Fixed Custom message_template placeholders that don't apply to the current target mode no longer raise KeyError — they render as empty strings instead. (#230) 🏆 Contributors Jirka Borovec (@Borda, LinkedIn) — the PEP 702 __deprecated__/__deprecation_config__ split, the deprecation policy lint, the exclude audit filter, and the shared Codex/Claude Code deprecation-workflow plugin Full changelog: https://github.com/Borda/pyDeprecate/compare/v0.12.0...v0.13.0
Publication details
- Journal / source
- Zenodo (CERN European Organization for Nuclear Research)
- Publication date
- 21 September 2026