Commit bf069fe9 authored by Benoit Pierre's avatar Benoit Pierre

setuptools: update vendored packaging

parent 734d09c5
...@@ -4,18 +4,24 @@ ...@@ -4,18 +4,24 @@
from __future__ import absolute_import, division, print_function from __future__ import absolute_import, division, print_function
__all__ = [ __all__ = [
"__title__", "__summary__", "__uri__", "__version__", "__author__", "__title__",
"__email__", "__license__", "__copyright__", "__summary__",
"__uri__",
"__version__",
"__author__",
"__email__",
"__license__",
"__copyright__",
] ]
__title__ = "packaging" __title__ = "packaging"
__summary__ = "Core utilities for Python packages" __summary__ = "Core utilities for Python packages"
__uri__ = "https://github.com/pypa/packaging" __uri__ = "https://github.com/pypa/packaging"
__version__ = "16.8" __version__ = "19.2"
__author__ = "Donald Stufft and individual contributors" __author__ = "Donald Stufft and individual contributors"
__email__ = "donald@stufft.io" __email__ = "donald@stufft.io"
__license__ = "BSD or Apache License, Version 2.0" __license__ = "BSD or Apache License, Version 2.0"
__copyright__ = "Copyright 2014-2016 %s" % __author__ __copyright__ = "Copyright 2014-2019 %s" % __author__
...@@ -4,11 +4,23 @@ ...@@ -4,11 +4,23 @@
from __future__ import absolute_import, division, print_function from __future__ import absolute_import, division, print_function
from .__about__ import ( from .__about__ import (
__author__, __copyright__, __email__, __license__, __summary__, __title__, __author__,
__uri__, __version__ __copyright__,
__email__,
__license__,
__summary__,
__title__,
__uri__,
__version__,
) )
__all__ = [ __all__ = [
"__title__", "__summary__", "__uri__", "__version__", "__author__", "__title__",
"__email__", "__license__", "__copyright__", "__summary__",
"__uri__",
"__version__",
"__author__",
"__email__",
"__license__",
"__copyright__",
] ]
...@@ -12,9 +12,9 @@ PY3 = sys.version_info[0] == 3 ...@@ -12,9 +12,9 @@ PY3 = sys.version_info[0] == 3
# flake8: noqa # flake8: noqa
if PY3: if PY3:
string_types = str, string_types = (str,)
else: else:
string_types = basestring, string_types = (basestring,)
def with_metaclass(meta, *bases): def with_metaclass(meta, *bases):
...@@ -27,4 +27,5 @@ def with_metaclass(meta, *bases): ...@@ -27,4 +27,5 @@ def with_metaclass(meta, *bases):
class metaclass(meta): class metaclass(meta):
def __new__(cls, name, this_bases, d): def __new__(cls, name, this_bases, d):
return meta(name, bases, d) return meta(name, bases, d)
return type.__new__(metaclass, 'temporary_class', (), {})
return type.__new__(metaclass, "temporary_class", (), {})
...@@ -5,7 +5,6 @@ from __future__ import absolute_import, division, print_function ...@@ -5,7 +5,6 @@ from __future__ import absolute_import, division, print_function
class Infinity(object): class Infinity(object):
def __repr__(self): def __repr__(self):
return "Infinity" return "Infinity"
...@@ -33,11 +32,11 @@ class Infinity(object): ...@@ -33,11 +32,11 @@ class Infinity(object):
def __neg__(self): def __neg__(self):
return NegativeInfinity return NegativeInfinity
Infinity = Infinity() Infinity = Infinity()
class NegativeInfinity(object): class NegativeInfinity(object):
def __repr__(self): def __repr__(self):
return "-Infinity" return "-Infinity"
...@@ -65,4 +64,5 @@ class NegativeInfinity(object): ...@@ -65,4 +64,5 @@ class NegativeInfinity(object):
def __neg__(self): def __neg__(self):
return Infinity return Infinity
NegativeInfinity = NegativeInfinity() NegativeInfinity = NegativeInfinity()
...@@ -17,8 +17,11 @@ from .specifiers import Specifier, InvalidSpecifier ...@@ -17,8 +17,11 @@ from .specifiers import Specifier, InvalidSpecifier
__all__ = [ __all__ = [
"InvalidMarker", "UndefinedComparison", "UndefinedEnvironmentName", "InvalidMarker",
"Marker", "default_environment", "UndefinedComparison",
"UndefinedEnvironmentName",
"Marker",
"default_environment",
] ]
...@@ -42,7 +45,6 @@ class UndefinedEnvironmentName(ValueError): ...@@ -42,7 +45,6 @@ class UndefinedEnvironmentName(ValueError):
class Node(object): class Node(object):
def __init__(self, value): def __init__(self, value):
self.value = value self.value = value
...@@ -57,62 +59,52 @@ class Node(object): ...@@ -57,62 +59,52 @@ class Node(object):
class Variable(Node): class Variable(Node):
def serialize(self): def serialize(self):
return str(self) return str(self)
class Value(Node): class Value(Node):
def serialize(self): def serialize(self):
return '"{0}"'.format(self) return '"{0}"'.format(self)
class Op(Node): class Op(Node):
def serialize(self): def serialize(self):
return str(self) return str(self)
VARIABLE = ( VARIABLE = (
L("implementation_version") | L("implementation_version")
L("platform_python_implementation") | | L("platform_python_implementation")
L("implementation_name") | | L("implementation_name")
L("python_full_version") | | L("python_full_version")
L("platform_release") | | L("platform_release")
L("platform_version") | | L("platform_version")
L("platform_machine") | | L("platform_machine")
L("platform_system") | | L("platform_system")
L("python_version") | | L("python_version")
L("sys_platform") | | L("sys_platform")
L("os_name") | | L("os_name")
L("os.name") | # PEP-345 | L("os.name")
L("sys.platform") | # PEP-345 | L("sys.platform") # PEP-345
L("platform.version") | # PEP-345 | L("platform.version") # PEP-345
L("platform.machine") | # PEP-345 | L("platform.machine") # PEP-345
L("platform.python_implementation") | # PEP-345 | L("platform.python_implementation") # PEP-345
L("python_implementation") | # undocumented setuptools legacy | L("python_implementation") # PEP-345
L("extra") | L("extra") # undocumented setuptools legacy
) )
ALIASES = { ALIASES = {
'os.name': 'os_name', "os.name": "os_name",
'sys.platform': 'sys_platform', "sys.platform": "sys_platform",
'platform.version': 'platform_version', "platform.version": "platform_version",
'platform.machine': 'platform_machine', "platform.machine": "platform_machine",
'platform.python_implementation': 'platform_python_implementation', "platform.python_implementation": "platform_python_implementation",
'python_implementation': 'platform_python_implementation' "python_implementation": "platform_python_implementation",
} }
VARIABLE.setParseAction(lambda s, l, t: Variable(ALIASES.get(t[0], t[0]))) VARIABLE.setParseAction(lambda s, l, t: Variable(ALIASES.get(t[0], t[0])))
VERSION_CMP = ( VERSION_CMP = (
L("===") | L("===") | L("==") | L(">=") | L("<=") | L("!=") | L("~=") | L(">") | L("<")
L("==") |
L(">=") |
L("<=") |
L("!=") |
L("~=") |
L(">") |
L("<")
) )
MARKER_OP = VERSION_CMP | L("not in") | L("in") MARKER_OP = VERSION_CMP | L("not in") | L("in")
...@@ -152,8 +144,11 @@ def _format_marker(marker, first=True): ...@@ -152,8 +144,11 @@ def _format_marker(marker, first=True):
# where the single item is itself it's own list. In that case we want skip # 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 # the rest of this function so that we don't get extraneous () on the
# outside. # outside.
if (isinstance(marker, list) and len(marker) == 1 and if (
isinstance(marker[0], (list, tuple))): isinstance(marker, list)
and len(marker) == 1
and isinstance(marker[0], (list, tuple))
):
return _format_marker(marker[0]) return _format_marker(marker[0])
if isinstance(marker, list): if isinstance(marker, list):
...@@ -239,20 +234,20 @@ def _evaluate_markers(markers, environment): ...@@ -239,20 +234,20 @@ def _evaluate_markers(markers, environment):
def format_full_version(info): def format_full_version(info):
version = '{0.major}.{0.minor}.{0.micro}'.format(info) version = "{0.major}.{0.minor}.{0.micro}".format(info)
kind = info.releaselevel kind = info.releaselevel
if kind != 'final': if kind != "final":
version += kind[0] + str(info.serial) version += kind[0] + str(info.serial)
return version return version
def default_environment(): def default_environment():
if hasattr(sys, 'implementation'): if hasattr(sys, "implementation"):
iver = format_full_version(sys.implementation.version) iver = format_full_version(sys.implementation.version)
implementation_name = sys.implementation.name implementation_name = sys.implementation.name
else: else:
iver = '0' iver = "0"
implementation_name = '' implementation_name = ""
return { return {
"implementation_name": implementation_name, "implementation_name": implementation_name,
...@@ -264,19 +259,19 @@ def default_environment(): ...@@ -264,19 +259,19 @@ def default_environment():
"platform_version": platform.version(), "platform_version": platform.version(),
"python_full_version": platform.python_version(), "python_full_version": platform.python_version(),
"platform_python_implementation": platform.python_implementation(), "platform_python_implementation": platform.python_implementation(),
"python_version": platform.python_version()[:3], "python_version": ".".join(platform.python_version_tuple()[:2]),
"sys_platform": sys.platform, "sys_platform": sys.platform,
} }
class Marker(object): class Marker(object):
def __init__(self, marker): def __init__(self, marker):
try: try:
self._markers = _coerce_parse_result(MARKER.parseString(marker)) self._markers = _coerce_parse_result(MARKER.parseString(marker))
except ParseException as e: except ParseException as e:
err_str = "Invalid marker: {0!r}, parse error at {1!r}".format( err_str = "Invalid marker: {0!r}, parse error at {1!r}".format(
marker, marker[e.loc:e.loc + 8]) marker, marker[e.loc : e.loc + 8]
)
raise InvalidMarker(err_str) raise InvalidMarker(err_str)
def __str__(self): def __str__(self):
......
...@@ -38,8 +38,8 @@ IDENTIFIER = Combine(ALPHANUM + ZeroOrMore(IDENTIFIER_END)) ...@@ -38,8 +38,8 @@ IDENTIFIER = Combine(ALPHANUM + ZeroOrMore(IDENTIFIER_END))
NAME = IDENTIFIER("name") NAME = IDENTIFIER("name")
EXTRA = IDENTIFIER EXTRA = IDENTIFIER
URI = Regex(r'[^ ]+')("url") URI = Regex(r"[^ ]+")("url")
URL = (AT + URI) URL = AT + URI
EXTRAS_LIST = EXTRA + ZeroOrMore(COMMA + EXTRA) EXTRAS_LIST = EXTRA + ZeroOrMore(COMMA + EXTRA)
EXTRAS = (LBRACKET + Optional(EXTRAS_LIST) + RBRACKET)("extras") EXTRAS = (LBRACKET + Optional(EXTRAS_LIST) + RBRACKET)("extras")
...@@ -48,28 +48,31 @@ VERSION_PEP440 = Regex(Specifier._regex_str, re.VERBOSE | re.IGNORECASE) ...@@ -48,28 +48,31 @@ VERSION_PEP440 = Regex(Specifier._regex_str, re.VERBOSE | re.IGNORECASE)
VERSION_LEGACY = Regex(LegacySpecifier._regex_str, re.VERBOSE | re.IGNORECASE) VERSION_LEGACY = Regex(LegacySpecifier._regex_str, re.VERBOSE | re.IGNORECASE)
VERSION_ONE = VERSION_PEP440 ^ VERSION_LEGACY VERSION_ONE = VERSION_PEP440 ^ VERSION_LEGACY
VERSION_MANY = Combine(VERSION_ONE + ZeroOrMore(COMMA + VERSION_ONE), VERSION_MANY = Combine(
joinString=",", adjacent=False)("_raw_spec") 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.setParseAction(lambda s, l, t: t._raw_spec or "")
VERSION_SPEC = originalTextFor(_VERSION_SPEC)("specifier") VERSION_SPEC = originalTextFor(_VERSION_SPEC)("specifier")
VERSION_SPEC.setParseAction(lambda s, l, t: t[1]) VERSION_SPEC.setParseAction(lambda s, l, t: t[1])
MARKER_EXPR = originalTextFor(MARKER_EXPR())("marker") MARKER_EXPR = originalTextFor(MARKER_EXPR())("marker")
MARKER_EXPR.setParseAction( MARKER_EXPR.setParseAction(
lambda s, l, t: Marker(s[t._original_start:t._original_end]) lambda s, l, t: Marker(s[t._original_start : t._original_end])
) )
MARKER_SEPERATOR = SEMICOLON MARKER_SEPARATOR = SEMICOLON
MARKER = MARKER_SEPERATOR + MARKER_EXPR MARKER = MARKER_SEPARATOR + MARKER_EXPR
VERSION_AND_MARKER = VERSION_SPEC + Optional(MARKER) VERSION_AND_MARKER = VERSION_SPEC + Optional(MARKER)
URL_AND_MARKER = URL + Optional(MARKER) URL_AND_MARKER = URL + Optional(MARKER)
NAMED_REQUIREMENT = \ NAMED_REQUIREMENT = NAME + Optional(EXTRAS) + (URL_AND_MARKER | VERSION_AND_MARKER)
NAME + Optional(EXTRAS) + (URL_AND_MARKER | VERSION_AND_MARKER)
REQUIREMENT = stringStart + NAMED_REQUIREMENT + stringEnd REQUIREMENT = stringStart + NAMED_REQUIREMENT + stringEnd
# setuptools.extern.pyparsing isn't thread safe during initialization, so we do it eagerly, see
# issue #104
REQUIREMENT.parseString("x[]")
class Requirement(object): class Requirement(object):
...@@ -90,15 +93,21 @@ class Requirement(object): ...@@ -90,15 +93,21 @@ class Requirement(object):
req = REQUIREMENT.parseString(requirement_string) req = REQUIREMENT.parseString(requirement_string)
except ParseException as e: except ParseException as e:
raise InvalidRequirement( raise InvalidRequirement(
"Invalid requirement, parse error at \"{0!r}\"".format( 'Parse error at "{0!r}": {1}'.format(
requirement_string[e.loc:e.loc + 8])) requirement_string[e.loc : e.loc + 8], e.msg
)
)
self.name = req.name self.name = req.name
if req.url: if req.url:
parsed_url = urlparse.urlparse(req.url) parsed_url = urlparse.urlparse(req.url)
if not (parsed_url.scheme and parsed_url.netloc) or ( if parsed_url.scheme == "file":
not parsed_url.scheme and not parsed_url.netloc): if urlparse.urlunparse(parsed_url) != req.url:
raise InvalidRequirement("Invalid URL given") raise InvalidRequirement("Invalid URL given")
elif not (parsed_url.scheme and parsed_url.netloc) or (
not parsed_url.scheme and not parsed_url.netloc
):
raise InvalidRequirement("Invalid URL: {0}".format(req.url))
self.url = req.url self.url = req.url
else: else:
self.url = None self.url = None
...@@ -117,6 +126,8 @@ class Requirement(object): ...@@ -117,6 +126,8 @@ class Requirement(object):
if self.url: if self.url:
parts.append("@ {0}".format(self.url)) parts.append("@ {0}".format(self.url))
if self.marker:
parts.append(" ")
if self.marker: if self.marker:
parts.append("; {0}".format(self.marker)) parts.append("; {0}".format(self.marker))
......
...@@ -19,7 +19,6 @@ class InvalidSpecifier(ValueError): ...@@ -19,7 +19,6 @@ class InvalidSpecifier(ValueError):
class BaseSpecifier(with_metaclass(abc.ABCMeta, object)): class BaseSpecifier(with_metaclass(abc.ABCMeta, object)):
@abc.abstractmethod @abc.abstractmethod
def __str__(self): def __str__(self):
""" """
...@@ -84,10 +83,7 @@ class _IndividualSpecifier(BaseSpecifier): ...@@ -84,10 +83,7 @@ class _IndividualSpecifier(BaseSpecifier):
if not match: if not match:
raise InvalidSpecifier("Invalid specifier: '{0}'".format(spec)) raise InvalidSpecifier("Invalid specifier: '{0}'".format(spec))
self._spec = ( self._spec = (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 # Store whether or not this Specifier should accept prereleases
self._prereleases = prereleases self._prereleases = prereleases
...@@ -99,11 +95,7 @@ class _IndividualSpecifier(BaseSpecifier): ...@@ -99,11 +95,7 @@ class _IndividualSpecifier(BaseSpecifier):
else "" else ""
) )
return "<{0}({1!r}{2})>".format( return "<{0}({1!r}{2})>".format(self.__class__.__name__, str(self), pre)
self.__class__.__name__,
str(self),
pre,
)
def __str__(self): def __str__(self):
return "{0}{1}".format(*self._spec) return "{0}{1}".format(*self._spec)
...@@ -194,11 +186,12 @@ class _IndividualSpecifier(BaseSpecifier): ...@@ -194,11 +186,12 @@ class _IndividualSpecifier(BaseSpecifier):
# If our version is a prerelease, and we were not set to allow # If our version is a prerelease, and we were not set to allow
# prereleases, then we'll store it for later incase nothing # prereleases, then we'll store it for later incase nothing
# else matches this specifier. # else matches this specifier.
if (parsed_version.is_prerelease and not if parsed_version.is_prerelease and not (
(prereleases or self.prereleases)): prereleases or self.prereleases
):
found_prereleases.append(version) found_prereleases.append(version)
# Either this is not a prerelease, or we should have been # Either this is not a prerelease, or we should have been
# accepting prereleases from the begining. # accepting prereleases from the beginning.
else: else:
yielded = True yielded = True
yield version yield version
...@@ -213,8 +206,7 @@ class _IndividualSpecifier(BaseSpecifier): ...@@ -213,8 +206,7 @@ class _IndividualSpecifier(BaseSpecifier):
class LegacySpecifier(_IndividualSpecifier): class LegacySpecifier(_IndividualSpecifier):
_regex_str = ( _regex_str = r"""
r"""
(?P<operator>(==|!=|<=|>=|<|>)) (?P<operator>(==|!=|<=|>=|<|>))
\s* \s*
(?P<version> (?P<version>
...@@ -225,10 +217,8 @@ class LegacySpecifier(_IndividualSpecifier): ...@@ -225,10 +217,8 @@ class LegacySpecifier(_IndividualSpecifier):
# them, and a comma since it's a version separator. # them, and a comma since it's a version separator.
) )
""" """
)
_regex = re.compile( _regex = re.compile(r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE)
r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE)
_operators = { _operators = {
"==": "equal", "==": "equal",
...@@ -269,13 +259,13 @@ def _require_version_compare(fn): ...@@ -269,13 +259,13 @@ def _require_version_compare(fn):
if not isinstance(prospective, Version): if not isinstance(prospective, Version):
return False return False
return fn(self, prospective, spec) return fn(self, prospective, spec)
return wrapped return wrapped
class Specifier(_IndividualSpecifier): class Specifier(_IndividualSpecifier):
_regex_str = ( _regex_str = r"""
r"""
(?P<operator>(~=|==|!=|<=|>=|<|>|===)) (?P<operator>(~=|==|!=|<=|>=|<|>|===))
(?P<version> (?P<version>
(?: (?:
...@@ -367,10 +357,8 @@ class Specifier(_IndividualSpecifier): ...@@ -367,10 +357,8 @@ class Specifier(_IndividualSpecifier):
) )
) )
""" """
)
_regex = re.compile( _regex = re.compile(r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE)
r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE)
_operators = { _operators = {
"~=": "compatible", "~=": "compatible",
...@@ -397,8 +385,7 @@ class Specifier(_IndividualSpecifier): ...@@ -397,8 +385,7 @@ class Specifier(_IndividualSpecifier):
prefix = ".".join( prefix = ".".join(
list( list(
itertools.takewhile( itertools.takewhile(
lambda x: (not x.startswith("post") and not lambda x: (not x.startswith("post") and not x.startswith("dev")),
x.startswith("dev")),
_version_split(spec), _version_split(spec),
) )
)[:-1] )[:-1]
...@@ -407,8 +394,9 @@ class Specifier(_IndividualSpecifier): ...@@ -407,8 +394,9 @@ class Specifier(_IndividualSpecifier):
# Add the prefix notation to the end of our string # Add the prefix notation to the end of our string
prefix += ".*" prefix += ".*"
return (self._get_operator(">=")(prospective, spec) and return self._get_operator(">=")(prospective, spec) and self._get_operator("==")(
self._get_operator("==")(prospective, prefix)) prospective, prefix
)
@_require_version_compare @_require_version_compare
def _compare_equal(self, prospective, spec): def _compare_equal(self, prospective, spec):
...@@ -428,7 +416,7 @@ class Specifier(_IndividualSpecifier): ...@@ -428,7 +416,7 @@ class Specifier(_IndividualSpecifier):
# Shorten the prospective version to be the same length as the spec # 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 # so that we can determine if the specifier is a prefix of the
# prospective version or not. # prospective version or not.
prospective = prospective[:len(spec)] prospective = prospective[: len(spec)]
# Pad out our two sides with zeros so that they both equal the same # Pad out our two sides with zeros so that they both equal the same
# length. # length.
...@@ -503,7 +491,7 @@ class Specifier(_IndividualSpecifier): ...@@ -503,7 +491,7 @@ class Specifier(_IndividualSpecifier):
return False return False
# Ensure that we do not allow a local version of the version mentioned # Ensure that we do not allow a local version of the version mentioned
# in the specifier, which is techincally greater than, to match. # in the specifier, which is technically greater than, to match.
if prospective.local is not None: if prospective.local is not None:
if Version(prospective.base_version) == Version(spec.base_version): if Version(prospective.base_version) == Version(spec.base_version):
return False return False
...@@ -567,27 +555,17 @@ def _pad_version(left, right): ...@@ -567,27 +555,17 @@ def _pad_version(left, right):
right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right))) right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right)))
# Get the rest of our versions # Get the rest of our versions
left_split.append(left[len(left_split[0]):]) left_split.append(left[len(left_split[0]) :])
right_split.append(right[len(right_split[0]):]) right_split.append(right[len(right_split[0]) :])
# Insert our padding # Insert our padding
left_split.insert( left_split.insert(1, ["0"] * max(0, len(right_split[0]) - len(left_split[0])))
1, right_split.insert(1, ["0"] * max(0, len(left_split[0]) - len(right_split[0])))
["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 ( return (list(itertools.chain(*left_split)), list(itertools.chain(*right_split)))
list(itertools.chain(*left_split)),
list(itertools.chain(*right_split)),
)
class SpecifierSet(BaseSpecifier): class SpecifierSet(BaseSpecifier):
def __init__(self, specifiers="", prereleases=None): def __init__(self, specifiers="", prereleases=None):
# Split on , to break each indidivual specifier into it's own item, and # Split on , to break each indidivual specifier into it's own item, and
# strip each item to remove leading/trailing whitespace. # strip each item to remove leading/trailing whitespace.
...@@ -721,10 +699,7 @@ class SpecifierSet(BaseSpecifier): ...@@ -721,10 +699,7 @@ class SpecifierSet(BaseSpecifier):
# given version is contained within all of them. # given version is contained within all of them.
# Note: This use of all() here means that an empty set of specifiers # Note: This use of all() here means that an empty set of specifiers
# will always return True, this is an explicit design decision. # will always return True, this is an explicit design decision.
return all( return all(s.contains(item, prereleases=prereleases) for s in self._specs)
s.contains(item, prereleases=prereleases)
for s in self._specs
)
def filter(self, iterable, prereleases=None): def filter(self, iterable, prereleases=None):
# Determine if we're forcing a prerelease or not, if we're not forcing # Determine if we're forcing a prerelease or not, if we're not forcing
......
This diff is collapsed.
...@@ -5,6 +5,8 @@ from __future__ import absolute_import, division, print_function ...@@ -5,6 +5,8 @@ from __future__ import absolute_import, division, print_function
import re import re
from .version import InvalidVersion, Version
_canonicalize_regex = re.compile(r"[-_.]+") _canonicalize_regex = re.compile(r"[-_.]+")
...@@ -12,3 +14,44 @@ _canonicalize_regex = re.compile(r"[-_.]+") ...@@ -12,3 +14,44 @@ _canonicalize_regex = re.compile(r"[-_.]+")
def canonicalize_name(name): def canonicalize_name(name):
# This is taken from PEP 503. # This is taken from PEP 503.
return _canonicalize_regex.sub("-", name).lower() return _canonicalize_regex.sub("-", name).lower()
def canonicalize_version(version):
"""
This is very similar to Version.__str__, but has one subtle differences
with the way it handles the release segment.
"""
try:
version = Version(version)
except InvalidVersion:
# Legacy versions cannot be normalized
return version
parts = []
# Epoch
if version.epoch != 0:
parts.append("{0}!".format(version.epoch))
# Release segment
# NB: This strips trailing '.0's to normalize
parts.append(re.sub(r"(\.0)+$", "", ".".join(str(x) for x in version.release)))
# Pre-release
if version.pre is not None:
parts.append("".join(str(x) for x in version.pre))
# Post-release
if version.post is not None:
parts.append(".post{0}".format(version.post))
# Development release
if version.dev is not None:
parts.append(".dev{0}".format(version.dev))
# Local version segment
if version.local is not None:
parts.append("+{0}".format(version.local))
return "".join(parts)
...@@ -10,14 +10,11 @@ import re ...@@ -10,14 +10,11 @@ import re
from ._structures import Infinity from ._structures import Infinity
__all__ = [ __all__ = ["parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN"]
"parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN"
]
_Version = collections.namedtuple( _Version = collections.namedtuple(
"_Version", "_Version", ["epoch", "release", "dev", "pre", "post", "local"]
["epoch", "release", "dev", "pre", "post", "local"],
) )
...@@ -40,7 +37,6 @@ class InvalidVersion(ValueError): ...@@ -40,7 +37,6 @@ class InvalidVersion(ValueError):
class _BaseVersion(object): class _BaseVersion(object):
def __hash__(self): def __hash__(self):
return hash(self._key) return hash(self._key)
...@@ -70,7 +66,6 @@ class _BaseVersion(object): ...@@ -70,7 +66,6 @@ class _BaseVersion(object):
class LegacyVersion(_BaseVersion): class LegacyVersion(_BaseVersion):
def __init__(self, version): def __init__(self, version):
self._version = str(version) self._version = str(version)
self._key = _legacy_cmpkey(self._version) self._key = _legacy_cmpkey(self._version)
...@@ -89,6 +84,26 @@ class LegacyVersion(_BaseVersion): ...@@ -89,6 +84,26 @@ class LegacyVersion(_BaseVersion):
def base_version(self): def base_version(self):
return self._version return self._version
@property
def epoch(self):
return -1
@property
def release(self):
return None
@property
def pre(self):
return None
@property
def post(self):
return None
@property
def dev(self):
return None
@property @property
def local(self): def local(self):
return None return None
...@@ -101,13 +116,19 @@ class LegacyVersion(_BaseVersion): ...@@ -101,13 +116,19 @@ class LegacyVersion(_BaseVersion):
def is_postrelease(self): def is_postrelease(self):
return False return False
@property
def is_devrelease(self):
return False
_legacy_version_component_re = re.compile(
r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE, _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": "@", "pre": "c",
"preview": "c",
"-": "final-",
"rc": "c",
"dev": "@",
} }
...@@ -154,6 +175,7 @@ def _legacy_cmpkey(version): ...@@ -154,6 +175,7 @@ def _legacy_cmpkey(version):
return epoch, parts return epoch, parts
# Deliberately not anchored to the start and end of the string, to make it # Deliberately not anchored to the start and end of the string, to make it
# easier for 3rd party code to reuse # easier for 3rd party code to reuse
VERSION_PATTERN = r""" VERSION_PATTERN = r"""
...@@ -190,10 +212,7 @@ VERSION_PATTERN = r""" ...@@ -190,10 +212,7 @@ VERSION_PATTERN = r"""
class Version(_BaseVersion): class Version(_BaseVersion):
_regex = re.compile( _regex = re.compile(r"^\s*" + VERSION_PATTERN + r"\s*$", re.VERBOSE | re.IGNORECASE)
r"^\s*" + VERSION_PATTERN + r"\s*$",
re.VERBOSE | re.IGNORECASE,
)
def __init__(self, version): def __init__(self, version):
# Validate the version and parse it into pieces # Validate the version and parse it into pieces
...@@ -205,18 +224,11 @@ class Version(_BaseVersion): ...@@ -205,18 +224,11 @@ class Version(_BaseVersion):
self._version = _Version( self._version = _Version(
epoch=int(match.group("epoch")) if match.group("epoch") else 0, epoch=int(match.group("epoch")) if match.group("epoch") else 0,
release=tuple(int(i) for i in match.group("release").split(".")), release=tuple(int(i) for i in match.group("release").split(".")),
pre=_parse_letter_version( pre=_parse_letter_version(match.group("pre_l"), match.group("pre_n")),
match.group("pre_l"),
match.group("pre_n"),
),
post=_parse_letter_version( post=_parse_letter_version(
match.group("post_l"), match.group("post_l"), match.group("post_n1") or match.group("post_n2")
match.group("post_n1") or match.group("post_n2"),
),
dev=_parse_letter_version(
match.group("dev_l"),
match.group("dev_n"),
), ),
dev=_parse_letter_version(match.group("dev_l"), match.group("dev_n")),
local=_parse_local_version(match.group("local")), local=_parse_local_version(match.group("local")),
) )
...@@ -237,32 +249,57 @@ class Version(_BaseVersion): ...@@ -237,32 +249,57 @@ class Version(_BaseVersion):
parts = [] parts = []
# Epoch # Epoch
if self._version.epoch != 0: if self.epoch != 0:
parts.append("{0}!".format(self._version.epoch)) parts.append("{0}!".format(self.epoch))
# Release segment # Release segment
parts.append(".".join(str(x) for x in self._version.release)) parts.append(".".join(str(x) for x in self.release))
# Pre-release # Pre-release
if self._version.pre is not None: if self.pre is not None:
parts.append("".join(str(x) for x in self._version.pre)) parts.append("".join(str(x) for x in self.pre))
# Post-release # Post-release
if self._version.post is not None: if self.post is not None:
parts.append(".post{0}".format(self._version.post[1])) parts.append(".post{0}".format(self.post))
# Development release # Development release
if self._version.dev is not None: if self.dev is not None:
parts.append(".dev{0}".format(self._version.dev[1])) parts.append(".dev{0}".format(self.dev))
# Local version segment # Local version segment
if self._version.local is not None: if self.local is not None:
parts.append( parts.append("+{0}".format(self.local))
"+{0}".format(".".join(str(x) for x in self._version.local))
)
return "".join(parts) return "".join(parts)
@property
def epoch(self):
return self._version.epoch
@property
def release(self):
return self._version.release
@property
def pre(self):
return self._version.pre
@property
def post(self):
return self._version.post[1] if self._version.post else None
@property
def dev(self):
return self._version.dev[1] if self._version.dev else None
@property
def local(self):
if self._version.local:
return ".".join(str(x) for x in self._version.local)
else:
return None
@property @property
def public(self): def public(self):
return str(self).split("+", 1)[0] return str(self).split("+", 1)[0]
...@@ -272,27 +309,25 @@ class Version(_BaseVersion): ...@@ -272,27 +309,25 @@ class Version(_BaseVersion):
parts = [] parts = []
# Epoch # Epoch
if self._version.epoch != 0: if self.epoch != 0:
parts.append("{0}!".format(self._version.epoch)) parts.append("{0}!".format(self.epoch))
# Release segment # Release segment
parts.append(".".join(str(x) for x in self._version.release)) parts.append(".".join(str(x) for x in self.release))
return "".join(parts) return "".join(parts)
@property
def local(self):
version_string = str(self)
if "+" in version_string:
return version_string.split("+", 1)[1]
@property @property
def is_prerelease(self): def is_prerelease(self):
return bool(self._version.dev or self._version.pre) return self.dev is not None or self.pre is not None
@property @property
def is_postrelease(self): def is_postrelease(self):
return bool(self._version.post) return self.post is not None
@property
def is_devrelease(self):
return self.dev is not None
def _parse_letter_version(letter, number): def _parse_letter_version(letter, number):
...@@ -326,7 +361,7 @@ def _parse_letter_version(letter, number): ...@@ -326,7 +361,7 @@ def _parse_letter_version(letter, number):
return letter, int(number) return letter, int(number)
_local_version_seperators = re.compile(r"[\._-]") _local_version_separators = re.compile(r"[\._-]")
def _parse_local_version(local): def _parse_local_version(local):
...@@ -336,7 +371,7 @@ def _parse_local_version(local): ...@@ -336,7 +371,7 @@ def _parse_local_version(local):
if local is not None: if local is not None:
return tuple( return tuple(
part.lower() if not part.isdigit() else int(part) part.lower() if not part.isdigit() else int(part)
for part in _local_version_seperators.split(local) for part in _local_version_separators.split(local)
) )
...@@ -347,12 +382,7 @@ def _cmpkey(epoch, release, pre, post, dev, local): ...@@ -347,12 +382,7 @@ def _cmpkey(epoch, release, pre, post, dev, local):
# re-reverse it back into the correct order and make it a tuple and use # re-reverse it back into the correct order and make it a tuple and use
# that for our sorting key. # that for our sorting key.
release = tuple( release = tuple(
reversed(list( reversed(list(itertools.dropwhile(lambda x: x == 0, reversed(release))))
itertools.dropwhile(
lambda x: x == 0,
reversed(release),
)
))
) )
# We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0. # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
...@@ -385,9 +415,6 @@ def _cmpkey(epoch, release, pre, post, dev, local): ...@@ -385,9 +415,6 @@ def _cmpkey(epoch, release, pre, post, dev, local):
# - Numeric segments sort numerically # - Numeric segments sort numerically
# - Shorter versions sort before longer versions when the prefixes # - Shorter versions sort before longer versions when the prefixes
# match exactly # match exactly
local = tuple( local = tuple((i, "") if isinstance(i, int) else (-Infinity, i) for i in local)
(i, "") if isinstance(i, int) else (-Infinity, i)
for i in local
)
return epoch, release, pre, post, dev, local return epoch, release, pre, post, dev, local
packaging==16.8 packaging==19.2
pyparsing==2.2.1 pyparsing==2.2.1
six==1.10.0 six==1.10.0
ordered-set==3.1.1 ordered-set==3.1.1
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment