Skip to content

Final and prerelease control for package selection#13647

Merged
notatallshaw merged 7 commits intopypa:mainfrom
notatallshaw:final-and-prerelease-control
Jan 25, 2026
Merged

Final and prerelease control for package selection#13647
notatallshaw merged 7 commits intopypa:mainfrom
notatallshaw:final-and-prerelease-control

Conversation

@notatallshaw
Copy link
Member

@notatallshaw notatallshaw commented Nov 15, 2025

Fixes #13221
Fixes #12470
Fixes #5503

This PR adds two new flags --all-releases and --only-final, they control package selection with the exact same semantics as --no-binary and --only-binary, but for pre vs final releases instead of binary vs. source distributions.

They are mutually exclusive with --pre, as there are edge cases to do with the semantics of --pre and these flags I didn't want to have to define. However, when only --pre is used it is converted to the equivalent --all-releases :all: in the code, to keep the logic simple.

The main feature I think users will be interested is only allowing final releases, to prevent pre-releases from being selected in any situation, e.g.

$ pip install --dry-run opentelemetry-exporter-prometheus  --only-final ":all:"
ERROR: Ignored the following yanked versions: 1.10a0, 1.12.0rc1
ERROR: Could not find a version that satisfies the requirement opentelemetry-exporter-prometheus (from versions: 0.12b0, 0.13b0, 0.14b0, 0.15b0, 0.16b0, 0.16b1, 0.17b0, 0.29b0, 0.30b0, 0.30b1, 0.32b0, 0.33b0, 0.34b0, 0.35b0, 0.36b0, 0.37b0, 0.38b0, 0.39b0, 0.40b0, 0.41b0, 0.42b0, 0.43b0, 0.44b0, 0.45b0, 0.46b0, 0.47b0, 0.48b0, 0.49b0, 0.49b1, 0.49b2, 0.50b0, 0.51b0, 0.52b0, 0.52b1, 0.53b0, 0.53b1, 0.54b0, 0.54b1, 0.55b0, 0.55b1, 0.56b0, 0.57b0, 0.58b0, 0.59b0)
ERROR: No matching distribution found for opentelemetry-exporter-prometheus

@notatallshaw notatallshaw force-pushed the final-and-prerelease-control branch 2 times, most recently from 5b4b0c1 to dbd03ab Compare November 15, 2025 03:43
@potiuk
Copy link
Contributor

potiuk commented Nov 15, 2025

Very nice - and very neeeded :)

Copy link
Member

@ichard26 ichard26 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First pass review. I'll need to take another look at this. Overall, logic looks good, but I'd like to take another look at the code.

Comment on lines +46 to +47
self.cmd_opts.add_option(cmdoptions.all_releases())
self.cmd_opts.add_option(cmdoptions.only_final())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I noted in the --uploaded-prior-to PR, I believe it would be better if we grouped our command options more aggressively. Any command that accepts --no-binary (and friends) should also support --only-final and --all-releases for free.

This can be addressed as a follow up since the scope would be larger than any of these two PRs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm up for grouping, but given there's no convenient existing group I'd rather do it in a much smaller follow up PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good!

@notatallshaw notatallshaw force-pushed the final-and-prerelease-control branch from ca2ffab to 44a24fe Compare January 10, 2026 16:27
@notatallshaw
Copy link
Member Author

notatallshaw commented Jan 10, 2026

This PR is ready for review/approval.

FYI, for some reason my remote origin and the remote upstream branches got out of sync in a way that was difficult to fix, I think I've managed to resolve this now though and apply all the review suggestions, but I might do a rebase to make the commits a bit cleaner.

The majority of the code in this PR is tests, the majority of the logic in this PR is CLI handling, the functional logic is actually quite simple.

Copy link
Member

@ichard26 ichard26 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! I'd like someone else to quickly give this a look over to make sure I didn't miss anything, but the tests are comprehensive enough to give me confidence this is ready to go.

I've pushed a commit to clean up the functional tests to use the modern test helpers I've recently added. I'm not sure about you, but I find the --no-cache-dir and --no-index flags distracting when trying to figure out what a test is doing.


If you're curious: review checklist

Feature quality

  • Does the change pass the "least surprising behaviour" test?
  • Has any required documentation been added?
  • What are the potential edge cases and failure modes? Are they handled appropriately? In particular, is the error handling user-friendly?

Code quality

  • Are tests comprehensive, readable, and well scoped?
  • Are tests using best practices and modern patterns? (RS: I will address this myself)
  • If the change adds tech debt, is there a plan for reducing/managing it?

@ichard26
Copy link
Member

but I might do a rebase to make the commits a bit cleaner.

Feel free to do so. I'm done reviewing so force pushes isn't going to be a problem 👍

@notatallshaw notatallshaw force-pushed the final-and-prerelease-control branch from 0823e58 to 7000e51 Compare January 11, 2026 18:52
@notatallshaw notatallshaw force-pushed the final-and-prerelease-control branch from 7000e51 to e18e237 Compare January 11, 2026 19:24
@notatallshaw
Copy link
Member Author

I'd like someone else to quickly give this a look over to make sure I didn't miss anything

FYI I will do one final pass myself, but I plan to merge this before 26.0 if there is no rejection.

I see this PR as going hand in hand with #13746 which completes most of pip's conformance to the version specifier spec, as a consequence pre-releases will be selected in certain edge cases where they are not now, and the specification says tools SHOULD provide a way to exclude all pre-releases.

@notatallshaw
Copy link
Member Author

FYI, packaging 26.0 is in, I will do a few smoke tests to ensure behavior works as expected with the new packaging, and then I plan to merge this this weekend.

As a reminder --all-releases <package> is a per-package control of enabling pre-releases by default, and --only-final <package> is a per-package control of disallowing pre and dev releases, with additional :none: and :all: syntax to clear or select all packages, same as --no-binary and --only-binary.

@notatallshaw notatallshaw merged commit c782c6b into pypa:main Jan 25, 2026
28 checks passed
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 10, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

3 participants