Skip to content

Commit 3e1e5d1

Browse files
committed
Vendorize LegacyVersion behavior for patterns like "2.4-openbsd"
We still need those to work - not to break pypi conformance, but since we use this for tmux versions.
1 parent d502d6b commit 3e1e5d1

File tree

1 file changed

+93
-1
lines changed

1 file changed

+93
-1
lines changed

src/libtmux/_compat.py

+93-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,98 @@ def str_from_console(s: t.Union[str, bytes]) -> str:
3434

3535

3636
try:
37-
from packaging.version import LegacyVersion as LooseVersion, Version
37+
import re
38+
39+
from packaging.version import Version, _BaseVersion
40+
41+
###
42+
### Legacy support for LooseVersion / LegacyVersion, e.g. 2.4-openbsd
43+
### https://github.com/pypa/packaging/blob/21.3/packaging/version.py#L106-L115
44+
### License: BSD, Accessed: Jan 14th, 2022
45+
###
46+
47+
_legacy_version_component_re = re.compile(r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE)
48+
_legacy_version_replacement_map = {
49+
"pre": "c",
50+
"preview": "c",
51+
"-": "final-",
52+
"rc": "c",
53+
"dev": "@",
54+
}
55+
56+
def _parse_version_parts(s):
57+
# type: (str) -> Iterator[str]
58+
for part in _legacy_version_component_re.split(s):
59+
part = _legacy_version_replacement_map.get(part, part)
60+
61+
if not part or part == ".":
62+
continue
63+
64+
if part[:1] in "0123456789":
65+
# pad for numeric comparison
66+
yield part.zfill(8)
67+
else:
68+
yield "*" + part
69+
70+
# ensure that alpha/beta/candidate are before final
71+
yield "*final"
72+
73+
def _legacy_cmpkey(version):
74+
# type: (str) -> LegacyCmpKey
75+
76+
# We hardcode an epoch of -1 here. A PEP 440 version can only have a epoch
77+
# greater than or equal to 0. This will effectively put the LegacyVersion,
78+
# which uses the defacto standard originally implemented by setuptools,
79+
# as before all PEP 440 versions.
80+
epoch = -1
81+
82+
# This scheme is taken from pkg_resources.parse_version setuptools prior to
83+
# it's adoption of the packaging library.
84+
parts = [] # type: List[str]
85+
for part in _parse_version_parts(version.lower()):
86+
if part.startswith("*"):
87+
# remove "-" before a prerelease tag
88+
if part < "*final":
89+
while parts and parts[-1] == "*final-":
90+
parts.pop()
91+
92+
# remove trailing zeros from each series of numeric parts
93+
while parts and parts[-1] == "00000000":
94+
parts.pop()
95+
96+
parts.append(part)
97+
98+
return epoch, tuple(parts)
99+
100+
class LegacyVersion(_BaseVersion):
101+
def __init__(self, version):
102+
# type: (str) -> None
103+
self._version = str(version)
104+
self._key = _legacy_cmpkey(self._version)
105+
106+
def __str__(self):
107+
# type: () -> str
108+
return self._version
109+
110+
def __repr__(self):
111+
# type: () -> str
112+
return "<LegacyVersion({0})>".format(repr(str(self)))
113+
114+
@property
115+
def public(self):
116+
# type: () -> str
117+
return self._version
118+
119+
@property
120+
def base_version(self):
121+
# type: () -> str
122+
return self._version
123+
124+
@property
125+
def epoch(self):
126+
# type: () -> int
127+
return -1
128+
129+
LooseVersion = LegacyVersion
38130
except ImportError:
39131
from distutils.version import LooseVersion, Version

0 commit comments

Comments
 (0)