Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pip does not support PEP 440-style prefix matches for pre-releases #12235

Closed
1 task done
vyasr opened this issue Aug 22, 2023 · 5 comments
Closed
1 task done

pip does not support PEP 440-style prefix matches for pre-releases #12235

vyasr opened this issue Aug 22, 2023 · 5 comments
Labels
resolution: duplicate Duplicate of an existing issue/PR

Comments

@vyasr
Copy link

vyasr commented Aug 22, 2023

What's the problem this feature will solve?

I would like to be able to specify alphas as dependencies in my package metadata where the alphas are constrained to a particular version. I would like to be able to use PEP 440-compliant versioning so that the behavior is predictable and consistent with the rest of the ecosystem's approach for specifying versions.

Describe the solution you'd like

The pip documentation on pre-releases indicates that there are two ways to install pre-releases: 1) with --pre, or 2) by specifying a constraint incorporating the pre-release like >=0.0.dev0. It's not clear to me whether pip intends to support the entire PEP 440 syntax, but according to PEP 440 it should also be possible to specify a pre-release by using an exact version match with a suffixed .* e.g. ==0.0.* would match 0.0a1 (see the Version matching section). It would be nice if pip also exhibited this behavior, but it does not: as of the time of this writing, pip download "numpy==1.26.*" --no-deps will not download the latest numpy 1.26.b1 beta. pip download "numpy>=1.26.*" --no-deps will, but AFAICT this requirement spec isn't actually PEP 440-compliant. packaging agrees:

>>> from packaging.version import Version                                                                                                                                                            [2/908]
>>> Requirement("numpy>=1.26.*").specifier.contains(Version("1.26.0b1"), prereleases=True)
>>> Requirement("numpy>=1.26.*").specifier.contains(Version("1.26.0b1"), prereleases=True)
Traceback (most recent call last):
...
    raise ParserSyntaxError(
packaging._tokenizer.ParserSyntaxError: .* suffix can only be used with `==` or `!=` operators
    numpy>=1.26.*
         ~~~~~~~^

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
...
packaging.requirements.InvalidRequirement: .* suffix can only be used with `==` or `!=` operators
    numpy>=1.26.*

Alternative Solutions

I can work around the issue by using the >= syntax with the prefix, or by modifying the version specifier to explicitly include a pre-release segment. It's not difficult to do, so this issue is not blocking me.

Additional context

N/A

Code of Conduct

@vyasr vyasr added S: needs triage Issues/PRs that need to be triaged type: feature request Request for a new feature labels Aug 22, 2023
@vyasr
Copy link
Author

vyasr commented Aug 22, 2023

There do appear to be various edge cases in the way that this type of PEP 440 string is supported that make the current state difficult to use, however. Here's an example of one challenge that is probably only partly pip's responsibility, but I'm not quite sure that there is a single best place to report such an issue since it touches multiple parts of the toolchain typically used to build a package.

If I have a pyproject.toml file like this:

  [build-system]
  requires = [
      "setuptools",
      "numpy==1.26.*",
  ]
  build-backend = "setuptools.build_meta"

  [project]
  name = "my_numpy_meta"
  version = "0.0.0"
  dependencies = [
      "numpy==1.26.*",                                                                                                                                                                                        ]

If I run pip wheel . in a directory with this pyproject.toml file, it fails to install build dependencies because pip won't find the 1.26.0b1 beta. I can change the build requirement to numpy>=1.26.*, in which case it successfully creates the build env and generates the wheel. When it gets around to installing runtime dependencies it fails again as expected. However, in this case I cannot fix it by changing the dependency specifier to >= because in this case that violates PEP 508:

  configuration error: `project.dependencies[0]` must be pep508                                                                                                                                     [16/813]
  DESCRIPTION:
      Project dependency specification according to PEP 508

  GIVEN VALUE:
      "numpy>=1.26.*"

  OFFENDING RULE: 'format'

  DEFINITION:
      {
          "$id": "#/definitions/dependency",
          "title": "Dependency",
          "type": "string",
          "format": "pep508"
      }
  Traceback (most recent call last):
...
      raise ValueError(f"{error}\n{summary}") from None
  ValueError: invalid pyproject.toml config: `project.dependencies[0]`.
  configuration error: `project.dependencies[0]` must be pep508

@uranusjr
Copy link
Member

See pypa/packaging#100. pip is unfortunately blocked by #11715 to merge the change.

@uranusjr uranusjr closed this as not planned Won't fix, can't repro, duplicate, stale Aug 23, 2023
@uranusjr uranusjr added resolution: duplicate Duplicate of an existing issue/PR and removed type: feature request Request for a new feature S: needs triage Issues/PRs that need to be triaged labels Aug 23, 2023
@uranusjr
Copy link
Member

But even with the change, ==0.0.* would not match 0.0a1 by default; you need to pass --pre.

@vyasr
Copy link
Author

vyasr commented Aug 23, 2023

Hmm so then is there no way to specify a package's dependencies in pyproject.toml that allows for pre-release dependencies? I assumed it would be possible based on the following:

if a requirement specifier includes a pre-release or development version (e.g. >=0.0.dev0) then pip will allow pre-release and development versions for that requirement.

Does that only apply to command line specs for pip install commands and not specs inside a package's metadata?

Would something like >=0.0.0a0 work?

@uranusjr
Copy link
Member

Would something like >=0.0.0a0 work?

Yes.

https://peps.python.org/pep-0440/#handling-of-pre-releases

Dependency resolution tools SHOULD also allow users to request the following alternative behaviours:

  • accepting pre-releases for all version specifiers

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 23, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
resolution: duplicate Duplicate of an existing issue/PR
Projects
None yet
Development

No branches or pull requests

2 participants