Skip to content

Commit dfecd4a

Browse files
committed
Subclassed version of Version that supports -platform
1 parent a74a1cf commit dfecd4a

File tree

1 file changed

+124
-1
lines changed

1 file changed

+124
-1
lines changed

src/libtmux/_compat.py

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,13 @@ def str_from_console(s: t.Union[str, bytes]) -> str:
3434

3535

3636
try:
37+
import collections
38+
import functools
3739
import re
3840
from typing import Iterator, List, Tuple
3941

40-
from packaging.version import Version, _BaseVersion
42+
from packaging import version as V
43+
from packaging.version import VERSION_PATTERN, Version, _BaseVersion
4144

4245
###
4346
### Legacy support for LooseVersion / LegacyVersion, e.g. 2.4-openbsd
@@ -133,6 +136,126 @@ def base_version(self) -> str:
133136
def epoch(self) -> int:
134137
return -1
135138

139+
@functools.total_ordering
140+
class _VersionCmpMixin:
141+
# Credit: @layday
142+
# Link: https://github.com/pypa/packaging/issues/465#issuecomment-1013715662
143+
def __eq__(self, other: object) -> bool:
144+
if isinstance(other, str):
145+
other = self.__class__(other)
146+
return super().__eq__(other)
147+
148+
def __lt__(self, other: object) -> bool:
149+
if isinstance(other, str):
150+
other = self.__class__(other)
151+
return super().__lt__(other)
152+
153+
_Version = collections.namedtuple(
154+
"_Version", ["epoch", "release", "dev", "pre", "post", "local", "platform"]
155+
)
156+
157+
def _cmpkey(
158+
epoch, # type: int
159+
release, # type: Tuple[int, ...]
160+
pre, # type: Optional[Tuple[str, int]]
161+
post, # type: Optional[Tuple[str, int]]
162+
dev, # type: Optional[Tuple[str, int]]
163+
local, # type: Optional[Tuple[SubLocalType]]
164+
platform, # type: Optional[Tuple[SubLocalType]]
165+
):
166+
return V._cmpkey(epoch, release, pre, post, dev, local) + (
167+
tuple(
168+
(i, "") if isinstance(i, int) else (V.NegativeInfinity, i)
169+
for i in platform
170+
)
171+
)
172+
173+
class LegacyVersion(Version):
174+
_regex = re.compile
175+
_regex = re.compile(
176+
r"^\s*"
177+
+ VERSION_PATTERN
178+
+ r"(?:(?P<platform>(?:[-_\.][a-z0-9]+)*))? # platform version"
179+
+ r"\s*$",
180+
re.VERBOSE | re.IGNORECASE,
181+
)
182+
183+
def __init__(self, version):
184+
# type: (str) -> None
185+
186+
# Validate the version and parse it into pieces
187+
match = self._regex.search(version)
188+
if not match:
189+
raise V.InvalidVersion("Invalid version: '{0}'".format(version))
190+
191+
# Store the parsed out pieces of the version
192+
self._version = _Version(
193+
epoch=int(match.group("epoch")) if match.group("epoch") else 0,
194+
release=tuple(int(i) for i in match.group("release").split(".")),
195+
pre=V._parse_letter_version(match.group("pre_l"), match.group("pre_n")),
196+
post=V._parse_letter_version(
197+
match.group("post_l"),
198+
match.group("post_n1") or match.group("post_n2"),
199+
),
200+
dev=V._parse_letter_version(match.group("dev_l"), match.group("dev_n")),
201+
local=V._parse_local_version(match.group("local")),
202+
platform=str(match.group("platform"))
203+
if match.group("platform")
204+
else "",
205+
)
206+
207+
# Generate a key which will be used for sorting
208+
self._key = _cmpkey(
209+
self._version.epoch,
210+
self._version.release,
211+
self._version.pre,
212+
self._version.post,
213+
self._version.dev,
214+
self._version.local,
215+
self._version.platform,
216+
)
217+
218+
@property
219+
def platform(self):
220+
# type: () -> Optional[str]
221+
if self._version.platform:
222+
return ".".join(str(x) for x in self._version.platform)
223+
else:
224+
return None
225+
226+
def __str__(self):
227+
# type: () -> str
228+
parts = []
229+
230+
# Epoch
231+
if self.epoch != 0:
232+
parts.append("{0}!".format(self.epoch))
233+
234+
# Release segment
235+
parts.append(".".join(str(x) for x in self.release))
236+
237+
# Pre-release
238+
if self.pre is not None:
239+
parts.append("".join(str(x) for x in self.pre))
240+
241+
# Post-release
242+
if self.post is not None:
243+
parts.append(".post{0}".format(self.post))
244+
245+
# Development release
246+
if self.dev is not None:
247+
parts.append(".dev{0}".format(self.dev))
248+
249+
# Local version segment
250+
if self.local is not None:
251+
parts.append("+{0}".format(self.local))
252+
253+
# Platform version segment
254+
if self.platform is not None:
255+
parts.append("_{0}".format(self.platform))
256+
257+
return "".join(parts)
258+
136259
LooseVersion = LegacyVersion
137260
except ImportError:
138261
from distutils.version import LooseVersion, Version

0 commit comments

Comments
 (0)