@@ -34,10 +34,13 @@ def str_from_console(s: t.Union[str, bytes]) -> str:
34
34
35
35
36
36
try :
37
+ import collections
38
+ import functools
37
39
import re
38
40
from typing import Iterator , List , Tuple
39
41
40
- from packaging .version import Version , _BaseVersion
42
+ from packaging import version as V
43
+ from packaging .version import VERSION_PATTERN , Version , _BaseVersion
41
44
42
45
###
43
46
### Legacy support for LooseVersion / LegacyVersion, e.g. 2.4-openbsd
@@ -133,6 +136,126 @@ def base_version(self) -> str:
133
136
def epoch (self ) -> int :
134
137
return - 1
135
138
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
+
136
259
LooseVersion = LegacyVersion
137
260
except ImportError :
138
261
from distutils .version import LooseVersion , Version
0 commit comments