Skip to content

Update vendored library: packaging #7559

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ exclude tox.ini
exclude noxfile.py

recursive-include src/pip/_vendor *.pem
recursive-include src/pip/_vendor py.typed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I don't think there's much point in doing this -- we're shadowing the relevant modules through .pyi files in the vendor directory.

recursive-include docs Makefile *.rst *.py *.bat

exclude src/pip/_vendor/six
Expand Down
1 change: 1 addition & 0 deletions news/packaging.vendor
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Update packaging to 20.0.
2 changes: 1 addition & 1 deletion src/pip/_vendor/packaging/LICENSE.APACHE
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,4 @@
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS
END OF TERMS AND CONDITIONS
2 changes: 1 addition & 1 deletion src/pip/_vendor/packaging/__about__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
__summary__ = "Core utilities for Python packages"
__uri__ = "https://github.com/pypa/packaging"

__version__ = "19.2"
__version__ = "20.0"

__author__ = "Donald Stufft and individual contributors"
__email__ = "[email protected]"
Expand Down
9 changes: 8 additions & 1 deletion src/pip/_vendor/packaging/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@

import sys

from ._typing import MYPY_CHECK_RUNNING

if MYPY_CHECK_RUNNING: # pragma: no cover
from typing import Any, Dict, Tuple, Type


PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3
Expand All @@ -18,14 +23,16 @@


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.
class metaclass(meta):
class metaclass(meta): # type: ignore
def __new__(cls, name, this_bases, d):
# type: (Type[Any], str, Tuple[Any], Dict[Any, Any]) -> Any
return meta(name, bases, d)

return type.__new__(metaclass, "temporary_class", (), {})
26 changes: 22 additions & 4 deletions src/pip/_vendor/packaging/_structures.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,65 +4,83 @@
from __future__ import absolute_import, division, print_function


class Infinity(object):
class InfinityType(object):
def __repr__(self):
# type: () -> str
return "Infinity"

def __hash__(self):
# type: () -> int
return hash(repr(self))

def __lt__(self, other):
# type: (object) -> bool
return False

def __le__(self, other):
# type: (object) -> bool
return False

def __eq__(self, other):
# type: (object) -> bool
return isinstance(other, self.__class__)

def __ne__(self, other):
# type: (object) -> bool
return not isinstance(other, self.__class__)

def __gt__(self, other):
# type: (object) -> bool
return True

def __ge__(self, other):
# type: (object) -> bool
return True

def __neg__(self):
# type: (object) -> NegativeInfinityType
return NegativeInfinity


Infinity = Infinity()
Infinity = InfinityType()


class NegativeInfinity(object):
class NegativeInfinityType(object):
def __repr__(self):
# type: () -> str
return "-Infinity"

def __hash__(self):
# type: () -> int
return hash(repr(self))

def __lt__(self, other):
# type: (object) -> bool
return True

def __le__(self, other):
# type: (object) -> bool
return True

def __eq__(self, other):
# type: (object) -> bool
return isinstance(other, self.__class__)

def __ne__(self, other):
# type: (object) -> bool
return not isinstance(other, self.__class__)

def __gt__(self, other):
# type: (object) -> bool
return False

def __ge__(self, other):
# type: (object) -> bool
return False

def __neg__(self):
# type: (object) -> InfinityType
return Infinity


NegativeInfinity = NegativeInfinity()
NegativeInfinity = NegativeInfinityType()
39 changes: 39 additions & 0 deletions src/pip/_vendor/packaging/_typing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""For neatly implementing static typing in packaging.

`mypy` - the static type analysis tool we use - uses the `typing` module, which
provides core functionality fundamental to mypy's functioning.

Generally, `typing` would be imported at runtime and used in that fashion -
it acts as a no-op at runtime and does not have any run-time overhead by
design.

As it turns out, `typing` is not vendorable - it uses separate sources for
Python 2/Python 3. Thus, this codebase can not expect it to be present.
To work around this, mypy allows the typing import to be behind a False-y
optional to prevent it from running at runtime and type-comments can be used
to remove the need for the types to be accessible directly during runtime.

This module provides the False-y guard in a nicely named fashion so that a
curious maintainer can reach here to read this.

In packaging, all static-typing related imports should be guarded as follows:

from pip._vendor.packaging._typing import MYPY_CHECK_RUNNING

if MYPY_CHECK_RUNNING:
from typing import ...

