aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/packaging
diff options
context:
space:
mode:
authororivej <orivej@yandex-team.ru>2022-02-10 16:45:01 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:45:01 +0300
commit2d37894b1b037cf24231090eda8589bbb44fb6fc (patch)
treebe835aa92c6248212e705f25388ebafcf84bc7a1 /contrib/python/packaging
parent718c552901d703c502ccbefdfc3c9028d608b947 (diff)
downloadydb-2d37894b1b037cf24231090eda8589bbb44fb6fc.tar.gz
Restoring authorship annotation for <orivej@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/python/packaging')
-rw-r--r--contrib/python/packaging/py2/packaging/__init__.py6
-rw-r--r--contrib/python/packaging/py2/packaging/_compat.py52
-rw-r--r--contrib/python/packaging/py2/packaging/_structures.py124
-rw-r--r--contrib/python/packaging/py2/packaging/markers.py482
-rw-r--r--contrib/python/packaging/py2/packaging/requirements.py202
-rw-r--r--contrib/python/packaging/py2/packaging/specifiers.py1386
-rw-r--r--contrib/python/packaging/py2/packaging/utils.py26
-rw-r--r--contrib/python/packaging/py2/packaging/version.py626
-rw-r--r--contrib/python/packaging/py2/ya.make38
-rw-r--r--contrib/python/packaging/py3/packaging/__init__.py6
-rw-r--r--contrib/python/packaging/py3/packaging/_structures.py78
-rw-r--r--contrib/python/packaging/py3/packaging/markers.py410
-rw-r--r--contrib/python/packaging/py3/packaging/requirements.py178
-rw-r--r--contrib/python/packaging/py3/packaging/specifiers.py1202
-rw-r--r--contrib/python/packaging/py3/packaging/utils.py22
-rw-r--r--contrib/python/packaging/py3/packaging/version.py562
-rw-r--r--contrib/python/packaging/py3/ya.make36
-rw-r--r--contrib/python/packaging/ya.make10
18 files changed, 2723 insertions, 2723 deletions
diff --git a/contrib/python/packaging/py2/packaging/__init__.py b/contrib/python/packaging/py2/packaging/__init__.py
index 8f8592ac60..a0cf67df52 100644
--- a/contrib/python/packaging/py2/packaging/__init__.py
+++ b/contrib/python/packaging/py2/packaging/__init__.py
@@ -1,6 +1,6 @@
-# This file is dual licensed under the terms of the Apache License, Version
-# 2.0, and the BSD License. See the LICENSE file in the root of this repository
-# for complete details.
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
from __future__ import absolute_import, division, print_function
from .__about__ import (
diff --git a/contrib/python/packaging/py2/packaging/_compat.py b/contrib/python/packaging/py2/packaging/_compat.py
index 6be0ce31ad..e54bd4ede8 100644
--- a/contrib/python/packaging/py2/packaging/_compat.py
+++ b/contrib/python/packaging/py2/packaging/_compat.py
@@ -1,38 +1,38 @@
-# This file is dual licensed under the terms of the Apache License, Version
-# 2.0, and the BSD License. See the LICENSE file in the root of this repository
-# for complete details.
-from __future__ import absolute_import, division, print_function
-
-import sys
-
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+from __future__ import absolute_import, division, print_function
+
+import sys
+
from ._typing import TYPE_CHECKING
-
+
if TYPE_CHECKING: # pragma: no cover
from typing import Any, Dict, Tuple, Type
-PY2 = sys.version_info[0] == 2
-PY3 = sys.version_info[0] == 3
-
-# flake8: noqa
-
-if PY3:
+PY2 = sys.version_info[0] == 2
+PY3 = sys.version_info[0] == 3
+
+# flake8: noqa
+
+if PY3:
string_types = (str,)
-else:
+else:
string_types = (basestring,)
-
-
-def with_metaclass(meta, *bases):
+
+
+def with_metaclass(meta, *bases):
# type: (Type[Any], Tuple[Type[Any], ...]) -> Any
- """
- Create a base class with a metaclass.
- """
- # This requires a bit of explanation: the basic idea is to make a dummy
- # metaclass for one level of class instantiation that replaces itself with
- # the actual metaclass.
+ """
+ Create a base class with a metaclass.
+ """
+ # This requires a bit of explanation: the basic idea is to make a dummy
+ # metaclass for one level of class instantiation that replaces itself with
+ # the actual metaclass.
class metaclass(meta): # type: ignore
- def __new__(cls, name, this_bases, d):
+ def __new__(cls, name, this_bases, d):
# type: (Type[Any], str, Tuple[Any], Dict[Any, Any]) -> Any
- return meta(name, bases, d)
+ return meta(name, bases, d)
return type.__new__(metaclass, "temporary_class", (), {})
diff --git a/contrib/python/packaging/py2/packaging/_structures.py b/contrib/python/packaging/py2/packaging/_structures.py
index cade21bd4b..800d5c5588 100644
--- a/contrib/python/packaging/py2/packaging/_structures.py
+++ b/contrib/python/packaging/py2/packaging/_structures.py
@@ -1,86 +1,86 @@
-# This file is dual licensed under the terms of the Apache License, Version
-# 2.0, and the BSD License. See the LICENSE file in the root of this repository
-# for complete details.
-from __future__ import absolute_import, division, print_function
-
-
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+from __future__ import absolute_import, division, print_function
+
+
class InfinityType(object):
- def __repr__(self):
+ def __repr__(self):
# type: () -> str
- return "Infinity"
-
- def __hash__(self):
+ return "Infinity"
+
+ def __hash__(self):
# type: () -> int
- return hash(repr(self))
-
- def __lt__(self, other):
+ return hash(repr(self))
+
+ def __lt__(self, other):
# type: (object) -> bool
- return False
-
- def __le__(self, other):
+ return False
+
+ def __le__(self, other):
# type: (object) -> bool
- return False
-
- def __eq__(self, other):
+ return False
+
+ def __eq__(self, other):
# type: (object) -> bool
- return isinstance(other, self.__class__)
-
- def __ne__(self, other):
+ return isinstance(other, self.__class__)
+
+ def __ne__(self, other):
# type: (object) -> bool
- return not isinstance(other, self.__class__)
-
- def __gt__(self, other):
+ return not isinstance(other, self.__class__)
+
+ def __gt__(self, other):
# type: (object) -> bool
- return True
-
- def __ge__(self, other):
+ return True
+
+ def __ge__(self, other):
# type: (object) -> bool
- return True
-
- def __neg__(self):
+ return True
+
+ def __neg__(self):
# type: (object) -> NegativeInfinityType
- return NegativeInfinity
-
+ return NegativeInfinity
+
Infinity = InfinityType()
-
-
+
+
class NegativeInfinityType(object):
- def __repr__(self):
+ def __repr__(self):
# type: () -> str
- return "-Infinity"
-
- def __hash__(self):
+ return "-Infinity"
+
+ def __hash__(self):
# type: () -> int
- return hash(repr(self))
-
- def __lt__(self, other):
+ return hash(repr(self))
+
+ def __lt__(self, other):
# type: (object) -> bool
- return True
-
- def __le__(self, other):
+ return True
+
+ def __le__(self, other):
# type: (object) -> bool
- return True
-
- def __eq__(self, other):
+ return True
+
+ def __eq__(self, other):
# type: (object) -> bool
- return isinstance(other, self.__class__)
-
- def __ne__(self, other):
+ return isinstance(other, self.__class__)
+
+ def __ne__(self, other):
# type: (object) -> bool
- return not isinstance(other, self.__class__)
-
- def __gt__(self, other):
+ return not isinstance(other, self.__class__)
+
+ def __gt__(self, other):
# type: (object) -> bool
- return False
-
- def __ge__(self, other):
+ return False
+
+ def __ge__(self, other):
# type: (object) -> bool
- return False
-
- def __neg__(self):
+ return False
+
+ def __neg__(self):
# type: (object) -> InfinityType
- return Infinity
-
+ return Infinity
+
NegativeInfinity = NegativeInfinityType()
diff --git a/contrib/python/packaging/py2/packaging/markers.py b/contrib/python/packaging/py2/packaging/markers.py
index 1d711d99ee..e0330ab6ab 100644
--- a/contrib/python/packaging/py2/packaging/markers.py
+++ b/contrib/python/packaging/py2/packaging/markers.py
@@ -1,13 +1,13 @@
-# This file is dual licensed under the terms of the Apache License, Version
-# 2.0, and the BSD License. See the LICENSE file in the root of this repository
-# for complete details.
-from __future__ import absolute_import, division, print_function
-
-import operator
-import os
-import platform
-import sys
-
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+from __future__ import absolute_import, division, print_function
+
+import operator
+import os
+import platform
+import sys
+
from pyparsing import ( # noqa: N817
Forward,
Group,
@@ -19,82 +19,82 @@ from pyparsing import ( # noqa: N817
stringEnd,
stringStart,
)
-
-from ._compat import string_types
+
+from ._compat import string_types
from ._typing import TYPE_CHECKING
from .specifiers import InvalidSpecifier, Specifier
-
+
if TYPE_CHECKING: # pragma: no cover
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
-
+
Operator = Callable[[str, str], bool]
-__all__ = [
+__all__ = [
"InvalidMarker",
"UndefinedComparison",
"UndefinedEnvironmentName",
"Marker",
"default_environment",
-]
-
-
-class InvalidMarker(ValueError):
- """
- An invalid marker was found, users should refer to PEP 508.
- """
-
-
-class UndefinedComparison(ValueError):
- """
- An invalid operation was attempted on a value that doesn't support it.
- """
-
-
-class UndefinedEnvironmentName(ValueError):
- """
- A name was attempted to be used that does not exist inside of the
- environment.
- """
-
-
-class Node(object):
- def __init__(self, value):
+]
+
+
+class InvalidMarker(ValueError):
+ """
+ An invalid marker was found, users should refer to PEP 508.
+ """
+
+
+class UndefinedComparison(ValueError):
+ """
+ An invalid operation was attempted on a value that doesn't support it.
+ """
+
+
+class UndefinedEnvironmentName(ValueError):
+ """
+ A name was attempted to be used that does not exist inside of the
+ environment.
+ """
+
+
+class Node(object):
+ def __init__(self, value):
# type: (Any) -> None
- self.value = value
-
- def __str__(self):
+ self.value = value
+
+ def __str__(self):
# type: () -> str
- return str(self.value)
-
- def __repr__(self):
+ return str(self.value)
+
+ def __repr__(self):
# type: () -> str
- return "<{0}({1!r})>".format(self.__class__.__name__, str(self))
-
- def serialize(self):
+ return "<{0}({1!r})>".format(self.__class__.__name__, str(self))
+
+ def serialize(self):
# type: () -> str
- raise NotImplementedError
-
-
-class Variable(Node):
- def serialize(self):
+ raise NotImplementedError
+
+
+class Variable(Node):
+ def serialize(self):
# type: () -> str
- return str(self)
-
-
-class Value(Node):
- def serialize(self):
+ return str(self)
+
+
+class Value(Node):
+ def serialize(self):
# type: () -> str
- return '"{0}"'.format(self)
-
-
-class Op(Node):
- def serialize(self):
+ return '"{0}"'.format(self)
+
+
+class Op(Node):
+ def serialize(self):
# type: () -> str
- return str(self)
-
-
-VARIABLE = (
+ return str(self)
+
+
+VARIABLE = (
L("implementation_version")
| L("platform_python_implementation")
| L("implementation_name")
@@ -113,167 +113,167 @@ VARIABLE = (
| L("platform.python_implementation") # PEP-345
| L("python_implementation") # undocumented setuptools legacy
| L("extra") # PEP-508
-)
-ALIASES = {
+)
+ALIASES = {
"os.name": "os_name",
"sys.platform": "sys_platform",
"platform.version": "platform_version",
"platform.machine": "platform_machine",
"platform.python_implementation": "platform_python_implementation",
"python_implementation": "platform_python_implementation",
-}
-VARIABLE.setParseAction(lambda s, l, t: Variable(ALIASES.get(t[0], t[0])))
-
-VERSION_CMP = (
+}
+VARIABLE.setParseAction(lambda s, l, t: Variable(ALIASES.get(t[0], t[0])))
+
+VERSION_CMP = (
L("===") | L("==") | L(">=") | L("<=") | L("!=") | L("~=") | L(">") | L("<")
-)
-
-MARKER_OP = VERSION_CMP | L("not in") | L("in")
-MARKER_OP.setParseAction(lambda s, l, t: Op(t[0]))
-
-MARKER_VALUE = QuotedString("'") | QuotedString('"')
-MARKER_VALUE.setParseAction(lambda s, l, t: Value(t[0]))
-
-BOOLOP = L("and") | L("or")
-
-MARKER_VAR = VARIABLE | MARKER_VALUE
-
-MARKER_ITEM = Group(MARKER_VAR + MARKER_OP + MARKER_VAR)
-MARKER_ITEM.setParseAction(lambda s, l, t: tuple(t[0]))
-
-LPAREN = L("(").suppress()
-RPAREN = L(")").suppress()
-
-MARKER_EXPR = Forward()
-MARKER_ATOM = MARKER_ITEM | Group(LPAREN + MARKER_EXPR + RPAREN)
-MARKER_EXPR << MARKER_ATOM + ZeroOrMore(BOOLOP + MARKER_EXPR)
-
-MARKER = stringStart + MARKER_EXPR + stringEnd
-
-
-def _coerce_parse_result(results):
+)
+
+MARKER_OP = VERSION_CMP | L("not in") | L("in")
+MARKER_OP.setParseAction(lambda s, l, t: Op(t[0]))
+
+MARKER_VALUE = QuotedString("'") | QuotedString('"')
+MARKER_VALUE.setParseAction(lambda s, l, t: Value(t[0]))
+
+BOOLOP = L("and") | L("or")
+
+MARKER_VAR = VARIABLE | MARKER_VALUE
+
+MARKER_ITEM = Group(MARKER_VAR + MARKER_OP + MARKER_VAR)
+MARKER_ITEM.setParseAction(lambda s, l, t: tuple(t[0]))
+
+LPAREN = L("(").suppress()
+RPAREN = L(")").suppress()
+
+MARKER_EXPR = Forward()
+MARKER_ATOM = MARKER_ITEM | Group(LPAREN + MARKER_EXPR + RPAREN)
+MARKER_EXPR << MARKER_ATOM + ZeroOrMore(BOOLOP + MARKER_EXPR)
+
+MARKER = stringStart + MARKER_EXPR + stringEnd
+
+
+def _coerce_parse_result(results):
# type: (Union[ParseResults, List[Any]]) -> List[Any]
- if isinstance(results, ParseResults):
- return [_coerce_parse_result(i) for i in results]
- else:
- return results
-
-
-def _format_marker(marker, first=True):
+ if isinstance(results, ParseResults):
+ return [_coerce_parse_result(i) for i in results]
+ else:
+ return results
+
+
+def _format_marker(marker, first=True):
# type: (Union[List[str], Tuple[Node, ...], str], Optional[bool]) -> str
- assert isinstance(marker, (list, tuple, string_types))
-
- # Sometimes we have a structure like [[...]] which is a single item list
- # where the single item is itself it's own list. In that case we want skip
- # the rest of this function so that we don't get extraneous () on the
- # outside.
+ assert isinstance(marker, (list, tuple, string_types))
+
+ # Sometimes we have a structure like [[...]] which is a single item list
+ # where the single item is itself it's own list. In that case we want skip
+ # the rest of this function so that we don't get extraneous () on the
+ # outside.
if (
isinstance(marker, list)
and len(marker) == 1
and isinstance(marker[0], (list, tuple))
):
- return _format_marker(marker[0])
-
- if isinstance(marker, list):
- inner = (_format_marker(m, first=False) for m in marker)
- if first:
- return " ".join(inner)
- else:
- return "(" + " ".join(inner) + ")"
- elif isinstance(marker, tuple):
- return " ".join([m.serialize() for m in marker])
- else:
- return marker
-
-
-_operators = {
- "in": lambda lhs, rhs: lhs in rhs,
- "not in": lambda lhs, rhs: lhs not in rhs,
- "<": operator.lt,
- "<=": operator.le,
- "==": operator.eq,
- "!=": operator.ne,
- ">=": operator.ge,
- ">": operator.gt,
+ return _format_marker(marker[0])
+
+ if isinstance(marker, list):
+ inner = (_format_marker(m, first=False) for m in marker)
+ if first:
+ return " ".join(inner)
+ else:
+ return "(" + " ".join(inner) + ")"
+ elif isinstance(marker, tuple):
+ return " ".join([m.serialize() for m in marker])
+ else:
+ return marker
+
+
+_operators = {
+ "in": lambda lhs, rhs: lhs in rhs,
+ "not in": lambda lhs, rhs: lhs not in rhs,
+ "<": operator.lt,
+ "<=": operator.le,
+ "==": operator.eq,
+ "!=": operator.ne,
+ ">=": operator.ge,
+ ">": operator.gt,
} # type: Dict[str, Operator]
-
-
-def _eval_op(lhs, op, rhs):
+
+
+def _eval_op(lhs, op, rhs):
# type: (str, Op, str) -> bool
- try:
- spec = Specifier("".join([op.serialize(), rhs]))
- except InvalidSpecifier:
- pass
- else:
- return spec.contains(lhs)
-
+ try:
+ spec = Specifier("".join([op.serialize(), rhs]))
+ except InvalidSpecifier:
+ pass
+ else:
+ return spec.contains(lhs)
+
oper = _operators.get(op.serialize()) # type: Optional[Operator]
- if oper is None:
- raise UndefinedComparison(
- "Undefined {0!r} on {1!r} and {2!r}.".format(op, lhs, rhs)
- )
-
- return oper(lhs, rhs)
-
-
+ if oper is None:
+ raise UndefinedComparison(
+ "Undefined {0!r} on {1!r} and {2!r}.".format(op, lhs, rhs)
+ )
+
+ return oper(lhs, rhs)
+
+
class Undefined(object):
pass
-
-
+
+
_undefined = Undefined()
-def _get_env(environment, name):
+def _get_env(environment, name):
# type: (Dict[str, str], str) -> str
value = environment.get(name, _undefined) # type: Union[str, Undefined]
-
+
if isinstance(value, Undefined):
- raise UndefinedEnvironmentName(
- "{0!r} does not exist in evaluation environment.".format(name)
- )
-
- return value
-
-
-def _evaluate_markers(markers, environment):
+ raise UndefinedEnvironmentName(
+ "{0!r} does not exist in evaluation environment.".format(name)
+ )
+
+ return value
+
+
+def _evaluate_markers(markers, environment):
# type: (List[Any], Dict[str, str]) -> bool
groups = [[]] # type: List[List[bool]]
-
- for marker in markers:
- assert isinstance(marker, (list, tuple, string_types))
-
- if isinstance(marker, list):
- groups[-1].append(_evaluate_markers(marker, environment))
- elif isinstance(marker, tuple):
- lhs, op, rhs = marker
-
- if isinstance(lhs, Variable):
- lhs_value = _get_env(environment, lhs.value)
- rhs_value = rhs.value
- else:
- lhs_value = lhs.value
- rhs_value = _get_env(environment, rhs.value)
-
- groups[-1].append(_eval_op(lhs_value, op, rhs_value))
- else:
- assert marker in ["and", "or"]
- if marker == "or":
- groups.append([])
-
- return any(all(item) for item in groups)
-
-
-def format_full_version(info):
+
+ for marker in markers:
+ assert isinstance(marker, (list, tuple, string_types))
+
+ if isinstance(marker, list):
+ groups[-1].append(_evaluate_markers(marker, environment))
+ elif isinstance(marker, tuple):
+ lhs, op, rhs = marker
+
+ if isinstance(lhs, Variable):
+ lhs_value = _get_env(environment, lhs.value)
+ rhs_value = rhs.value
+ else:
+ lhs_value = lhs.value
+ rhs_value = _get_env(environment, rhs.value)
+
+ groups[-1].append(_eval_op(lhs_value, op, rhs_value))
+ else:
+ assert marker in ["and", "or"]
+ if marker == "or":
+ groups.append([])
+
+ return any(all(item) for item in groups)
+
+
+def format_full_version(info):
# type: (sys._version_info) -> str
version = "{0.major}.{0.minor}.{0.micro}".format(info)
- kind = info.releaselevel
+ kind = info.releaselevel
if kind != "final":
- version += kind[0] + str(info.serial)
- return version
-
-
-def default_environment():
+ version += kind[0] + str(info.serial)
+ return version
+
+
+def default_environment():
# type: () -> Dict[str, str]
if hasattr(sys, "implementation"):
# Ignoring the `sys.implementation` reference for type checking due to
@@ -281,56 +281,56 @@ def default_environment():
# run with the `--py27` flag.
iver = format_full_version(sys.implementation.version) # type: ignore
implementation_name = sys.implementation.name # type: ignore
- else:
+ else:
iver = "0"
implementation_name = ""
-
- return {
- "implementation_name": implementation_name,
- "implementation_version": iver,
- "os_name": os.name,
- "platform_machine": platform.machine(),
- "platform_release": platform.release(),
- "platform_system": platform.system(),
- "platform_version": platform.version(),
- "python_full_version": platform.python_version(),
- "platform_python_implementation": platform.python_implementation(),
+
+ return {
+ "implementation_name": implementation_name,
+ "implementation_version": iver,
+ "os_name": os.name,
+ "platform_machine": platform.machine(),
+ "platform_release": platform.release(),
+ "platform_system": platform.system(),
+ "platform_version": platform.version(),
+ "python_full_version": platform.python_version(),
+ "platform_python_implementation": platform.python_implementation(),
"python_version": ".".join(platform.python_version_tuple()[:2]),
- "sys_platform": sys.platform,
- }
-
-
-class Marker(object):
- def __init__(self, marker):
+ "sys_platform": sys.platform,
+ }
+
+
+class Marker(object):
+ def __init__(self, marker):
# type: (str) -> None
- try:
- self._markers = _coerce_parse_result(MARKER.parseString(marker))
- except ParseException as e:
- err_str = "Invalid marker: {0!r}, parse error at {1!r}".format(
+ try:
+ self._markers = _coerce_parse_result(MARKER.parseString(marker))
+ except ParseException as e:
+ err_str = "Invalid marker: {0!r}, parse error at {1!r}".format(
marker, marker[e.loc : e.loc + 8]
)
- raise InvalidMarker(err_str)
-
- def __str__(self):
+ raise InvalidMarker(err_str)
+
+ def __str__(self):
# type: () -> str
- return _format_marker(self._markers)
-
- def __repr__(self):
+ return _format_marker(self._markers)
+
+ def __repr__(self):
# type: () -> str
- return "<Marker({0!r})>".format(str(self))
-
- def evaluate(self, environment=None):
+ return "<Marker({0!r})>".format(str(self))
+
+ def evaluate(self, environment=None):
# type: (Optional[Dict[str, str]]) -> bool
- """Evaluate a marker.
-
- Return the boolean from evaluating the given marker against the
- environment. environment is an optional argument to override all or
- part of the determined environment.
-
- The environment is determined from the current Python process.
- """
- current_environment = default_environment()
- if environment is not None:
- current_environment.update(environment)
-
- return _evaluate_markers(self._markers, current_environment)
+ """Evaluate a marker.
+
+ Return the boolean from evaluating the given marker against the
+ environment. environment is an optional argument to override all or
+ part of the determined environment.
+
+ The environment is determined from the current Python process.
+ """
+ current_environment = default_environment()
+ if environment is not None:
+ current_environment.update(environment)
+
+ return _evaluate_markers(self._markers, current_environment)
diff --git a/contrib/python/packaging/py2/packaging/requirements.py b/contrib/python/packaging/py2/packaging/requirements.py
index 36ed88223d..aa69d50d1a 100644
--- a/contrib/python/packaging/py2/packaging/requirements.py
+++ b/contrib/python/packaging/py2/packaging/requirements.py
@@ -1,12 +1,12 @@
-# This file is dual licensed under the terms of the Apache License, Version
-# 2.0, and the BSD License. See the LICENSE file in the root of this repository
-# for complete details.
-from __future__ import absolute_import, division, print_function
-
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+from __future__ import absolute_import, division, print_function
+
import re
-import string
+import string
import sys
-
+
from pyparsing import ( # noqa: N817
Combine,
Literal as L,
@@ -19,11 +19,11 @@ from pyparsing import ( # noqa: N817
stringEnd,
stringStart,
)
-
+
from ._typing import TYPE_CHECKING
-from .markers import MARKER_EXPR, Marker
-from .specifiers import LegacySpecifier, Specifier, SpecifierSet
-
+from .markers import MARKER_EXPR, Marker
+from .specifiers import LegacySpecifier, Specifier, SpecifierSet
+
if sys.version_info[0] >= 3:
from urllib import parse as urlparse # pragma: no cover
else: # pragma: no cover
@@ -32,95 +32,95 @@ else: # pragma: no cover
if TYPE_CHECKING: # pragma: no cover
from typing import List, Optional as TOptional, Set
-
-
-class InvalidRequirement(ValueError):
- """
- An invalid requirement was found, users should refer to PEP 508.
- """
-
-
-ALPHANUM = Word(string.ascii_letters + string.digits)
-
-LBRACKET = L("[").suppress()
-RBRACKET = L("]").suppress()
-LPAREN = L("(").suppress()
-RPAREN = L(")").suppress()
-COMMA = L(",").suppress()
-SEMICOLON = L(";").suppress()
-AT = L("@").suppress()
-
-PUNCTUATION = Word("-_.")
-IDENTIFIER_END = ALPHANUM | (ZeroOrMore(PUNCTUATION) + ALPHANUM)
-IDENTIFIER = Combine(ALPHANUM + ZeroOrMore(IDENTIFIER_END))
-
-NAME = IDENTIFIER("name")
-EXTRA = IDENTIFIER
-
+
+
+class InvalidRequirement(ValueError):
+ """
+ An invalid requirement was found, users should refer to PEP 508.
+ """
+
+
+ALPHANUM = Word(string.ascii_letters + string.digits)
+
+LBRACKET = L("[").suppress()
+RBRACKET = L("]").suppress()
+LPAREN = L("(").suppress()
+RPAREN = L(")").suppress()
+COMMA = L(",").suppress()
+SEMICOLON = L(";").suppress()
+AT = L("@").suppress()
+
+PUNCTUATION = Word("-_.")
+IDENTIFIER_END = ALPHANUM | (ZeroOrMore(PUNCTUATION) + ALPHANUM)
+IDENTIFIER = Combine(ALPHANUM + ZeroOrMore(IDENTIFIER_END))
+
+NAME = IDENTIFIER("name")
+EXTRA = IDENTIFIER
+
URI = Regex(r"[^ ]+")("url")
URL = AT + URI
-
-EXTRAS_LIST = EXTRA + ZeroOrMore(COMMA + EXTRA)
-EXTRAS = (LBRACKET + Optional(EXTRAS_LIST) + RBRACKET)("extras")
-
-VERSION_PEP440 = Regex(Specifier._regex_str, re.VERBOSE | re.IGNORECASE)
-VERSION_LEGACY = Regex(LegacySpecifier._regex_str, re.VERBOSE | re.IGNORECASE)
-
-VERSION_ONE = VERSION_PEP440 ^ VERSION_LEGACY
+
+EXTRAS_LIST = EXTRA + ZeroOrMore(COMMA + EXTRA)
+EXTRAS = (LBRACKET + Optional(EXTRAS_LIST) + RBRACKET)("extras")
+
+VERSION_PEP440 = Regex(Specifier._regex_str, re.VERBOSE | re.IGNORECASE)
+VERSION_LEGACY = Regex(LegacySpecifier._regex_str, re.VERBOSE | re.IGNORECASE)
+
+VERSION_ONE = VERSION_PEP440 ^ VERSION_LEGACY
VERSION_MANY = Combine(
VERSION_ONE + ZeroOrMore(COMMA + VERSION_ONE), joinString=",", adjacent=False
)("_raw_spec")
-_VERSION_SPEC = Optional(((LPAREN + VERSION_MANY + RPAREN) | VERSION_MANY))
+_VERSION_SPEC = Optional(((LPAREN + VERSION_MANY + RPAREN) | VERSION_MANY))
_VERSION_SPEC.setParseAction(lambda s, l, t: t._raw_spec or "")
-
-VERSION_SPEC = originalTextFor(_VERSION_SPEC)("specifier")
-VERSION_SPEC.setParseAction(lambda s, l, t: t[1])
-
-MARKER_EXPR = originalTextFor(MARKER_EXPR())("marker")
-MARKER_EXPR.setParseAction(
+
+VERSION_SPEC = originalTextFor(_VERSION_SPEC)("specifier")
+VERSION_SPEC.setParseAction(lambda s, l, t: t[1])
+
+MARKER_EXPR = originalTextFor(MARKER_EXPR())("marker")
+MARKER_EXPR.setParseAction(
lambda s, l, t: Marker(s[t._original_start : t._original_end])
-)
+)
MARKER_SEPARATOR = SEMICOLON
MARKER = MARKER_SEPARATOR + MARKER_EXPR
-
-VERSION_AND_MARKER = VERSION_SPEC + Optional(MARKER)
-URL_AND_MARKER = URL + Optional(MARKER)
-
+
+VERSION_AND_MARKER = VERSION_SPEC + Optional(MARKER)
+URL_AND_MARKER = URL + Optional(MARKER)
+
NAMED_REQUIREMENT = NAME + Optional(EXTRAS) + (URL_AND_MARKER | VERSION_AND_MARKER)
-
-REQUIREMENT = stringStart + NAMED_REQUIREMENT + stringEnd
+
+REQUIREMENT = stringStart + NAMED_REQUIREMENT + stringEnd
# pyparsing isn't thread safe during initialization, so we do it eagerly, see
# issue #104
REQUIREMENT.parseString("x[]")
-
-
-class Requirement(object):
- """Parse a requirement.
-
- Parse a given requirement string into its parts, such as name, specifier,
- URL, and extras. Raises InvalidRequirement on a badly-formed requirement
- string.
- """
-
- # TODO: Can we test whether something is contained within a requirement?
- # If so how do we do that? Do we need to test against the _name_ of
- # the thing as well as the version? What about the markers?
- # TODO: Can we normalize the name and extra name?
-
- def __init__(self, requirement_string):
+
+
+class Requirement(object):
+ """Parse a requirement.
+
+ Parse a given requirement string into its parts, such as name, specifier,
+ URL, and extras. Raises InvalidRequirement on a badly-formed requirement
+ string.
+ """
+
+ # TODO: Can we test whether something is contained within a requirement?
+ # If so how do we do that? Do we need to test against the _name_ of
+ # the thing as well as the version? What about the markers?
+ # TODO: Can we normalize the name and extra name?
+
+ def __init__(self, requirement_string):
# type: (str) -> None
- try:
- req = REQUIREMENT.parseString(requirement_string)
- except ParseException as e:
+ try:
+ req = REQUIREMENT.parseString(requirement_string)
+ except ParseException as e:
raise InvalidRequirement(
'Parse error at "{0!r}": {1}'.format(
requirement_string[e.loc : e.loc + 8], e.msg
)
)
-
+
self.name = req.name # type: str
- if req.url:
- parsed_url = urlparse.urlparse(req.url)
+ if req.url:
+ parsed_url = urlparse.urlparse(req.url)
if parsed_url.scheme == "file":
if urlparse.urlunparse(parsed_url) != req.url:
raise InvalidRequirement("Invalid URL given")
@@ -129,32 +129,32 @@ class Requirement(object):
):
raise InvalidRequirement("Invalid URL: {0}".format(req.url))
self.url = req.url # type: TOptional[str]
- else:
- self.url = None
+ else:
+ self.url = None
self.extras = set(req.extras.asList() if req.extras else []) # type: Set[str]
self.specifier = SpecifierSet(req.specifier) # type: SpecifierSet
self.marker = req.marker if req.marker else None # type: TOptional[Marker]
-
- def __str__(self):
+
+ def __str__(self):
# type: () -> str
parts = [self.name] # type: List[str]
-
- if self.extras:
- parts.append("[{0}]".format(",".join(sorted(self.extras))))
-
- if self.specifier:
- parts.append(str(self.specifier))
-
- if self.url:
- parts.append("@ {0}".format(self.url))
+
+ if self.extras:
+ parts.append("[{0}]".format(",".join(sorted(self.extras))))
+
+ if self.specifier:
+ parts.append(str(self.specifier))
+
+ if self.url:
+ parts.append("@ {0}".format(self.url))
if self.marker:
parts.append(" ")
-
- if self.marker:
- parts.append("; {0}".format(self.marker))
-
- return "".join(parts)
-
- def __repr__(self):
+
+ if self.marker:
+ parts.append("; {0}".format(self.marker))
+
+ return "".join(parts)
+
+ def __repr__(self):
# type: () -> str
- return "<Requirement({0!r})>".format(str(self))
+ return "<Requirement({0!r})>".format(str(self))
diff --git a/contrib/python/packaging/py2/packaging/specifiers.py b/contrib/python/packaging/py2/packaging/specifiers.py
index f0a52f3c6f..a6a83c1fe9 100644
--- a/contrib/python/packaging/py2/packaging/specifiers.py
+++ b/contrib/python/packaging/py2/packaging/specifiers.py
@@ -1,281 +1,281 @@
-# This file is dual licensed under the terms of the Apache License, Version
-# 2.0, and the BSD License. See the LICENSE file in the root of this repository
-# for complete details.
-from __future__ import absolute_import, division, print_function
-
-import abc
-import functools
-import itertools
-import re
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+from __future__ import absolute_import, division, print_function
+
+import abc
+import functools
+import itertools
+import re
import warnings
-
-from ._compat import string_types, with_metaclass
+
+from ._compat import string_types, with_metaclass
from ._typing import TYPE_CHECKING
from .utils import canonicalize_version
from .version import LegacyVersion, Version, parse
-
+
if TYPE_CHECKING: # pragma: no cover
from typing import Callable, Dict, Iterable, Iterator, List, Optional, Tuple, Union
-
+
ParsedVersion = Union[Version, LegacyVersion]
UnparsedVersion = Union[Version, LegacyVersion, str]
CallableOperator = Callable[[ParsedVersion, str], bool]
-class InvalidSpecifier(ValueError):
- """
- An invalid specifier was found, users should refer to PEP 440.
- """
-
-
+class InvalidSpecifier(ValueError):
+ """
+ An invalid specifier was found, users should refer to PEP 440.
+ """
+
+
class BaseSpecifier(with_metaclass(abc.ABCMeta, object)): # type: ignore
- @abc.abstractmethod
- def __str__(self):
+ @abc.abstractmethod
+ def __str__(self):
# type: () -> str
- """
- Returns the str representation of this Specifier like object. This
- should be representative of the Specifier itself.
- """
-
- @abc.abstractmethod
- def __hash__(self):
+ """
+ Returns the str representation of this Specifier like object. This
+ should be representative of the Specifier itself.
+ """
+
+ @abc.abstractmethod
+ def __hash__(self):
# type: () -> int
- """
- Returns a hash value for this Specifier like object.
- """
-
- @abc.abstractmethod
- def __eq__(self, other):
+ """
+ Returns a hash value for this Specifier like object.
+ """
+
+ @abc.abstractmethod
+ def __eq__(self, other):
# type: (object) -> bool
- """
- Returns a boolean representing whether or not the two Specifier like
- objects are equal.
- """
-
- @abc.abstractmethod
- def __ne__(self, other):
+ """
+ Returns a boolean representing whether or not the two Specifier like
+ objects are equal.
+ """
+
+ @abc.abstractmethod
+ def __ne__(self, other):
# type: (object) -> bool
- """
- Returns a boolean representing whether or not the two Specifier like
- objects are not equal.
- """
-
- @abc.abstractproperty
- def prereleases(self):
+ """
+ Returns a boolean representing whether or not the two Specifier like
+ objects are not equal.
+ """
+
+ @abc.abstractproperty
+ def prereleases(self):
# type: () -> Optional[bool]
- """
- Returns whether or not pre-releases as a whole are allowed by this
- specifier.
- """
-
- @prereleases.setter
- def prereleases(self, value):
+ """
+ Returns whether or not pre-releases as a whole are allowed by this
+ specifier.
+ """
+
+ @prereleases.setter
+ def prereleases(self, value):
# type: (bool) -> None
- """
- Sets whether or not pre-releases as a whole are allowed by this
- specifier.
- """
-
- @abc.abstractmethod
- def contains(self, item, prereleases=None):
+ """
+ Sets whether or not pre-releases as a whole are allowed by this
+ specifier.
+ """
+
+ @abc.abstractmethod
+ def contains(self, item, prereleases=None):
# type: (str, Optional[bool]) -> bool
- """
- Determines if the given item is contained within this specifier.
- """
-
- @abc.abstractmethod
- def filter(self, iterable, prereleases=None):
+ """
+ Determines if the given item is contained within this specifier.
+ """
+
+ @abc.abstractmethod
+ def filter(self, iterable, prereleases=None):
# type: (Iterable[UnparsedVersion], Optional[bool]) -> Iterable[UnparsedVersion]
- """
- Takes an iterable of items and filters them so that only items which
- are contained within this specifier are allowed in it.
- """
-
-
-class _IndividualSpecifier(BaseSpecifier):
-
+ """
+ Takes an iterable of items and filters them so that only items which
+ are contained within this specifier are allowed in it.
+ """
+
+
+class _IndividualSpecifier(BaseSpecifier):
+
_operators = {} # type: Dict[str, str]
-
- def __init__(self, spec="", prereleases=None):
+
+ def __init__(self, spec="", prereleases=None):
# type: (str, Optional[bool]) -> None
- match = self._regex.search(spec)
- if not match:
- raise InvalidSpecifier("Invalid specifier: '{0}'".format(spec))
-
- self._spec = (
- match.group("operator").strip(),
- match.group("version").strip(),
+ match = self._regex.search(spec)
+ if not match:
+ raise InvalidSpecifier("Invalid specifier: '{0}'".format(spec))
+
+ self._spec = (
+ match.group("operator").strip(),
+ match.group("version").strip(),
) # type: Tuple[str, str]
-
- # Store whether or not this Specifier should accept prereleases
- self._prereleases = prereleases
-
- def __repr__(self):
+
+ # Store whether or not this Specifier should accept prereleases
+ self._prereleases = prereleases
+
+ def __repr__(self):
# type: () -> str
- pre = (
- ", prereleases={0!r}".format(self.prereleases)
- if self._prereleases is not None
- else ""
- )
-
+ pre = (
+ ", prereleases={0!r}".format(self.prereleases)
+ if self._prereleases is not None
+ else ""
+ )
+
return "<{0}({1!r}{2})>".format(self.__class__.__name__, str(self), pre)
-
- def __str__(self):
+
+ def __str__(self):
# type: () -> str
- return "{0}{1}".format(*self._spec)
-
+ return "{0}{1}".format(*self._spec)
+
@property
def _canonical_spec(self):
# type: () -> Tuple[str, Union[Version, str]]
return self._spec[0], canonicalize_version(self._spec[1])
- def __hash__(self):
+ def __hash__(self):
# type: () -> int
return hash(self._canonical_spec)
-
- def __eq__(self, other):
+
+ def __eq__(self, other):
# type: (object) -> bool
- if isinstance(other, string_types):
- try:
+ if isinstance(other, string_types):
+ try:
other = self.__class__(str(other))
- except InvalidSpecifier:
- return NotImplemented
- elif not isinstance(other, self.__class__):
- return NotImplemented
-
+ except InvalidSpecifier:
+ return NotImplemented
+ elif not isinstance(other, self.__class__):
+ return NotImplemented
+
return self._canonical_spec == other._canonical_spec
-
- def __ne__(self, other):
+
+ def __ne__(self, other):
# type: (object) -> bool
- if isinstance(other, string_types):
- try:
+ if isinstance(other, string_types):
+ try:
other = self.__class__(str(other))
- except InvalidSpecifier:
- return NotImplemented
- elif not isinstance(other, self.__class__):
- return NotImplemented
-
- return self._spec != other._spec
-
- def _get_operator(self, op):
+ except InvalidSpecifier:
+ return NotImplemented
+ elif not isinstance(other, self.__class__):
+ return NotImplemented
+
+ return self._spec != other._spec
+
+ def _get_operator(self, op):
# type: (str) -> CallableOperator
operator_callable = getattr(
self, "_compare_{0}".format(self._operators[op])
) # type: CallableOperator
return operator_callable
-
- def _coerce_version(self, version):
+
+ def _coerce_version(self, version):
# type: (UnparsedVersion) -> ParsedVersion
- if not isinstance(version, (LegacyVersion, Version)):
- version = parse(version)
- return version
-
- @property
- def operator(self):
+ if not isinstance(version, (LegacyVersion, Version)):
+ version = parse(version)
+ return version
+
+ @property
+ def operator(self):
# type: () -> str
- return self._spec[0]
-
- @property
- def version(self):
+ return self._spec[0]
+
+ @property
+ def version(self):
# type: () -> str
- return self._spec[1]
-
- @property
- def prereleases(self):
+ return self._spec[1]
+
+ @property
+ def prereleases(self):
# type: () -> Optional[bool]
- return self._prereleases
-
- @prereleases.setter
- def prereleases(self, value):
+ return self._prereleases
+
+ @prereleases.setter
+ def prereleases(self, value):
# type: (bool) -> None
- self._prereleases = value
-
- def __contains__(self, item):
+ self._prereleases = value
+
+ def __contains__(self, item):
# type: (str) -> bool
- return self.contains(item)
-
- def contains(self, item, prereleases=None):
+ return self.contains(item)
+
+ def contains(self, item, prereleases=None):
# type: (UnparsedVersion, Optional[bool]) -> bool
- # Determine if prereleases are to be allowed or not.
- if prereleases is None:
- prereleases = self.prereleases
-
- # Normalize item to a Version or LegacyVersion, this allows us to have
- # a shortcut for ``"2.0" in Specifier(">=2")
+ # Determine if prereleases are to be allowed or not.
+ if prereleases is None:
+ prereleases = self.prereleases
+
+ # Normalize item to a Version or LegacyVersion, this allows us to have
+ # a shortcut for ``"2.0" in Specifier(">=2")
normalized_item = self._coerce_version(item)
-
- # Determine if we should be supporting prereleases in this specifier
- # or not, if we do not support prereleases than we can short circuit
- # logic if this version is a prereleases.
+
+ # Determine if we should be supporting prereleases in this specifier
+ # or not, if we do not support prereleases than we can short circuit
+ # logic if this version is a prereleases.
if normalized_item.is_prerelease and not prereleases:
- return False
-
- # Actually do the comparison to determine if this item is contained
- # within this Specifier or not.
+ return False
+
+ # Actually do the comparison to determine if this item is contained
+ # within this Specifier or not.
operator_callable = self._get_operator(self.operator) # type: CallableOperator
return operator_callable(normalized_item, self.version)
-
- def filter(self, iterable, prereleases=None):
+
+ def filter(self, iterable, prereleases=None):
# type: (Iterable[UnparsedVersion], Optional[bool]) -> Iterable[UnparsedVersion]
- yielded = False
- found_prereleases = []
-
- kw = {"prereleases": prereleases if prereleases is not None else True}
-
- # Attempt to iterate over all the values in the iterable and if any of
- # them match, yield them.
- for version in iterable:
- parsed_version = self._coerce_version(version)
-
- if self.contains(parsed_version, **kw):
- # If our version is a prerelease, and we were not set to allow
- # prereleases, then we'll store it for later incase nothing
- # else matches this specifier.
+ yielded = False
+ found_prereleases = []
+
+ kw = {"prereleases": prereleases if prereleases is not None else True}
+
+ # Attempt to iterate over all the values in the iterable and if any of
+ # them match, yield them.
+ for version in iterable:
+ parsed_version = self._coerce_version(version)
+
+ if self.contains(parsed_version, **kw):
+ # If our version is a prerelease, and we were not set to allow
+ # prereleases, then we'll store it for later incase nothing
+ # else matches this specifier.
if parsed_version.is_prerelease and not (
prereleases or self.prereleases
):
- found_prereleases.append(version)
- # Either this is not a prerelease, or we should have been
+ found_prereleases.append(version)
+ # Either this is not a prerelease, or we should have been
# accepting prereleases from the beginning.
- else:
- yielded = True
- yield version
-
- # Now that we've iterated over everything, determine if we've yielded
- # any values, and if we have not and we have any prereleases stored up
- # then we will go ahead and yield the prereleases.
- if not yielded and found_prereleases:
- for version in found_prereleases:
- yield version
-
-
-class LegacySpecifier(_IndividualSpecifier):
-
+ else:
+ yielded = True
+ yield version
+
+ # Now that we've iterated over everything, determine if we've yielded
+ # any values, and if we have not and we have any prereleases stored up
+ # then we will go ahead and yield the prereleases.
+ if not yielded and found_prereleases:
+ for version in found_prereleases:
+ yield version
+
+
+class LegacySpecifier(_IndividualSpecifier):
+
_regex_str = r"""
- (?P<operator>(==|!=|<=|>=|<|>))
- \s*
- (?P<version>
- [^,;\s)]* # Since this is a "legacy" specifier, and the version
- # string can be just about anything, we match everything
- # except for whitespace, a semi-colon for marker support,
- # a closing paren since versions can be enclosed in
- # them, and a comma since it's a version separator.
- )
- """
-
+ (?P<operator>(==|!=|<=|>=|<|>))
+ \s*
+ (?P<version>
+ [^,;\s)]* # Since this is a "legacy" specifier, and the version
+ # string can be just about anything, we match everything
+ # except for whitespace, a semi-colon for marker support,
+ # a closing paren since versions can be enclosed in
+ # them, and a comma since it's a version separator.
+ )
+ """
+
_regex = re.compile(r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE)
-
- _operators = {
- "==": "equal",
- "!=": "not_equal",
- "<=": "less_than_equal",
- ">=": "greater_than_equal",
- "<": "less_than",
- ">": "greater_than",
- }
-
+
+ _operators = {
+ "==": "equal",
+ "!=": "not_equal",
+ "<=": "less_than_equal",
+ ">=": "greater_than_equal",
+ "<": "less_than",
+ ">": "greater_than",
+ }
+
def __init__(self, spec="", prereleases=None):
# type: (str, Optional[bool]) -> None
super(LegacySpecifier, self).__init__(spec, prereleases)
@@ -286,530 +286,530 @@ class LegacySpecifier(_IndividualSpecifier):
DeprecationWarning,
)
- def _coerce_version(self, version):
+ def _coerce_version(self, version):
# type: (Union[ParsedVersion, str]) -> LegacyVersion
- if not isinstance(version, LegacyVersion):
- version = LegacyVersion(str(version))
- return version
-
- def _compare_equal(self, prospective, spec):
+ if not isinstance(version, LegacyVersion):
+ version = LegacyVersion(str(version))
+ return version
+
+ def _compare_equal(self, prospective, spec):
# type: (LegacyVersion, str) -> bool
- return prospective == self._coerce_version(spec)
-
- def _compare_not_equal(self, prospective, spec):
+ return prospective == self._coerce_version(spec)
+
+ def _compare_not_equal(self, prospective, spec):
# type: (LegacyVersion, str) -> bool
- return prospective != self._coerce_version(spec)
-
- def _compare_less_than_equal(self, prospective, spec):
+ return prospective != self._coerce_version(spec)
+
+ def _compare_less_than_equal(self, prospective, spec):
# type: (LegacyVersion, str) -> bool
- return prospective <= self._coerce_version(spec)
-
- def _compare_greater_than_equal(self, prospective, spec):
+ return prospective <= self._coerce_version(spec)
+
+ def _compare_greater_than_equal(self, prospective, spec):
# type: (LegacyVersion, str) -> bool
- return prospective >= self._coerce_version(spec)
-
- def _compare_less_than(self, prospective, spec):
+ return prospective >= self._coerce_version(spec)
+
+ def _compare_less_than(self, prospective, spec):
# type: (LegacyVersion, str) -> bool
- return prospective < self._coerce_version(spec)
-
- def _compare_greater_than(self, prospective, spec):
+ return prospective < self._coerce_version(spec)
+
+ def _compare_greater_than(self, prospective, spec):
# type: (LegacyVersion, str) -> bool
- return prospective > self._coerce_version(spec)
-
-
+ return prospective > self._coerce_version(spec)
+
+
def _require_version_compare(
fn, # type: (Callable[[Specifier, ParsedVersion, str], bool])
):
# type: (...) -> Callable[[Specifier, ParsedVersion, str], bool]
- @functools.wraps(fn)
- def wrapped(self, prospective, spec):
+ @functools.wraps(fn)
+ def wrapped(self, prospective, spec):
# type: (Specifier, ParsedVersion, str) -> bool
- if not isinstance(prospective, Version):
- return False
- return fn(self, prospective, spec)
-
- return wrapped
-
-
-class Specifier(_IndividualSpecifier):
-
+ if not isinstance(prospective, Version):
+ return False
+ return fn(self, prospective, spec)
+
+ return wrapped
+
+
+class Specifier(_IndividualSpecifier):
+
_regex_str = r"""
- (?P<operator>(~=|==|!=|<=|>=|<|>|===))
- (?P<version>
- (?:
- # The identity operators allow for an escape hatch that will
- # do an exact string match of the version you wish to install.
- # This will not be parsed by PEP 440 and we cannot determine
- # any semantic meaning from it. This operator is discouraged
- # but included entirely as an escape hatch.
- (?<====) # Only match for the identity operator
- \s*
- [^\s]* # We just match everything, except for whitespace
- # since we are only testing for strict identity.
- )
- |
- (?:
- # The (non)equality operators allow for wild card and local
- # versions to be specified so we have to define these two
- # operators separately to enable that.
- (?<===|!=) # Only match for equals and not equals
-
- \s*
- v?
- (?:[0-9]+!)? # epoch
- [0-9]+(?:\.[0-9]+)* # release
- (?: # pre release
- [-_\.]?
- (a|b|c|rc|alpha|beta|pre|preview)
- [-_\.]?
- [0-9]*
- )?
- (?: # post release
- (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
- )?
-
- # You cannot use a wild card and a dev or local version
- # together so group them with a | and make them optional.
- (?:
- (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
- (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local
- |
- \.\* # Wild card syntax of .*
- )?
- )
- |
- (?:
- # The compatible operator requires at least two digits in the
- # release segment.
- (?<=~=) # Only match for the compatible operator
-
- \s*
- v?
- (?:[0-9]+!)? # epoch
- [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *)
- (?: # pre release
- [-_\.]?
- (a|b|c|rc|alpha|beta|pre|preview)
- [-_\.]?
- [0-9]*
- )?
- (?: # post release
- (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
- )?
- (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
- )
- |
- (?:
- # All other operators only allow a sub set of what the
- # (non)equality operators do. Specifically they do not allow
- # local versions to be specified nor do they allow the prefix
- # matching wild cards.
- (?<!==|!=|~=) # We have special cases for these
- # operators so we want to make sure they
- # don't match here.
-
- \s*
- v?
- (?:[0-9]+!)? # epoch
- [0-9]+(?:\.[0-9]+)* # release
- (?: # pre release
- [-_\.]?
- (a|b|c|rc|alpha|beta|pre|preview)
- [-_\.]?
- [0-9]*
- )?
- (?: # post release
- (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
- )?
- (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
- )
- )
- """
-
+ (?P<operator>(~=|==|!=|<=|>=|<|>|===))
+ (?P<version>
+ (?:
+ # The identity operators allow for an escape hatch that will
+ # do an exact string match of the version you wish to install.
+ # This will not be parsed by PEP 440 and we cannot determine
+ # any semantic meaning from it. This operator is discouraged
+ # but included entirely as an escape hatch.
+ (?<====) # Only match for the identity operator
+ \s*
+ [^\s]* # We just match everything, except for whitespace
+ # since we are only testing for strict identity.
+ )
+ |
+ (?:
+ # The (non)equality operators allow for wild card and local
+ # versions to be specified so we have to define these two
+ # operators separately to enable that.
+ (?<===|!=) # Only match for equals and not equals
+
+ \s*
+ v?
+ (?:[0-9]+!)? # epoch
+ [0-9]+(?:\.[0-9]+)* # release
+ (?: # pre release
+ [-_\.]?
+ (a|b|c|rc|alpha|beta|pre|preview)
+ [-_\.]?
+ [0-9]*
+ )?
+ (?: # post release
+ (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
+ )?
+
+ # You cannot use a wild card and a dev or local version
+ # together so group them with a | and make them optional.
+ (?:
+ (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
+ (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local
+ |
+ \.\* # Wild card syntax of .*
+ )?
+ )
+ |
+ (?:
+ # The compatible operator requires at least two digits in the
+ # release segment.
+ (?<=~=) # Only match for the compatible operator
+
+ \s*
+ v?
+ (?:[0-9]+!)? # epoch
+ [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *)
+ (?: # pre release
+ [-_\.]?
+ (a|b|c|rc|alpha|beta|pre|preview)
+ [-_\.]?
+ [0-9]*
+ )?
+ (?: # post release
+ (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
+ )?
+ (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
+ )
+ |
+ (?:
+ # All other operators only allow a sub set of what the
+ # (non)equality operators do. Specifically they do not allow
+ # local versions to be specified nor do they allow the prefix
+ # matching wild cards.
+ (?<!==|!=|~=) # We have special cases for these
+ # operators so we want to make sure they
+ # don't match here.
+
+ \s*
+ v?
+ (?:[0-9]+!)? # epoch
+ [0-9]+(?:\.[0-9]+)* # release
+ (?: # pre release
+ [-_\.]?
+ (a|b|c|rc|alpha|beta|pre|preview)
+ [-_\.]?
+ [0-9]*
+ )?
+ (?: # post release
+ (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
+ )?
+ (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
+ )
+ )
+ """
+
_regex = re.compile(r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE)
-
- _operators = {
- "~=": "compatible",
- "==": "equal",
- "!=": "not_equal",
- "<=": "less_than_equal",
- ">=": "greater_than_equal",
- "<": "less_than",
- ">": "greater_than",
- "===": "arbitrary",
- }
-
- @_require_version_compare
- def _compare_compatible(self, prospective, spec):
+
+ _operators = {
+ "~=": "compatible",
+ "==": "equal",
+ "!=": "not_equal",
+ "<=": "less_than_equal",
+ ">=": "greater_than_equal",
+ "<": "less_than",
+ ">": "greater_than",
+ "===": "arbitrary",
+ }
+
+ @_require_version_compare
+ def _compare_compatible(self, prospective, spec):
# type: (ParsedVersion, str) -> bool
- # Compatible releases have an equivalent combination of >= and ==. That
- # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to
- # implement this in terms of the other specifiers instead of
- # implementing it ourselves. The only thing we need to do is construct
- # the other specifiers.
-
- # We want everything but the last item in the version, but we want to
- # ignore post and dev releases and we want to treat the pre-release as
- # it's own separate segment.
- prefix = ".".join(
- list(
- itertools.takewhile(
+ # Compatible releases have an equivalent combination of >= and ==. That
+ # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to
+ # implement this in terms of the other specifiers instead of
+ # implementing it ourselves. The only thing we need to do is construct
+ # the other specifiers.
+
+ # We want everything but the last item in the version, but we want to
+ # ignore post and dev releases and we want to treat the pre-release as
+ # it's own separate segment.
+ prefix = ".".join(
+ list(
+ itertools.takewhile(
lambda x: (not x.startswith("post") and not x.startswith("dev")),
- _version_split(spec),
- )
- )[:-1]
- )
-
- # Add the prefix notation to the end of our string
- prefix += ".*"
-
+ _version_split(spec),
+ )
+ )[:-1]
+ )
+
+ # Add the prefix notation to the end of our string
+ prefix += ".*"
+
return self._get_operator(">=")(prospective, spec) and self._get_operator("==")(
prospective, prefix
)
-
- @_require_version_compare
- def _compare_equal(self, prospective, spec):
+
+ @_require_version_compare
+ def _compare_equal(self, prospective, spec):
# type: (ParsedVersion, str) -> bool
- # We need special logic to handle prefix matching
- if spec.endswith(".*"):
- # In the case of prefix matching we want to ignore local segment.
- prospective = Version(prospective.public)
- # Split the spec out by dots, and pretend that there is an implicit
- # dot in between a release segment and a pre-release segment.
+ # We need special logic to handle prefix matching
+ if spec.endswith(".*"):
+ # In the case of prefix matching we want to ignore local segment.
+ prospective = Version(prospective.public)
+ # Split the spec out by dots, and pretend that there is an implicit
+ # dot in between a release segment and a pre-release segment.
split_spec = _version_split(spec[:-2]) # Remove the trailing .*
-
- # Split the prospective version out by dots, and pretend that there
- # is an implicit dot in between a release segment and a pre-release
- # segment.
+
+ # Split the prospective version out by dots, and pretend that there
+ # is an implicit dot in between a release segment and a pre-release
+ # segment.
split_prospective = _version_split(str(prospective))
-
- # Shorten the prospective version to be the same length as the spec
- # so that we can determine if the specifier is a prefix of the
- # prospective version or not.
+
+ # Shorten the prospective version to be the same length as the spec
+ # so that we can determine if the specifier is a prefix of the
+ # prospective version or not.
shortened_prospective = split_prospective[: len(split_spec)]
-
- # Pad out our two sides with zeros so that they both equal the same
- # length.
+
+ # Pad out our two sides with zeros so that they both equal the same
+ # length.
padded_spec, padded_prospective = _pad_version(
split_spec, shortened_prospective
)
return padded_prospective == padded_spec
- else:
- # Convert our spec string into a Version
+ else:
+ # Convert our spec string into a Version
spec_version = Version(spec)
-
- # If the specifier does not have a local segment, then we want to
- # act as if the prospective version also does not have a local
- # segment.
+
+ # If the specifier does not have a local segment, then we want to
+ # act as if the prospective version also does not have a local
+ # segment.
if not spec_version.local:
- prospective = Version(prospective.public)
-
+ prospective = Version(prospective.public)
+
return prospective == spec_version
-
- @_require_version_compare
- def _compare_not_equal(self, prospective, spec):
+
+ @_require_version_compare
+ def _compare_not_equal(self, prospective, spec):
# type: (ParsedVersion, str) -> bool
- return not self._compare_equal(prospective, spec)
-
- @_require_version_compare
- def _compare_less_than_equal(self, prospective, spec):
+ return not self._compare_equal(prospective, spec)
+
+ @_require_version_compare
+ def _compare_less_than_equal(self, prospective, spec):
# type: (ParsedVersion, str) -> bool
-
+
# NB: Local version identifiers are NOT permitted in the version
# specifier, so local version labels can be universally removed from
# the prospective version.
return Version(prospective.public) <= Version(spec)
- @_require_version_compare
- def _compare_greater_than_equal(self, prospective, spec):
+ @_require_version_compare
+ def _compare_greater_than_equal(self, prospective, spec):
# type: (ParsedVersion, str) -> bool
-
+
# NB: Local version identifiers are NOT permitted in the version
# specifier, so local version labels can be universally removed from
# the prospective version.
return Version(prospective.public) >= Version(spec)
- @_require_version_compare
+ @_require_version_compare
def _compare_less_than(self, prospective, spec_str):
# type: (ParsedVersion, str) -> bool
- # Convert our spec to a Version instance, since we'll want to work with
- # it as a version.
+ # Convert our spec to a Version instance, since we'll want to work with
+ # it as a version.
spec = Version(spec_str)
-
- # Check to see if the prospective version is less than the spec
- # version. If it's not we can short circuit and just return False now
- # instead of doing extra unneeded work.
- if not prospective < spec:
- return False
-
- # This special case is here so that, unless the specifier itself
- # includes is a pre-release version, that we do not accept pre-release
- # versions for the version mentioned in the specifier (e.g. <3.1 should
- # not match 3.1.dev0, but should match 3.0.dev0).
- if not spec.is_prerelease and prospective.is_prerelease:
- if Version(prospective.base_version) == Version(spec.base_version):
- return False
-
- # If we've gotten to here, it means that prospective version is both
- # less than the spec version *and* it's not a pre-release of the same
- # version in the spec.
- return True
-
- @_require_version_compare
+
+ # Check to see if the prospective version is less than the spec
+ # version. If it's not we can short circuit and just return False now
+ # instead of doing extra unneeded work.
+ if not prospective < spec:
+ return False
+
+ # This special case is here so that, unless the specifier itself
+ # includes is a pre-release version, that we do not accept pre-release
+ # versions for the version mentioned in the specifier (e.g. <3.1 should
+ # not match 3.1.dev0, but should match 3.0.dev0).
+ if not spec.is_prerelease and prospective.is_prerelease:
+ if Version(prospective.base_version) == Version(spec.base_version):
+ return False
+
+ # If we've gotten to here, it means that prospective version is both
+ # less than the spec version *and* it's not a pre-release of the same
+ # version in the spec.
+ return True
+
+ @_require_version_compare
def _compare_greater_than(self, prospective, spec_str):
# type: (ParsedVersion, str) -> bool
- # Convert our spec to a Version instance, since we'll want to work with
- # it as a version.
+ # Convert our spec to a Version instance, since we'll want to work with
+ # it as a version.
spec = Version(spec_str)
-
- # Check to see if the prospective version is greater than the spec
- # version. If it's not we can short circuit and just return False now
- # instead of doing extra unneeded work.
- if not prospective > spec:
- return False
-
- # This special case is here so that, unless the specifier itself
- # includes is a post-release version, that we do not accept
- # post-release versions for the version mentioned in the specifier
- # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0).
- if not spec.is_postrelease and prospective.is_postrelease:
- if Version(prospective.base_version) == Version(spec.base_version):
- return False
-
- # Ensure that we do not allow a local version of the version mentioned
+
+ # Check to see if the prospective version is greater than the spec
+ # version. If it's not we can short circuit and just return False now
+ # instead of doing extra unneeded work.
+ if not prospective > spec:
+ return False
+
+ # This special case is here so that, unless the specifier itself
+ # includes is a post-release version, that we do not accept
+ # post-release versions for the version mentioned in the specifier
+ # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0).
+ if not spec.is_postrelease and prospective.is_postrelease:
+ if Version(prospective.base_version) == Version(spec.base_version):
+ return False
+
+ # Ensure that we do not allow a local version of the version mentioned
# in the specifier, which is technically greater than, to match.
- if prospective.local is not None:
- if Version(prospective.base_version) == Version(spec.base_version):
- return False
-
- # If we've gotten to here, it means that prospective version is both
- # greater than the spec version *and* it's not a pre-release of the
- # same version in the spec.
- return True
-
- def _compare_arbitrary(self, prospective, spec):
+ if prospective.local is not None:
+ if Version(prospective.base_version) == Version(spec.base_version):
+ return False
+
+ # If we've gotten to here, it means that prospective version is both
+ # greater than the spec version *and* it's not a pre-release of the
+ # same version in the spec.
+ return True
+
+ def _compare_arbitrary(self, prospective, spec):
# type: (Version, str) -> bool
- return str(prospective).lower() == str(spec).lower()
-
- @property
- def prereleases(self):
+ return str(prospective).lower() == str(spec).lower()
+
+ @property
+ def prereleases(self):
# type: () -> bool
- # If there is an explicit prereleases set for this, then we'll just
- # blindly use that.
- if self._prereleases is not None:
- return self._prereleases
-
- # Look at all of our specifiers and determine if they are inclusive
- # operators, and if they are if they are including an explicit
- # prerelease.
- operator, version = self._spec
- if operator in ["==", ">=", "<=", "~=", "==="]:
- # The == specifier can include a trailing .*, if it does we
- # want to remove before parsing.
- if operator == "==" and version.endswith(".*"):
- version = version[:-2]
-
- # Parse the version, and if it is a pre-release than this
- # specifier allows pre-releases.
- if parse(version).is_prerelease:
- return True
-
- return False
-
- @prereleases.setter
- def prereleases(self, value):
+ # If there is an explicit prereleases set for this, then we'll just
+ # blindly use that.
+ if self._prereleases is not None:
+ return self._prereleases
+
+ # Look at all of our specifiers and determine if they are inclusive
+ # operators, and if they are if they are including an explicit
+ # prerelease.
+ operator, version = self._spec
+ if operator in ["==", ">=", "<=", "~=", "==="]:
+ # The == specifier can include a trailing .*, if it does we
+ # want to remove before parsing.
+ if operator == "==" and version.endswith(".*"):
+ version = version[:-2]
+
+ # Parse the version, and if it is a pre-release than this
+ # specifier allows pre-releases.
+ if parse(version).is_prerelease:
+ return True
+
+ return False
+
+ @prereleases.setter
+ def prereleases(self, value):
# type: (bool) -> None
- self._prereleases = value
-
-
-_prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$")
-
-
-def _version_split(version):
+ self._prereleases = value
+
+
+_prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$")
+
+
+def _version_split(version):
# type: (str) -> List[str]
result = [] # type: List[str]
- for item in version.split("."):
- match = _prefix_regex.search(item)
- if match:
- result.extend(match.groups())
- else:
- result.append(item)
- return result
-
-
-def _pad_version(left, right):
+ for item in version.split("."):
+ match = _prefix_regex.search(item)
+ if match:
+ result.extend(match.groups())
+ else:
+ result.append(item)
+ return result
+
+
+def _pad_version(left, right):
# type: (List[str], List[str]) -> Tuple[List[str], List[str]]
- left_split, right_split = [], []
-
- # Get the release segment of our versions
- left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left)))
- right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right)))
-
- # Get the rest of our versions
+ left_split, right_split = [], []
+
+ # Get the release segment of our versions
+ left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left)))
+ right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right)))
+
+ # Get the rest of our versions
left_split.append(left[len(left_split[0]) :])
right_split.append(right[len(right_split[0]) :])
-
- # Insert our padding
+
+ # Insert our padding
left_split.insert(1, ["0"] * max(0, len(right_split[0]) - len(left_split[0])))
right_split.insert(1, ["0"] * max(0, len(left_split[0]) - len(right_split[0])))
-
+
return (list(itertools.chain(*left_split)), list(itertools.chain(*right_split)))
-
-
-class SpecifierSet(BaseSpecifier):
+
+
+class SpecifierSet(BaseSpecifier):
def __init__(self, specifiers="", prereleases=None):
# type: (str, Optional[bool]) -> None
-
+
# Split on , to break each individual specifier into it's own item, and
- # strip each item to remove leading/trailing whitespace.
+ # strip each item to remove leading/trailing whitespace.
split_specifiers = [s.strip() for s in specifiers.split(",") if s.strip()]
-
- # Parsed each individual specifier, attempting first to make it a
- # Specifier and falling back to a LegacySpecifier.
- parsed = set()
+
+ # Parsed each individual specifier, attempting first to make it a
+ # Specifier and falling back to a LegacySpecifier.
+ parsed = set()
for specifier in split_specifiers:
- try:
- parsed.add(Specifier(specifier))
- except InvalidSpecifier:
- parsed.add(LegacySpecifier(specifier))
-
- # Turn our parsed specifiers into a frozen set and save them for later.
- self._specs = frozenset(parsed)
-
- # Store our prereleases value so we can use it later to determine if
- # we accept prereleases or not.
- self._prereleases = prereleases
-
- def __repr__(self):
+ try:
+ parsed.add(Specifier(specifier))
+ except InvalidSpecifier:
+ parsed.add(LegacySpecifier(specifier))
+
+ # Turn our parsed specifiers into a frozen set and save them for later.
+ self._specs = frozenset(parsed)
+
+ # Store our prereleases value so we can use it later to determine if
+ # we accept prereleases or not.
+ self._prereleases = prereleases
+
+ def __repr__(self):
# type: () -> str
- pre = (
- ", prereleases={0!r}".format(self.prereleases)
- if self._prereleases is not None
- else ""
- )
-
- return "<SpecifierSet({0!r}{1})>".format(str(self), pre)
-
- def __str__(self):
+ pre = (
+ ", prereleases={0!r}".format(self.prereleases)
+ if self._prereleases is not None
+ else ""
+ )
+
+ return "<SpecifierSet({0!r}{1})>".format(str(self), pre)
+
+ def __str__(self):
# type: () -> str
- return ",".join(sorted(str(s) for s in self._specs))
-
- def __hash__(self):
+ return ",".join(sorted(str(s) for s in self._specs))
+
+ def __hash__(self):
# type: () -> int
- return hash(self._specs)
-
- def __and__(self, other):
+ return hash(self._specs)
+
+ def __and__(self, other):
# type: (Union[SpecifierSet, str]) -> SpecifierSet
- if isinstance(other, string_types):
- other = SpecifierSet(other)
- elif not isinstance(other, SpecifierSet):
- return NotImplemented
-
- specifier = SpecifierSet()
- specifier._specs = frozenset(self._specs | other._specs)
-
- if self._prereleases is None and other._prereleases is not None:
- specifier._prereleases = other._prereleases
- elif self._prereleases is not None and other._prereleases is None:
- specifier._prereleases = self._prereleases
- elif self._prereleases == other._prereleases:
- specifier._prereleases = self._prereleases
- else:
- raise ValueError(
- "Cannot combine SpecifierSets with True and False prerelease "
- "overrides."
- )
-
- return specifier
-
- def __eq__(self, other):
+ if isinstance(other, string_types):
+ other = SpecifierSet(other)
+ elif not isinstance(other, SpecifierSet):
+ return NotImplemented
+
+ specifier = SpecifierSet()
+ specifier._specs = frozenset(self._specs | other._specs)
+
+ if self._prereleases is None and other._prereleases is not None:
+ specifier._prereleases = other._prereleases
+ elif self._prereleases is not None and other._prereleases is None:
+ specifier._prereleases = self._prereleases
+ elif self._prereleases == other._prereleases:
+ specifier._prereleases = self._prereleases
+ else:
+ raise ValueError(
+ "Cannot combine SpecifierSets with True and False prerelease "
+ "overrides."
+ )
+
+ return specifier
+
+ def __eq__(self, other):
# type: (object) -> bool
if isinstance(other, (string_types, _IndividualSpecifier)):
- other = SpecifierSet(str(other))
- elif not isinstance(other, SpecifierSet):
- return NotImplemented
-
- return self._specs == other._specs
-
- def __ne__(self, other):
+ other = SpecifierSet(str(other))
+ elif not isinstance(other, SpecifierSet):
+ return NotImplemented
+
+ return self._specs == other._specs
+
+ def __ne__(self, other):
# type: (object) -> bool
if isinstance(other, (string_types, _IndividualSpecifier)):
- other = SpecifierSet(str(other))
- elif not isinstance(other, SpecifierSet):
- return NotImplemented
-
- return self._specs != other._specs
-
- def __len__(self):
+ other = SpecifierSet(str(other))
+ elif not isinstance(other, SpecifierSet):
+ return NotImplemented
+
+ return self._specs != other._specs
+
+ def __len__(self):
# type: () -> int
- return len(self._specs)
-
- def __iter__(self):
+ return len(self._specs)
+
+ def __iter__(self):
# type: () -> Iterator[_IndividualSpecifier]
- return iter(self._specs)
-
- @property
- def prereleases(self):
+ return iter(self._specs)
+
+ @property
+ def prereleases(self):
# type: () -> Optional[bool]
- # If we have been given an explicit prerelease modifier, then we'll
- # pass that through here.
- if self._prereleases is not None:
- return self._prereleases
-
- # If we don't have any specifiers, and we don't have a forced value,
- # then we'll just return None since we don't know if this should have
- # pre-releases or not.
- if not self._specs:
- return None
-
- # Otherwise we'll see if any of the given specifiers accept
- # prereleases, if any of them do we'll return True, otherwise False.
- return any(s.prereleases for s in self._specs)
-
- @prereleases.setter
- def prereleases(self, value):
+ # If we have been given an explicit prerelease modifier, then we'll
+ # pass that through here.
+ if self._prereleases is not None:
+ return self._prereleases
+
+ # If we don't have any specifiers, and we don't have a forced value,
+ # then we'll just return None since we don't know if this should have
+ # pre-releases or not.
+ if not self._specs:
+ return None
+
+ # Otherwise we'll see if any of the given specifiers accept
+ # prereleases, if any of them do we'll return True, otherwise False.
+ return any(s.prereleases for s in self._specs)
+
+ @prereleases.setter
+ def prereleases(self, value):
# type: (bool) -> None
- self._prereleases = value
-
- def __contains__(self, item):
+ self._prereleases = value
+
+ def __contains__(self, item):
# type: (Union[ParsedVersion, str]) -> bool
- return self.contains(item)
-
- def contains(self, item, prereleases=None):
+ return self.contains(item)
+
+ def contains(self, item, prereleases=None):
# type: (Union[ParsedVersion, str], Optional[bool]) -> bool
- # Ensure that our item is a Version or LegacyVersion instance.
- if not isinstance(item, (LegacyVersion, Version)):
- item = parse(item)
-
- # Determine if we're forcing a prerelease or not, if we're not forcing
- # one for this particular filter call, then we'll use whatever the
- # SpecifierSet thinks for whether or not we should support prereleases.
- if prereleases is None:
- prereleases = self.prereleases
-
- # We can determine if we're going to allow pre-releases by looking to
- # see if any of the underlying items supports them. If none of them do
- # and this item is a pre-release then we do not allow it and we can
- # short circuit that here.
- # Note: This means that 1.0.dev1 would not be contained in something
- # like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0
- if not prereleases and item.is_prerelease:
- return False
-
- # We simply dispatch to the underlying specs here to make sure that the
- # given version is contained within all of them.
- # Note: This use of all() here means that an empty set of specifiers
- # will always return True, this is an explicit design decision.
+ # Ensure that our item is a Version or LegacyVersion instance.
+ if not isinstance(item, (LegacyVersion, Version)):
+ item = parse(item)
+
+ # Determine if we're forcing a prerelease or not, if we're not forcing
+ # one for this particular filter call, then we'll use whatever the
+ # SpecifierSet thinks for whether or not we should support prereleases.
+ if prereleases is None:
+ prereleases = self.prereleases
+
+ # We can determine if we're going to allow pre-releases by looking to
+ # see if any of the underlying items supports them. If none of them do
+ # and this item is a pre-release then we do not allow it and we can
+ # short circuit that here.
+ # Note: This means that 1.0.dev1 would not be contained in something
+ # like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0
+ if not prereleases and item.is_prerelease:
+ return False
+
+ # We simply dispatch to the underlying specs here to make sure that the
+ # given version is contained within all of them.
+ # Note: This use of all() here means that an empty set of specifiers
+ # will always return True, this is an explicit design decision.
return all(s.contains(item, prereleases=prereleases) for s in self._specs)
-
+
def filter(
self,
iterable, # type: Iterable[Union[ParsedVersion, str]]
@@ -817,48 +817,48 @@ class SpecifierSet(BaseSpecifier):
):
# type: (...) -> Iterable[Union[ParsedVersion, str]]
- # Determine if we're forcing a prerelease or not, if we're not forcing
- # one for this particular filter call, then we'll use whatever the
- # SpecifierSet thinks for whether or not we should support prereleases.
- if prereleases is None:
- prereleases = self.prereleases
-
- # If we have any specifiers, then we want to wrap our iterable in the
- # filter method for each one, this will act as a logical AND amongst
- # each specifier.
- if self._specs:
- for spec in self._specs:
- iterable = spec.filter(iterable, prereleases=bool(prereleases))
- return iterable
- # If we do not have any specifiers, then we need to have a rough filter
- # which will filter out any pre-releases, unless there are no final
- # releases, and which will filter out LegacyVersion in general.
- else:
+ # Determine if we're forcing a prerelease or not, if we're not forcing
+ # one for this particular filter call, then we'll use whatever the
+ # SpecifierSet thinks for whether or not we should support prereleases.
+ if prereleases is None:
+ prereleases = self.prereleases
+
+ # If we have any specifiers, then we want to wrap our iterable in the
+ # filter method for each one, this will act as a logical AND amongst
+ # each specifier.
+ if self._specs:
+ for spec in self._specs:
+ iterable = spec.filter(iterable, prereleases=bool(prereleases))
+ return iterable
+ # If we do not have any specifiers, then we need to have a rough filter
+ # which will filter out any pre-releases, unless there are no final
+ # releases, and which will filter out LegacyVersion in general.
+ else:
filtered = [] # type: List[Union[ParsedVersion, str]]
found_prereleases = [] # type: List[Union[ParsedVersion, str]]
-
- for item in iterable:
- # Ensure that we some kind of Version class for this item.
- if not isinstance(item, (LegacyVersion, Version)):
- parsed_version = parse(item)
- else:
- parsed_version = item
-
- # Filter out any item which is parsed as a LegacyVersion
- if isinstance(parsed_version, LegacyVersion):
- continue
-
- # Store any item which is a pre-release for later unless we've
- # already found a final version or we are accepting prereleases
- if parsed_version.is_prerelease and not prereleases:
- if not filtered:
- found_prereleases.append(item)
- else:
- filtered.append(item)
-
- # If we've found no items except for pre-releases, then we'll go
- # ahead and use the pre-releases
- if not filtered and found_prereleases and prereleases is None:
- return found_prereleases
-
- return filtered
+
+ for item in iterable:
+ # Ensure that we some kind of Version class for this item.
+ if not isinstance(item, (LegacyVersion, Version)):
+ parsed_version = parse(item)
+ else:
+ parsed_version = item
+
+ # Filter out any item which is parsed as a LegacyVersion
+ if isinstance(parsed_version, LegacyVersion):
+ continue
+
+ # Store any item which is a pre-release for later unless we've
+ # already found a final version or we are accepting prereleases
+ if parsed_version.is_prerelease and not prereleases:
+ if not filtered:
+ found_prereleases.append(item)
+ else:
+ filtered.append(item)
+
+ # If we've found no items except for pre-releases, then we'll go
+ # ahead and use the pre-releases
+ if not filtered and found_prereleases and prereleases is None:
+ return found_prereleases
+
+ return filtered
diff --git a/contrib/python/packaging/py2/packaging/utils.py b/contrib/python/packaging/py2/packaging/utils.py
index 7fcba8a8f8..6e8c2a3e5b 100644
--- a/contrib/python/packaging/py2/packaging/utils.py
+++ b/contrib/python/packaging/py2/packaging/utils.py
@@ -1,14 +1,14 @@
-# This file is dual licensed under the terms of the Apache License, Version
-# 2.0, and the BSD License. See the LICENSE file in the root of this repository
-# for complete details.
-from __future__ import absolute_import, division, print_function
-
-import re
-
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+from __future__ import absolute_import, division, print_function
+
+import re
+
from ._typing import TYPE_CHECKING, cast
from .tags import Tag, parse_tag
from .version import InvalidVersion, Version
-
+
if TYPE_CHECKING: # pragma: no cover
from typing import FrozenSet, NewType, Tuple, Union
@@ -31,14 +31,14 @@ class InvalidSdistFilename(ValueError):
"""
-_canonicalize_regex = re.compile(r"[-_.]+")
+_canonicalize_regex = re.compile(r"[-_.]+")
# PEP 427: The build number must start with a digit.
_build_tag_regex = re.compile(r"(\d+)(.*)")
-
-
-def canonicalize_name(name):
+
+
+def canonicalize_name(name):
# type: (str) -> NormalizedName
- # This is taken from PEP 503.
+ # This is taken from PEP 503.
value = _canonicalize_regex.sub("-", name).lower()
return cast(NormalizedName, value)
diff --git a/contrib/python/packaging/py2/packaging/version.py b/contrib/python/packaging/py2/packaging/version.py
index e687e63cb6..517d91f248 100644
--- a/contrib/python/packaging/py2/packaging/version.py
+++ b/contrib/python/packaging/py2/packaging/version.py
@@ -1,21 +1,21 @@
-# This file is dual licensed under the terms of the Apache License, Version
-# 2.0, and the BSD License. See the LICENSE file in the root of this repository
-# for complete details.
-from __future__ import absolute_import, division, print_function
-
-import collections
-import itertools
-import re
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+from __future__ import absolute_import, division, print_function
+
+import collections
+import itertools
+import re
import warnings
-
+
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]
@@ -37,118 +37,118 @@ if TYPE_CHECKING: # pragma: no cover
VersionComparisonMethod = Callable[
[Union[CmpKey, LegacyCmpKey], Union[CmpKey, LegacyCmpKey]], bool
]
-
+
__all__ = ["parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN"]
-_Version = collections.namedtuple(
+_Version = collections.namedtuple(
"_Version", ["epoch", "release", "dev", "pre", "post", "local"]
-)
-
-
-def parse(version):
+)
+
+
+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
- a valid PEP 440 version or a legacy version.
- """
- try:
- return Version(version)
- except InvalidVersion:
- return LegacyVersion(version)
-
-
-class InvalidVersion(ValueError):
- """
- An invalid version was found, users should refer to PEP 440.
- """
-
-
-class _BaseVersion(object):
+ """
+ Parse the given version string and return either a :class:`Version` object
+ or a :class:`LegacyVersion` object depending on if the given version is
+ a valid PEP 440 version or a legacy version.
+ """
+ try:
+ return Version(version)
+ except InvalidVersion:
+ return LegacyVersion(version)
+
+
+class InvalidVersion(ValueError):
+ """
+ An invalid version was found, users should refer to PEP 440.
+ """
+
+
+class _BaseVersion(object):
_key = None # type: Union[CmpKey, LegacyCmpKey]
-
- def __hash__(self):
+
+ def __hash__(self):
# type: () -> int
- return hash(self._key)
-
+ return hash(self._key)
+
# Please keep the duplicated `isinstance` check
# in the six comparisons hereunder
# unless you find a way to avoid adding overhead function calls.
- def __lt__(self, other):
+ def __lt__(self, other):
# type: (_BaseVersion) -> bool
if not isinstance(other, _BaseVersion):
return NotImplemented
-
+
return self._key < other._key
- def __le__(self, other):
+ def __le__(self, other):
# type: (_BaseVersion) -> bool
if not isinstance(other, _BaseVersion):
return NotImplemented
-
+
return self._key <= other._key
- def __eq__(self, other):
+ def __eq__(self, other):
# type: (object) -> bool
if not isinstance(other, _BaseVersion):
return NotImplemented
-
+
return self._key == other._key
- def __ge__(self, other):
+ def __ge__(self, other):
# type: (_BaseVersion) -> bool
if not isinstance(other, _BaseVersion):
return NotImplemented
-
+
return self._key >= other._key
- def __gt__(self, other):
+ def __gt__(self, other):
# type: (_BaseVersion) -> bool
if not isinstance(other, _BaseVersion):
return NotImplemented
-
+
return self._key > other._key
- def __ne__(self, other):
+ def __ne__(self, other):
# type: (object) -> bool
- if not isinstance(other, _BaseVersion):
- return NotImplemented
-
+ if not isinstance(other, _BaseVersion):
+ return NotImplemented
+
return self._key != other._key
-
-
-class LegacyVersion(_BaseVersion):
- def __init__(self, version):
+
+
+class LegacyVersion(_BaseVersion):
+ def __init__(self, version):
# type: (str) -> None
- self._version = str(version)
- self._key = _legacy_cmpkey(self._version)
-
+ self._version = str(version)
+ self._key = _legacy_cmpkey(self._version)
+
warnings.warn(
"Creating a LegacyVersion has been deprecated and will be "
"removed in the next major release",
DeprecationWarning,
)
- def __str__(self):
+ def __str__(self):
# type: () -> str
- return self._version
-
- def __repr__(self):
+ return self._version
+
+ def __repr__(self):
# type: () -> str
- return "<LegacyVersion({0})>".format(repr(str(self)))
-
- @property
- def public(self):
+ return "<LegacyVersion({0})>".format(repr(str(self)))
+
+ @property
+ def public(self):
# type: () -> str
- return self._version
-
- @property
- def base_version(self):
+ return self._version
+
+ @property
+ def base_version(self):
# type: () -> str
- return self._version
-
- @property
+ return self._version
+
+ @property
def epoch(self):
# type: () -> int
return -1
@@ -174,185 +174,185 @@ class LegacyVersion(_BaseVersion):
return None
@property
- def local(self):
+ def local(self):
# type: () -> None
- return None
-
- @property
- def is_prerelease(self):
+ return None
+
+ @property
+ def is_prerelease(self):
# type: () -> bool
- return False
-
- @property
- def is_postrelease(self):
+ return False
+
+ @property
+ def is_postrelease(self):
# type: () -> bool
- return False
-
+ return False
+
@property
def is_devrelease(self):
# type: () -> bool
return False
-
+
_legacy_version_component_re = re.compile(r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE)
-
-_legacy_version_replacement_map = {
+
+_legacy_version_replacement_map = {
"pre": "c",
"preview": "c",
"-": "final-",
"rc": "c",
"dev": "@",
-}
-
-
-def _parse_version_parts(s):
+}
+
+
+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)
-
- if not part or part == ".":
- continue
-
- if part[:1] in "0123456789":
- # pad for numeric comparison
- yield part.zfill(8)
- else:
- yield "*" + part
-
- # ensure that alpha/beta/candidate are before final
- yield "*final"
-
-
-def _legacy_cmpkey(version):
+ for part in _legacy_version_component_re.split(s):
+ part = _legacy_version_replacement_map.get(part, part)
+
+ if not part or part == ".":
+ continue
+
+ if part[:1] in "0123456789":
+ # pad for numeric comparison
+ yield part.zfill(8)
+ else:
+ yield "*" + part
+
+ # ensure that alpha/beta/candidate are before final
+ yield "*final"
+
+
+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,
- # as before all PEP 440 versions.
- epoch = -1
-
- # This scheme is taken from pkg_resources.parse_version setuptools prior to
- # it's adoption of the packaging library.
+ # 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,
+ # as before all PEP 440 versions.
+ epoch = -1
+
+ # This scheme is taken from pkg_resources.parse_version setuptools prior to
+ # it's adoption of the packaging library.
parts = [] # type: List[str]
- for part in _parse_version_parts(version.lower()):
- if part.startswith("*"):
- # remove "-" before a prerelease tag
- if part < "*final":
- while parts and parts[-1] == "*final-":
- parts.pop()
-
- # remove trailing zeros from each series of numeric parts
- while parts and parts[-1] == "00000000":
- parts.pop()
-
- parts.append(part)
-
+ for part in _parse_version_parts(version.lower()):
+ if part.startswith("*"):
+ # remove "-" before a prerelease tag
+ if part < "*final":
+ while parts and parts[-1] == "*final-":
+ parts.pop()
+
+ # remove trailing zeros from each series of numeric parts
+ while parts and parts[-1] == "00000000":
+ parts.pop()
+
+ parts.append(part)
+
return epoch, tuple(parts)
-
-
-# Deliberately not anchored to the start and end of the string, to make it
-# easier for 3rd party code to reuse
-VERSION_PATTERN = r"""
- v?
- (?:
- (?:(?P<epoch>[0-9]+)!)? # epoch
- (?P<release>[0-9]+(?:\.[0-9]+)*) # release segment
- (?P<pre> # pre-release
- [-_\.]?
- (?P<pre_l>(a|b|c|rc|alpha|beta|pre|preview))
- [-_\.]?
- (?P<pre_n>[0-9]+)?
- )?
- (?P<post> # post release
- (?:-(?P<post_n1>[0-9]+))
- |
- (?:
- [-_\.]?
- (?P<post_l>post|rev|r)
- [-_\.]?
- (?P<post_n2>[0-9]+)?
- )
- )?
- (?P<dev> # dev release
- [-_\.]?
- (?P<dev_l>dev)
- [-_\.]?
- (?P<dev_n>[0-9]+)?
- )?
- )
- (?:\+(?P<local>[a-z0-9]+(?:[-_\.][a-z0-9]+)*))? # local version
-"""
-
-
-class Version(_BaseVersion):
-
+
+
+# Deliberately not anchored to the start and end of the string, to make it
+# easier for 3rd party code to reuse
+VERSION_PATTERN = r"""
+ v?
+ (?:
+ (?:(?P<epoch>[0-9]+)!)? # epoch
+ (?P<release>[0-9]+(?:\.[0-9]+)*) # release segment
+ (?P<pre> # pre-release
+ [-_\.]?
+ (?P<pre_l>(a|b|c|rc|alpha|beta|pre|preview))
+ [-_\.]?
+ (?P<pre_n>[0-9]+)?
+ )?
+ (?P<post> # post release
+ (?:-(?P<post_n1>[0-9]+))
+ |
+ (?:
+ [-_\.]?
+ (?P<post_l>post|rev|r)
+ [-_\.]?
+ (?P<post_n2>[0-9]+)?
+ )
+ )?
+ (?P<dev> # dev release
+ [-_\.]?
+ (?P<dev_l>dev)
+ [-_\.]?
+ (?P<dev_n>[0-9]+)?
+ )?
+ )
+ (?:\+(?P<local>[a-z0-9]+(?:[-_\.][a-z0-9]+)*))? # local version
+"""
+
+
+class Version(_BaseVersion):
+
_regex = re.compile(r"^\s*" + VERSION_PATTERN + r"\s*$", re.VERBOSE | re.IGNORECASE)
-
- def __init__(self, version):
+
+ def __init__(self, version):
# type: (str) -> None
- # Validate the version and parse it into pieces
- match = self._regex.search(version)
- if not match:
- raise InvalidVersion("Invalid version: '{0}'".format(version))
-
- # Store the parsed out pieces of the version
- self._version = _Version(
- epoch=int(match.group("epoch")) if match.group("epoch") else 0,
- release=tuple(int(i) for i in match.group("release").split(".")),
+ # Validate the version and parse it into pieces
+ match = self._regex.search(version)
+ if not match:
+ raise InvalidVersion("Invalid version: '{0}'".format(version))
+
+ # Store the parsed out pieces of the version
+ self._version = _Version(
+ epoch=int(match.group("epoch")) if match.group("epoch") else 0,
+ release=tuple(int(i) for i in match.group("release").split(".")),
pre=_parse_letter_version(match.group("pre_l"), match.group("pre_n")),
- post=_parse_letter_version(
+ post=_parse_letter_version(
match.group("post_l"), match.group("post_n1") or match.group("post_n2")
- ),
+ ),
dev=_parse_letter_version(match.group("dev_l"), match.group("dev_n")),
- local=_parse_local_version(match.group("local")),
- )
-
- # Generate a key which will be used for sorting
- self._key = _cmpkey(
- self._version.epoch,
- self._version.release,
- self._version.pre,
- self._version.post,
- self._version.dev,
- self._version.local,
- )
-
- def __repr__(self):
+ local=_parse_local_version(match.group("local")),
+ )
+
+ # Generate a key which will be used for sorting
+ self._key = _cmpkey(
+ self._version.epoch,
+ self._version.release,
+ self._version.pre,
+ self._version.post,
+ self._version.dev,
+ self._version.local,
+ )
+
+ def __repr__(self):
# type: () -> str
- return "<Version({0})>".format(repr(str(self)))
-
- def __str__(self):
+ return "<Version({0})>".format(repr(str(self)))
+
+ def __str__(self):
# type: () -> str
- parts = []
-
- # Epoch
+ parts = []
+
+ # Epoch
if self.epoch != 0:
parts.append("{0}!".format(self.epoch))
-
- # Release segment
+
+ # Release segment
parts.append(".".join(str(x) for x in self.release))
-
- # Pre-release
+
+ # Pre-release
if self.pre is not None:
parts.append("".join(str(x) for x in self.pre))
-
- # Post-release
+
+ # Post-release
if self.post is not None:
parts.append(".post{0}".format(self.post))
-
- # Development release
+
+ # Development release
if self.dev is not None:
parts.append(".dev{0}".format(self.dev))
-
- # Local version segment
+
+ # Local version segment
if self.local is not None:
parts.append("+{0}".format(self.local))
-
- return "".join(parts)
-
- @property
+
+ return "".join(parts)
+
+ @property
def epoch(self):
# type: () -> int
_epoch = self._version.epoch # type: int
@@ -389,39 +389,39 @@ class Version(_BaseVersion):
return None
@property
- def public(self):
+ def public(self):
# type: () -> str
- return str(self).split("+", 1)[0]
-
- @property
- def base_version(self):
+ return str(self).split("+", 1)[0]
+
+ @property
+ def base_version(self):
# type: () -> str
- parts = []
-
- # Epoch
+ parts = []
+
+ # Epoch
if self.epoch != 0:
parts.append("{0}!".format(self.epoch))
-
- # Release segment
+
+ # Release segment
parts.append(".".join(str(x) for x in self.release))
-
- return "".join(parts)
-
- @property
- def is_prerelease(self):
+
+ return "".join(parts)
+
+ @property
+ def is_prerelease(self):
# type: () -> bool
return self.dev is not None or self.pre is not None
-
- @property
- def is_postrelease(self):
+
+ @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
@@ -444,54 +444,54 @@ def _parse_letter_version(
):
# type: (...) -> Optional[Tuple[str, int]]
- if letter:
- # We consider there to be an implicit 0 in a pre-release if there is
- # not a numeral associated with it.
- if number is None:
- number = 0
-
- # We normalize any letters to their lower case form
- letter = letter.lower()
-
- # We consider some words to be alternate spellings of other words and
- # in those cases we want to normalize the spellings to our preferred
- # spelling.
- if letter == "alpha":
- letter = "a"
- elif letter == "beta":
- letter = "b"
- elif letter in ["c", "pre", "preview"]:
- letter = "rc"
- elif letter in ["rev", "r"]:
- letter = "post"
-
- return letter, int(number)
- if not letter and number:
- # We assume if we are given a number, but we are not given a letter
- # then this is using the implicit post release syntax (e.g. 1.0-1)
- letter = "post"
-
- return letter, int(number)
-
+ if letter:
+ # We consider there to be an implicit 0 in a pre-release if there is
+ # not a numeral associated with it.
+ if number is None:
+ number = 0
+
+ # We normalize any letters to their lower case form
+ letter = letter.lower()
+
+ # We consider some words to be alternate spellings of other words and
+ # in those cases we want to normalize the spellings to our preferred
+ # spelling.
+ if letter == "alpha":
+ letter = "a"
+ elif letter == "beta":
+ letter = "b"
+ elif letter in ["c", "pre", "preview"]:
+ letter = "rc"
+ elif letter in ["rev", "r"]:
+ letter = "post"
+
+ return letter, int(number)
+ if not letter and number:
+ # We assume if we are given a number, but we are not given a letter
+ # then this is using the implicit post release syntax (e.g. 1.0-1)
+ letter = "post"
+
+ return letter, int(number)
+
return None
-
+
_local_version_separators = re.compile(r"[\._-]")
-
-
-def _parse_local_version(local):
+
+
+def _parse_local_version(local):
# type: (str) -> Optional[LocalType]
- """
- Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
- """
- if local is not None:
- return tuple(
- part.lower() if not part.isdigit() else int(part)
+ """
+ Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
+ """
+ if local is not None:
+ return tuple(
+ 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, ...]
@@ -502,55 +502,55 @@ def _cmpkey(
):
# type: (...) -> CmpKey
- # 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.
+ # 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(
reversed(list(itertools.dropwhile(lambda x: x == 0, reversed(release))))
- )
-
- # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
- # We'll do this by abusing the pre segment, but we _only_ want to do this
- # 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:
+ )
+
+ # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
+ # We'll do this by abusing the pre segment, but we _only_ want to do this
+ # 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 = NegativeInfinity # type: PrePostDevType
- # Versions without a pre-release (except as noted above) should sort after
- # those with one.
- elif pre is None:
+ # Versions without a pre-release (except as noted above) should sort after
+ # those with one.
+ elif pre is None:
_pre = Infinity
else:
_pre = pre
-
- # Versions without a post segment should sort before those with one.
- if post is None:
+
+ # Versions without a post segment should sort before those with one.
+ if post is None:
_post = NegativeInfinity # type: PrePostDevType
-
+
else:
_post = post
- # Versions without a development segment should sort after those with one.
- if dev is None:
+ # Versions without a development segment should sort after those with one.
+ if dev is None:
_dev = Infinity # type: PrePostDevType
-
+
else:
_dev = dev
- if local is None:
- # Versions without a local segment should sort before those with one.
+ if local is None:
+ # Versions without a local segment should sort before those with one.
_local = NegativeInfinity # type: LocalType
- else:
- # Versions with a local segment need that segment parsed to implement
- # the sorting rules in PEP440.
- # - Alpha numeric segments sort before numeric segments
- # - Alpha numeric segments sort lexicographically
- # - Numeric segments sort numerically
- # - Shorter versions sort before longer versions when the prefixes
- # match exactly
+ else:
+ # Versions with a local segment need that segment parsed to implement
+ # the sorting rules in PEP440.
+ # - Alpha numeric segments sort before numeric segments
+ # - Alpha numeric segments sort lexicographically
+ # - Numeric segments sort numerically
+ # - Shorter versions sort before longer versions when the prefixes
+ # match exactly
_local = tuple(
(i, "") if isinstance(i, int) else (NegativeInfinity, i) for i in local
- )
-
+ )
+
return epoch, _release, _pre, _post, _dev, _local
diff --git a/contrib/python/packaging/py2/ya.make b/contrib/python/packaging/py2/ya.make
index 2680f0f210..916ebde32c 100644
--- a/contrib/python/packaging/py2/ya.make
+++ b/contrib/python/packaging/py2/ya.make
@@ -1,34 +1,34 @@
# Generated by devtools/yamaker (pypi).
PY2_LIBRARY()
-
+
OWNER(orivej g:python-contrib)
VERSION(20.9)
-
+
LICENSE(BSD-3-Clause)
-PEERDIR(
- contrib/python/pyparsing
-)
-
+PEERDIR(
+ contrib/python/pyparsing
+)
+
NO_LINT()
-PY_SRCS(
- TOP_LEVEL
+PY_SRCS(
+ TOP_LEVEL
packaging/__about__.py
- packaging/__init__.py
- packaging/_compat.py
- packaging/_structures.py
+ packaging/__init__.py
+ packaging/_compat.py
+ packaging/_structures.py
packaging/_typing.py
- packaging/markers.py
- packaging/requirements.py
- packaging/specifiers.py
+ packaging/markers.py
+ packaging/requirements.py
+ packaging/specifiers.py
packaging/tags.py
- packaging/utils.py
- packaging/version.py
-)
-
+ packaging/utils.py
+ packaging/version.py
+)
+
RESOURCE_FILES(
PREFIX contrib/python/packaging/py2/
.dist-info/METADATA
@@ -36,4 +36,4 @@ RESOURCE_FILES(
packaging/py.typed
)
-END()
+END()
diff --git a/contrib/python/packaging/py3/packaging/__init__.py b/contrib/python/packaging/py3/packaging/__init__.py
index 9e7be5ef16..3c50c5dcfe 100644
--- a/contrib/python/packaging/py3/packaging/__init__.py
+++ b/contrib/python/packaging/py3/packaging/__init__.py
@@ -1,6 +1,6 @@
-# This file is dual licensed under the terms of the Apache License, Version
-# 2.0, and the BSD License. See the LICENSE file in the root of this repository
-# for complete details.
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
from .__about__ import (
__author__,
diff --git a/contrib/python/packaging/py3/packaging/_structures.py b/contrib/python/packaging/py3/packaging/_structures.py
index a54460baf7..90a6465f96 100644
--- a/contrib/python/packaging/py3/packaging/_structures.py
+++ b/contrib/python/packaging/py3/packaging/_structures.py
@@ -1,61 +1,61 @@
-# This file is dual licensed under the terms of the Apache License, Version
-# 2.0, and the BSD License. See the LICENSE file in the root of this repository
-# for complete details.
-
-
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+
class InfinityType:
def __repr__(self) -> str:
- return "Infinity"
-
+ return "Infinity"
+
def __hash__(self) -> int:
- return hash(repr(self))
-
+ return hash(repr(self))
+
def __lt__(self, other: object) -> bool:
- return False
-
+ return False
+
def __le__(self, other: object) -> bool:
- return False
-
+ return False
+
def __eq__(self, other: object) -> bool:
- return isinstance(other, self.__class__)
-
+ return isinstance(other, self.__class__)
+
def __gt__(self, other: object) -> bool:
- return True
-
+ return True
+
def __ge__(self, other: object) -> bool:
- return True
-
+ return True
+
def __neg__(self: object) -> "NegativeInfinityType":
- return NegativeInfinity
-
+ return NegativeInfinity
+
Infinity = InfinityType()
-
-
+
+
class NegativeInfinityType:
def __repr__(self) -> str:
- return "-Infinity"
-
+ return "-Infinity"
+
def __hash__(self) -> int:
- return hash(repr(self))
-
+ return hash(repr(self))
+
def __lt__(self, other: object) -> bool:
- return True
-
+ return True
+
def __le__(self, other: object) -> bool:
- return True
-
+ return True
+
def __eq__(self, other: object) -> bool:
- return isinstance(other, self.__class__)
-
+ return isinstance(other, self.__class__)
+
def __gt__(self, other: object) -> bool:
- return False
-
+ return False
+
def __ge__(self, other: object) -> bool:
- return False
-
+ return False
+
def __neg__(self: object) -> InfinityType:
- return Infinity
-
+ return Infinity
+
NegativeInfinity = NegativeInfinityType()
diff --git a/contrib/python/packaging/py3/packaging/markers.py b/contrib/python/packaging/py3/packaging/markers.py
index 7932ce6be5..cb640e8f9b 100644
--- a/contrib/python/packaging/py3/packaging/markers.py
+++ b/contrib/python/packaging/py3/packaging/markers.py
@@ -1,13 +1,13 @@
-# This file is dual licensed under the terms of the Apache License, Version
-# 2.0, and the BSD License. See the LICENSE file in the root of this repository
-# for complete details.
-
-import operator
-import os
-import platform
-import sys
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+import operator
+import os
+import platform
+import sys
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
-
+
from pyparsing import ( # noqa: N817
Forward,
Group,
@@ -19,69 +19,69 @@ from pyparsing import ( # noqa: N817
stringEnd,
stringStart,
)
-
+
from .specifiers import InvalidSpecifier, Specifier
-
-__all__ = [
+
+__all__ = [
"InvalidMarker",
"UndefinedComparison",
"UndefinedEnvironmentName",
"Marker",
"default_environment",
-]
-
+]
+
Operator = Callable[[str, str], bool]
-
-
-class InvalidMarker(ValueError):
- """
- An invalid marker was found, users should refer to PEP 508.
- """
-
-
-class UndefinedComparison(ValueError):
- """
- An invalid operation was attempted on a value that doesn't support it.
- """
-
-
-class UndefinedEnvironmentName(ValueError):
- """
- A name was attempted to be used that does not exist inside of the
- environment.
- """
-
-
+
+
+class InvalidMarker(ValueError):
+ """
+ An invalid marker was found, users should refer to PEP 508.
+ """
+
+
+class UndefinedComparison(ValueError):
+ """
+ An invalid operation was attempted on a value that doesn't support it.
+ """
+
+
+class UndefinedEnvironmentName(ValueError):
+ """
+ A name was attempted to be used that does not exist inside of the
+ environment.
+ """
+
+
class Node:
def __init__(self, value: Any) -> None:
- self.value = value
-
+ self.value = value
+
def __str__(self) -> str:
- return str(self.value)
-
+ return str(self.value)
+
def __repr__(self) -> str:
return f"<{self.__class__.__name__}('{self}')>"
-
+
def serialize(self) -> str:
- raise NotImplementedError
-
-
-class Variable(Node):
+ raise NotImplementedError
+
+
+class Variable(Node):
def serialize(self) -> str:
- return str(self)
-
-
-class Value(Node):
+ return str(self)
+
+
+class Value(Node):
def serialize(self) -> str:
return f'"{self}"'
-
-
-class Op(Node):
+
+
+class Op(Node):
def serialize(self) -> str:
- return str(self)
-
-
-VARIABLE = (
+ return str(self)
+
+
+VARIABLE = (
L("implementation_version")
| L("platform_python_implementation")
| L("implementation_name")
@@ -100,205 +100,205 @@ VARIABLE = (
| L("platform.python_implementation") # PEP-345
| L("python_implementation") # undocumented setuptools legacy
| L("extra") # PEP-508
-)
-ALIASES = {
+)
+ALIASES = {
"os.name": "os_name",
"sys.platform": "sys_platform",
"platform.version": "platform_version",
"platform.machine": "platform_machine",
"platform.python_implementation": "platform_python_implementation",
"python_implementation": "platform_python_implementation",
-}
-VARIABLE.setParseAction(lambda s, l, t: Variable(ALIASES.get(t[0], t[0])))
-
-VERSION_CMP = (
+}
+VARIABLE.setParseAction(lambda s, l, t: Variable(ALIASES.get(t[0], t[0])))
+
+VERSION_CMP = (
L("===") | L("==") | L(">=") | L("<=") | L("!=") | L("~=") | L(">") | L("<")
-)
-
-MARKER_OP = VERSION_CMP | L("not in") | L("in")
-MARKER_OP.setParseAction(lambda s, l, t: Op(t[0]))
-
-MARKER_VALUE = QuotedString("'") | QuotedString('"')
-MARKER_VALUE.setParseAction(lambda s, l, t: Value(t[0]))
-
-BOOLOP = L("and") | L("or")
-
-MARKER_VAR = VARIABLE | MARKER_VALUE
-
-MARKER_ITEM = Group(MARKER_VAR + MARKER_OP + MARKER_VAR)
-MARKER_ITEM.setParseAction(lambda s, l, t: tuple(t[0]))
-
-LPAREN = L("(").suppress()
-RPAREN = L(")").suppress()
-
-MARKER_EXPR = Forward()
-MARKER_ATOM = MARKER_ITEM | Group(LPAREN + MARKER_EXPR + RPAREN)
-MARKER_EXPR << MARKER_ATOM + ZeroOrMore(BOOLOP + MARKER_EXPR)
-
-MARKER = stringStart + MARKER_EXPR + stringEnd
-
-
+)
+
+MARKER_OP = VERSION_CMP | L("not in") | L("in")
+MARKER_OP.setParseAction(lambda s, l, t: Op(t[0]))
+
+MARKER_VALUE = QuotedString("'") | QuotedString('"')
+MARKER_VALUE.setParseAction(lambda s, l, t: Value(t[0]))
+
+BOOLOP = L("and") | L("or")
+
+MARKER_VAR = VARIABLE | MARKER_VALUE
+
+MARKER_ITEM = Group(MARKER_VAR + MARKER_OP + MARKER_VAR)
+MARKER_ITEM.setParseAction(lambda s, l, t: tuple(t[0]))
+
+LPAREN = L("(").suppress()
+RPAREN = L(")").suppress()
+
+MARKER_EXPR = Forward()
+MARKER_ATOM = MARKER_ITEM | Group(LPAREN + MARKER_EXPR + RPAREN)
+MARKER_EXPR << MARKER_ATOM + ZeroOrMore(BOOLOP + MARKER_EXPR)
+
+MARKER = stringStart + MARKER_EXPR + stringEnd
+
+
def _coerce_parse_result(results: Union[ParseResults, List[Any]]) -> List[Any]:
- if isinstance(results, ParseResults):
- return [_coerce_parse_result(i) for i in results]
- else:
- return results
-
-
+ if isinstance(results, ParseResults):
+ return [_coerce_parse_result(i) for i in results]
+ else:
+ return results
+
+
def _format_marker(
marker: Union[List[str], Tuple[Node, ...], str], first: Optional[bool] = True
) -> str:
assert isinstance(marker, (list, tuple, str))
-
- # Sometimes we have a structure like [[...]] which is a single item list
- # where the single item is itself it's own list. In that case we want skip
- # the rest of this function so that we don't get extraneous () on the
- # outside.
+
+ # Sometimes we have a structure like [[...]] which is a single item list
+ # where the single item is itself it's own list. In that case we want skip
+ # the rest of this function so that we don't get extraneous () on the
+ # outside.
if (
isinstance(marker, list)
and len(marker) == 1
and isinstance(marker[0], (list, tuple))
):
- return _format_marker(marker[0])
-
- if isinstance(marker, list):
- inner = (_format_marker(m, first=False) for m in marker)
- if first:
- return " ".join(inner)
- else:
- return "(" + " ".join(inner) + ")"
- elif isinstance(marker, tuple):
- return " ".join([m.serialize() for m in marker])
- else:
- return marker
-
-
+ return _format_marker(marker[0])
+
+ if isinstance(marker, list):
+ inner = (_format_marker(m, first=False) for m in marker)
+ if first:
+ return " ".join(inner)
+ else:
+ return "(" + " ".join(inner) + ")"
+ elif isinstance(marker, tuple):
+ return " ".join([m.serialize() for m in marker])
+ else:
+ return marker
+
+
_operators: Dict[str, Operator] = {
- "in": lambda lhs, rhs: lhs in rhs,
- "not in": lambda lhs, rhs: lhs not in rhs,
- "<": operator.lt,
- "<=": operator.le,
- "==": operator.eq,
- "!=": operator.ne,
- ">=": operator.ge,
- ">": operator.gt,
+ "in": lambda lhs, rhs: lhs in rhs,
+ "not in": lambda lhs, rhs: lhs not in rhs,
+ "<": operator.lt,
+ "<=": operator.le,
+ "==": operator.eq,
+ "!=": operator.ne,
+ ">=": operator.ge,
+ ">": operator.gt,
}
-
-
+
+
def _eval_op(lhs: str, op: Op, rhs: str) -> bool:
- try:
- spec = Specifier("".join([op.serialize(), rhs]))
- except InvalidSpecifier:
- pass
- else:
- return spec.contains(lhs)
-
+ try:
+ spec = Specifier("".join([op.serialize(), rhs]))
+ except InvalidSpecifier:
+ pass
+ else:
+ return spec.contains(lhs)
+
oper: Optional[Operator] = _operators.get(op.serialize())
- if oper is None:
+ if oper is None:
raise UndefinedComparison(f"Undefined {op!r} on {lhs!r} and {rhs!r}.")
-
- return oper(lhs, rhs)
-
-
+
+ return oper(lhs, rhs)
+
+
class Undefined:
pass
-
-
+
+
_undefined = Undefined()
def _get_env(environment: Dict[str, str], name: str) -> str:
value: Union[str, Undefined] = environment.get(name, _undefined)
-
+
if isinstance(value, Undefined):
- raise UndefinedEnvironmentName(
+ raise UndefinedEnvironmentName(
f"{name!r} does not exist in evaluation environment."
- )
-
- return value
-
-
+ )
+
+ return value
+
+
def _evaluate_markers(markers: List[Any], environment: Dict[str, str]) -> bool:
groups: List[List[bool]] = [[]]
-
- for marker in markers:
+
+ for marker in markers:
assert isinstance(marker, (list, tuple, str))
-
- if isinstance(marker, list):
- groups[-1].append(_evaluate_markers(marker, environment))
- elif isinstance(marker, tuple):
- lhs, op, rhs = marker
-
- if isinstance(lhs, Variable):
- lhs_value = _get_env(environment, lhs.value)
- rhs_value = rhs.value
- else:
- lhs_value = lhs.value
- rhs_value = _get_env(environment, rhs.value)
-
- groups[-1].append(_eval_op(lhs_value, op, rhs_value))
- else:
- assert marker in ["and", "or"]
- if marker == "or":
- groups.append([])
-
- return any(all(item) for item in groups)
-
-
+
+ if isinstance(marker, list):
+ groups[-1].append(_evaluate_markers(marker, environment))
+ elif isinstance(marker, tuple):
+ lhs, op, rhs = marker
+
+ if isinstance(lhs, Variable):
+ lhs_value = _get_env(environment, lhs.value)
+ rhs_value = rhs.value
+ else:
+ lhs_value = lhs.value
+ rhs_value = _get_env(environment, rhs.value)
+
+ groups[-1].append(_eval_op(lhs_value, op, rhs_value))
+ else:
+ assert marker in ["and", "or"]
+ if marker == "or":
+ groups.append([])
+
+ return any(all(item) for item in groups)
+
+
def format_full_version(info: "sys._version_info") -> str:
version = "{0.major}.{0.minor}.{0.micro}".format(info)
- kind = info.releaselevel
+ kind = info.releaselevel
if kind != "final":
- version += kind[0] + str(info.serial)
- return version
-
-
+ version += kind[0] + str(info.serial)
+ return version
+
+
def default_environment() -> Dict[str, str]:
iver = format_full_version(sys.implementation.version)
implementation_name = sys.implementation.name
- return {
- "implementation_name": implementation_name,
- "implementation_version": iver,
- "os_name": os.name,
- "platform_machine": platform.machine(),
- "platform_release": platform.release(),
- "platform_system": platform.system(),
- "platform_version": platform.version(),
- "python_full_version": platform.python_version(),
- "platform_python_implementation": platform.python_implementation(),
+ return {
+ "implementation_name": implementation_name,
+ "implementation_version": iver,
+ "os_name": os.name,
+ "platform_machine": platform.machine(),
+ "platform_release": platform.release(),
+ "platform_system": platform.system(),
+ "platform_version": platform.version(),
+ "python_full_version": platform.python_version(),
+ "platform_python_implementation": platform.python_implementation(),
"python_version": ".".join(platform.python_version_tuple()[:2]),
- "sys_platform": sys.platform,
- }
-
-
+ "sys_platform": sys.platform,
+ }
+
+
class Marker:
def __init__(self, marker: str) -> None:
- try:
- self._markers = _coerce_parse_result(MARKER.parseString(marker))
- except ParseException as e:
+ try:
+ self._markers = _coerce_parse_result(MARKER.parseString(marker))
+ except ParseException as e:
raise InvalidMarker(
f"Invalid marker: {marker!r}, parse error at "
f"{marker[e.loc : e.loc + 8]!r}"
)
-
+
def __str__(self) -> str:
- return _format_marker(self._markers)
-
+ return _format_marker(self._markers)
+
def __repr__(self) -> str:
return f"<Marker('{self}')>"
-
+
def evaluate(self, environment: Optional[Dict[str, str]] = None) -> bool:
- """Evaluate a marker.
-
- Return the boolean from evaluating the given marker against the
- environment. environment is an optional argument to override all or
- part of the determined environment.
-
- The environment is determined from the current Python process.
- """
- current_environment = default_environment()
- if environment is not None:
- current_environment.update(environment)
-
- return _evaluate_markers(self._markers, current_environment)
+ """Evaluate a marker.
+
+ Return the boolean from evaluating the given marker against the
+ environment. environment is an optional argument to override all or
+ part of the determined environment.
+
+ The environment is determined from the current Python process.
+ """
+ current_environment = default_environment()
+ if environment is not None:
+ current_environment.update(environment)
+
+ return _evaluate_markers(self._markers, current_environment)
diff --git a/contrib/python/packaging/py3/packaging/requirements.py b/contrib/python/packaging/py3/packaging/requirements.py
index a83a8e7946..53f9a3aa42 100644
--- a/contrib/python/packaging/py3/packaging/requirements.py
+++ b/contrib/python/packaging/py3/packaging/requirements.py
@@ -1,12 +1,12 @@
-# This file is dual licensed under the terms of the Apache License, Version
-# 2.0, and the BSD License. See the LICENSE file in the root of this repository
-# for complete details.
-
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
import re
-import string
+import string
import urllib.parse
from typing import List, Optional as TOptional, Set
-
+
from pyparsing import ( # noqa
Combine,
Literal as L,
@@ -19,94 +19,94 @@ from pyparsing import ( # noqa
stringEnd,
stringStart,
)
-
-from .markers import MARKER_EXPR, Marker
-from .specifiers import LegacySpecifier, Specifier, SpecifierSet
-
-
-class InvalidRequirement(ValueError):
- """
- An invalid requirement was found, users should refer to PEP 508.
- """
-
-
-ALPHANUM = Word(string.ascii_letters + string.digits)
-
-LBRACKET = L("[").suppress()
-RBRACKET = L("]").suppress()
-LPAREN = L("(").suppress()
-RPAREN = L(")").suppress()
-COMMA = L(",").suppress()
-SEMICOLON = L(";").suppress()
-AT = L("@").suppress()
-
-PUNCTUATION = Word("-_.")
-IDENTIFIER_END = ALPHANUM | (ZeroOrMore(PUNCTUATION) + ALPHANUM)
-IDENTIFIER = Combine(ALPHANUM + ZeroOrMore(IDENTIFIER_END))
-
-NAME = IDENTIFIER("name")
-EXTRA = IDENTIFIER
-
+
+from .markers import MARKER_EXPR, Marker
+from .specifiers import LegacySpecifier, Specifier, SpecifierSet
+
+
+class InvalidRequirement(ValueError):
+ """
+ An invalid requirement was found, users should refer to PEP 508.
+ """
+
+
+ALPHANUM = Word(string.ascii_letters + string.digits)
+
+LBRACKET = L("[").suppress()
+RBRACKET = L("]").suppress()
+LPAREN = L("(").suppress()
+RPAREN = L(")").suppress()
+COMMA = L(",").suppress()
+SEMICOLON = L(";").suppress()
+AT = L("@").suppress()
+
+PUNCTUATION = Word("-_.")
+IDENTIFIER_END = ALPHANUM | (ZeroOrMore(PUNCTUATION) + ALPHANUM)
+IDENTIFIER = Combine(ALPHANUM + ZeroOrMore(IDENTIFIER_END))
+
+NAME = IDENTIFIER("name")
+EXTRA = IDENTIFIER
+
URI = Regex(r"[^ ]+")("url")
URL = AT + URI
-
-EXTRAS_LIST = EXTRA + ZeroOrMore(COMMA + EXTRA)
-EXTRAS = (LBRACKET + Optional(EXTRAS_LIST) + RBRACKET)("extras")
-
-VERSION_PEP440 = Regex(Specifier._regex_str, re.VERBOSE | re.IGNORECASE)
-VERSION_LEGACY = Regex(LegacySpecifier._regex_str, re.VERBOSE | re.IGNORECASE)
-
-VERSION_ONE = VERSION_PEP440 ^ VERSION_LEGACY
+
+EXTRAS_LIST = EXTRA + ZeroOrMore(COMMA + EXTRA)
+EXTRAS = (LBRACKET + Optional(EXTRAS_LIST) + RBRACKET)("extras")
+
+VERSION_PEP440 = Regex(Specifier._regex_str, re.VERBOSE | re.IGNORECASE)
+VERSION_LEGACY = Regex(LegacySpecifier._regex_str, re.VERBOSE | re.IGNORECASE)
+
+VERSION_ONE = VERSION_PEP440 ^ VERSION_LEGACY
VERSION_MANY = Combine(
VERSION_ONE + ZeroOrMore(COMMA + VERSION_ONE), joinString=",", adjacent=False
)("_raw_spec")
_VERSION_SPEC = Optional((LPAREN + VERSION_MANY + RPAREN) | VERSION_MANY)
_VERSION_SPEC.setParseAction(lambda s, l, t: t._raw_spec or "")
-
-VERSION_SPEC = originalTextFor(_VERSION_SPEC)("specifier")
-VERSION_SPEC.setParseAction(lambda s, l, t: t[1])
-
-MARKER_EXPR = originalTextFor(MARKER_EXPR())("marker")
-MARKER_EXPR.setParseAction(
+
+VERSION_SPEC = originalTextFor(_VERSION_SPEC)("specifier")
+VERSION_SPEC.setParseAction(lambda s, l, t: t[1])
+
+MARKER_EXPR = originalTextFor(MARKER_EXPR())("marker")
+MARKER_EXPR.setParseAction(
lambda s, l, t: Marker(s[t._original_start : t._original_end])
-)
+)
MARKER_SEPARATOR = SEMICOLON
MARKER = MARKER_SEPARATOR + MARKER_EXPR
-
-VERSION_AND_MARKER = VERSION_SPEC + Optional(MARKER)
-URL_AND_MARKER = URL + Optional(MARKER)
-
+
+VERSION_AND_MARKER = VERSION_SPEC + Optional(MARKER)
+URL_AND_MARKER = URL + Optional(MARKER)
+
NAMED_REQUIREMENT = NAME + Optional(EXTRAS) + (URL_AND_MARKER | VERSION_AND_MARKER)
-
-REQUIREMENT = stringStart + NAMED_REQUIREMENT + stringEnd
+
+REQUIREMENT = stringStart + NAMED_REQUIREMENT + stringEnd
# pyparsing isn't thread safe during initialization, so we do it eagerly, see
# issue #104
REQUIREMENT.parseString("x[]")
-
-
+
+
class Requirement:
- """Parse a requirement.
-
- Parse a given requirement string into its parts, such as name, specifier,
- URL, and extras. Raises InvalidRequirement on a badly-formed requirement
- string.
- """
-
- # TODO: Can we test whether something is contained within a requirement?
- # If so how do we do that? Do we need to test against the _name_ of
- # the thing as well as the version? What about the markers?
- # TODO: Can we normalize the name and extra name?
-
+ """Parse a requirement.
+
+ Parse a given requirement string into its parts, such as name, specifier,
+ URL, and extras. Raises InvalidRequirement on a badly-formed requirement
+ string.
+ """
+
+ # TODO: Can we test whether something is contained within a requirement?
+ # If so how do we do that? Do we need to test against the _name_ of
+ # the thing as well as the version? What about the markers?
+ # TODO: Can we normalize the name and extra name?
+
def __init__(self, requirement_string: str) -> None:
- try:
- req = REQUIREMENT.parseString(requirement_string)
- except ParseException as e:
+ try:
+ req = REQUIREMENT.parseString(requirement_string)
+ except ParseException as e:
raise InvalidRequirement(
f'Parse error at "{ requirement_string[e.loc : e.loc + 8]!r}": {e.msg}'
)
-
+
self.name: str = req.name
- if req.url:
+ if req.url:
parsed_url = urllib.parse.urlparse(req.url)
if parsed_url.scheme == "file":
if urllib.parse.urlunparse(parsed_url) != req.url:
@@ -116,31 +116,31 @@ class Requirement:
):
raise InvalidRequirement(f"Invalid URL: {req.url}")
self.url: TOptional[str] = req.url
- else:
- self.url = None
+ else:
+ self.url = None
self.extras: Set[str] = set(req.extras.asList() if req.extras else [])
self.specifier: SpecifierSet = SpecifierSet(req.specifier)
self.marker: TOptional[Marker] = req.marker if req.marker else None
-
+
def __str__(self) -> str:
parts: List[str] = [self.name]
-
- if self.extras:
+
+ if self.extras:
formatted_extras = ",".join(sorted(self.extras))
parts.append(f"[{formatted_extras}]")
-
- if self.specifier:
- parts.append(str(self.specifier))
-
- if self.url:
+
+ if self.specifier:
+ parts.append(str(self.specifier))
+
+ if self.url:
parts.append(f"@ {self.url}")
if self.marker:
parts.append(" ")
-
- if self.marker:
+
+ if self.marker:
parts.append(f"; {self.marker}")
-
- return "".join(parts)
-
+
+ return "".join(parts)
+
def __repr__(self) -> str:
return f"<Requirement('{self}')>"
diff --git a/contrib/python/packaging/py3/packaging/specifiers.py b/contrib/python/packaging/py3/packaging/specifiers.py
index f4415f6cce..0e218a6f9f 100644
--- a/contrib/python/packaging/py3/packaging/specifiers.py
+++ b/contrib/python/packaging/py3/packaging/specifiers.py
@@ -1,11 +1,11 @@
-# This file is dual licensed under the terms of the Apache License, Version
-# 2.0, and the BSD License. See the LICENSE file in the root of this repository
-# for complete details.
-
-import abc
-import functools
-import itertools
-import re
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+import abc
+import functools
+import itertools
+import re
import warnings
from typing import (
Callable,
@@ -20,235 +20,235 @@ from typing import (
TypeVar,
Union,
)
-
+
from .utils import canonicalize_version
from .version import LegacyVersion, Version, parse
-
+
ParsedVersion = Union[Version, LegacyVersion]
UnparsedVersion = Union[Version, LegacyVersion, str]
VersionTypeVar = TypeVar("VersionTypeVar", bound=UnparsedVersion)
CallableOperator = Callable[[ParsedVersion, str], bool]
-
-
-class InvalidSpecifier(ValueError):
- """
- An invalid specifier was found, users should refer to PEP 440.
- """
-
-
+
+
+class InvalidSpecifier(ValueError):
+ """
+ An invalid specifier was found, users should refer to PEP 440.
+ """
+
+
class BaseSpecifier(metaclass=abc.ABCMeta):
- @abc.abstractmethod
+ @abc.abstractmethod
def __str__(self) -> str:
- """
- Returns the str representation of this Specifier like object. This
- should be representative of the Specifier itself.
- """
-
- @abc.abstractmethod
+ """
+ Returns the str representation of this Specifier like object. This
+ should be representative of the Specifier itself.
+ """
+
+ @abc.abstractmethod
def __hash__(self) -> int:
- """
- Returns a hash value for this Specifier like object.
- """
-
- @abc.abstractmethod
+ """
+ Returns a hash value for this Specifier like object.
+ """
+
+ @abc.abstractmethod
def __eq__(self, other: object) -> bool:
- """
- Returns a boolean representing whether or not the two Specifier like
- objects are equal.
- """
-
- @abc.abstractproperty
+ """
+ Returns a boolean representing whether or not the two Specifier like
+ objects are equal.
+ """
+
+ @abc.abstractproperty
def prereleases(self) -> Optional[bool]:
- """
- Returns whether or not pre-releases as a whole are allowed by this
- specifier.
- """
-
- @prereleases.setter
+ """
+ Returns whether or not pre-releases as a whole are allowed by this
+ specifier.
+ """
+
+ @prereleases.setter
def prereleases(self, value: bool) -> None:
- """
- Sets whether or not pre-releases as a whole are allowed by this
- specifier.
- """
-
- @abc.abstractmethod
+ """
+ Sets whether or not pre-releases as a whole are allowed by this
+ specifier.
+ """
+
+ @abc.abstractmethod
def contains(self, item: str, prereleases: Optional[bool] = None) -> bool:
- """
- Determines if the given item is contained within this specifier.
- """
-
- @abc.abstractmethod
+ """
+ Determines if the given item is contained within this specifier.
+ """
+
+ @abc.abstractmethod
def filter(
self, iterable: Iterable[VersionTypeVar], prereleases: Optional[bool] = None
) -> Iterable[VersionTypeVar]:
- """
- Takes an iterable of items and filters them so that only items which
- are contained within this specifier are allowed in it.
- """
-
-
-class _IndividualSpecifier(BaseSpecifier):
-
+ """
+ Takes an iterable of items and filters them so that only items which
+ are contained within this specifier are allowed in it.
+ """
+
+
+class _IndividualSpecifier(BaseSpecifier):
+
_operators: Dict[str, str] = {}
_regex: Pattern[str]
-
+
def __init__(self, spec: str = "", prereleases: Optional[bool] = None) -> None:
- match = self._regex.search(spec)
- if not match:
+ match = self._regex.search(spec)
+ if not match:
raise InvalidSpecifier(f"Invalid specifier: '{spec}'")
-
+
self._spec: Tuple[str, str] = (
- match.group("operator").strip(),
- match.group("version").strip(),
+ match.group("operator").strip(),
+ match.group("version").strip(),
)
-
- # Store whether or not this Specifier should accept prereleases
- self._prereleases = prereleases
-
+
+ # Store whether or not this Specifier should accept prereleases
+ self._prereleases = prereleases
+
def __repr__(self) -> str:
- pre = (
+ pre = (
f", prereleases={self.prereleases!r}"
- if self._prereleases is not None
- else ""
- )
-
+ if self._prereleases is not None
+ else ""
+ )
+
return f"<{self.__class__.__name__}({str(self)!r}{pre})>"
-
+
def __str__(self) -> str:
return "{}{}".format(*self._spec)
-
+
@property
def _canonical_spec(self) -> Tuple[str, str]:
return self._spec[0], canonicalize_version(self._spec[1])
def __hash__(self) -> int:
return hash(self._canonical_spec)
-
+
def __eq__(self, other: object) -> bool:
if isinstance(other, str):
- try:
+ try:
other = self.__class__(str(other))
- except InvalidSpecifier:
- return NotImplemented
- elif not isinstance(other, self.__class__):
- return NotImplemented
-
+ except InvalidSpecifier:
+ return NotImplemented
+ elif not isinstance(other, self.__class__):
+ return NotImplemented
+
return self._canonical_spec == other._canonical_spec
-
+
def _get_operator(self, op: str) -> CallableOperator:
operator_callable: CallableOperator = getattr(
self, f"_compare_{self._operators[op]}"
)
return operator_callable
-
+
def _coerce_version(self, version: UnparsedVersion) -> ParsedVersion:
- if not isinstance(version, (LegacyVersion, Version)):
- version = parse(version)
- return version
-
- @property
+ if not isinstance(version, (LegacyVersion, Version)):
+ version = parse(version)
+ return version
+
+ @property
def operator(self) -> str:
- return self._spec[0]
-
- @property
+ return self._spec[0]
+
+ @property
def version(self) -> str:
- return self._spec[1]
-
- @property
+ return self._spec[1]
+
+ @property
def prereleases(self) -> Optional[bool]:
- return self._prereleases
-
- @prereleases.setter
+ return self._prereleases
+
+ @prereleases.setter
def prereleases(self, value: bool) -> None:
- self._prereleases = value
-
+ self._prereleases = value
+
def __contains__(self, item: str) -> bool:
- return self.contains(item)
-
+ return self.contains(item)
+
def contains(
self, item: UnparsedVersion, prereleases: Optional[bool] = None
) -> bool:
- # Determine if prereleases are to be allowed or not.
- if prereleases is None:
- prereleases = self.prereleases
-
- # Normalize item to a Version or LegacyVersion, this allows us to have
- # a shortcut for ``"2.0" in Specifier(">=2")
+ # Determine if prereleases are to be allowed or not.
+ if prereleases is None:
+ prereleases = self.prereleases
+
+ # Normalize item to a Version or LegacyVersion, this allows us to have
+ # a shortcut for ``"2.0" in Specifier(">=2")
normalized_item = self._coerce_version(item)
-
- # Determine if we should be supporting prereleases in this specifier
- # or not, if we do not support prereleases than we can short circuit
- # logic if this version is a prereleases.
+
+ # Determine if we should be supporting prereleases in this specifier
+ # or not, if we do not support prereleases than we can short circuit
+ # logic if this version is a prereleases.
if normalized_item.is_prerelease and not prereleases:
- return False
-
- # Actually do the comparison to determine if this item is contained
- # within this Specifier or not.
+ return False
+
+ # Actually do the comparison to determine if this item is contained
+ # within this Specifier or not.
operator_callable: CallableOperator = self._get_operator(self.operator)
return operator_callable(normalized_item, self.version)
-
+
def filter(
self, iterable: Iterable[VersionTypeVar], prereleases: Optional[bool] = None
) -> Iterable[VersionTypeVar]:
- yielded = False
- found_prereleases = []
-
- kw = {"prereleases": prereleases if prereleases is not None else True}
-
- # Attempt to iterate over all the values in the iterable and if any of
- # them match, yield them.
- for version in iterable:
- parsed_version = self._coerce_version(version)
-
- if self.contains(parsed_version, **kw):
- # If our version is a prerelease, and we were not set to allow
+ yielded = False
+ found_prereleases = []
+
+ kw = {"prereleases": prereleases if prereleases is not None else True}
+
+ # Attempt to iterate over all the values in the iterable and if any of
+ # them match, yield them.
+ for version in iterable:
+ parsed_version = self._coerce_version(version)
+
+ if self.contains(parsed_version, **kw):
+ # If our version is a prerelease, and we were not set to allow
# prereleases, then we'll store it for later in case nothing
- # else matches this specifier.
+ # else matches this specifier.
if parsed_version.is_prerelease and not (
prereleases or self.prereleases
):
- found_prereleases.append(version)
- # Either this is not a prerelease, or we should have been
+ found_prereleases.append(version)
+ # Either this is not a prerelease, or we should have been
# accepting prereleases from the beginning.
- else:
- yielded = True
- yield version
-
- # Now that we've iterated over everything, determine if we've yielded
- # any values, and if we have not and we have any prereleases stored up
- # then we will go ahead and yield the prereleases.
- if not yielded and found_prereleases:
- for version in found_prereleases:
- yield version
-
-
-class LegacySpecifier(_IndividualSpecifier):
-
+ else:
+ yielded = True
+ yield version
+
+ # Now that we've iterated over everything, determine if we've yielded
+ # any values, and if we have not and we have any prereleases stored up
+ # then we will go ahead and yield the prereleases.
+ if not yielded and found_prereleases:
+ for version in found_prereleases:
+ yield version
+
+
+class LegacySpecifier(_IndividualSpecifier):
+
_regex_str = r"""
- (?P<operator>(==|!=|<=|>=|<|>))
- \s*
- (?P<version>
- [^,;\s)]* # Since this is a "legacy" specifier, and the version
- # string can be just about anything, we match everything
- # except for whitespace, a semi-colon for marker support,
- # a closing paren since versions can be enclosed in
- # them, and a comma since it's a version separator.
- )
- """
-
+ (?P<operator>(==|!=|<=|>=|<|>))
+ \s*
+ (?P<version>
+ [^,;\s)]* # Since this is a "legacy" specifier, and the version
+ # string can be just about anything, we match everything
+ # except for whitespace, a semi-colon for marker support,
+ # a closing paren since versions can be enclosed in
+ # them, and a comma since it's a version separator.
+ )
+ """
+
_regex = re.compile(r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE)
-
- _operators = {
- "==": "equal",
- "!=": "not_equal",
- "<=": "less_than_equal",
- ">=": "greater_than_equal",
- "<": "less_than",
- ">": "greater_than",
- }
-
+
+ _operators = {
+ "==": "equal",
+ "!=": "not_equal",
+ "<=": "less_than_equal",
+ ">=": "greater_than_equal",
+ "<": "less_than",
+ ">": "greater_than",
+ }
+
def __init__(self, spec: str = "", prereleases: Optional[bool] = None) -> None:
super().__init__(spec, prereleases)
@@ -259,340 +259,340 @@ class LegacySpecifier(_IndividualSpecifier):
)
def _coerce_version(self, version: UnparsedVersion) -> LegacyVersion:
- if not isinstance(version, LegacyVersion):
- version = LegacyVersion(str(version))
- return version
-
+ if not isinstance(version, LegacyVersion):
+ version = LegacyVersion(str(version))
+ return version
+
def _compare_equal(self, prospective: LegacyVersion, spec: str) -> bool:
- return prospective == self._coerce_version(spec)
-
+ return prospective == self._coerce_version(spec)
+
def _compare_not_equal(self, prospective: LegacyVersion, spec: str) -> bool:
- return prospective != self._coerce_version(spec)
-
+ return prospective != self._coerce_version(spec)
+
def _compare_less_than_equal(self, prospective: LegacyVersion, spec: str) -> bool:
- return prospective <= self._coerce_version(spec)
-
+ return prospective <= self._coerce_version(spec)
+
def _compare_greater_than_equal(
self, prospective: LegacyVersion, spec: str
) -> bool:
- return prospective >= self._coerce_version(spec)
-
+ return prospective >= self._coerce_version(spec)
+
def _compare_less_than(self, prospective: LegacyVersion, spec: str) -> bool:
- return prospective < self._coerce_version(spec)
-
+ return prospective < self._coerce_version(spec)
+
def _compare_greater_than(self, prospective: LegacyVersion, spec: str) -> bool:
- return prospective > self._coerce_version(spec)
-
-
+ return prospective > self._coerce_version(spec)
+
+
def _require_version_compare(
fn: Callable[["Specifier", ParsedVersion, str], bool]
) -> Callable[["Specifier", ParsedVersion, str], bool]:
- @functools.wraps(fn)
+ @functools.wraps(fn)
def wrapped(self: "Specifier", prospective: ParsedVersion, spec: str) -> bool:
- if not isinstance(prospective, Version):
- return False
- return fn(self, prospective, spec)
-
- return wrapped
-
-
-class Specifier(_IndividualSpecifier):
-
+ if not isinstance(prospective, Version):
+ return False
+ return fn(self, prospective, spec)
+
+ return wrapped
+
+
+class Specifier(_IndividualSpecifier):
+
_regex_str = r"""
- (?P<operator>(~=|==|!=|<=|>=|<|>|===))
- (?P<version>
- (?:
- # The identity operators allow for an escape hatch that will
- # do an exact string match of the version you wish to install.
- # This will not be parsed by PEP 440 and we cannot determine
- # any semantic meaning from it. This operator is discouraged
- # but included entirely as an escape hatch.
- (?<====) # Only match for the identity operator
- \s*
- [^\s]* # We just match everything, except for whitespace
- # since we are only testing for strict identity.
- )
- |
- (?:
- # The (non)equality operators allow for wild card and local
- # versions to be specified so we have to define these two
- # operators separately to enable that.
- (?<===|!=) # Only match for equals and not equals
-
- \s*
- v?
- (?:[0-9]+!)? # epoch
- [0-9]+(?:\.[0-9]+)* # release
- (?: # pre release
- [-_\.]?
- (a|b|c|rc|alpha|beta|pre|preview)
- [-_\.]?
- [0-9]*
- )?
- (?: # post release
- (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
- )?
-
- # You cannot use a wild card and a dev or local version
- # together so group them with a | and make them optional.
- (?:
- (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
- (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local
- |
- \.\* # Wild card syntax of .*
- )?
- )
- |
- (?:
- # The compatible operator requires at least two digits in the
- # release segment.
- (?<=~=) # Only match for the compatible operator
-
- \s*
- v?
- (?:[0-9]+!)? # epoch
- [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *)
- (?: # pre release
- [-_\.]?
- (a|b|c|rc|alpha|beta|pre|preview)
- [-_\.]?
- [0-9]*
- )?
- (?: # post release
- (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
- )?
- (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
- )
- |
- (?:
- # All other operators only allow a sub set of what the
- # (non)equality operators do. Specifically they do not allow
- # local versions to be specified nor do they allow the prefix
- # matching wild cards.
- (?<!==|!=|~=) # We have special cases for these
- # operators so we want to make sure they
- # don't match here.
-
- \s*
- v?
- (?:[0-9]+!)? # epoch
- [0-9]+(?:\.[0-9]+)* # release
- (?: # pre release
- [-_\.]?
- (a|b|c|rc|alpha|beta|pre|preview)
- [-_\.]?
- [0-9]*
- )?
- (?: # post release
- (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
- )?
- (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
- )
- )
- """
-
+ (?P<operator>(~=|==|!=|<=|>=|<|>|===))
+ (?P<version>
+ (?:
+ # The identity operators allow for an escape hatch that will
+ # do an exact string match of the version you wish to install.
+ # This will not be parsed by PEP 440 and we cannot determine
+ # any semantic meaning from it. This operator is discouraged
+ # but included entirely as an escape hatch.
+ (?<====) # Only match for the identity operator
+ \s*
+ [^\s]* # We just match everything, except for whitespace
+ # since we are only testing for strict identity.
+ )
+ |
+ (?:
+ # The (non)equality operators allow for wild card and local
+ # versions to be specified so we have to define these two
+ # operators separately to enable that.
+ (?<===|!=) # Only match for equals and not equals
+
+ \s*
+ v?
+ (?:[0-9]+!)? # epoch
+ [0-9]+(?:\.[0-9]+)* # release
+ (?: # pre release
+ [-_\.]?
+ (a|b|c|rc|alpha|beta|pre|preview)
+ [-_\.]?
+ [0-9]*
+ )?
+ (?: # post release
+ (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
+ )?
+
+ # You cannot use a wild card and a dev or local version
+ # together so group them with a | and make them optional.
+ (?:
+ (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
+ (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local
+ |
+ \.\* # Wild card syntax of .*
+ )?
+ )
+ |
+ (?:
+ # The compatible operator requires at least two digits in the
+ # release segment.
+ (?<=~=) # Only match for the compatible operator
+
+ \s*
+ v?
+ (?:[0-9]+!)? # epoch
+ [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *)
+ (?: # pre release
+ [-_\.]?
+ (a|b|c|rc|alpha|beta|pre|preview)
+ [-_\.]?
+ [0-9]*
+ )?
+ (?: # post release
+ (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
+ )?
+ (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
+ )
+ |
+ (?:
+ # All other operators only allow a sub set of what the
+ # (non)equality operators do. Specifically they do not allow
+ # local versions to be specified nor do they allow the prefix
+ # matching wild cards.
+ (?<!==|!=|~=) # We have special cases for these
+ # operators so we want to make sure they
+ # don't match here.
+
+ \s*
+ v?
+ (?:[0-9]+!)? # epoch
+ [0-9]+(?:\.[0-9]+)* # release
+ (?: # pre release
+ [-_\.]?
+ (a|b|c|rc|alpha|beta|pre|preview)
+ [-_\.]?
+ [0-9]*
+ )?
+ (?: # post release
+ (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
+ )?
+ (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
+ )
+ )
+ """
+
_regex = re.compile(r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE)
-
- _operators = {
- "~=": "compatible",
- "==": "equal",
- "!=": "not_equal",
- "<=": "less_than_equal",
- ">=": "greater_than_equal",
- "<": "less_than",
- ">": "greater_than",
- "===": "arbitrary",
- }
-
- @_require_version_compare
+
+ _operators = {
+ "~=": "compatible",
+ "==": "equal",
+ "!=": "not_equal",
+ "<=": "less_than_equal",
+ ">=": "greater_than_equal",
+ "<": "less_than",
+ ">": "greater_than",
+ "===": "arbitrary",
+ }
+
+ @_require_version_compare
def _compare_compatible(self, prospective: ParsedVersion, spec: str) -> bool:
- # Compatible releases have an equivalent combination of >= and ==. That
- # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to
- # implement this in terms of the other specifiers instead of
- # implementing it ourselves. The only thing we need to do is construct
- # the other specifiers.
-
- # We want everything but the last item in the version, but we want to
+ # Compatible releases have an equivalent combination of >= and ==. That
+ # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to
+ # implement this in terms of the other specifiers instead of
+ # implementing it ourselves. The only thing we need to do is construct
+ # the other specifiers.
+
+ # We want everything but the last item in the version, but we want to
# ignore suffix segments.
- prefix = ".".join(
+ prefix = ".".join(
list(itertools.takewhile(_is_not_suffix, _version_split(spec)))[:-1]
- )
-
- # Add the prefix notation to the end of our string
- prefix += ".*"
-
+ )
+
+ # Add the prefix notation to the end of our string
+ prefix += ".*"
+
return self._get_operator(">=")(prospective, spec) and self._get_operator("==")(
prospective, prefix
)
-
- @_require_version_compare
+
+ @_require_version_compare
def _compare_equal(self, prospective: ParsedVersion, spec: str) -> bool:
- # We need special logic to handle prefix matching
- if spec.endswith(".*"):
- # In the case of prefix matching we want to ignore local segment.
- prospective = Version(prospective.public)
- # Split the spec out by dots, and pretend that there is an implicit
- # dot in between a release segment and a pre-release segment.
+ # We need special logic to handle prefix matching
+ if spec.endswith(".*"):
+ # In the case of prefix matching we want to ignore local segment.
+ prospective = Version(prospective.public)
+ # Split the spec out by dots, and pretend that there is an implicit
+ # dot in between a release segment and a pre-release segment.
split_spec = _version_split(spec[:-2]) # Remove the trailing .*
-
- # Split the prospective version out by dots, and pretend that there
- # is an implicit dot in between a release segment and a pre-release
- # segment.
+
+ # Split the prospective version out by dots, and pretend that there
+ # is an implicit dot in between a release segment and a pre-release
+ # segment.
split_prospective = _version_split(str(prospective))
-
- # Shorten the prospective version to be the same length as the spec
- # so that we can determine if the specifier is a prefix of the
- # prospective version or not.
+
+ # Shorten the prospective version to be the same length as the spec
+ # so that we can determine if the specifier is a prefix of the
+ # prospective version or not.
shortened_prospective = split_prospective[: len(split_spec)]
-
- # Pad out our two sides with zeros so that they both equal the same
- # length.
+
+ # Pad out our two sides with zeros so that they both equal the same
+ # length.
padded_spec, padded_prospective = _pad_version(
split_spec, shortened_prospective
)
return padded_prospective == padded_spec
- else:
- # Convert our spec string into a Version
+ else:
+ # Convert our spec string into a Version
spec_version = Version(spec)
-
- # If the specifier does not have a local segment, then we want to
- # act as if the prospective version also does not have a local
- # segment.
+
+ # If the specifier does not have a local segment, then we want to
+ # act as if the prospective version also does not have a local
+ # segment.
if not spec_version.local:
- prospective = Version(prospective.public)
-
+ prospective = Version(prospective.public)
+
return prospective == spec_version
-
- @_require_version_compare
+
+ @_require_version_compare
def _compare_not_equal(self, prospective: ParsedVersion, spec: str) -> bool:
- return not self._compare_equal(prospective, spec)
-
- @_require_version_compare
+ return not self._compare_equal(prospective, spec)
+
+ @_require_version_compare
def _compare_less_than_equal(self, prospective: ParsedVersion, spec: str) -> bool:
-
+
# NB: Local version identifiers are NOT permitted in the version
# specifier, so local version labels can be universally removed from
# the prospective version.
return Version(prospective.public) <= Version(spec)
- @_require_version_compare
+ @_require_version_compare
def _compare_greater_than_equal(
self, prospective: ParsedVersion, spec: str
) -> bool:
-
+
# NB: Local version identifiers are NOT permitted in the version
# specifier, so local version labels can be universally removed from
# the prospective version.
return Version(prospective.public) >= Version(spec)
- @_require_version_compare
+ @_require_version_compare
def _compare_less_than(self, prospective: ParsedVersion, spec_str: str) -> bool:
- # Convert our spec to a Version instance, since we'll want to work with
- # it as a version.
+ # Convert our spec to a Version instance, since we'll want to work with
+ # it as a version.
spec = Version(spec_str)
-
- # Check to see if the prospective version is less than the spec
- # version. If it's not we can short circuit and just return False now
- # instead of doing extra unneeded work.
- if not prospective < spec:
- return False
-
- # This special case is here so that, unless the specifier itself
- # includes is a pre-release version, that we do not accept pre-release
- # versions for the version mentioned in the specifier (e.g. <3.1 should
- # not match 3.1.dev0, but should match 3.0.dev0).
- if not spec.is_prerelease and prospective.is_prerelease:
- if Version(prospective.base_version) == Version(spec.base_version):
- return False
-
- # If we've gotten to here, it means that prospective version is both
- # less than the spec version *and* it's not a pre-release of the same
- # version in the spec.
- return True
-
- @_require_version_compare
+
+ # Check to see if the prospective version is less than the spec
+ # version. If it's not we can short circuit and just return False now
+ # instead of doing extra unneeded work.
+ if not prospective < spec:
+ return False
+
+ # This special case is here so that, unless the specifier itself
+ # includes is a pre-release version, that we do not accept pre-release
+ # versions for the version mentioned in the specifier (e.g. <3.1 should
+ # not match 3.1.dev0, but should match 3.0.dev0).
+ if not spec.is_prerelease and prospective.is_prerelease:
+ if Version(prospective.base_version) == Version(spec.base_version):
+ return False
+
+ # If we've gotten to here, it means that prospective version is both
+ # less than the spec version *and* it's not a pre-release of the same
+ # version in the spec.
+ return True
+
+ @_require_version_compare
def _compare_greater_than(self, prospective: ParsedVersion, spec_str: str) -> bool:
- # Convert our spec to a Version instance, since we'll want to work with
- # it as a version.
+ # Convert our spec to a Version instance, since we'll want to work with
+ # it as a version.
spec = Version(spec_str)
-
- # Check to see if the prospective version is greater than the spec
- # version. If it's not we can short circuit and just return False now
- # instead of doing extra unneeded work.
- if not prospective > spec:
- return False
-
- # This special case is here so that, unless the specifier itself
- # includes is a post-release version, that we do not accept
- # post-release versions for the version mentioned in the specifier
- # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0).
- if not spec.is_postrelease and prospective.is_postrelease:
- if Version(prospective.base_version) == Version(spec.base_version):
- return False
-
- # Ensure that we do not allow a local version of the version mentioned
+
+ # Check to see if the prospective version is greater than the spec
+ # version. If it's not we can short circuit and just return False now
+ # instead of doing extra unneeded work.
+ if not prospective > spec:
+ return False
+
+ # This special case is here so that, unless the specifier itself
+ # includes is a post-release version, that we do not accept
+ # post-release versions for the version mentioned in the specifier
+ # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0).
+ if not spec.is_postrelease and prospective.is_postrelease:
+ if Version(prospective.base_version) == Version(spec.base_version):
+ return False
+
+ # Ensure that we do not allow a local version of the version mentioned
# in the specifier, which is technically greater than, to match.
- if prospective.local is not None:
- if Version(prospective.base_version) == Version(spec.base_version):
- return False
-
- # If we've gotten to here, it means that prospective version is both
- # greater than the spec version *and* it's not a pre-release of the
- # same version in the spec.
- return True
-
+ if prospective.local is not None:
+ if Version(prospective.base_version) == Version(spec.base_version):
+ return False
+
+ # If we've gotten to here, it means that prospective version is both
+ # greater than the spec version *and* it's not a pre-release of the
+ # same version in the spec.
+ return True
+
def _compare_arbitrary(self, prospective: Version, spec: str) -> bool:
- return str(prospective).lower() == str(spec).lower()
-
- @property
+ return str(prospective).lower() == str(spec).lower()
+
+ @property
def prereleases(self) -> bool:
- # If there is an explicit prereleases set for this, then we'll just
- # blindly use that.
- if self._prereleases is not None:
- return self._prereleases
-
- # Look at all of our specifiers and determine if they are inclusive
- # operators, and if they are if they are including an explicit
- # prerelease.
- operator, version = self._spec
- if operator in ["==", ">=", "<=", "~=", "==="]:
- # The == specifier can include a trailing .*, if it does we
- # want to remove before parsing.
- if operator == "==" and version.endswith(".*"):
- version = version[:-2]
-
- # Parse the version, and if it is a pre-release than this
- # specifier allows pre-releases.
- if parse(version).is_prerelease:
- return True
-
- return False
-
- @prereleases.setter
+ # If there is an explicit prereleases set for this, then we'll just
+ # blindly use that.
+ if self._prereleases is not None:
+ return self._prereleases
+
+ # Look at all of our specifiers and determine if they are inclusive
+ # operators, and if they are if they are including an explicit
+ # prerelease.
+ operator, version = self._spec
+ if operator in ["==", ">=", "<=", "~=", "==="]:
+ # The == specifier can include a trailing .*, if it does we
+ # want to remove before parsing.
+ if operator == "==" and version.endswith(".*"):
+ version = version[:-2]
+
+ # Parse the version, and if it is a pre-release than this
+ # specifier allows pre-releases.
+ if parse(version).is_prerelease:
+ return True
+
+ return False
+
+ @prereleases.setter
def prereleases(self, value: bool) -> None:
- self._prereleases = value
-
-
-_prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$")
-
-
+ self._prereleases = value
+
+
+_prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$")
+
+
def _version_split(version: str) -> List[str]:
result: List[str] = []
- for item in version.split("."):
- match = _prefix_regex.search(item)
- if match:
- result.extend(match.groups())
- else:
- result.append(item)
- return result
-
-
+ for item in version.split("."):
+ match = _prefix_regex.search(item)
+ if match:
+ result.extend(match.groups())
+ else:
+ result.append(item)
+ return result
+
+
def _is_not_suffix(segment: str) -> bool:
return not any(
segment.startswith(prefix) for prefix in ("dev", "a", "b", "rc", "post")
@@ -600,203 +600,203 @@ def _is_not_suffix(segment: str) -> bool:
def _pad_version(left: List[str], right: List[str]) -> Tuple[List[str], List[str]]:
- left_split, right_split = [], []
-
- # Get the release segment of our versions
- left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left)))
- right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right)))
-
- # Get the rest of our versions
+ left_split, right_split = [], []
+
+ # Get the release segment of our versions
+ left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left)))
+ right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right)))
+
+ # Get the rest of our versions
left_split.append(left[len(left_split[0]) :])
right_split.append(right[len(right_split[0]) :])
-
- # Insert our padding
+
+ # Insert our padding
left_split.insert(1, ["0"] * max(0, len(right_split[0]) - len(left_split[0])))
right_split.insert(1, ["0"] * max(0, len(left_split[0]) - len(right_split[0])))
-
+
return (list(itertools.chain(*left_split)), list(itertools.chain(*right_split)))
-
-
-class SpecifierSet(BaseSpecifier):
+
+
+class SpecifierSet(BaseSpecifier):
def __init__(
self, specifiers: str = "", prereleases: Optional[bool] = None
) -> None:
-
+
# Split on , to break each individual specifier into it's own item, and
- # strip each item to remove leading/trailing whitespace.
+ # strip each item to remove leading/trailing whitespace.
split_specifiers = [s.strip() for s in specifiers.split(",") if s.strip()]
-
- # Parsed each individual specifier, attempting first to make it a
- # Specifier and falling back to a LegacySpecifier.
+
+ # Parsed each individual specifier, attempting first to make it a
+ # Specifier and falling back to a LegacySpecifier.
parsed: Set[_IndividualSpecifier] = set()
for specifier in split_specifiers:
- try:
- parsed.add(Specifier(specifier))
- except InvalidSpecifier:
- parsed.add(LegacySpecifier(specifier))
-
- # Turn our parsed specifiers into a frozen set and save them for later.
- self._specs = frozenset(parsed)
-
- # Store our prereleases value so we can use it later to determine if
- # we accept prereleases or not.
- self._prereleases = prereleases
-
+ try:
+ parsed.add(Specifier(specifier))
+ except InvalidSpecifier:
+ parsed.add(LegacySpecifier(specifier))
+
+ # Turn our parsed specifiers into a frozen set and save them for later.
+ self._specs = frozenset(parsed)
+
+ # Store our prereleases value so we can use it later to determine if
+ # we accept prereleases or not.
+ self._prereleases = prereleases
+
def __repr__(self) -> str:
- pre = (
+ pre = (
f", prereleases={self.prereleases!r}"
- if self._prereleases is not None
- else ""
- )
-
+ if self._prereleases is not None
+ else ""
+ )
+
return f"<SpecifierSet({str(self)!r}{pre})>"
-
+
def __str__(self) -> str:
- return ",".join(sorted(str(s) for s in self._specs))
-
+ return ",".join(sorted(str(s) for s in self._specs))
+
def __hash__(self) -> int:
- return hash(self._specs)
-
+ return hash(self._specs)
+
def __and__(self, other: Union["SpecifierSet", str]) -> "SpecifierSet":
if isinstance(other, str):
- other = SpecifierSet(other)
- elif not isinstance(other, SpecifierSet):
- return NotImplemented
-
- specifier = SpecifierSet()
- specifier._specs = frozenset(self._specs | other._specs)
-
- if self._prereleases is None and other._prereleases is not None:
- specifier._prereleases = other._prereleases
- elif self._prereleases is not None and other._prereleases is None:
- specifier._prereleases = self._prereleases
- elif self._prereleases == other._prereleases:
- specifier._prereleases = self._prereleases
- else:
- raise ValueError(
- "Cannot combine SpecifierSets with True and False prerelease "
- "overrides."
- )
-
- return specifier
-
+ other = SpecifierSet(other)
+ elif not isinstance(other, SpecifierSet):
+ return NotImplemented
+
+ specifier = SpecifierSet()
+ specifier._specs = frozenset(self._specs | other._specs)
+
+ if self._prereleases is None and other._prereleases is not None:
+ specifier._prereleases = other._prereleases
+ elif self._prereleases is not None and other._prereleases is None:
+ specifier._prereleases = self._prereleases
+ elif self._prereleases == other._prereleases:
+ specifier._prereleases = self._prereleases
+ else:
+ raise ValueError(
+ "Cannot combine SpecifierSets with True and False prerelease "
+ "overrides."
+ )
+
+ return specifier
+
def __eq__(self, other: object) -> bool:
if isinstance(other, (str, _IndividualSpecifier)):
- other = SpecifierSet(str(other))
- elif not isinstance(other, SpecifierSet):
- return NotImplemented
-
- return self._specs == other._specs
-
+ other = SpecifierSet(str(other))
+ elif not isinstance(other, SpecifierSet):
+ return NotImplemented
+
+ return self._specs == other._specs
+
def __len__(self) -> int:
- return len(self._specs)
-
+ return len(self._specs)
+
def __iter__(self) -> Iterator[_IndividualSpecifier]:
- return iter(self._specs)
-
- @property
+ return iter(self._specs)
+
+ @property
def prereleases(self) -> Optional[bool]:
- # If we have been given an explicit prerelease modifier, then we'll
- # pass that through here.
- if self._prereleases is not None:
- return self._prereleases
-
- # If we don't have any specifiers, and we don't have a forced value,
- # then we'll just return None since we don't know if this should have
- # pre-releases or not.
- if not self._specs:
- return None
-
- # Otherwise we'll see if any of the given specifiers accept
- # prereleases, if any of them do we'll return True, otherwise False.
- return any(s.prereleases for s in self._specs)
-
- @prereleases.setter
+ # If we have been given an explicit prerelease modifier, then we'll
+ # pass that through here.
+ if self._prereleases is not None:
+ return self._prereleases
+
+ # If we don't have any specifiers, and we don't have a forced value,
+ # then we'll just return None since we don't know if this should have
+ # pre-releases or not.
+ if not self._specs:
+ return None
+
+ # Otherwise we'll see if any of the given specifiers accept
+ # prereleases, if any of them do we'll return True, otherwise False.
+ return any(s.prereleases for s in self._specs)
+
+ @prereleases.setter
def prereleases(self, value: bool) -> None:
- self._prereleases = value
-
+ self._prereleases = value
+
def __contains__(self, item: UnparsedVersion) -> bool:
- return self.contains(item)
-
+ return self.contains(item)
+
def contains(
self, item: UnparsedVersion, prereleases: Optional[bool] = None
) -> bool:
- # Ensure that our item is a Version or LegacyVersion instance.
- if not isinstance(item, (LegacyVersion, Version)):
- item = parse(item)
-
- # Determine if we're forcing a prerelease or not, if we're not forcing
- # one for this particular filter call, then we'll use whatever the
- # SpecifierSet thinks for whether or not we should support prereleases.
- if prereleases is None:
- prereleases = self.prereleases
-
- # We can determine if we're going to allow pre-releases by looking to
- # see if any of the underlying items supports them. If none of them do
- # and this item is a pre-release then we do not allow it and we can
- # short circuit that here.
- # Note: This means that 1.0.dev1 would not be contained in something
- # like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0
- if not prereleases and item.is_prerelease:
- return False
-
- # We simply dispatch to the underlying specs here to make sure that the
- # given version is contained within all of them.
- # Note: This use of all() here means that an empty set of specifiers
- # will always return True, this is an explicit design decision.
+ # Ensure that our item is a Version or LegacyVersion instance.
+ if not isinstance(item, (LegacyVersion, Version)):
+ item = parse(item)
+
+ # Determine if we're forcing a prerelease or not, if we're not forcing
+ # one for this particular filter call, then we'll use whatever the
+ # SpecifierSet thinks for whether or not we should support prereleases.
+ if prereleases is None:
+ prereleases = self.prereleases
+
+ # We can determine if we're going to allow pre-releases by looking to
+ # see if any of the underlying items supports them. If none of them do
+ # and this item is a pre-release then we do not allow it and we can
+ # short circuit that here.
+ # Note: This means that 1.0.dev1 would not be contained in something
+ # like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0
+ if not prereleases and item.is_prerelease:
+ return False
+
+ # We simply dispatch to the underlying specs here to make sure that the
+ # given version is contained within all of them.
+ # Note: This use of all() here means that an empty set of specifiers
+ # will always return True, this is an explicit design decision.
return all(s.contains(item, prereleases=prereleases) for s in self._specs)
-
+
def filter(
self, iterable: Iterable[VersionTypeVar], prereleases: Optional[bool] = None
) -> Iterable[VersionTypeVar]:
- # Determine if we're forcing a prerelease or not, if we're not forcing
- # one for this particular filter call, then we'll use whatever the
- # SpecifierSet thinks for whether or not we should support prereleases.
- if prereleases is None:
- prereleases = self.prereleases
-
- # If we have any specifiers, then we want to wrap our iterable in the
- # filter method for each one, this will act as a logical AND amongst
- # each specifier.
- if self._specs:
- for spec in self._specs:
- iterable = spec.filter(iterable, prereleases=bool(prereleases))
- return iterable
- # If we do not have any specifiers, then we need to have a rough filter
- # which will filter out any pre-releases, unless there are no final
- # releases, and which will filter out LegacyVersion in general.
- else:
+ # Determine if we're forcing a prerelease or not, if we're not forcing
+ # one for this particular filter call, then we'll use whatever the
+ # SpecifierSet thinks for whether or not we should support prereleases.
+ if prereleases is None:
+ prereleases = self.prereleases
+
+ # If we have any specifiers, then we want to wrap our iterable in the
+ # filter method for each one, this will act as a logical AND amongst
+ # each specifier.
+ if self._specs:
+ for spec in self._specs:
+ iterable = spec.filter(iterable, prereleases=bool(prereleases))
+ return iterable
+ # If we do not have any specifiers, then we need to have a rough filter
+ # which will filter out any pre-releases, unless there are no final
+ # releases, and which will filter out LegacyVersion in general.
+ else:
filtered: List[VersionTypeVar] = []
found_prereleases: List[VersionTypeVar] = []
-
+
item: UnparsedVersion
parsed_version: Union[Version, LegacyVersion]
- for item in iterable:
- # Ensure that we some kind of Version class for this item.
- if not isinstance(item, (LegacyVersion, Version)):
- parsed_version = parse(item)
- else:
- parsed_version = item
-
- # Filter out any item which is parsed as a LegacyVersion
- if isinstance(parsed_version, LegacyVersion):
- continue
-
- # Store any item which is a pre-release for later unless we've
- # already found a final version or we are accepting prereleases
- if parsed_version.is_prerelease and not prereleases:
- if not filtered:
- found_prereleases.append(item)
- else:
- filtered.append(item)
-
- # If we've found no items except for pre-releases, then we'll go
- # ahead and use the pre-releases
- if not filtered and found_prereleases and prereleases is None:
- return found_prereleases
-
- return filtered
+ for item in iterable:
+ # Ensure that we some kind of Version class for this item.
+ if not isinstance(item, (LegacyVersion, Version)):
+ parsed_version = parse(item)
+ else:
+ parsed_version = item
+
+ # Filter out any item which is parsed as a LegacyVersion
+ if isinstance(parsed_version, LegacyVersion):
+ continue
+
+ # Store any item which is a pre-release for later unless we've
+ # already found a final version or we are accepting prereleases
+ if parsed_version.is_prerelease and not prereleases:
+ if not filtered:
+ found_prereleases.append(item)
+ else:
+ filtered.append(item)
+
+ # If we've found no items except for pre-releases, then we'll go
+ # ahead and use the pre-releases
+ if not filtered and found_prereleases and prereleases is None:
+ return found_prereleases
+
+ return filtered
diff --git a/contrib/python/packaging/py3/packaging/utils.py b/contrib/python/packaging/py3/packaging/utils.py
index 902d2ac31b..bab11b80c6 100644
--- a/contrib/python/packaging/py3/packaging/utils.py
+++ b/contrib/python/packaging/py3/packaging/utils.py
@@ -1,13 +1,13 @@
-# This file is dual licensed under the terms of the Apache License, Version
-# 2.0, and the BSD License. See the LICENSE file in the root of this repository
-# for complete details.
-
-import re
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+import re
from typing import FrozenSet, NewType, Tuple, Union, cast
-
+
from .tags import Tag, parse_tag
from .version import InvalidVersion, Version
-
+
BuildTag = Union[Tuple[()], Tuple[int, str]]
NormalizedName = NewType("NormalizedName", str)
@@ -24,13 +24,13 @@ class InvalidSdistFilename(ValueError):
"""
-_canonicalize_regex = re.compile(r"[-_.]+")
+_canonicalize_regex = re.compile(r"[-_.]+")
# PEP 427: The build number must start with a digit.
_build_tag_regex = re.compile(r"(\d+)(.*)")
-
-
+
+
def canonicalize_name(name: str) -> NormalizedName:
- # This is taken from PEP 503.
+ # This is taken from PEP 503.
value = _canonicalize_regex.sub("-", name).lower()
return cast(NormalizedName, value)
diff --git a/contrib/python/packaging/py3/packaging/version.py b/contrib/python/packaging/py3/packaging/version.py
index faeab05164..de9a09a4ed 100644
--- a/contrib/python/packaging/py3/packaging/version.py
+++ b/contrib/python/packaging/py3/packaging/version.py
@@ -1,17 +1,17 @@
-# This file is dual licensed under the terms of the Apache License, Version
-# 2.0, and the BSD License. See the LICENSE file in the root of this repository
-# for complete details.
-
-import collections
-import itertools
-import re
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+import collections
+import itertools
+import re
import warnings
from typing import Callable, Iterator, List, Optional, SupportsInt, Tuple, Union
-
+
from ._structures import Infinity, InfinityType, NegativeInfinity, NegativeInfinityType
-
+
__all__ = ["parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN"]
-
+
InfiniteTypes = Union[InfinityType, NegativeInfinityType]
PrePostDevType = Union[InfiniteTypes, Tuple[str, int]]
SubLocalType = Union[InfiniteTypes, int, str]
@@ -33,81 +33,81 @@ LegacyCmpKey = Tuple[int, Tuple[str, ...]]
VersionComparisonMethod = Callable[
[Union[CmpKey, LegacyCmpKey], Union[CmpKey, LegacyCmpKey]], bool
]
-
-_Version = collections.namedtuple(
+
+_Version = collections.namedtuple(
"_Version", ["epoch", "release", "dev", "pre", "post", "local"]
-)
-
-
+)
+
+
def parse(version: 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
- a valid PEP 440 version or a legacy version.
- """
- try:
- return Version(version)
- except InvalidVersion:
- return LegacyVersion(version)
-
-
-class InvalidVersion(ValueError):
- """
- An invalid version was found, users should refer to PEP 440.
- """
-
-
+ """
+ Parse the given version string and return either a :class:`Version` object
+ or a :class:`LegacyVersion` object depending on if the given version is
+ a valid PEP 440 version or a legacy version.
+ """
+ try:
+ return Version(version)
+ except InvalidVersion:
+ return LegacyVersion(version)
+
+
+class InvalidVersion(ValueError):
+ """
+ An invalid version was found, users should refer to PEP 440.
+ """
+
+
class _BaseVersion:
_key: Union[CmpKey, LegacyCmpKey]
-
+
def __hash__(self) -> int:
- return hash(self._key)
-
+ return hash(self._key)
+
# Please keep the duplicated `isinstance` check
# in the six comparisons hereunder
# unless you find a way to avoid adding overhead function calls.
def __lt__(self, other: "_BaseVersion") -> bool:
if not isinstance(other, _BaseVersion):
return NotImplemented
-
+
return self._key < other._key
def __le__(self, other: "_BaseVersion") -> bool:
if not isinstance(other, _BaseVersion):
return NotImplemented
-
+
return self._key <= other._key
def __eq__(self, other: object) -> bool:
if not isinstance(other, _BaseVersion):
return NotImplemented
-
+
return self._key == other._key
def __ge__(self, other: "_BaseVersion") -> bool:
if not isinstance(other, _BaseVersion):
return NotImplemented
-
+
return self._key >= other._key
def __gt__(self, other: "_BaseVersion") -> bool:
if not isinstance(other, _BaseVersion):
return NotImplemented
-
+
return self._key > other._key
def __ne__(self, other: object) -> bool:
- if not isinstance(other, _BaseVersion):
- return NotImplemented
-
+ if not isinstance(other, _BaseVersion):
+ return NotImplemented
+
return self._key != other._key
-
-
-class LegacyVersion(_BaseVersion):
+
+
+class LegacyVersion(_BaseVersion):
def __init__(self, version: str) -> None:
- self._version = str(version)
- self._key = _legacy_cmpkey(self._version)
-
+ self._version = str(version)
+ self._key = _legacy_cmpkey(self._version)
+
warnings.warn(
"Creating a LegacyVersion has been deprecated and will be "
"removed in the next major release",
@@ -115,20 +115,20 @@ class LegacyVersion(_BaseVersion):
)
def __str__(self) -> str:
- return self._version
-
+ return self._version
+
def __repr__(self) -> str:
return f"<LegacyVersion('{self}')>"
-
- @property
+
+ @property
def public(self) -> str:
- return self._version
-
- @property
+ return self._version
+
+ @property
def base_version(self) -> str:
- return self._version
-
- @property
+ return self._version
+
+ @property
def epoch(self) -> int:
return -1
@@ -150,175 +150,175 @@ class LegacyVersion(_BaseVersion):
@property
def local(self) -> None:
- return None
-
- @property
+ return None
+
+ @property
def is_prerelease(self) -> bool:
- return False
-
- @property
+ return False
+
+ @property
def is_postrelease(self) -> bool:
- return False
-
+ return False
+
@property
def is_devrelease(self) -> bool:
return False
-
+
_legacy_version_component_re = re.compile(r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE)
-
-_legacy_version_replacement_map = {
+
+_legacy_version_replacement_map = {
"pre": "c",
"preview": "c",
"-": "final-",
"rc": "c",
"dev": "@",
-}
-
-
+}
+
+
def _parse_version_parts(s: str) -> Iterator[str]:
- for part in _legacy_version_component_re.split(s):
- part = _legacy_version_replacement_map.get(part, part)
-
- if not part or part == ".":
- continue
-
- if part[:1] in "0123456789":
- # pad for numeric comparison
- yield part.zfill(8)
- else:
- yield "*" + part
-
- # ensure that alpha/beta/candidate are before final
- yield "*final"
-
-
+ for part in _legacy_version_component_re.split(s):
+ part = _legacy_version_replacement_map.get(part, part)
+
+ if not part or part == ".":
+ continue
+
+ if part[:1] in "0123456789":
+ # pad for numeric comparison
+ yield part.zfill(8)
+ else:
+ yield "*" + part
+
+ # ensure that alpha/beta/candidate are before final
+ yield "*final"
+
+
def _legacy_cmpkey(version: 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,
- # as before all PEP 440 versions.
- epoch = -1
-
- # This scheme is taken from pkg_resources.parse_version setuptools prior to
- # it's adoption of the packaging library.
+ # 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,
+ # as before all PEP 440 versions.
+ epoch = -1
+
+ # This scheme is taken from pkg_resources.parse_version setuptools prior to
+ # it's adoption of the packaging library.
parts: List[str] = []
- for part in _parse_version_parts(version.lower()):
- if part.startswith("*"):
- # remove "-" before a prerelease tag
- if part < "*final":
- while parts and parts[-1] == "*final-":
- parts.pop()
-
- # remove trailing zeros from each series of numeric parts
- while parts and parts[-1] == "00000000":
- parts.pop()
-
- parts.append(part)
-
+ for part in _parse_version_parts(version.lower()):
+ if part.startswith("*"):
+ # remove "-" before a prerelease tag
+ if part < "*final":
+ while parts and parts[-1] == "*final-":
+ parts.pop()
+
+ # remove trailing zeros from each series of numeric parts
+ while parts and parts[-1] == "00000000":
+ parts.pop()
+
+ parts.append(part)
+
return epoch, tuple(parts)
-
-
-# Deliberately not anchored to the start and end of the string, to make it
-# easier for 3rd party code to reuse
-VERSION_PATTERN = r"""
- v?
- (?:
- (?:(?P<epoch>[0-9]+)!)? # epoch
- (?P<release>[0-9]+(?:\.[0-9]+)*) # release segment
- (?P<pre> # pre-release
- [-_\.]?
- (?P<pre_l>(a|b|c|rc|alpha|beta|pre|preview))
- [-_\.]?
- (?P<pre_n>[0-9]+)?
- )?
- (?P<post> # post release
- (?:-(?P<post_n1>[0-9]+))
- |
- (?:
- [-_\.]?
- (?P<post_l>post|rev|r)
- [-_\.]?
- (?P<post_n2>[0-9]+)?
- )
- )?
- (?P<dev> # dev release
- [-_\.]?
- (?P<dev_l>dev)
- [-_\.]?
- (?P<dev_n>[0-9]+)?
- )?
- )
- (?:\+(?P<local>[a-z0-9]+(?:[-_\.][a-z0-9]+)*))? # local version
-"""
-
-
-class Version(_BaseVersion):
-
+
+
+# Deliberately not anchored to the start and end of the string, to make it
+# easier for 3rd party code to reuse
+VERSION_PATTERN = r"""
+ v?
+ (?:
+ (?:(?P<epoch>[0-9]+)!)? # epoch
+ (?P<release>[0-9]+(?:\.[0-9]+)*) # release segment
+ (?P<pre> # pre-release
+ [-_\.]?
+ (?P<pre_l>(a|b|c|rc|alpha|beta|pre|preview))
+ [-_\.]?
+ (?P<pre_n>[0-9]+)?
+ )?
+ (?P<post> # post release
+ (?:-(?P<post_n1>[0-9]+))
+ |
+ (?:
+ [-_\.]?
+ (?P<post_l>post|rev|r)
+ [-_\.]?
+ (?P<post_n2>[0-9]+)?
+ )
+ )?
+ (?P<dev> # dev release
+ [-_\.]?
+ (?P<dev_l>dev)
+ [-_\.]?
+ (?P<dev_n>[0-9]+)?
+ )?
+ )
+ (?:\+(?P<local>[a-z0-9]+(?:[-_\.][a-z0-9]+)*))? # local version
+"""
+
+
+class Version(_BaseVersion):
+
_regex = re.compile(r"^\s*" + VERSION_PATTERN + r"\s*$", re.VERBOSE | re.IGNORECASE)
-
+
def __init__(self, version: str) -> None:
- # Validate the version and parse it into pieces
- match = self._regex.search(version)
- if not match:
+ # Validate the version and parse it into pieces
+ match = self._regex.search(version)
+ if not match:
raise InvalidVersion(f"Invalid version: '{version}'")
-
- # Store the parsed out pieces of the version
- self._version = _Version(
- epoch=int(match.group("epoch")) if match.group("epoch") else 0,
- release=tuple(int(i) for i in match.group("release").split(".")),
+
+ # Store the parsed out pieces of the version
+ self._version = _Version(
+ epoch=int(match.group("epoch")) if match.group("epoch") else 0,
+ release=tuple(int(i) for i in match.group("release").split(".")),
pre=_parse_letter_version(match.group("pre_l"), match.group("pre_n")),
- post=_parse_letter_version(
+ post=_parse_letter_version(
match.group("post_l"), match.group("post_n1") or match.group("post_n2")
- ),
+ ),
dev=_parse_letter_version(match.group("dev_l"), match.group("dev_n")),
- local=_parse_local_version(match.group("local")),
- )
-
- # Generate a key which will be used for sorting
- self._key = _cmpkey(
- self._version.epoch,
- self._version.release,
- self._version.pre,
- self._version.post,
- self._version.dev,
- self._version.local,
- )
-
+ local=_parse_local_version(match.group("local")),
+ )
+
+ # Generate a key which will be used for sorting
+ self._key = _cmpkey(
+ self._version.epoch,
+ self._version.release,
+ self._version.pre,
+ self._version.post,
+ self._version.dev,
+ self._version.local,
+ )
+
def __repr__(self) -> str:
return f"<Version('{self}')>"
-
+
def __str__(self) -> str:
- parts = []
-
- # Epoch
+ parts = []
+
+ # Epoch
if self.epoch != 0:
parts.append(f"{self.epoch}!")
-
- # Release segment
+
+ # Release segment
parts.append(".".join(str(x) for x in self.release))
-
- # Pre-release
+
+ # Pre-release
if self.pre is not None:
parts.append("".join(str(x) for x in self.pre))
-
- # Post-release
+
+ # Post-release
if self.post is not None:
parts.append(f".post{self.post}")
-
- # Development release
+
+ # Development release
if self.dev is not None:
parts.append(f".dev{self.dev}")
-
- # Local version segment
+
+ # Local version segment
if self.local is not None:
parts.append(f"+{self.local}")
-
- return "".join(parts)
-
- @property
+
+ return "".join(parts)
+
+ @property
def epoch(self) -> int:
_epoch: int = self._version.epoch
return _epoch
@@ -350,33 +350,33 @@ class Version(_BaseVersion):
@property
def public(self) -> str:
- return str(self).split("+", 1)[0]
-
- @property
+ return str(self).split("+", 1)[0]
+
+ @property
def base_version(self) -> str:
- parts = []
-
- # Epoch
+ parts = []
+
+ # Epoch
if self.epoch != 0:
parts.append(f"{self.epoch}!")
-
- # Release segment
+
+ # Release segment
parts.append(".".join(str(x) for x in self.release))
-
- return "".join(parts)
-
- @property
+
+ return "".join(parts)
+
+ @property
def is_prerelease(self) -> bool:
return self.dev is not None or self.pre is not None
-
- @property
+
+ @property
def is_postrelease(self) -> bool:
return self.post is not None
-
+
@property
def is_devrelease(self) -> bool:
return self.dev is not None
-
+
@property
def major(self) -> int:
return self.release[0] if len(self.release) >= 1 else 0
@@ -394,53 +394,53 @@ def _parse_letter_version(
letter: str, number: Union[str, bytes, SupportsInt]
) -> Optional[Tuple[str, int]]:
- if letter:
- # We consider there to be an implicit 0 in a pre-release if there is
- # not a numeral associated with it.
- if number is None:
- number = 0
-
- # We normalize any letters to their lower case form
- letter = letter.lower()
-
- # We consider some words to be alternate spellings of other words and
- # in those cases we want to normalize the spellings to our preferred
- # spelling.
- if letter == "alpha":
- letter = "a"
- elif letter == "beta":
- letter = "b"
- elif letter in ["c", "pre", "preview"]:
- letter = "rc"
- elif letter in ["rev", "r"]:
- letter = "post"
-
- return letter, int(number)
- if not letter and number:
- # We assume if we are given a number, but we are not given a letter
- # then this is using the implicit post release syntax (e.g. 1.0-1)
- letter = "post"
-
- return letter, int(number)
-
+ if letter:
+ # We consider there to be an implicit 0 in a pre-release if there is
+ # not a numeral associated with it.
+ if number is None:
+ number = 0
+
+ # We normalize any letters to their lower case form
+ letter = letter.lower()
+
+ # We consider some words to be alternate spellings of other words and
+ # in those cases we want to normalize the spellings to our preferred
+ # spelling.
+ if letter == "alpha":
+ letter = "a"
+ elif letter == "beta":
+ letter = "b"
+ elif letter in ["c", "pre", "preview"]:
+ letter = "rc"
+ elif letter in ["rev", "r"]:
+ letter = "post"
+
+ return letter, int(number)
+ if not letter and number:
+ # We assume if we are given a number, but we are not given a letter
+ # then this is using the implicit post release syntax (e.g. 1.0-1)
+ letter = "post"
+
+ return letter, int(number)
+
return None
-
+
_local_version_separators = re.compile(r"[\._-]")
-
-
+
+
def _parse_local_version(local: str) -> Optional[LocalType]:
- """
- Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
- """
- if local is not None:
- return tuple(
- part.lower() if not part.isdigit() else int(part)
+ """
+ Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
+ """
+ if local is not None:
+ return tuple(
+ part.lower() if not part.isdigit() else int(part)
for part in _local_version_separators.split(local)
- )
+ )
return None
-
-
+
+
def _cmpkey(
epoch: int,
release: Tuple[int, ...],
@@ -450,55 +450,55 @@ def _cmpkey(
local: Optional[Tuple[SubLocalType]],
) -> CmpKey:
- # 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.
+ # 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(
reversed(list(itertools.dropwhile(lambda x: x == 0, reversed(release))))
- )
-
- # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
- # We'll do this by abusing the pre segment, but we _only_ want to do this
- # 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:
+ )
+
+ # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
+ # We'll do this by abusing the pre segment, but we _only_ want to do this
+ # 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
- # Versions without a pre-release (except as noted above) should sort after
- # those with one.
- elif pre is None:
+ # Versions without a pre-release (except as noted above) should sort after
+ # those with one.
+ elif pre is None:
_pre = Infinity
else:
_pre = pre
-
- # Versions without a post segment should sort before those with one.
- if post is None:
+
+ # Versions without a post segment should sort before those with one.
+ if post is None:
_post: PrePostDevType = NegativeInfinity
-
+
else:
_post = post
- # Versions without a development segment should sort after those with one.
- if dev is None:
+ # Versions without a development segment should sort after those with one.
+ if dev is None:
_dev: PrePostDevType = Infinity
-
+
else:
_dev = dev
- if local is None:
- # Versions without a local segment should sort before those with one.
+ if local is None:
+ # Versions without a local segment should sort before those with one.
_local: LocalType = NegativeInfinity
- else:
- # Versions with a local segment need that segment parsed to implement
- # the sorting rules in PEP440.
- # - Alpha numeric segments sort before numeric segments
- # - Alpha numeric segments sort lexicographically
- # - Numeric segments sort numerically
- # - Shorter versions sort before longer versions when the prefixes
- # match exactly
+ else:
+ # Versions with a local segment need that segment parsed to implement
+ # the sorting rules in PEP440.
+ # - Alpha numeric segments sort before numeric segments
+ # - Alpha numeric segments sort lexicographically
+ # - Numeric segments sort numerically
+ # - Shorter versions sort before longer versions when the prefixes
+ # match exactly
_local = tuple(
(i, "") if isinstance(i, int) else (NegativeInfinity, i) for i in local
- )
-
+ )
+
return epoch, _release, _pre, _post, _dev, _local
diff --git a/contrib/python/packaging/py3/ya.make b/contrib/python/packaging/py3/ya.make
index 60b96efe69..de7f8cd056 100644
--- a/contrib/python/packaging/py3/ya.make
+++ b/contrib/python/packaging/py3/ya.make
@@ -1,40 +1,40 @@
# Generated by devtools/yamaker (pypi).
PY3_LIBRARY()
-
+
OWNER(
orivej
g:python-contrib
)
VERSION(21.3)
-
+
LICENSE(
BSD-2-Clause OR
Apache-2.0
)
-PEERDIR(
- contrib/python/pyparsing
-)
-
+PEERDIR(
+ contrib/python/pyparsing
+)
+
NO_LINT()
-PY_SRCS(
- TOP_LEVEL
+PY_SRCS(
+ TOP_LEVEL
packaging/__about__.py
- packaging/__init__.py
+ packaging/__init__.py
packaging/_manylinux.py
packaging/_musllinux.py
- packaging/_structures.py
- packaging/markers.py
- packaging/requirements.py
- packaging/specifiers.py
+ packaging/_structures.py
+ packaging/markers.py
+ packaging/requirements.py
+ packaging/specifiers.py
packaging/tags.py
- packaging/utils.py
- packaging/version.py
-)
-
+ packaging/utils.py
+ packaging/version.py
+)
+
RESOURCE_FILES(
PREFIX contrib/python/packaging/py3/
.dist-info/METADATA
@@ -42,4 +42,4 @@ RESOURCE_FILES(
packaging/py.typed
)
-END()
+END()
diff --git a/contrib/python/packaging/ya.make b/contrib/python/packaging/ya.make
index 40d458c3c6..45549cf137 100644
--- a/contrib/python/packaging/ya.make
+++ b/contrib/python/packaging/ya.make
@@ -1,19 +1,19 @@
PY23_LIBRARY()
-
+
LICENSE(Service-Py23-Proxy)
OWNER(g:python-contrib)
-
+
IF (PYTHON2)
PEERDIR(contrib/python/packaging/py2)
ELSE()
PEERDIR(contrib/python/packaging/py3)
ENDIF()
-
+
NO_LINT()
-
+
END()
-
+
RECURSE(
py2
py3