packaging icon indicating copy to clipboard operation
packaging copied to clipboard

Cannot allow pre-/developmental releases in a Requirement

Open genevieve-me opened this issue 10 months ago • 2 comments

I recently hit the following unexpected behavior with packaging:

>>> Requirement("foo>=3.0").specifier.contains("3.1.10.dev1")
False

I took a look at the version string specification, and it seems to suggest that this should be valid.

Developmental releases are ordered by their numerical component, immediately before the corresponding release (and before any pre-releases with the same release segment), and following any previous release (including any post-releases).

Edit: It does make sense that packaging chooses to default to not treating pre-release and developmental releases as the latest version, as consumers of the project may prefer to only get stable releases. But I still wanted to raise this issue to ask about the rationale, and if it is possible to add a feature to Requirement to allow pre-releases in the same way that SpecifierSets have prereleases=True.

I noticed that the documentation say that prereleases=None (the default) has different behavior than prereleases=False, but I can't seem to find more information on it. These results are quite unexpected to me (the first one makes sense after some thought, the second and third I would expect to be true, and the fourth makes sense but I'm not sure why the >= is necessary):

>>> packaging.requirements.Requirement("foo>1.0").specifier.contains("3.0b1")
False
>>> packaging.requirements.Requirement("foo>0.1a1").specifier.contains("1.0a1")
False
>>> packaging.requirements.Requirement("foo>0.1.dev1").specifier.contains("1.0.dev1")
False
>>> packaging.requirements.Requirement("foo>=0.1.dev1").specifier.contains("1.0.dev1")
True

genevieve-me avatar Apr 05 '24 01:04 genevieve-me

FYI I believe some important parts of the spec that related to this:

https://packaging.python.org/en/latest/specifications/version-specifiers/#handling-of-pre-releases

Pre-releases of any kind, including developmental releases, are implicitly excluded from all version specifiers, unless they are already present on the system, explicitly requested by the user, or if the only available version that satisfies the version specifier is a pre-release.

https://packaging.python.org/en/latest/specifications/version-specifiers/#exclusive-ordered-comparison

The exclusive ordered comparison <V MUST NOT allow a pre-release of the specified version unless the specified version is itself a pre-release. Allowing pre-releases that are earlier than, but not equal to a specific pre-release may be accomplished by using <V.rc1 or similar.

I beleive in your list of four examples the second and third are bugs, due to the last part of this spec I quoted, I recently created an issue for it https://github.com/pypa/packaging/issues/788

notatallshaw avatar Apr 13 '24 16:04 notatallshaw

I still wanted to raise this issue to ask about the rationale

You will have to do some code spelunking to find that out since the docstring for the abstract method is a decade old.

But my guess is most people don't want to install pre-releases, so the defaults reflect that in a broad way without trying to be clever about detecting on using pre-releases on both sides and assuming that's on purpose.

if it is possible to add a feature to Requirement to allow pre-releases in the same way that SpecifierSets have prereleases=True

What would you expect that to do? propagate through Requirement.specifier?

brettcannon avatar Aug 07 '24 23:08 brettcannon