Ref: https://github.com/python/mypy/issues/3216
"""

MYPY_CHECK_RUNNING = False

if MYPY_CHECK_RUNNING: # pragma: no cover
import typing

cast = typing.cast
else:
# typing's cast() is needed at runtime, but we don't want to import typing.
# Thus, we use a dummy no-op version, which we tell mypy to ignore.
def cast(type_, value): # type: ignore
return value
54 changes: 43 additions & 11 deletions src/pip/_vendor/packaging/markers.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,14 @@
from pip._vendor.pyparsing import Literal as L # noqa

from ._compat import string_types
from ._typing import MYPY_CHECK_RUNNING
from .specifiers import Specifier, InvalidSpecifier

if MYPY_CHECK_RUNNING: # pragma: no cover
from typing import Any, Callable, Dict, List, Optional, Tuple, Union

Operator = Callable[[str, str], bool]


__all__ = [
"InvalidMarker",
Expand Down Expand Up @@ -46,30 +52,37 @@ class UndefinedEnvironmentName(ValueError):

class Node(object):
def __init__(self, value):
# type: (Any) -> None
self.value = value

def __str__(self):
# type: () -> str
return str(self.value)

def __repr__(self):
# type: () -> str
return "<{0}({1!r})>".format(self.__class__.__name__, str(self))

def serialize(self):
# type: () -> str
raise NotImplementedError


class Variable(Node):
def serialize(self):
# type: () -> str
return str(self)


class Value(Node):
def serialize(self):
# type: () -> str
return '"{0}"'.format(self)


class Op(Node):
def serialize(self):
# type: () -> str
return str(self)


Expand All @@ -85,13 +98,13 @@ def serialize(self):
| L("python_version")
| L("sys_platform")
| L("os_name")
| L("os.name")
| L("os.name") # PEP-345
| L("sys.platform") # PEP-345
| L("platform.version") # PEP-345
| L("platform.machine") # PEP-345
| L("platform.python_implementation") # PEP-345
| L("python_implementation") # PEP-345
| L("extra") # undocumented setuptools legacy
| L("python_implementation") # undocumented setuptools legacy
| L("extra") # PEP-508
)
ALIASES = {
"os.name": "os_name",
Expand Down Expand Up @@ -131,13 +144,16 @@ def serialize(self):


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):
# 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
Expand Down Expand Up @@ -172,18 +188,19 @@ def _format_marker(marker, first=True):
"!=": operator.ne,
">=": operator.ge,
">": operator.gt,
}
} # type: Dict[str, Operator]


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)

oper = _operators.get(op.serialize())
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)
Expand All @@ -192,13 +209,18 @@ def _eval_op(lhs, op, rhs):
return oper(lhs, rhs)


_undefined = object()
class Undefined(object):
pass


_undefined = Undefined()


def _get_env(environment, name):
value = environment.get(name, _undefined)
# type: (Dict[str, str], str) -> str
value = environment.get(name, _undefined) # type: Union[str, Undefined]

if value is _undefined:
if isinstance(value, Undefined):
raise UndefinedEnvironmentName(
"{0!r} does not exist in evaluation environment.".format(name)
)
Expand All @@ -207,7 +229,8 @@ def _get_env(environment, name):


def _evaluate_markers(markers, environment):
groups = [[]]
# type: (List[Any], Dict[str, str]) -> bool
groups = [[]] # type: List[List[bool]]

for marker in markers:
assert isinstance(marker, (list, tuple, string_types))
Expand All @@ -234,6 +257,7 @@ def _evaluate_markers(markers, environment):


def format_full_version(info):
# type: (sys._version_info) -> str
version = "{0.major}.{0.minor}.{0.micro}".format(info)
kind = info.releaselevel
if kind != "final":
Expand All @@ -242,9 +266,13 @@ def format_full_version(info):


def default_environment():
# type: () -> Dict[str, str]
if hasattr(sys, "implementation"):
iver = format_full_version(sys.implementation.version)
implementation_name = sys.implementation.name
# Ignoring the `sys.implementation` reference for type checking due to
# mypy not liking that the attribute doesn't exist in Python 2.7 when
# run with the `--py27` flag.
iver = format_full_version(sys.implementation.version) # type: ignore
implementation_name = sys.implementation.name # type: ignore
else:
iver = "0"
implementation_name = ""
Expand All @@ -266,6 +294,7 @@ def default_environment():

class Marker(object):
def __init__(self, marker):
# type: (str) -> None
try:
self._markers = _coerce_parse_result(MARKER.parseString(marker))
except ParseException as e:
Expand All @@ -275,12 +304,15 @@ def __init__(self, marker):
raise InvalidMarker(err_str)

def __str__(self):
# type: () -> str
return _format_marker(self._markers)

def __repr__(self):
# type: () -> str
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
Expand Down
Empty file.
Loading