# Formalize the concept of "soft deprecation" (don't schedule removal) in PEP 387 "Backwards Compatibility Policy"

**URL:** <https://discuss.python.org/t/formalize-the-concept-of-soft-deprecation-dont-schedule-removal-in-pep-387-backwards-compatibility-policy/27957>\
**Category:** Core Development\
**Created:** [June 16, 2023, 10:04am UTC](https://discuss.python.org/t/formalize-the-concept-of-soft-deprecation-dont-schedule-removal-in-pep-387-backwards-compatibility-policy/27957 "2023-06-16T10:04:48Z")\
**Posts on this page:** 1\
**Showing post:** 73

<div class="post-metadata">

**Author:** ![encukou](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/encukou/32/2461_2.png) [@encukou](https://discuss.python.org/u/encukou)\
**Post date:** [July 3, 2023, 9:21am UTC](https://discuss.python.org/t/formalize-the-concept-of-soft-deprecation-dont-schedule-removal-in-pep-387-backwards-compatibility-policy/27957/73 "2023-07-03T09:21:13Z")

</div>

Lately I’ve been thinking about effects of our policies on users – specifically, them needing to litter their code with `if sys.version_info ≶…:` or `ifdef Py_HEX_VERSION ≶…` to avoid warnings for their users.  
If we don’t want to make them do that, but also want to remove old API eventually, and don’t want a massively breaking “4.0”, the process for API we’re in no rush to get rid of it could be:

- Leave old API be until the last version without a replacement goes EOL.
- Then, turn on `DeprecationWarning` and schedule removal – perhaps in another decade or so.

We’d need to keep a list. We kinda already do, in [What’s New](https://docs.python.org/3.12/whatsnew/3.12.html#pending-removal-in-future-versions), but something more directly usable by linters would be better.

* * *

> [@vstinner](#):
>
> [R Project](https://cran.r-project.org/web/packages/lifecycle/vignettes/stages.html): gentler form of deprecation designed to **prevent new uses** of a function and **encourage** package developers **to move away from it**. Soft deprecated allows a package to change its interface to encourage package developers to update their code before their users are forced to change.

That’s **Soft deprecated**. R also has **superseded** , which sounds pretty useful:

> A **superseded** function has a known better alternative, but the function itself is not going away . A superseded function will not emit a warning (since there’s no risk if you keep using it), but the documentation will tell you what we recommend instead.

(Ideally there’d be an easy way for linters to flag these in _new_ code…)

And **defunct** , which also sounds useful:

> **Defunct** comes after deprecated. In most cases, a deprecated function will eventually just be deleted. For very important functions, we’ll instead make the function defunct, which means that function continues to exist but the deprecation warning turns into an error. This is more user-friendly than just removing the function because users will get a clear error message explaining why their code no longer works and how they can fix it.

I imagine the API still has docs entry, so old URLs and cross-references work, but the description has been replaced by porting instructions.  
I love that idea.

* * *

Speaking of docs, I also like MDN icons (see e.g. the ToC sidebar for [Document](https://developer.mozilla.org/en-US/docs/Web/API/Document)), as a compact way to flag the status in overviews:

- 🗑 = deprecated
- ⚠ = non-standard/implementation-specific
- 🧪 = experimental/unstable

---

_[View the full topic](https://discuss.python.org/t/formalize-the-concept-of-soft-deprecation-dont-schedule-removal-in-pep-387-backwards-compatibility-policy/27957)._
