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

pep440: fix version ordering #1883

Merged
merged 1 commit into from
Feb 22, 2024
Merged

pep440: fix version ordering #1883

merged 1 commit into from
Feb 22, 2024

Conversation

BurntSushi
Copy link
Member

A couple moons ago, I introduced an optimization for version comparisons
by devising a format where most versions would be represented by a
single u64. This in turn meant most comparisons (of which many are
done during resolution) would be extremely cheap.

Unfortunately, when I did that, I screwed up the preservation of
ordering as defined by the Version Specifiers spec. I think I messed
it up because I had originally devised the representation so that we
could pack things like 1.2.3.dev1.post5, but later realized it would
be better to limit ourselves to a single suffix. However, I never
updated the binary encoding to better match "up to 4 release versions
and up to precisely 1 suffix." Because of that, there were cases where
versions weren't ordered correctly. For example, this fixes a bug where
1.0a2 < 1.0dev2, even though all dev releases should order before
pre-releases.

We also update a test so that it catches these kinds of bugs in the
future. (By testing all pairs of versions in a sequence instead of just
the adjacent versions.)

@BurntSushi BurntSushi requested review from charliermarsh and konstin and removed request for charliermarsh February 22, 2024 20:57
@MichaReiser
Copy link
Member

Nice find. I'm too tired to review this today. Does this have any implications on perf?

@BurntSushi
Copy link
Member Author

I don't think. I can check later. If anything, it will help, because it expands the set of versions that can be represented in a packed format.

But also, do not merge this yet. We need a way to invalidate the cache before we can ship this. Otherwise existing versions in the cache will be interpreted incorrectly. (Which might lead to panics or even silent logic bugs.)

@konstin
Copy link
Member

konstin commented Feb 22, 2024

We need a way to invalidate the cache before we can ship this.

We can bump the cache bucket suffixes (-v1 -> -v2). (I'll review tomorrow)

A couple moons ago, I introduced an optimization for version comparisons
by devising a format where *most* versions would be represented by a
single `u64`. This in turn meant most comparisons (of which many are
done during resolution) would be extremely cheap.

Unfortunately, when I did that, I screwed up the preservation of
ordering as defined by the [Version Specifiers spec]. I think I messed
it up because I had originally devised the representation so that we
could pack things like `1.2.3.dev1.post5`, but later realized it would
be better to limit ourselves to a single suffix. However, I never
updated the binary encoding to better match "up to 4 release versions
and up to precisely 1 suffix." Because of that, there were cases where
versions weren't ordered correctly. For example, this fixes a bug where
`1.0a2 < 1.0dev2`, even though all dev releases should order before
pre-releases.

We also update a test so that it catches these kinds of bugs in the
future. (By testing all pairs of versions in a sequence instead of just
the adjacent versions.)

[Version Specifiers spec]: https://packaging.python.org/en/latest/specifications/version-specifiers/#summary-of-permitted-suffixes-and-relative-ordering
@BurntSushi
Copy link
Member Author

We need a way to invalidate the cache before we can ship this.

We can bump the cache bucket suffixes (-v1 -> -v2). (I'll review tomorrow)

Done!

Copy link
Member

@charliermarsh charliermarsh left a comment

Choose a reason for hiding this comment

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

Awesome, thanks! I read it closely.

number,
})
} else {
None
Copy link
Member

Choose a reason for hiding this comment

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

Should number be 0 here? (Should we assert?)

Copy link
Member Author

Choose a reason for hiding this comment

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

Nope! If the kind isn't a pre-release, then it could be something else with a non-zero number.

@charliermarsh charliermarsh merged commit b794216 into main Feb 22, 2024
7 checks passed
@charliermarsh charliermarsh deleted the ag/fix-version-order branch February 22, 2024 23:01
@BurntSushi BurntSushi added the bug Something isn't working label Feb 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants