Across the CPython Lib/ source tree, there around 70 places referring to DeprecationWarning that set no target removal version. Sometimes, the deprecated-since version is given, but not typically.
For example, to_bytes is marked and mentioned in “pending-removal-in-future.rst”
# urllib/parse.py
def to_bytes(url):
warnings.warn("urllib.parse.to_bytes() is deprecated as of 3.8",
DeprecationWarning, stacklevel=2)
return _to_bytes(url)
The use of positional count in re.sub is not, as far as I could see:
# re/__init__.py
import warnings
warnings.warn(
"'count' is passed as positional argument",
DeprecationWarning, stacklevel=2
)
A 5-year deprecation period is recommended, but it is also possible to not remove it indefinitely.
It says, “The warning message should include the release the incompatibility is expected to become the default and a link to an issue that users can post feedback to.” However, not all existing warnings follow this. Especially for deprecations that are not planned to be removed indefinitely, it is difficult to follow “the release the incompatibility is expected” because it does not exist.
I think your PR is good except that one line exceeds 80 characters.
Doesn’t this match the definition of soft deprecation under PEP 387?
The main difference between a “soft” and a (regular) “hard” deprecation is that the soft deprecation does not imply scheduling the removal of the deprecated API. – PEP 387
If a feature that have been deprecated without scheduling a removal yet, what is the earliest path for them to be removed? Let me give an example: gh-87999 was merged in 2021. Can that functionality removed now at any time (deprecated since 5 years) or would it be 5 years after scheduling a removal (PEP 387 is not completely clear on that). It the docs, gh-87999 is listed under “Pending removal in future versions” after “Pending Removal in Python 3.21”.
So, long story short: Would it actually make sense to merge the category “deprecated without a removal scheduled” into the category “soft deprecation”?
The PEP says soft-deprecation doesn’t issue a warning.
DeprecationWarning without schedule is not soft.
Another difference is that a soft deprecation does not issue a warning: it’s only mentioned in the documentation
I think it already meets the recommended 5-year deprecation period.
Since minimum deprecation period is two minor releases, I think the fastest path is to issue a scheduled deprecation warning from 3.16 and remove it in 3.18.
Of course, if approved by the SC, it is possible to remove it earlier as an exceptional case, but there is no need to do it that quickly.
We can base the decision on how widespread it is still used, such as amongst the top PyPI packages, on GitHub and https://grep.app. This can never represent actual usage in all the private and other places, but can be a useful proxy.
It also depends on the maintenance cost of the old code. Sometimes it’s only a single line of code or so, and it doesn’t really matter if we keep it indefinitely.
In general, including a removal version is useful, as it gives an actionable deadline rather than something that can be put off for another day. But we should also be aiming for the PEP’s recommended five years unless there’s a compelling reason for the minimum two years.
The cost of retaining the old interface indefinitely is the key.
Some deprecations aren’t worth escalating to removals because the API is an attractive nuisance (so we want to discourage new users from adopting it), but not detrimental enough (either to maintain or in use) to justify imposing the cost of a forced transition on the ecosystem as a whole.
It’s a spectrum from multiple supported interfaces through soft deprecation (old interfaces discouraged, but no programmatic nudge) and indefinite deprecation (old interfaces emit a warning if not filtered out) to actual legacy interface removal (affected code will eventually break outright unless updated to the new interface).