Updating PEP 387 to prefer 5 year deprecations instead of 2 years

I would like to propose to the SC the following change to PEP 387 (note you will need to scroll the code block to see it all):

diff --git a/peps/pep-0387.rst b/peps/pep-0387.rst
index dec4868e..883bd6cd 100644
--- a/peps/pep-0387.rst
+++ b/peps/pep-0387.rst
@@ -168,10 +168,11 @@ several releases:
 
 3. Wait for the warning to appear in at least two minor Python
    versions of the same major version, or one minor version in an older
-   major version (e.g. for a warning in Python 3.10.0, you either wait
-   until at least Python 3.12 or Python 4.0 to make the change).
-
-   It's fine to wait more than two releases, for example:
+   major version (e.g., for a warning in Python 3.10.0, you either wait
+   until at least Python 3.12 or Python 4.0 to make the change). It is
+   preferred, though, to wait 5 years before removal (e.g., warn starting in
+   Python 3.10, removal in 3.15; this happens to coincide with the current
+   lifetime of a minor release of Python).
 
    - If the expected maintenance overhead and security risk of the
      deprecated behavior is small (e.g. an old function is reimplemented

Effectively I’m trying to say that while the minimum for a deprecation is still 2 years, we should strive for 5 years. That covers the lifetime of a minor release and means people don’t have an excuse for being caught off-guard by a removal. It also explicitly does not tie this to the EOL of a release so that they are decoupled.

Any objections to this idea?

16 Likes

If you’re trying to really smooth out the process, one more year would be ideal. I would love to split dropping support for a version, adding support for a version, and migrating to new features / purging deprecated APIs into three (or four) separate tasks. In my experience, I have contributors who I would readily assign to each task while not expecting them to be interested in the others.

That said, minimizing the need for if sys.version_info[:2] >= ... blocks would already be a huge improvement, so I’m still pleased to see this.

3 Likes

Isn’t the proposed example (“warn starting in Python 3.10, removal in 3.14”) showing a 4 years wait rather than 5 years?

1 Like

Yep, it’s a typo. Talking about too many releases at the core dev sprint. :sweat_smile: I’ll fix the example.

2 Likes

Why would another year past the lifetime of the first release with the deprecation specifically help? I mean I’m sure never removing would help some people, but we have to draw the line somewhere.

This is a great change.

It might be nice to include some words to serve as the basis for discussion if someone wants to effect a removal sooner, i.e. move a specific onus onto the remover to mention why some condition holds. Maybe:

However, it is preferred to wait 5 years before removal — especially
if the maintenance burden is small or impacted users are not rare
(e.g., warn starting in Python 3.10, removal in 3.15; this happens to
coincide with the current lifetime of a minor release of Python).

1 Like

I’m generally in favor of supporting things as long as possible, so sounds good to me. :slight_smile: I agree that having the deprecation period span a full minor release is important to allow a smooth transition.

The main thing that would be nice is a period between the need to continue supporting a Python version that contains a deprecated feature but lacks its replacement and demands to support a Python version that has removed the deprecated feature. I’ll note that Python 3.8 is not quite EOL, and I’m already getting support requests for Python 3.13 as Fedora rushes to have its entire package repository ready to adopt 3.13.

Another way to achieve the same thing is to deprecate replaced APIs one release after their replacement is released.

---old-feature-python----|
   |---new-feature-python---------
       |-----deprecation-----|
     breathing-space --> |---|

Edit: Also, apologies if this proposal already achieves what I’m suggesting, and I’m suffering from an off-by-one error. And again, this is still an improvement.

2 Likes

I agree that this is the best way,. We shouldn’t cut our suspenders until our belt is secure. :slight_smile: My sense is that there is a preference for deprecation periods to be specified in terms of years or releases rather than in terms of the lifespan of particular functionality, but I certainly would prefer an explicit policy along the lines of “no feature will be removed until after an alternative is added”.

That seems much too strict, as it implies that no feature should ever be removed, even if there’s no longer a need for it (or the need has become so esoteric that it is better met by a third-party).

1 Like

That’s true, I was assuming the preceding context where we’re talking about “a new way of doing X”, but I didn’t make that explicit. What we want to avoid is a situation where we have a new way and an old way and a gap in the middle where there’s no way. (I also tend to think we should be quite reluctant to remove functionality entirely, but that’s a somewhat distinct issue.)

I support adding an optional&recommended 3-year deprecation period.

I want to resolve DeprecationWarnings as soon as possible. When there are neglected DeprecationWarnings, it becomes easier to overlook warnings that need to be fixed quickly.
Therefore, even if the deprecation period becomes longer, I will still need to write version-specific branching code immediately.

To make the transition smoother, how about reusing PendingDeprecationWarning?

Currently, when running unittest or pytest, PendingDeprecationWarning is displayed along with DeprecationWarning. -Wd option also display both warnings.

My proposal is:

  • Use PendingDeprecationWarning in additonal deprecation period.
  • unittest doesn’t show PendingDeprecationWarning by default. It has an option to enable PendingDeprecationWarning.
  • devmode shows DeprecationWarning but PendingDeprecationWarning.
2 Likes

If you want to test on pre-releases of Python (which is hard not to since, even if you’d rather wait, there are always downstream users who feel otherwise) then a Python version’s life cycle is more like 5.5 years.

3 Likes

If other people come forward and ask for 6 years then I’m willing to consider it, but if something was deprecated in 3.8 then why not replace it before 3.13 comes out? The hope is it would have been dealt w/ already, so something leaving in 3.13 isn’t impossible. And something deprecated in 3.9 means you have until 3.14 before it goes away.

So basically you’re trying to avoid your code ever triggering the deprecation warning?

That’s a bigger change than I’m willing to propose as my proposal changes a number while yours changes the actual approach. Getting to where we are now took years and I don’t want to drive that conversation again (but you can totally try to yourself if you’re passionate about this!).

1 Like

I don’t want to start up the whole PendingDeprecationWarning discussion personally, but obviously you can if you’re up for it.

2 Likes

Apologies for the poor communication, but I feel like attempting to clarify again would result in me saying the same things. Consider the request withdrawn.

1 Like