PEP 440 - Request additional example(s) be added to remove ambiquity

Introduction

I went down a rabbit hole today with poetry Issue 7047 (hyperlink removed due to 2 link limit for new users) That more or less arose due to (what i feel was) ambiguity inside the PEP 440 spec. The core of issue was that PEP 440 was not IMO clear on how to handle ">=1.3.0" when only "1.3.0rc1" was available.

I read PEP 440 and understood that 1.3.0rc1 would be a valid solution due to it falling into the following category in #handling-of-pre-releases

  • accept remotely available pre-releases for version specifiers where there is no final or post release that satisfies the version specifier

However, the poetry maintainer had another understanding of the spec that I could find no fault with given the literal text of PEP 440. In summary they argued that 1.3.0rc1 was less than 1.3.0 and thus not a valid solution, however if no 1.3.0 existed but a 1.3.1rc1 did that would be a valid solution due to it being >=1.3.0.

There was some additional confusion here as tools like pip & pipenv considered 1.3.0rc1 to be a valid solution for >=1.3.0 whereas poetry did not for the aforementioned reason.

Request

In PEP 440 it makes the callout that

The versioning specification may be updated with clarifications without requiring a new PEP or a change to the metadata version.

Therefore I’m asking that the pre-release / examples section in PEP 440 be updated to include several example(s) to illustrate the intent of the spec (one way or the other).

i.e. something like

`>=3.1`: version 3.1dev0 or later

Or

`>=3.1`: version 3.1 or later
2 Likes

I think that this should be moved under documentation.

It’s probably better under Packaging, as this isn’t part of the core Python docs.

1 Like

I think there’s two steps to ‘solving’ this:

  1. Does the version specification include a prerelease version? Or are there only prereleases available? If either are true, prereleases can be included.

So in the case of >=1.3.0 when only 1.3.0rc1 is available, prereleases can be included and the next step is:

  1. Determining which of the following are true:
  • 1.3.0rc1>1.3.0
  • 1.3.0rc1==1.3.0
  • 1.3.0rc1<1.3.0

At https://peps.python.org/pep-0440/#summary-of-permitted-suffixes-and-relative-ordering, the PEP says:

Within a numeric release (1.0, 2.7.3), the following suffixes are permitted and MUST be ordered as shown:

.devN, aN, bN, rcN, <no suffix>, .postN

Which means that indeed 1.3.0rc1<1.3.0 and thus 1.3.0rc1 does not satisfy >=1.3.0.

And we can see that the packaging library confirms this as well:

>>> from packaging.version import Version
>>> Version('1.3.0rc1') >= Version('1.3.0')
False
>>> Version('1.3.0rc1') < Version('1.3.0')
True

That said, based on some related open issues (https://github.com/pypa/pip/issues/9121, https://github.com/pypa/pip/issues/5503, etc) it seems like pip’s implementation of PEP 440 is already known to be somewhat faulty regarding prereleases.

This matches my intuition when reasoning about versions, regardless of what the tools currently do. However, maybe the behavior (whether the rc1 satisfies the constraint or not) should depend on a flag, e.g. pip install --pre?

Thanks for confirming / reviewing. Would it be possible to include this or something very similar as an example in the PEP 440 section mentioned above?

As for the pip thing it certainly contributed to the confusion so I hope it gets resolved but if the example gets added it will help prevent some of that confusion.

Genenrally, once marked Final PEPs don’t get updated. They are intended to be the historical record of the change proposal, discussion, and resolution, not the living documentation.

Normally, I wouldn’t ask however that PEP specifically called out the following

The versioning specification may be updated with clarifications without requiring a new PEP or a change to the metadata version.

If that comment wasn’t in reference to the example(s) section for clarifications in the PEP what was it referencing?

Best thing to do is to file a PR against the PEPs repo and @-ping the authors.

I would say that quote should not have been in the PEP in the first place. Everything should be going to PyPA specifications - Python Packaging User Guide at this point, and if a PEP hasn’t been migrated over to there then it’s simply lacking someone to take the time to do it.

1 Like

Moving PEP 440 to instead a “Python Version Specification” under packaging.python.org, and making PEP 440 prominently and consistently link to it would be great to have.

No one has volunteered to do this yet though.

1 Like

What needs to be done? Just copying the file over and removing the PEP specific parts, or am I missing some crucial part?

For a first pass, that’s probably good enough. After that we can see how it feels/flows and consider tweaking it to read better if need be.