We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Everyday Standard Library Tools step 37 of 55
Sort Version Strings with Pre-Releases First
A release page lists versions such as 1.2.3-alpha, 1.2.3 and 1.10.0, and
must sort them correctly. Write a SemVer class with @total_ordering, then
report on some comparisons. This exercise uses a simplified version format,
not the full Semantic Versioning standard.
versions = [SemVer.parse(text) for text in ["1.2.3", "1.2.3-alpha", "1.10.0"]]
[str(version) for version in sorted(versions)]
# ["1.2.3-alpha", "1.2.3", "1.10.0"]
The format
Each input is major.minor.patch, optionally followed by -tag. The three
numbers are integers, 0 or more, with no leading zeros. A tag is one or more
ASCII letters, digits, dots and hyphens. There is no build metadata, and every
input is valid.
What to write
@total_ordering
class SemVer:
def __init__(self, major: int, minor: int, patch: int, pre: str = "") -> None: ...
@classmethod
def parse(cls, text: str) -> "SemVer": ...
def __str__(self) -> str: ...
- Parsing
"1.2.3"stores an empty tag, and parsing"1.2.3-rc.1"stores"rc.1". Converting a parsed version withstr()gives back its original text. - Compare
(major, minor, patch)as numbers first. With the same numbers, a pre-release comes before the release, so1.2.3-alpha < 1.2.3. Two tags compare as plain strings, sorc.10 < rc.2here. Two versions are equal when the numbers and the tag all match. - Use
@total_orderingwith__eq__and one ordering method, such as__lt__. - Return
NotImplementedwhen the other operand is not aSemVer. - Make instances hashable, by hashing the same values that equality compares. Do not change the fields after construction.
The report
Write solve(versions: list[str], pairs: list[list[str]]) -> dict[str, object].
Each pair holds two version strings. Return these keys:
| Key | Value |
|---|---|
sorted |
Every version in ascending order, as strings, duplicates kept |
comparisons |
One list per pair, in order: [left < right, left <= right, left > right, left >= right, left == right, left != right] |
eq_with_str |
SemVer(1, 0, 0) == "1.0.0", which is False |
lt_with_str |
"TypeError" if SemVer(1, 0, 0) < "1.0.0" raises TypeError, otherwise "compared" |
distinct |
The size of a set of the parsed versions |
For versions ["1.2.3", "1.2.3-alpha"] and the pair ["1.2.3-alpha", "1.2.3"],
sorted is ["1.2.3-alpha", "1.2.3"], the comparison row is
[True, True, False, False, False, True], and distinct is 2.
Edge cases
- Empty
versionsandpairslists are valid. - Equal versions count once in
distinct.
The starter's @dataclass(order=True) compares the raw fields in order, so the
empty tag of a release sorts before any pre-release tag. Replace that with a
comparison key that puts pre-releases first. The tests check only behavior,
but the lesson is total_ordering.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Python reference solution
Sign in to track your attempts toward unlocking the reference solution.