-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcode.py
More file actions
85 lines (71 loc) · 2.62 KB
/
Copy pathcode.py
File metadata and controls
85 lines (71 loc) · 2.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
"""
A first look at the `packaging` library.
`packaging` is the canonical implementation of Python packaging
interoperability standards (PEP 440, PEP 508, PEP 425, and friends).
If you have ever wondered how pip decides whether "1.10.0" is newer
than "1.9.0", or whether "2.0.0rc1" satisfies ">=2,<3", this is the
library doing the work.
Docs: https://packaging.pypa.io/
"""
import pandas as pd
from IPython.core.display import display, HTML
# Package imports for this example.
from packaging.version import Version, InvalidVersion
from packaging.specifiers import SpecifierSet
heading("Parsing and comparing versions")
note(
"PEP 440 says version strings have a precise structure: an "
"optional epoch, a release segment, and pre/post/dev tags. "
"<code>Version</code> parses them and compares them correctly, "
"even when string ordering would get it wrong."
)
raw_versions = [
"1.0",
"1.0.0",
"1.0.1",
"1.0a1", # alpha pre-release
"1.0rc2", # release candidate
"1.0.post1", # post-release
"1.0.dev3", # development release
"2!1.0", # epoch 2 -- jumps ahead of any non-epoch version
"1.10", # newer than 1.9, despite shorter string sort
]
parsed = [Version(v) for v in raw_versions]
ordered = sorted(parsed)
table = pd.DataFrame({
"version": [str(v) for v in ordered],
"is_prerelease": [v.is_prerelease for v in ordered],
"is_postrelease": [v.is_postrelease for v in ordered],
"release_tuple": [v.release for v in ordered],
})
note("Sorted from oldest to newest by PEP 440 rules:")
display(table, append=True)
# Invalid versions raise a clear exception.
try:
Version("not-a-version")
except InvalidVersion as exc:
note(f"<code>Version('not-a-version')</code> raises: <em>{exc}</em>")
heading("Matching versions against a specifier")
note(
"A <code>SpecifierSet</code> is the comma-separated constraint "
"you write in a requirements file, like <code>>=1.0,<2</code>. "
"By default it excludes pre-releases unless you opt in."
)
constraint = SpecifierSet(">=1.0,<2")
candidates = ["0.9", "1.0", "1.0rc2", "1.5", "1.99", "2.0", "2!1.0"]
rows = []
for raw in candidates:
v = Version(raw)
rows.append({
"candidate": raw,
f"matches '{constraint}'": v in constraint,
"matches (with prereleases)": constraint.contains(
v, prereleases=True,
),
})
display(pd.DataFrame(rows), append=True)
note(
"Notice <code>1.0rc2</code> only matches when pre-releases are "
"allowed, and the epoch-bumped <code>2!1.0</code> sorts above "
"<code>2.0</code> so it falls outside the upper bound."
)