mirror of https://github.com/pypa/pip
Update vendored `pkg_resources`
This commit is contained in:
parent
e3e7bc34eb
commit
eb7b4ed62e
|
@ -0,0 +1 @@
|
|||
Patch pkg_resources to remove dependency on ``jaraco.text``.
|
|
@ -0,0 +1 @@
|
|||
Update pkg_resources (via setuptools) to 65.6.3
|
|
@ -50,6 +50,8 @@ drop = [
|
|||
"easy_install.py",
|
||||
"setuptools",
|
||||
"pkg_resources/_vendor/",
|
||||
"_distutils_hack",
|
||||
"distutils-precedence.pth",
|
||||
"pkg_resources/extern/",
|
||||
# trim vendored pygments styles and lexers
|
||||
"pygments/styles/[!_]*.py",
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
"""Functions brought over from jaraco.text.
|
||||
|
||||
These functions are not supposed to be used within `pip._internal`. These are
|
||||
helper functions brought over from `jaraco.text` to enable vendoring newer
|
||||
copies of `pkg_resources` without having to vendor `jaraco.text` and its entire
|
||||
dependency cone; something that our vendoring setup is not currently capable of
|
||||
handling.
|
||||
|
||||
License reproduced from original source below:
|
||||
|
||||
Copyright Jason R. Coombs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
"""
|
||||
|
||||
import functools
|
||||
import itertools
|
||||
|
||||
|
||||
def _nonblank(str):
|
||||
return str and not str.startswith("#")
|
||||
|
||||
|
||||
@functools.singledispatch
|
||||
def yield_lines(iterable):
|
||||
r"""
|
||||
Yield valid lines of a string or iterable.
|
||||
|
||||
>>> list(yield_lines(''))
|
||||
[]
|
||||
>>> list(yield_lines(['foo', 'bar']))
|
||||
['foo', 'bar']
|
||||
>>> list(yield_lines('foo\nbar'))
|
||||
['foo', 'bar']
|
||||
>>> list(yield_lines('\nfoo\n#bar\nbaz #comment'))
|
||||
['foo', 'baz #comment']
|
||||
>>> list(yield_lines(['foo\nbar', 'baz', 'bing\n\n\n']))
|
||||
['foo', 'bar', 'baz', 'bing']
|
||||
"""
|
||||
return itertools.chain.from_iterable(map(yield_lines, iterable))
|
||||
|
||||
|
||||
@yield_lines.register(str)
|
||||
def _(text):
|
||||
return filter(_nonblank, map(str.strip, text.splitlines()))
|
||||
|
||||
|
||||
def drop_comment(line):
|
||||
"""
|
||||
Drop comments.
|
||||
|
||||
>>> drop_comment('foo # bar')
|
||||
'foo'
|
||||
|
||||
A hash without a space may be in a URL.
|
||||
|
||||
>>> drop_comment('http://example.com/foo#bar')
|
||||
'http://example.com/foo#bar'
|
||||
"""
|
||||
return line.partition(" #")[0]
|
||||
|
||||
|
||||
def join_continuation(lines):
|
||||
r"""
|
||||
Join lines continued by a trailing backslash.
|
||||
|
||||
>>> list(join_continuation(['foo \\', 'bar', 'baz']))
|
||||
['foobar', 'baz']
|
||||
>>> list(join_continuation(['foo \\', 'bar', 'baz']))
|
||||
['foobar', 'baz']
|
||||
>>> list(join_continuation(['foo \\', 'bar \\', 'baz']))
|
||||
['foobarbaz']
|
||||
|
||||
Not sure why, but...
|
||||
The character preceeding the backslash is also elided.
|
||||
|
||||
>>> list(join_continuation(['goo\\', 'dly']))
|
||||
['godly']
|
||||
|
||||
A terrible idea, but...
|
||||
If no line is available to continue, suppress the lines.
|
||||
|
||||
>>> list(join_continuation(['foo', 'bar\\', 'baz\\']))
|
||||
['foo']
|
||||
"""
|
||||
lines = iter(lines)
|
||||
for item in lines:
|
||||
while item.endswith("\\"):
|
||||
try:
|
||||
item = item[:-2].strip() + next(lines)
|
||||
except StopIteration:
|
||||
return
|
||||
yield item
|
|
@ -1,19 +1,19 @@
|
|||
Copyright (C) 2016 Jason R Coombs <jaraco@jaraco.com>
|
||||
Copyright Jason R. Coombs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# coding: utf-8
|
||||
"""
|
||||
Package resource API
|
||||
--------------------
|
||||
|
@ -15,8 +14,6 @@ The package resource API is designed to work with normal filesystem packages,
|
|||
method.
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import sys
|
||||
import os
|
||||
import io
|
||||
|
@ -41,6 +38,7 @@ import itertools
|
|||
import inspect
|
||||
import ntpath
|
||||
import posixpath
|
||||
import importlib
|
||||
from pkgutil import get_importer
|
||||
|
||||
try:
|
||||
|
@ -54,9 +52,6 @@ try:
|
|||
except NameError:
|
||||
FileExistsError = OSError
|
||||
|
||||
from pip._vendor import six
|
||||
from pip._vendor.six.moves import urllib, map, filter
|
||||
|
||||
# capture these to bypass sandboxing
|
||||
from os import utime
|
||||
try:
|
||||
|
@ -76,26 +71,23 @@ try:
|
|||
except ImportError:
|
||||
importlib_machinery = None
|
||||
|
||||
from . import py31compat
|
||||
from pip._internal.utils._jaraco_text import (
|
||||
yield_lines,
|
||||
drop_comment,
|
||||
join_continuation,
|
||||
)
|
||||
|
||||
from pip._vendor import platformdirs
|
||||
from pip._vendor import packaging
|
||||
__import__('pip._vendor.packaging.version')
|
||||
__import__('pip._vendor.packaging.specifiers')
|
||||
__import__('pip._vendor.packaging.requirements')
|
||||
__import__('pip._vendor.packaging.markers')
|
||||
__import__('pip._vendor.packaging.utils')
|
||||
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
if (3, 0) < sys.version_info < (3, 5):
|
||||
if sys.version_info < (3, 5):
|
||||
raise RuntimeError("Python 3.5 or later is required")
|
||||
|
||||
if six.PY2:
|
||||
# Those builtin exceptions are only defined in Python 3
|
||||
PermissionError = None
|
||||
NotADirectoryError = None
|
||||
|
||||
# declare some globals that will be defined later to
|
||||
# satisfy the linters.
|
||||
require = None
|
||||
|
@ -128,6 +120,11 @@ def parse_version(v):
|
|||
try:
|
||||
return packaging.version.Version(v)
|
||||
except packaging.version.InvalidVersion:
|
||||
warnings.warn(
|
||||
f"{v} is an invalid version and will not be supported in "
|
||||
"a future release",
|
||||
PkgResourcesDeprecationWarning,
|
||||
)
|
||||
return packaging.version.LegacyVersion(v)
|
||||
|
||||
|
||||
|
@ -178,10 +175,10 @@ def get_supported_platform():
|
|||
"""Return this platform's maximum compatible version.
|
||||
|
||||
distutils.util.get_platform() normally reports the minimum version
|
||||
of Mac OS X that would be required to *use* extensions produced by
|
||||
of macOS that would be required to *use* extensions produced by
|
||||
distutils. But what we want when checking compatibility is to know the
|
||||
version of Mac OS X that we are *running*. To allow usage of packages that
|
||||
explicitly require a newer version of Mac OS X, we must also know the
|
||||
version of macOS that we are *running*. To allow usage of packages that
|
||||
explicitly require a newer version of macOS, we must also know the
|
||||
current version of the OS.
|
||||
|
||||
If this condition occurs for any other platform with a version in its
|
||||
|
@ -191,9 +188,9 @@ def get_supported_platform():
|
|||
m = macosVersionString.match(plat)
|
||||
if m is not None and sys.platform == "darwin":
|
||||
try:
|
||||
plat = 'macosx-%s-%s' % ('.'.join(_macosx_vers()[:2]), m.group(3))
|
||||
plat = 'macosx-%s-%s' % ('.'.join(_macos_vers()[:2]), m.group(3))
|
||||
except ValueError:
|
||||
# not Mac OS X
|
||||
# not macOS
|
||||
pass
|
||||
return plat
|
||||
|
||||
|
@ -364,7 +361,7 @@ def get_provider(moduleOrReq):
|
|||
return _find_adapter(_provider_factories, loader)(module)
|
||||
|
||||
|
||||
def _macosx_vers(_cache=[]):
|
||||
def _macos_vers(_cache=[]):
|
||||
if not _cache:
|
||||
version = platform.mac_ver()[0]
|
||||
# fallback for MacPorts
|
||||
|
@ -380,7 +377,7 @@ def _macosx_vers(_cache=[]):
|
|||
return _cache[0]
|
||||
|
||||
|
||||
def _macosx_arch(machine):
|
||||
def _macos_arch(machine):
|
||||
return {'PowerPC': 'ppc', 'Power_Macintosh': 'ppc'}.get(machine, machine)
|
||||
|
||||
|
||||
|
@ -388,18 +385,18 @@ def get_build_platform():
|
|||
"""Return this platform's string for platform-specific distributions
|
||||
|
||||
XXX Currently this is the same as ``distutils.util.get_platform()``, but it
|
||||
needs some hacks for Linux and Mac OS X.
|
||||
needs some hacks for Linux and macOS.
|
||||
"""
|
||||
from sysconfig import get_platform
|
||||
|
||||
plat = get_platform()
|
||||
if sys.platform == "darwin" and not plat.startswith('macosx-'):
|
||||
try:
|
||||
version = _macosx_vers()
|
||||
version = _macos_vers()
|
||||
machine = os.uname()[4].replace(" ", "_")
|
||||
return "macosx-%d.%d-%s" % (
|
||||
int(version[0]), int(version[1]),
|
||||
_macosx_arch(machine),
|
||||
_macos_arch(machine),
|
||||
)
|
||||
except ValueError:
|
||||
# if someone is running a non-Mac darwin system, this will fall
|
||||
|
@ -425,7 +422,7 @@ def compatible_platforms(provided, required):
|
|||
# easy case
|
||||
return True
|
||||
|
||||
# Mac OS X special cases
|
||||
# macOS special cases
|
||||
reqMac = macosVersionString.match(required)
|
||||
if reqMac:
|
||||
provMac = macosVersionString.match(provided)
|
||||
|
@ -434,7 +431,7 @@ def compatible_platforms(provided, required):
|
|||
if not provMac:
|
||||
# this is backwards compatibility for packages built before
|
||||
# setuptools 0.6. All packages built after this point will
|
||||
# use the new macosx designation.
|
||||
# use the new macOS designation.
|
||||
provDarwin = darwinVersionString.match(provided)
|
||||
if provDarwin:
|
||||
dversion = int(provDarwin.group(1))
|
||||
|
@ -442,7 +439,7 @@ def compatible_platforms(provided, required):
|
|||
if dversion == 7 and macosversion >= "10.3" or \
|
||||
dversion == 8 and macosversion >= "10.4":
|
||||
return True
|
||||
# egg isn't macosx or legacy darwin
|
||||
# egg isn't macOS or legacy darwin
|
||||
return False
|
||||
|
||||
# are they the same major version and machine type?
|
||||
|
@ -475,7 +472,7 @@ run_main = run_script
|
|||
|
||||
def get_distribution(dist):
|
||||
"""Return a current distribution object for a Requirement or string"""
|
||||
if isinstance(dist, six.string_types):
|
||||
if isinstance(dist, str):
|
||||
dist = Requirement.parse(dist)
|
||||
if isinstance(dist, Requirement):
|
||||
dist = get_provider(dist)
|
||||
|
@ -558,6 +555,7 @@ class WorkingSet:
|
|||
self.entries = []
|
||||
self.entry_keys = {}
|
||||
self.by_key = {}
|
||||
self.normalized_to_canonical_keys = {}
|
||||
self.callbacks = []
|
||||
|
||||
if entries is None:
|
||||
|
@ -638,6 +636,14 @@ class WorkingSet:
|
|||
is returned.
|
||||
"""
|
||||
dist = self.by_key.get(req.key)
|
||||
|
||||
if dist is None:
|
||||
canonical_key = self.normalized_to_canonical_keys.get(req.key)
|
||||
|
||||
if canonical_key is not None:
|
||||
req.key = canonical_key
|
||||
dist = self.by_key.get(canonical_key)
|
||||
|
||||
if dist is not None and dist not in req:
|
||||
# XXX add more info
|
||||
raise VersionConflict(dist, req)
|
||||
|
@ -706,13 +712,16 @@ class WorkingSet:
|
|||
return
|
||||
|
||||
self.by_key[dist.key] = dist
|
||||
normalized_name = packaging.utils.canonicalize_name(dist.key)
|
||||
self.normalized_to_canonical_keys[normalized_name] = dist.key
|
||||
if dist.key not in keys:
|
||||
keys.append(dist.key)
|
||||
if dist.key not in keys2:
|
||||
keys2.append(dist.key)
|
||||
self._added_new(dist)
|
||||
|
||||
def resolve(self, requirements, env=None, installer=None,
|
||||
# FIXME: 'WorkingSet.resolve' is too complex (11)
|
||||
def resolve(self, requirements, env=None, installer=None, # noqa: C901
|
||||
replace_conflicting=False, extras=None):
|
||||
"""List all distributions needed to (recursively) meet `requirements`
|
||||
|
||||
|
@ -925,14 +934,15 @@ class WorkingSet:
|
|||
def __getstate__(self):
|
||||
return (
|
||||
self.entries[:], self.entry_keys.copy(), self.by_key.copy(),
|
||||
self.callbacks[:]
|
||||
self.normalized_to_canonical_keys.copy(), self.callbacks[:]
|
||||
)
|
||||
|
||||
def __setstate__(self, e_k_b_c):
|
||||
entries, keys, by_key, callbacks = e_k_b_c
|
||||
def __setstate__(self, e_k_b_n_c):
|
||||
entries, keys, by_key, normalized_to_canonical_keys, callbacks = e_k_b_n_c
|
||||
self.entries = entries[:]
|
||||
self.entry_keys = keys.copy()
|
||||
self.by_key = by_key.copy()
|
||||
self.normalized_to_canonical_keys = normalized_to_canonical_keys.copy()
|
||||
self.callbacks = callbacks[:]
|
||||
|
||||
|
||||
|
@ -1234,12 +1244,13 @@ class ResourceManager:
|
|||
mode = os.stat(path).st_mode
|
||||
if mode & stat.S_IWOTH or mode & stat.S_IWGRP:
|
||||
msg = (
|
||||
"%s is writable by group/others and vulnerable to attack "
|
||||
"when "
|
||||
"used with get_resource_filename. Consider a more secure "
|
||||
"Extraction path is writable by group/others "
|
||||
"and vulnerable to attack when "
|
||||
"used with get_resource_filename ({path}). "
|
||||
"Consider a more secure "
|
||||
"location (set with .set_extraction_path or the "
|
||||
"PYTHON_EGG_CACHE environment variable)." % path
|
||||
)
|
||||
"PYTHON_EGG_CACHE environment variable)."
|
||||
).format(**locals())
|
||||
warnings.warn(msg, UserWarning)
|
||||
|
||||
def postprocess(self, tempname, filename):
|
||||
|
@ -1377,7 +1388,7 @@ def evaluate_marker(text, extra=None):
|
|||
marker = packaging.markers.Marker(text)
|
||||
return marker.evaluate()
|
||||
except packaging.markers.InvalidMarker as e:
|
||||
raise SyntaxError(e)
|
||||
raise SyntaxError(e) from e
|
||||
|
||||
|
||||
class NullProvider:
|
||||
|
@ -1418,8 +1429,6 @@ class NullProvider:
|
|||
return ""
|
||||
path = self._get_metadata_path(name)
|
||||
value = self._get(path)
|
||||
if six.PY2:
|
||||
return value
|
||||
try:
|
||||
return value.decode('utf-8')
|
||||
except UnicodeDecodeError as exc:
|
||||
|
@ -1457,7 +1466,8 @@ class NullProvider:
|
|||
script_filename = self._fn(self.egg_info, script)
|
||||
namespace['__file__'] = script_filename
|
||||
if os.path.exists(script_filename):
|
||||
source = open(script_filename).read()
|
||||
with open(script_filename) as fid:
|
||||
source = fid.read()
|
||||
code = compile(source, script_filename, 'exec')
|
||||
exec(code, namespace, namespace)
|
||||
else:
|
||||
|
@ -1493,7 +1503,7 @@ class NullProvider:
|
|||
def _validate_resource_path(path):
|
||||
"""
|
||||
Validate the resource paths according to the docs.
|
||||
https://setuptools.readthedocs.io/en/latest/pkg_resources.html#basic-resource-access
|
||||
https://setuptools.pypa.io/en/latest/pkg_resources.html#basic-resource-access
|
||||
|
||||
>>> warned = getfixture('recwarn')
|
||||
>>> warnings.simplefilter('always')
|
||||
|
@ -1575,26 +1585,35 @@ is not allowed.
|
|||
register_loader_type(object, NullProvider)
|
||||
|
||||
|
||||
def _parents(path):
|
||||
"""
|
||||
yield all parents of path including path
|
||||
"""
|
||||
last = None
|
||||
while path != last:
|
||||
yield path
|
||||
last = path
|
||||
path, _ = os.path.split(path)
|
||||
|
||||
|
||||
class EggProvider(NullProvider):
|
||||
"""Provider based on a virtual filesystem"""
|
||||
|
||||
def __init__(self, module):
|
||||
NullProvider.__init__(self, module)
|
||||
super().__init__(module)
|
||||
self._setup_prefix()
|
||||
|
||||
def _setup_prefix(self):
|
||||
# we assume here that our metadata may be nested inside a "basket"
|
||||
# of multiple eggs; that's why we use module_path instead of .archive
|
||||
path = self.module_path
|
||||
old = None
|
||||
while path != old:
|
||||
if _is_egg_path(path):
|
||||
self.egg_name = os.path.basename(path)
|
||||
self.egg_info = os.path.join(path, 'EGG-INFO')
|
||||
self.egg_root = path
|
||||
break
|
||||
old = path
|
||||
path, base = os.path.split(path)
|
||||
# Assume that metadata may be nested inside a "basket"
|
||||
# of multiple eggs and use module_path instead of .archive.
|
||||
eggs = filter(_is_egg_path, _parents(self.module_path))
|
||||
egg = next(eggs, None)
|
||||
egg and self._set_egg(egg)
|
||||
|
||||
def _set_egg(self, path):
|
||||
self.egg_name = os.path.basename(path)
|
||||
self.egg_info = os.path.join(path, 'EGG-INFO')
|
||||
self.egg_root = path
|
||||
|
||||
|
||||
class DefaultProvider(EggProvider):
|
||||
|
@ -1701,7 +1720,7 @@ class ZipProvider(EggProvider):
|
|||
_zip_manifests = MemoizedZipManifests()
|
||||
|
||||
def __init__(self, module):
|
||||
EggProvider.__init__(self, module)
|
||||
super().__init__(module)
|
||||
self.zip_pre = self.loader.archive + os.sep
|
||||
|
||||
def _zipinfo_name(self, fspath):
|
||||
|
@ -1752,7 +1771,8 @@ class ZipProvider(EggProvider):
|
|||
timestamp = time.mktime(date_time)
|
||||
return timestamp, size
|
||||
|
||||
def _extract_resource(self, manager, zip_path):
|
||||
# FIXME: 'ZipProvider._extract_resource' is too complex (12)
|
||||
def _extract_resource(self, manager, zip_path): # noqa: C901
|
||||
|
||||
if zip_path in self._index():
|
||||
for name in self._index()[zip_path]:
|
||||
|
@ -1900,8 +1920,7 @@ class FileMetadata(EmptyProvider):
|
|||
return metadata
|
||||
|
||||
def _warn_on_replacement(self, metadata):
|
||||
# Python 2.7 compat for: replacement_char = '<27>'
|
||||
replacement_char = b'\xef\xbf\xbd'.decode('utf-8')
|
||||
replacement_char = '<EFBFBD>'
|
||||
if replacement_char in metadata:
|
||||
tmpl = "{self.path} could not be properly decoded in UTF-8"
|
||||
msg = tmpl.format(**locals())
|
||||
|
@ -1991,7 +2010,7 @@ def find_eggs_in_zip(importer, path_item, only=False):
|
|||
dists = find_eggs_in_zip(zipimport.zipimporter(subpath), subpath)
|
||||
for dist in dists:
|
||||
yield dist
|
||||
elif subitem.lower().endswith('.dist-info'):
|
||||
elif subitem.lower().endswith(('.dist-info', '.egg-info')):
|
||||
subpath = os.path.join(path_item, subitem)
|
||||
submeta = EggMetadata(zipimport.zipimporter(subpath))
|
||||
submeta.egg_info = subpath
|
||||
|
@ -2015,7 +2034,7 @@ def _by_version_descending(names):
|
|||
|
||||
>>> names = 'bar', 'foo', 'Python-2.7.10.egg', 'Python-2.7.2.egg'
|
||||
>>> _by_version_descending(names)
|
||||
['Python-2.7.10.egg', 'Python-2.7.2.egg', 'foo', 'bar']
|
||||
['Python-2.7.10.egg', 'Python-2.7.2.egg', 'bar', 'foo']
|
||||
>>> names = 'Setuptools-1.2.3b1.egg', 'Setuptools-1.2.3.egg'
|
||||
>>> _by_version_descending(names)
|
||||
['Setuptools-1.2.3.egg', 'Setuptools-1.2.3b1.egg']
|
||||
|
@ -2023,13 +2042,22 @@ def _by_version_descending(names):
|
|||
>>> _by_version_descending(names)
|
||||
['Setuptools-1.2.3.post1.egg', 'Setuptools-1.2.3b1.egg']
|
||||
"""
|
||||
def try_parse(name):
|
||||
"""
|
||||
Attempt to parse as a version or return a null version.
|
||||
"""
|
||||
try:
|
||||
return packaging.version.Version(name)
|
||||
except Exception:
|
||||
return packaging.version.Version('0')
|
||||
|
||||
def _by_version(name):
|
||||
"""
|
||||
Parse each component of the filename
|
||||
"""
|
||||
name, ext = os.path.splitext(name)
|
||||
parts = itertools.chain(name.split('-'), [ext])
|
||||
return [packaging.version.parse(part) for part in parts]
|
||||
return [try_parse(part) for part in parts]
|
||||
|
||||
return sorted(names, key=_by_version, reverse=True)
|
||||
|
||||
|
@ -2046,7 +2074,10 @@ def find_on_path(importer, path_item, only=False):
|
|||
)
|
||||
return
|
||||
|
||||
entries = safe_listdir(path_item)
|
||||
entries = (
|
||||
os.path.join(path_item, child)
|
||||
for child in safe_listdir(path_item)
|
||||
)
|
||||
|
||||
# for performance, before sorting by version,
|
||||
# screen entries for only those that will yield
|
||||
|
@ -2067,11 +2098,14 @@ def find_on_path(importer, path_item, only=False):
|
|||
|
||||
|
||||
def dist_factory(path_item, entry, only):
|
||||
"""
|
||||
Return a dist_factory for a path_item and entry
|
||||
"""
|
||||
"""Return a dist_factory for the given entry."""
|
||||
lower = entry.lower()
|
||||
is_meta = any(map(lower.endswith, ('.egg-info', '.dist-info')))
|
||||
is_egg_info = lower.endswith('.egg-info')
|
||||
is_dist_info = (
|
||||
lower.endswith('.dist-info') and
|
||||
os.path.isdir(os.path.join(path_item, entry))
|
||||
)
|
||||
is_meta = is_egg_info or is_dist_info
|
||||
return (
|
||||
distributions_from_metadata
|
||||
if is_meta else
|
||||
|
@ -2093,8 +2127,6 @@ class NoDists:
|
|||
"""
|
||||
def __bool__(self):
|
||||
return False
|
||||
if six.PY2:
|
||||
__nonzero__ = __bool__
|
||||
|
||||
def __call__(self, fullpath):
|
||||
return iter(())
|
||||
|
@ -2111,12 +2143,7 @@ def safe_listdir(path):
|
|||
except OSError as e:
|
||||
# Ignore the directory if does not exist, not a directory or
|
||||
# permission denied
|
||||
ignorable = (
|
||||
e.errno in (errno.ENOTDIR, errno.EACCES, errno.ENOENT)
|
||||
# Python 2 on Windows needs to be handled this way :(
|
||||
or getattr(e, "winerror", None) == 267
|
||||
)
|
||||
if not ignorable:
|
||||
if e.errno not in (errno.ENOTDIR, errno.EACCES, errno.ENOENT):
|
||||
raise
|
||||
return ()
|
||||
|
||||
|
@ -2195,10 +2222,16 @@ def _handle_ns(packageName, path_item):
|
|||
if importer is None:
|
||||
return None
|
||||
|
||||
# capture warnings due to #1111
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
loader = importer.find_module(packageName)
|
||||
# use find_spec (PEP 451) and fall-back to find_module (PEP 302)
|
||||
try:
|
||||
spec = importer.find_spec(packageName)
|
||||
except AttributeError:
|
||||
# capture warnings due to #1111
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
loader = importer.find_module(packageName)
|
||||
else:
|
||||
loader = spec.loader if spec else None
|
||||
|
||||
if loader is None:
|
||||
return None
|
||||
|
@ -2214,7 +2247,7 @@ def _handle_ns(packageName, path_item):
|
|||
if subpath is not None:
|
||||
path = module.__path__
|
||||
path.append(subpath)
|
||||
loader.load_module(packageName)
|
||||
importlib.import_module(packageName)
|
||||
_rebuild_mod_path(path, packageName, module)
|
||||
return subpath
|
||||
|
||||
|
@ -2270,8 +2303,8 @@ def declare_namespace(packageName):
|
|||
__import__(parent)
|
||||
try:
|
||||
path = sys.modules[parent].__path__
|
||||
except AttributeError:
|
||||
raise TypeError("Not a package:", parent)
|
||||
except AttributeError as e:
|
||||
raise TypeError("Not a package:", parent) from e
|
||||
|
||||
# Track what packages are namespaces, so when new path items are added,
|
||||
# they can be updated
|
||||
|
@ -2328,7 +2361,8 @@ register_namespace_handler(object, null_ns_handler)
|
|||
|
||||
def normalize_path(filename):
|
||||
"""Normalize a file/dir name for comparison purposes"""
|
||||
return os.path.normcase(os.path.realpath(os.path.normpath(_cygwin_patch(filename))))
|
||||
return os.path.normcase(os.path.realpath(os.path.normpath(
|
||||
_cygwin_patch(filename))))
|
||||
|
||||
|
||||
def _cygwin_patch(filename): # pragma: nocover
|
||||
|
@ -2354,7 +2388,15 @@ def _is_egg_path(path):
|
|||
"""
|
||||
Determine if given path appears to be an egg.
|
||||
"""
|
||||
return path.lower().endswith('.egg')
|
||||
return _is_zip_egg(path) or _is_unpacked_egg(path)
|
||||
|
||||
|
||||
def _is_zip_egg(path):
|
||||
return (
|
||||
path.lower().endswith('.egg') and
|
||||
os.path.isfile(path) and
|
||||
zipfile.is_zipfile(path)
|
||||
)
|
||||
|
||||
|
||||
def _is_unpacked_egg(path):
|
||||
|
@ -2362,7 +2404,7 @@ def _is_unpacked_egg(path):
|
|||
Determine if given path appears to be an unpacked egg.
|
||||
"""
|
||||
return (
|
||||
_is_egg_path(path) and
|
||||
path.lower().endswith('.egg') and
|
||||
os.path.isfile(os.path.join(path, 'EGG-INFO', 'PKG-INFO'))
|
||||
)
|
||||
|
||||
|
@ -2375,20 +2417,6 @@ def _set_parent_ns(packageName):
|
|||
setattr(sys.modules[parent], name, sys.modules[packageName])
|
||||
|
||||
|
||||
def yield_lines(strs):
|
||||
"""Yield non-empty/non-comment lines of a string or sequence"""
|
||||
if isinstance(strs, six.string_types):
|
||||
for s in strs.splitlines():
|
||||
s = s.strip()
|
||||
# skip blank lines/comments
|
||||
if s and not s.startswith('#'):
|
||||
yield s
|
||||
else:
|
||||
for ss in strs:
|
||||
for s in yield_lines(ss):
|
||||
yield s
|
||||
|
||||
|
||||
MODULE = re.compile(r"\w+(\.\w+)*$").match
|
||||
EGG_NAME = re.compile(
|
||||
r"""
|
||||
|
@ -2450,7 +2478,7 @@ class EntryPoint:
|
|||
try:
|
||||
return functools.reduce(getattr, self.attrs, module)
|
||||
except AttributeError as exc:
|
||||
raise ImportError(str(exc))
|
||||
raise ImportError(str(exc)) from exc
|
||||
|
||||
def require(self, env=None, installer=None):
|
||||
if self.extras and not self.dist:
|
||||
|
@ -2536,15 +2564,6 @@ class EntryPoint:
|
|||
return maps
|
||||
|
||||
|
||||
def _remove_md5_fragment(location):
|
||||
if not location:
|
||||
return ''
|
||||
parsed = urllib.parse.urlparse(location)
|
||||
if parsed[-1].startswith('md5='):
|
||||
return urllib.parse.urlunparse(parsed[:-1] + ('',))
|
||||
return location
|
||||
|
||||
|
||||
def _version_from_file(lines):
|
||||
"""
|
||||
Given an iterable of lines from a Metadata file, return
|
||||
|
@ -2601,7 +2620,7 @@ class Distribution:
|
|||
self.parsed_version,
|
||||
self.precedence,
|
||||
self.key,
|
||||
_remove_md5_fragment(self.location),
|
||||
self.location,
|
||||
self.py_version or '',
|
||||
self.platform or '',
|
||||
)
|
||||
|
@ -2679,14 +2698,14 @@ class Distribution:
|
|||
def version(self):
|
||||
try:
|
||||
return self._version
|
||||
except AttributeError:
|
||||
except AttributeError as e:
|
||||
version = self._get_version()
|
||||
if version is None:
|
||||
path = self._get_metadata_path_for_display(self.PKG_INFO)
|
||||
msg = (
|
||||
"Missing 'Version:' header and/or {} file at path: {}"
|
||||
).format(self.PKG_INFO, path)
|
||||
raise ValueError(msg, self)
|
||||
raise ValueError(msg, self) from e
|
||||
|
||||
return version
|
||||
|
||||
|
@ -2739,10 +2758,10 @@ class Distribution:
|
|||
for ext in extras:
|
||||
try:
|
||||
deps.extend(dm[safe_extra(ext)])
|
||||
except KeyError:
|
||||
except KeyError as e:
|
||||
raise UnknownExtra(
|
||||
"%s has no such extra feature %r" % (self, ext)
|
||||
)
|
||||
) from e
|
||||
return deps
|
||||
|
||||
def _get_metadata_path_for_display(self, name):
|
||||
|
@ -2824,10 +2843,6 @@ class Distribution:
|
|||
)
|
||||
)
|
||||
|
||||
if not hasattr(object, '__dir__'):
|
||||
# python 2.7 not supported
|
||||
del __dir__
|
||||
|
||||
@classmethod
|
||||
def from_filename(cls, filename, metadata=None, **kw):
|
||||
return cls.from_location(
|
||||
|
@ -2867,7 +2882,8 @@ class Distribution:
|
|||
"""Return the EntryPoint object for `group`+`name`, or ``None``"""
|
||||
return self.get_entry_map(group).get(name)
|
||||
|
||||
def insert_on(self, path, loc=None, replace=False):
|
||||
# FIXME: 'Distribution.insert_on' is too complex (13)
|
||||
def insert_on(self, path, loc=None, replace=False): # noqa: C901
|
||||
"""Ensure self.location is on path
|
||||
|
||||
If replace=False (default):
|
||||
|
@ -3037,12 +3053,12 @@ class DistInfoDistribution(Distribution):
|
|||
if not req.marker or req.marker.evaluate({'extra': extra}):
|
||||
yield req
|
||||
|
||||
common = frozenset(reqs_for_extra(None))
|
||||
common = types.MappingProxyType(dict.fromkeys(reqs_for_extra(None)))
|
||||
dm[None].extend(common)
|
||||
|
||||
for extra in self._parsed_pkg_info.get_all('Provides-Extra') or []:
|
||||
s_extra = safe_extra(extra.strip())
|
||||
dm[s_extra] = list(frozenset(reqs_for_extra(extra)) - common)
|
||||
dm[s_extra] = [r for r in reqs_for_extra(extra) if r not in common]
|
||||
|
||||
return dm
|
||||
|
||||
|
@ -3067,40 +3083,23 @@ def issue_warning(*args, **kw):
|
|||
warnings.warn(stacklevel=level + 1, *args, **kw)
|
||||
|
||||
|
||||
class RequirementParseError(ValueError):
|
||||
def __str__(self):
|
||||
return ' '.join(self.args)
|
||||
|
||||
|
||||
def parse_requirements(strs):
|
||||
"""Yield ``Requirement`` objects for each specification in `strs`
|
||||
"""
|
||||
Yield ``Requirement`` objects for each specification in `strs`.
|
||||
|
||||
`strs` must be a string, or a (possibly-nested) iterable thereof.
|
||||
"""
|
||||
# create a steppable iterator, so we can handle \-continuations
|
||||
lines = iter(yield_lines(strs))
|
||||
return map(Requirement, join_continuation(map(drop_comment, yield_lines(strs))))
|
||||
|
||||
for line in lines:
|
||||
# Drop comments -- a hash without a space may be in a URL.
|
||||
if ' #' in line:
|
||||
line = line[:line.find(' #')]
|
||||
# If there is a line continuation, drop it, and append the next line.
|
||||
if line.endswith('\\'):
|
||||
line = line[:-2].strip()
|
||||
try:
|
||||
line += next(lines)
|
||||
except StopIteration:
|
||||
return
|
||||
yield Requirement(line)
|
||||
|
||||
class RequirementParseError(packaging.requirements.InvalidRequirement):
|
||||
"Compatibility wrapper for InvalidRequirement"
|
||||
|
||||
|
||||
class Requirement(packaging.requirements.Requirement):
|
||||
def __init__(self, requirement_string):
|
||||
"""DO NOT CALL THIS UNDOCUMENTED METHOD; use Requirement.parse()!"""
|
||||
try:
|
||||
super(Requirement, self).__init__(requirement_string)
|
||||
except packaging.requirements.InvalidRequirement as e:
|
||||
raise RequirementParseError(str(e))
|
||||
super(Requirement, self).__init__(requirement_string)
|
||||
self.unsafe_name = self.name
|
||||
project_name = safe_name(self.name)
|
||||
self.project_name, self.key = project_name, project_name.lower()
|
||||
|
@ -3170,7 +3169,7 @@ def _find_adapter(registry, ob):
|
|||
def ensure_directory(path):
|
||||
"""Ensure that the parent directory of `path` exists"""
|
||||
dirname = os.path.dirname(path)
|
||||
py31compat.makedirs(dirname, exist_ok=True)
|
||||
os.makedirs(dirname, exist_ok=True)
|
||||
|
||||
|
||||
def _bypass_ensure_directory(path):
|
||||
|
@ -3248,6 +3247,15 @@ def _initialize(g=globals()):
|
|||
)
|
||||
|
||||
|
||||
class PkgResourcesDeprecationWarning(Warning):
|
||||
"""
|
||||
Base class for warning about deprecations in ``pkg_resources``
|
||||
|
||||
This class is not derived from ``DeprecationWarning``, and as such is
|
||||
visible by default.
|
||||
"""
|
||||
|
||||
|
||||
@_call_aside
|
||||
def _initialize_master_working_set():
|
||||
"""
|
||||
|
@ -3286,11 +3294,3 @@ def _initialize_master_working_set():
|
|||
# match order
|
||||
list(map(working_set.add_entry, sys.path))
|
||||
globals().update(locals())
|
||||
|
||||
class PkgResourcesDeprecationWarning(Warning):
|
||||
"""
|
||||
Base class for warning about deprecations in ``pkg_resources``
|
||||
|
||||
This class is not derived from ``DeprecationWarning``, and as such is
|
||||
visible by default.
|
||||
"""
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
import os
|
||||
import errno
|
||||
import sys
|
||||
|
||||
from pip._vendor import six
|
||||
|
||||
|
||||
def _makedirs_31(path, exist_ok=False):
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except OSError as exc:
|
||||
if not exist_ok or exc.errno != errno.EEXIST:
|
||||
raise
|
||||
|
||||
|
||||
# rely on compatibility behavior until mode considerations
|
||||
# and exists_ok considerations are disentangled.
|
||||
# See https://github.com/pypa/setuptools/pull/1083#issuecomment-315168663
|
||||
needs_makedirs = (
|
||||
six.PY2 or
|
||||
(3, 4) <= sys.version_info < (3, 4, 1)
|
||||
)
|
||||
makedirs = _makedirs_31 if needs_makedirs else os.makedirs
|
|
@ -16,7 +16,7 @@ rich==12.6.0
|
|||
pygments==2.13.0
|
||||
typing_extensions==4.4.0
|
||||
resolvelib==0.8.1
|
||||
setuptools==44.0.0
|
||||
setuptools==65.6.3
|
||||
six==1.16.0
|
||||
tenacity==8.1.0
|
||||
tomli==2.0.1
|
||||
|
|
|
@ -1,22 +1,35 @@
|
|||
diff --git a/src/pip/_vendor/pkg_resources/__init__.py b/src/pip/_vendor/pkg_resources/__init__.py
|
||||
index a457ff27e..4cd562cf9 100644
|
||||
index d59226af9..3b9565893 100644
|
||||
--- a/src/pip/_vendor/pkg_resources/__init__.py
|
||||
+++ b/src/pip/_vendor/pkg_resources/__init__.py
|
||||
@@ -77,7 +77,7 @@ except ImportError:
|
||||
importlib_machinery = None
|
||||
@@ -77,7 +77,7 @@
|
||||
join_continuation,
|
||||
)
|
||||
|
||||
from . import py31compat
|
||||
-from pkg_resources.extern import appdirs
|
||||
+from pkg_resources.extern import platformdirs
|
||||
from pkg_resources.extern import packaging
|
||||
__import__('pkg_resources.extern.packaging.version')
|
||||
__import__('pkg_resources.extern.packaging.specifiers')
|
||||
@@ -1310,7 +1310,7 @@ def get_default_cache():
|
||||
@@ -1321,7 +1321,7 @@ def get_default_cache():
|
||||
"""
|
||||
return (
|
||||
os.environ.get('PYTHON_EGG_CACHE')
|
||||
- or appdirs.user_cache_dir(appname='Python-Eggs')
|
||||
+ or platformdirs.user_cache_dir(appname='Python-Eggs')
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
diff --git a/src/pip/_vendor/pkg_resources/__init__.py b/src/pip/_vendor/pkg_resources/__init__.py
|
||||
index 3f2476a0c..8d5727d35 100644
|
||||
--- a/src/pip/_vendor/pkg_resources/__init__.py
|
||||
+++ b/src/pip/_vendor/pkg_resources/__init__.py
|
||||
@@ -71,7 +71,7 @@
|
||||
except ImportError:
|
||||
importlib_machinery = None
|
||||
|
||||
-from pkg_resources.extern.jaraco.text import (
|
||||
+from pip._internal.utils._jaraco_text import (
|
||||
yield_lines,
|
||||
drop_comment,
|
||||
join_continuation,
|
||||
|
|
Loading…
Reference in New Issue