From 8a193271bbb73a7c2f7474eaf671fdd146a58e7f Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Mon, 16 Jan 2023 23:41:13 -0800 Subject: [PATCH 1/2] Add types for packaging.version._Version This makes interactions with the internal _version object type safe, instead of having them all resolve to Any. I also separate out the actual types (which do not contain infinities) from the types used by _cmpkey (which could). This types things more accurately and makes the types easier to understand in the actual case. --- src/packaging/version.py | 48 +++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/src/packaging/version.py b/src/packaging/version.py index e5c738cf..12273aad 100644 --- a/src/packaging/version.py +++ b/src/packaging/version.py @@ -7,37 +7,39 @@ from packaging.version import parse, Version """ -import collections import itertools import re -from typing import Callable, Optional, SupportsInt, Tuple, Union +from typing import Callable, NamedTuple, Optional, SupportsInt, Tuple, Union from ._structures import Infinity, InfinityType, NegativeInfinity, NegativeInfinityType __all__ = ["VERSION_PATTERN", "parse", "Version", "InvalidVersion"] -InfiniteTypes = Union[InfinityType, NegativeInfinityType] -PrePostDevType = Union[InfiniteTypes, Tuple[str, int]] -SubLocalType = Union[InfiniteTypes, int, str] -LocalType = Union[ +LocalType = Tuple[Union[int, str], ...] + +CmpPrePostDevType = Union[InfinityType, NegativeInfinityType, Tuple[str, int]] +CmpLocalType = Union[ NegativeInfinityType, - Tuple[ - Union[ - SubLocalType, - Tuple[SubLocalType, str], - Tuple[NegativeInfinityType, SubLocalType], - ], - ..., - ], + Tuple[Union[Tuple[int, str], Tuple[NegativeInfinityType, Union[int, str]]], ...], ] CmpKey = Tuple[ - int, Tuple[int, ...], PrePostDevType, PrePostDevType, PrePostDevType, LocalType + int, + Tuple[int, ...], + CmpPrePostDevType, + CmpPrePostDevType, + CmpPrePostDevType, + CmpLocalType, ] VersionComparisonMethod = Callable[[CmpKey, CmpKey], bool] -_Version = collections.namedtuple( - "_Version", ["epoch", "release", "dev", "pre", "post", "local"] -) + +class _Version(NamedTuple): + epoch: int + release: Tuple[int, ...] + dev: Optional[Tuple[str, int]] + pre: Optional[Tuple[str, int]] + post: Optional[Tuple[str, int]] + local: Optional[LocalType] def parse(version: str) -> "Version": @@ -506,7 +508,7 @@ def _cmpkey( pre: Optional[Tuple[str, int]], post: Optional[Tuple[str, int]], dev: Optional[Tuple[str, int]], - local: Optional[Tuple[SubLocalType]], + local: Optional[LocalType], ) -> CmpKey: # When we compare a release version, we want to compare it with all of the @@ -523,7 +525,7 @@ def _cmpkey( # 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: PrePostDevType = NegativeInfinity + _pre: CmpPrePostDevType = NegativeInfinity # Versions without a pre-release (except as noted above) should sort after # those with one. elif pre is None: @@ -533,21 +535,21 @@ def _cmpkey( # Versions without a post segment should sort before those with one. if post is None: - _post: PrePostDevType = NegativeInfinity + _post: CmpPrePostDevType = NegativeInfinity else: _post = post # Versions without a development segment should sort after those with one. if dev is None: - _dev: PrePostDevType = Infinity + _dev: CmpPrePostDevType = Infinity else: _dev = dev if local is None: # Versions without a local segment should sort before those with one. - _local: LocalType = NegativeInfinity + _local: CmpLocalType = NegativeInfinity else: # Versions with a local segment need that segment parsed to implement # the sorting rules in PEP440. From fc520de0541c4faad7e6da535a5b31253048c277 Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Mon, 16 Jan 2023 23:53:26 -0800 Subject: [PATCH 2/2] simplify properties --- src/packaging/version.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/packaging/version.py b/src/packaging/version.py index 12273aad..8177b483 100644 --- a/src/packaging/version.py +++ b/src/packaging/version.py @@ -270,8 +270,7 @@ def epoch(self) -> int: >>> Version("1!2.0.0").epoch 1 """ - _epoch: int = self._version.epoch - return _epoch + return self._version.epoch @property def release(self) -> Tuple[int, ...]: @@ -287,8 +286,7 @@ def release(self) -> Tuple[int, ...]: Includes trailing zeroes but not the epoch or any pre-release / development / post-release suffixes. """ - _release: Tuple[int, ...] = self._version.release - return _release + return self._version.release @property def pre(self) -> Optional[Tuple[str, int]]: @@ -303,8 +301,7 @@ def pre(self) -> Optional[Tuple[str, int]]: >>> Version("1.2.3rc1").pre ('rc', 1) """ - _pre: Optional[Tuple[str, int]] = self._version.pre - return _pre + return self._version.pre @property def post(self) -> Optional[int]: