summaryrefslogtreecommitdiff
path: root/setuptools/_vendor/packaging/version.py
diff options
context:
space:
mode:
Diffstat (limited to 'setuptools/_vendor/packaging/version.py')
-rw-r--r--setuptools/_vendor/packaging/version.py151
1 files changed, 133 insertions, 18 deletions
diff --git a/setuptools/_vendor/packaging/version.py b/setuptools/_vendor/packaging/version.py
index 95157a1f..00371e86 100644
--- a/setuptools/_vendor/packaging/version.py
+++ b/setuptools/_vendor/packaging/version.py
@@ -7,8 +7,35 @@ import collections
import itertools
import re
-from ._structures import Infinity
-
+from ._structures import Infinity, NegativeInfinity
+from ._typing import TYPE_CHECKING
+
+if TYPE_CHECKING: # pragma: no cover
+ from typing import Callable, Iterator, List, Optional, SupportsInt, Tuple, Union
+
+ from ._structures import InfinityType, NegativeInfinityType
+
+ InfiniteTypes = Union[InfinityType, NegativeInfinityType]
+ PrePostDevType = Union[InfiniteTypes, Tuple[str, int]]
+ SubLocalType = Union[InfiniteTypes, int, str]
+ LocalType = Union[
+ NegativeInfinityType,
+ Tuple[
+ Union[
+ SubLocalType,
+ Tuple[SubLocalType, str],
+ Tuple[NegativeInfinityType, SubLocalType],
+ ],
+ ...,
+ ],
+ ]
+ CmpKey = Tuple[
+ int, Tuple[int, ...], PrePostDevType, PrePostDevType, PrePostDevType, LocalType
+ ]
+ LegacyCmpKey = Tuple[int, Tuple[str, ...]]
+ VersionComparisonMethod = Callable[
+ [Union[CmpKey, LegacyCmpKey], Union[CmpKey, LegacyCmpKey]], bool
+ ]
__all__ = ["parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN"]
@@ -19,6 +46,7 @@ _Version = collections.namedtuple(
def parse(version):
+ # type: (str) -> Union[LegacyVersion, Version]
"""
Parse the given version string and return either a :class:`Version` object
or a :class:`LegacyVersion` object depending on if the given version is
@@ -37,28 +65,38 @@ class InvalidVersion(ValueError):
class _BaseVersion(object):
+ _key = None # type: Union[CmpKey, LegacyCmpKey]
+
def __hash__(self):
+ # type: () -> int
return hash(self._key)
def __lt__(self, other):
+ # type: (_BaseVersion) -> bool
return self._compare(other, lambda s, o: s < o)
def __le__(self, other):
+ # type: (_BaseVersion) -> bool
return self._compare(other, lambda s, o: s <= o)
def __eq__(self, other):
+ # type: (object) -> bool
return self._compare(other, lambda s, o: s == o)
def __ge__(self, other):
+ # type: (_BaseVersion) -> bool
return self._compare(other, lambda s, o: s >= o)
def __gt__(self, other):
+ # type: (_BaseVersion) -> bool
return self._compare(other, lambda s, o: s > o)
def __ne__(self, other):
+ # type: (object) -> bool
return self._compare(other, lambda s, o: s != o)
def _compare(self, other, method):
+ # type: (object, VersionComparisonMethod) -> Union[bool, NotImplemented]
if not isinstance(other, _BaseVersion):
return NotImplemented
@@ -67,57 +105,71 @@ class _BaseVersion(object):
class LegacyVersion(_BaseVersion):
def __init__(self, version):
+ # type: (str) -> None
self._version = str(version)
self._key = _legacy_cmpkey(self._version)
def __str__(self):
+ # type: () -> str
return self._version
def __repr__(self):
+ # type: () -> str
return "<LegacyVersion({0})>".format(repr(str(self)))
@property
def public(self):
+ # type: () -> str
return self._version
@property
def base_version(self):
+ # type: () -> str
return self._version
@property
def epoch(self):
+ # type: () -> int
return -1
@property
def release(self):
+ # type: () -> None
return None
@property
def pre(self):
+ # type: () -> None
return None
@property
def post(self):
+ # type: () -> None
return None
@property
def dev(self):
+ # type: () -> None
return None
@property
def local(self):
+ # type: () -> None
return None
@property
def is_prerelease(self):
+ # type: () -> bool
return False
@property
def is_postrelease(self):
+ # type: () -> bool
return False
@property
def is_devrelease(self):
+ # type: () -> bool
return False
@@ -133,6 +185,7 @@ _legacy_version_replacement_map = {
def _parse_version_parts(s):
+ # type: (str) -> Iterator[str]
for part in _legacy_version_component_re.split(s):
part = _legacy_version_replacement_map.get(part, part)
@@ -150,6 +203,8 @@ def _parse_version_parts(s):
def _legacy_cmpkey(version):
+ # type: (str) -> LegacyCmpKey
+
# We hardcode an epoch of -1 here. A PEP 440 version can only have a epoch
# greater than or equal to 0. This will effectively put the LegacyVersion,
# which uses the defacto standard originally implemented by setuptools,
@@ -158,7 +213,7 @@ def _legacy_cmpkey(version):
# This scheme is taken from pkg_resources.parse_version setuptools prior to
# it's adoption of the packaging library.
- parts = []
+ parts = [] # type: List[str]
for part in _parse_version_parts(version.lower()):
if part.startswith("*"):
# remove "-" before a prerelease tag
@@ -171,9 +226,8 @@ def _legacy_cmpkey(version):
parts.pop()
parts.append(part)
- parts = tuple(parts)
- return epoch, parts
+ return epoch, tuple(parts)
# Deliberately not anchored to the start and end of the string, to make it
@@ -215,6 +269,8 @@ class Version(_BaseVersion):
_regex = re.compile(r"^\s*" + VERSION_PATTERN + r"\s*$", re.VERBOSE | re.IGNORECASE)
def __init__(self, version):
+ # type: (str) -> None
+
# Validate the version and parse it into pieces
match = self._regex.search(version)
if not match:
@@ -243,9 +299,11 @@ class Version(_BaseVersion):
)
def __repr__(self):
+ # type: () -> str
return "<Version({0})>".format(repr(str(self)))
def __str__(self):
+ # type: () -> str
parts = []
# Epoch
@@ -275,26 +333,35 @@ class Version(_BaseVersion):
@property
def epoch(self):
- return self._version.epoch
+ # type: () -> int
+ _epoch = self._version.epoch # type: int
+ return _epoch
@property
def release(self):
- return self._version.release
+ # type: () -> Tuple[int, ...]
+ _release = self._version.release # type: Tuple[int, ...]
+ return _release
@property
def pre(self):
- return self._version.pre
+ # type: () -> Optional[Tuple[str, int]]
+ _pre = self._version.pre # type: Optional[Tuple[str, int]]
+ return _pre
@property
def post(self):
+ # type: () -> Optional[Tuple[str, int]]
return self._version.post[1] if self._version.post else None
@property
def dev(self):
+ # type: () -> Optional[Tuple[str, int]]
return self._version.dev[1] if self._version.dev else None
@property
def local(self):
+ # type: () -> Optional[str]
if self._version.local:
return ".".join(str(x) for x in self._version.local)
else:
@@ -302,10 +369,12 @@ class Version(_BaseVersion):
@property
def public(self):
+ # type: () -> str
return str(self).split("+", 1)[0]
@property
def base_version(self):
+ # type: () -> str
parts = []
# Epoch
@@ -319,18 +388,41 @@ class Version(_BaseVersion):
@property
def is_prerelease(self):
+ # type: () -> bool
return self.dev is not None or self.pre is not None
@property
def is_postrelease(self):
+ # type: () -> bool
return self.post is not None
@property
def is_devrelease(self):
+ # type: () -> bool
return self.dev is not None
+ @property
+ def major(self):
+ # type: () -> int
+ return self.release[0] if len(self.release) >= 1 else 0
+
+ @property
+ def minor(self):
+ # type: () -> int
+ return self.release[1] if len(self.release) >= 2 else 0
+
+ @property
+ def micro(self):
+ # type: () -> int
+ return self.release[2] if len(self.release) >= 3 else 0
+
+
+def _parse_letter_version(
+ letter, # type: str
+ number, # type: Union[str, bytes, SupportsInt]
+):
+ # type: (...) -> Optional[Tuple[str, int]]
-def _parse_letter_version(letter, number):
if letter:
# We consider there to be an implicit 0 in a pre-release if there is
# not a numeral associated with it.
@@ -360,11 +452,14 @@ def _parse_letter_version(letter, number):
return letter, int(number)
+ return None
+
_local_version_separators = re.compile(r"[\._-]")
def _parse_local_version(local):
+ # type: (str) -> Optional[LocalType]
"""
Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
"""
@@ -373,15 +468,25 @@ def _parse_local_version(local):
part.lower() if not part.isdigit() else int(part)
for part in _local_version_separators.split(local)
)
+ return None
+
+def _cmpkey(
+ epoch, # type: int
+ release, # type: Tuple[int, ...]
+ pre, # type: Optional[Tuple[str, int]]
+ post, # type: Optional[Tuple[str, int]]
+ dev, # type: Optional[Tuple[str, int]]
+ local, # type: Optional[Tuple[SubLocalType]]
+):
+ # type: (...) -> CmpKey
-def _cmpkey(epoch, release, pre, post, dev, local):
# When we compare a release version, we want to compare it with all of the
# trailing zeros removed. So we'll use a reverse the list, drop all the now
# leading zeros until we come to something non zero, then take the rest
# re-reverse it back into the correct order and make it a tuple and use
# that for our sorting key.
- release = tuple(
+ _release = tuple(
reversed(list(itertools.dropwhile(lambda x: x == 0, reversed(release))))
)
@@ -390,23 +495,31 @@ def _cmpkey(epoch, release, pre, post, dev, local):
# if there is not a pre or a post segment. If we have one of those then
# the normal sorting rules will handle this case correctly.
if pre is None and post is None and dev is not None:
- pre = -Infinity
+ _pre = NegativeInfinity # type: PrePostDevType
# Versions without a pre-release (except as noted above) should sort after
# those with one.
elif pre is None:
- pre = Infinity
+ _pre = Infinity
+ else:
+ _pre = pre
# Versions without a post segment should sort before those with one.
if post is None:
- post = -Infinity
+ _post = NegativeInfinity # type: PrePostDevType
+
+ else:
+ _post = post
# Versions without a development segment should sort after those with one.
if dev is None:
- dev = Infinity
+ _dev = Infinity # type: PrePostDevType
+
+ else:
+ _dev = dev
if local is None:
# Versions without a local segment should sort before those with one.
- local = -Infinity
+ _local = NegativeInfinity # type: LocalType
else:
# Versions with a local segment need that segment parsed to implement
# the sorting rules in PEP440.
@@ -415,6 +528,8 @@ def _cmpkey(epoch, release, pre, post, dev, local):
# - Numeric segments sort numerically
# - Shorter versions sort before longer versions when the prefixes
# match exactly
- local = tuple((i, "") if isinstance(i, int) else (-Infinity, i) for i in local)
+ _local = tuple(
+ (i, "") if isinstance(i, int) else (NegativeInfinity, i) for i in local
+ )
- return epoch, release, pre, post, dev, local
+ return epoch, _release, _pre, _post, _dev, _local