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?

20 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.

4 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?

2 Likes

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).

3 Likes

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.)

1 Like

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.
3 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

Just adding a timing perspective to this proposal.

Imagine that we had this back in python3.8 days. It came out in late 2019.
If something was deprecated in python3.8, we would only delete it in late 2024, when python3.13 came out. That’s how long it would take.

I think that 5 years is a very long period of time. 3 years seems like the best compromise between stability and inovation to me.

17 Likes

The central issue isn’t stability, really. It’s adoption, specifically adoption of new Python versions. That directly affects innovation, too. Every removal increases the burden on library maintainers, making it harder for them to test with new versions. If libraries can’t be used with a new version, users of that library can’t use the new version. That means they can’t use the new innovations, but it also means they can’t build (meaning further innovate) on those innovations. They can’t experience the new innovations and suggest improvements, issues and further innovations. The speed with which we remove things from Python is hampering innovation in Python.

15 Likes

Personally I don’t have any intention to rewrite my smarthome software (originally written by me) to move from asynccore to asyncio. I guess when I upgrade the stable distribution it runs on I’ll have to import the dumped modules from another source forever.

But this tells me that python is not viable for “write it once and use it forever” projects, since instead of making Python4 you decided to break something every release instead.

Of course for work I can keep using it, since they pay me to do constant maintenance. But having to do constant maintenance solely to be able to use the current openssl seems a bit of a waste of time.

Since there’s so many people in the world, I doubt I’m an isolated case.

5 Likes

I do wonder to what degree a longer deprecation period would actually help solve these issues instead of just giving us 3 years of relatively few issues and then facing the same problems we do now.

As somebody involved with bumping interpreter versions and dependencies in various settings what I have noticed is that such bumps are often blocked on projects that are less actively maintained as they used to be but that were notified of breaking changes well in advance.

To make it more concrete: if a project is using something that was deprecated in 3.10 in most cases issues are already opened during the beta or shortly after release of 3.10. However, they are not being picked up and then when 3.12 comes around people are scrambling to update the project, either through trying to get the attention of maintainers again or just forking the project. If we were to bump the period to 5 years I’m afraid we’ll just run into the issue when 3.15 comes around. At that point we’re back to square one because next year (3.16) we will be dealing with projects that didn’t migrate away from stuff in 3.11.
Of course the versions will be different depending on when this is accepted, but you get the point I hope.

I have honestly seen very few cases where an issue was opened during the beta/release of 3.10 and the two year period was “too short” for all the work to be done and a five year period would have been sufficient for the project to mitigate the deprecations.
To use my example in the way you framed the issue: if libraries can’t be used with version 3.10, users of the library also can’t use 3.10. We are now running into people facing issues with adopting 3.12 and to me this proposal only seems to move the problem to the adoption of 3.15.

I hope you forgive me for liberally paraphrasing you.

1 Like