@@ -34,6 +34,98 @@ def str_from_console(s: t.Union[str, bytes]) -> str:
3434
3535
3636try :
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
38130except ImportError :
39131 from distutils .version import LooseVersion , Version
0 commit comments