diff options
Diffstat (limited to 'venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/packaging/version.py')
-rw-r--r-- | venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/packaging/version.py | 441 |
1 files changed, 441 insertions, 0 deletions
diff --git a/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/packaging/version.py b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/packaging/version.py new file mode 100644 index 0000000..a8affbd --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip-10.0.1-py3.7.egg/pip/_vendor/packaging/version.py | |||
@@ -0,0 +1,441 @@ | |||
1 | # This file is dual licensed under the terms of the Apache License, Version | ||
2 | # 2.0, and the BSD License. See the LICENSE file in the root of this repository | ||
3 | # for complete details. | ||
4 | from __future__ import absolute_import, division, print_function | ||
5 | |||
6 | import collections | ||
7 | import itertools | ||
8 | import re | ||
9 | |||
10 | from ._structures import Infinity | ||
11 | |||
12 | |||
13 | __all__ = [ | ||
14 | "parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN" | ||
15 | ] | ||
16 | |||
17 | |||
18 | _Version = collections.namedtuple( | ||
19 | "_Version", | ||
20 | ["epoch", "release", "dev", "pre", "post", "local"], | ||
21 | ) | ||
22 | |||
23 | |||
24 | def parse(version): | ||
25 | """ | ||
26 | Parse the given version string and return either a :class:`Version` object | ||
27 | or a :class:`LegacyVersion` object depending on if the given version is | ||
28 | a valid PEP 440 version or a legacy version. | ||
29 | """ | ||
30 | try: | ||
31 | return Version(version) | ||
32 | except InvalidVersion: | ||
33 | return LegacyVersion(version) | ||
34 | |||
35 | |||
36 | class InvalidVersion(ValueError): | ||
37 | """ | ||
38 | An invalid version was found, users should refer to PEP 440. | ||
39 | """ | ||
40 | |||
41 | |||
42 | class _BaseVersion(object): | ||
43 | |||
44 | def __hash__(self): | ||
45 | return hash(self._key) | ||
46 | |||
47 | def __lt__(self, other): | ||
48 | return self._compare(other, lambda s, o: s < o) | ||
49 | |||
50 | def __le__(self, other): | ||
51 | return self._compare(other, lambda s, o: s <= o) | ||
52 | |||
53 | def __eq__(self, other): | ||
54 | return self._compare(other, lambda s, o: s == o) | ||
55 | |||
56 | def __ge__(self, other): | ||
57 | return self._compare(other, lambda s, o: s >= o) | ||
58 | |||
59 | def __gt__(self, other): | ||
60 | return self._compare(other, lambda s, o: s > o) | ||
61 | |||
62 | def __ne__(self, other): | ||
63 | return self._compare(other, lambda s, o: s != o) | ||
64 | |||
65 | def _compare(self, other, method): | ||
66 | if not isinstance(other, _BaseVersion): | ||
67 | return NotImplemented | ||
68 | |||
69 | return method(self._key, other._key) | ||
70 | |||
71 | |||
72 | class LegacyVersion(_BaseVersion): | ||
73 | |||
74 | def __init__(self, version): | ||
75 | self._version = str(version) | ||
76 | self._key = _legacy_cmpkey(self._version) | ||
77 | |||
78 | def __str__(self): | ||
79 | return self._version | ||
80 | |||
81 | def __repr__(self): | ||
82 | return "<LegacyVersion({0})>".format(repr(str(self))) | ||
83 | |||
84 | @property | ||
85 | def public(self): | ||
86 | return self._version | ||
87 | |||
88 | @property | ||
89 | def base_version(self): | ||
90 | return self._version | ||
91 | |||
92 | @property | ||
93 | def epoch(self): | ||
94 | return -1 | ||
95 | |||
96 | @property | ||
97 | def release(self): | ||
98 | return None | ||
99 | |||
100 | @property | ||
101 | def pre(self): | ||
102 | return None | ||
103 | |||
104 | @property | ||
105 | def post(self): | ||
106 | return None | ||
107 | |||
108 | @property | ||
109 | def dev(self): | ||
110 | return None | ||
111 | |||
112 | @property | ||
113 | def local(self): | ||
114 | return None | ||
115 | |||
116 | @property | ||
117 | def is_prerelease(self): | ||
118 | return False | ||
119 | |||
120 | @property | ||
121 | def is_postrelease(self): | ||
122 | return False | ||
123 | |||
124 | @property | ||
125 | def is_devrelease(self): | ||
126 | return False | ||
127 | |||
128 | |||
129 | _legacy_version_component_re = re.compile( | ||
130 | r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE, | ||
131 | ) | ||
132 | |||
133 | _legacy_version_replacement_map = { | ||
134 | "pre": "c", "preview": "c", "-": "final-", "rc": "c", "dev": "@", | ||
135 | } | ||
136 | |||
137 | |||
138 | def _parse_version_parts(s): | ||
139 | for part in _legacy_version_component_re.split(s): | ||
140 | part = _legacy_version_replacement_map.get(part, part) | ||
141 | |||
142 | if not part or part == ".": | ||
143 | continue | ||
144 | |||
145 | if part[:1] in "0123456789": | ||
146 | # pad for numeric comparison | ||
147 | yield part.zfill(8) | ||
148 | else: | ||
149 | yield "*" + part | ||
150 | |||
151 | # ensure that alpha/beta/candidate are before final | ||
152 | yield "*final" | ||
153 | |||
154 | |||
155 | def _legacy_cmpkey(version): | ||
156 | # We hardcode an epoch of -1 here. A PEP 440 version can only have a epoch | ||
157 | # greater than or equal to 0. This will effectively put the LegacyVersion, | ||
158 | # which uses the defacto standard originally implemented by setuptools, | ||
159 | # as before all PEP 440 versions. | ||
160 | epoch = -1 | ||
161 | |||
162 | # This scheme is taken from pkg_resources.parse_version setuptools prior to | ||
163 | # it's adoption of the packaging library. | ||
164 | parts = [] | ||
165 | for part in _parse_version_parts(version.lower()): | ||
166 | if part.startswith("*"): | ||
167 | # remove "-" before a prerelease tag | ||
168 | if part < "*final": | ||
169 | while parts and parts[-1] == "*final-": | ||
170 | parts.pop() | ||
171 | |||
172 | # remove trailing zeros from each series of numeric parts | ||
173 | while parts and parts[-1] == "00000000": | ||
174 | parts.pop() | ||
175 | |||
176 | parts.append(part) | ||
177 | parts = tuple(parts) | ||
178 | |||
179 | return epoch, parts | ||
180 | |||
181 | |||
182 | # Deliberately not anchored to the start and end of the string, to make it | ||
183 | # easier for 3rd party code to reuse | ||
184 | VERSION_PATTERN = r""" | ||
185 | v? | ||
186 | (?: | ||
187 | (?:(?P<epoch>[0-9]+)!)? # epoch | ||
188 | (?P<release>[0-9]+(?:\.[0-9]+)*) # release segment | ||
189 | (?P<pre> # pre-release | ||
190 | [-_\.]? | ||
191 | (?P<pre_l>(a|b|c|rc|alpha|beta|pre|preview)) | ||
192 | [-_\.]? | ||
193 | (?P<pre_n>[0-9]+)? | ||
194 | )? | ||
195 | (?P<post> # post release | ||
196 | (?:-(?P<post_n1>[0-9]+)) | ||
197 | | | ||
198 | (?: | ||
199 | [-_\.]? | ||
200 | (?P<post_l>post|rev|r) | ||
201 | [-_\.]? | ||
202 | (?P<post_n2>[0-9]+)? | ||
203 | ) | ||
204 | )? | ||
205 | (?P<dev> # dev release | ||
206 | [-_\.]? | ||
207 | (?P<dev_l>dev) | ||
208 | [-_\.]? | ||
209 | (?P<dev_n>[0-9]+)? | ||
210 | )? | ||
211 | ) | ||
212 | (?:\+(?P<local>[a-z0-9]+(?:[-_\.][a-z0-9]+)*))? # local version | ||
213 | """ | ||
214 | |||
215 | |||
216 | class Version(_BaseVersion): | ||
217 | |||
218 | _regex = re.compile( | ||
219 | r"^\s*" + VERSION_PATTERN + r"\s*$", | ||
220 | re.VERBOSE | re.IGNORECASE, | ||
221 | ) | ||
222 | |||
223 | def __init__(self, version): | ||
224 | # Validate the version and parse it into pieces | ||
225 | match = self._regex.search(version) | ||
226 | if not match: | ||
227 | raise InvalidVersion("Invalid version: '{0}'".format(version)) | ||
228 | |||
229 | # Store the parsed out pieces of the version | ||
230 | self._version = _Version( | ||
231 | epoch=int(match.group("epoch")) if match.group("epoch") else 0, | ||
232 | release=tuple(int(i) for i in match.group("release").split(".")), | ||
233 | pre=_parse_letter_version( | ||
234 | match.group("pre_l"), | ||
235 | match.group("pre_n"), | ||
236 | ), | ||
237 | post=_parse_letter_version( | ||
238 | match.group("post_l"), | ||
239 | match.group("post_n1") or match.group("post_n2"), | ||
240 | ), | ||
241 | dev=_parse_letter_version( | ||
242 | match.group("dev_l"), | ||
243 | match.group("dev_n"), | ||
244 | ), | ||
245 | local=_parse_local_version(match.group("local")), | ||
246 | ) | ||
247 | |||
248 | # Generate a key which will be used for sorting | ||
249 | self._key = _cmpkey( | ||
250 | self._version.epoch, | ||
251 | self._version.release, | ||
252 | self._version.pre, | ||
253 | self._version.post, | ||
254 | self._version.dev, | ||
255 | self._version.local, | ||
256 | ) | ||
257 | |||
258 | def __repr__(self): | ||
259 | return "<Version({0})>".format(repr(str(self))) | ||
260 | |||
261 | def __str__(self): | ||
262 | parts = [] | ||
263 | |||
264 | # Epoch | ||
265 | if self.epoch != 0: | ||
266 | parts.append("{0}!".format(self.epoch)) | ||
267 | |||
268 | # Release segment | ||
269 | parts.append(".".join(str(x) for x in self.release)) | ||
270 | |||
271 | # Pre-release | ||
272 | if self.pre is not None: | ||
273 | parts.append("".join(str(x) for x in self.pre)) | ||
274 | |||
275 | # Post-release | ||
276 | if self.post is not None: | ||
277 | parts.append(".post{0}".format(self.post)) | ||
278 | |||
279 | # Development release | ||
280 | if self.dev is not None: | ||
281 | parts.append(".dev{0}".format(self.dev)) | ||
282 | |||
283 | # Local version segment | ||
284 | if self.local is not None: | ||
285 | parts.append("+{0}".format(self.local)) | ||
286 | |||
287 | return "".join(parts) | ||
288 | |||
289 | @property | ||
290 | def epoch(self): | ||
291 | return self._version.epoch | ||
292 | |||
293 | @property | ||
294 | def release(self): | ||
295 | return self._version.release | ||
296 | |||
297 | @property | ||
298 | def pre(self): | ||
299 | return self._version.pre | ||
300 | |||
301 | @property | ||
302 | def post(self): | ||
303 | return self._version.post[1] if self._version.post else None | ||
304 | |||
305 | @property | ||
306 | def dev(self): | ||
307 | return self._version.dev[1] if self._version.dev else None | ||
308 | |||
309 | @property | ||
310 | def local(self): | ||
311 | if self._version.local: | ||
312 | return ".".join(str(x) for x in self._version.local) | ||
313 | else: | ||
314 | return None | ||
315 | |||
316 | @property | ||
317 | def public(self): | ||
318 | return str(self).split("+", 1)[0] | ||
319 | |||
320 | @property | ||
321 | def base_version(self): | ||
322 | parts = [] | ||
323 | |||
324 | # Epoch | ||
325 | if self.epoch != 0: | ||
326 | parts.append("{0}!".format(self.epoch)) | ||
327 | |||
328 | # Release segment | ||
329 | parts.append(".".join(str(x) for x in self.release)) | ||
330 | |||
331 | return "".join(parts) | ||
332 | |||
333 | @property | ||
334 | def is_prerelease(self): | ||
335 | return self.dev is not None or self.pre is not None | ||
336 | |||
337 | @property | ||
338 | def is_postrelease(self): | ||
339 | return self.post is not None | ||
340 | |||
341 | @property | ||
342 | def is_devrelease(self): | ||
343 | return self.dev is not None | ||
344 | |||
345 | |||
346 | def _parse_letter_version(letter, number): | ||
347 | if letter: | ||
348 | # We consider there to be an implicit 0 in a pre-release if there is | ||
349 | # not a numeral associated with it. | ||
350 | if number is None: | ||
351 | number = 0 | ||
352 | |||
353 | # We normalize any letters to their lower case form | ||
354 | letter = letter.lower() | ||
355 | |||
356 | # We consider some words to be alternate spellings of other words and | ||
357 | # in those cases we want to normalize the spellings to our preferred | ||
358 | # spelling. | ||
359 | if letter == "alpha": | ||
360 | letter = "a" | ||
361 | elif letter == "beta": | ||
362 | letter = "b" | ||
363 | elif letter in ["c", "pre", "preview"]: | ||
364 | letter = "rc" | ||
365 | elif letter in ["rev", "r"]: | ||
366 | letter = "post" | ||
367 | |||
368 | return letter, int(number) | ||
369 | if not letter and number: | ||
370 | # We assume if we are given a number, but we are not given a letter | ||
371 | # then this is using the implicit post release syntax (e.g. 1.0-1) | ||
372 | letter = "post" | ||
373 | |||
374 | return letter, int(number) | ||
375 | |||
376 | |||
377 | _local_version_separators = re.compile(r"[\._-]") | ||
378 | |||
379 | |||
380 | def _parse_local_version(local): | ||
381 | """ | ||
382 | Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve"). | ||
383 | """ | ||
384 | if local is not None: | ||
385 | return tuple( | ||
386 | part.lower() if not part.isdigit() else int(part) | ||
387 | for part in _local_version_separators.split(local) | ||
388 | ) | ||
389 | |||
390 | |||
391 | def _cmpkey(epoch, release, pre, post, dev, local): | ||
392 | # When we compare a release version, we want to compare it with all of the | ||
393 | # trailing zeros removed. So we'll use a reverse the list, drop all the now | ||
394 | # leading zeros until we come to something non zero, then take the rest | ||
395 | # re-reverse it back into the correct order and make it a tuple and use | ||
396 | # that for our sorting key. | ||
397 | release = tuple( | ||
398 | reversed(list( | ||
399 | itertools.dropwhile( | ||
400 | lambda x: x == 0, | ||
401 | reversed(release), | ||
402 | ) | ||
403 | )) | ||
404 | ) | ||
405 | |||
406 | # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0. | ||
407 | # We'll do this by abusing the pre segment, but we _only_ want to do this | ||
408 | # if there is not a pre or a post segment. If we have one of those then | ||
409 | # the normal sorting rules will handle this case correctly. | ||
410 | if pre is None and post is None and dev is not None: | ||
411 | pre = -Infinity | ||
412 | # Versions without a pre-release (except as noted above) should sort after | ||
413 | # those with one. | ||
414 | elif pre is None: | ||
415 | pre = Infinity | ||
416 | |||
417 | # Versions without a post segment should sort before those with one. | ||
418 | if post is None: | ||
419 | post = -Infinity | ||
420 | |||
421 | # Versions without a development segment should sort after those with one. | ||
422 | if dev is None: | ||
423 | dev = Infinity | ||
424 | |||
425 | if local is None: | ||
426 | # Versions without a local segment should sort before those with one. | ||
427 | local = -Infinity | ||
428 | else: | ||
429 | # Versions with a local segment need that segment parsed to implement | ||
430 | # the sorting rules in PEP440. | ||
431 | # - Alpha numeric segments sort before numeric segments | ||
432 | # - Alpha numeric segments sort lexicographically | ||
433 | # - Numeric segments sort numerically | ||
434 | # - Shorter versions sort before longer versions when the prefixes | ||
435 | # match exactly | ||
436 | local = tuple( | ||
437 | (i, "") if isinstance(i, int) else (-Infinity, i) | ||
438 | for i in local | ||
439 | ) | ||
440 | |||
441 | return epoch, release, pre, post, dev, local | ||