summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Pierre <benoit.pierre@gmail.com>2022-07-03 21:10:01 +0000
committerGitHub <noreply@github.com>2022-07-03 21:10:01 +0000
commitd680efc8b4cd9aa388d07d3e298b870d26e9e04b (patch)
treea00f19970c7d27863a93cf48568c5f16da555fa5
parent641cb8955923f5b23c5be7cdd3edb7427c40995c (diff)
parentdc64dfdb42d72f86b26ab592b1a71c91c9f2be70 (diff)
downloadpython-setuptools-git-d680efc8b4cd9aa388d07d3e298b870d26e9e04b.tar.gz
Merge pull request #3421 from benoit-pierre/pr/fix_60.8.0+_performance
Drop support for installing dependencies when resolving distutils commands
-rw-r--r--changelog.d/3421.breaking.rst4
-rw-r--r--setuptools/_vendor/nspektr-0.3.0.dist-info/INSTALLER1
-rw-r--r--setuptools/_vendor/nspektr-0.3.0.dist-info/LICENSE19
-rw-r--r--setuptools/_vendor/nspektr-0.3.0.dist-info/METADATA57
-rw-r--r--setuptools/_vendor/nspektr-0.3.0.dist-info/RECORD11
-rw-r--r--setuptools/_vendor/nspektr-0.3.0.dist-info/REQUESTED0
-rw-r--r--setuptools/_vendor/nspektr-0.3.0.dist-info/WHEEL5
-rw-r--r--setuptools/_vendor/nspektr-0.3.0.dist-info/top_level.txt1
-rw-r--r--setuptools/_vendor/nspektr/__init__.py145
-rw-r--r--setuptools/_vendor/nspektr/_compat.py21
-rw-r--r--setuptools/_vendor/vendored.txt1
-rw-r--r--setuptools/command/egg_info.py1
-rw-r--r--setuptools/dist.py12
-rw-r--r--setuptools/extern/__init__.py2
-rw-r--r--setuptools/tests/test_easy_install.py77
-rw-r--r--tools/vendored.py11
16 files changed, 79 insertions, 289 deletions
diff --git a/changelog.d/3421.breaking.rst b/changelog.d/3421.breaking.rst
new file mode 100644
index 00000000..003e6d33
--- /dev/null
+++ b/changelog.d/3421.breaking.rst
@@ -0,0 +1,4 @@
+Drop setuptools' support for installing an entrypoint extra requirements at load time:
+- the functionality has been broken since v60.8.0.
+- the mechanism to do so is deprecated (`fetch_build_eggs`).
+- that use case (e.g. a custom command class entrypoint) is covered by making sure the necessary build requirements are declared.
diff --git a/setuptools/_vendor/nspektr-0.3.0.dist-info/INSTALLER b/setuptools/_vendor/nspektr-0.3.0.dist-info/INSTALLER
deleted file mode 100644
index a1b589e3..00000000
--- a/setuptools/_vendor/nspektr-0.3.0.dist-info/INSTALLER
+++ /dev/null
@@ -1 +0,0 @@
-pip
diff --git a/setuptools/_vendor/nspektr-0.3.0.dist-info/LICENSE b/setuptools/_vendor/nspektr-0.3.0.dist-info/LICENSE
deleted file mode 100644
index 353924be..00000000
--- a/setuptools/_vendor/nspektr-0.3.0.dist-info/LICENSE
+++ /dev/null
@@ -1,19 +0,0 @@
-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.
diff --git a/setuptools/_vendor/nspektr-0.3.0.dist-info/METADATA b/setuptools/_vendor/nspektr-0.3.0.dist-info/METADATA
deleted file mode 100644
index aadc3749..00000000
--- a/setuptools/_vendor/nspektr-0.3.0.dist-info/METADATA
+++ /dev/null
@@ -1,57 +0,0 @@
-Metadata-Version: 2.1
-Name: nspektr
-Version: 0.3.0
-Summary: package inspector
-Home-page: https://github.com/jaraco/nspektr
-Author: Jason R. Coombs
-Author-email: jaraco@jaraco.com
-License: UNKNOWN
-Platform: UNKNOWN
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: MIT License
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3 :: Only
-Requires-Python: >=3.7
-License-File: LICENSE
-Requires-Dist: jaraco.context
-Requires-Dist: jaraco.functools
-Requires-Dist: more-itertools
-Requires-Dist: packaging
-Requires-Dist: importlib-metadata (>=3.6) ; python_version < "3.10"
-Provides-Extra: docs
-Requires-Dist: sphinx ; extra == 'docs'
-Requires-Dist: jaraco.packaging (>=9) ; extra == 'docs'
-Requires-Dist: rst.linker (>=1.9) ; extra == 'docs'
-Provides-Extra: testing
-Requires-Dist: pytest (>=6) ; extra == 'testing'
-Requires-Dist: pytest-checkdocs (>=2.4) ; extra == 'testing'
-Requires-Dist: pytest-flake8 ; extra == 'testing'
-Requires-Dist: pytest-cov ; extra == 'testing'
-Requires-Dist: pytest-enabler (>=1.0.1) ; extra == 'testing'
-Requires-Dist: pytest-black (>=0.3.7) ; (platform_python_implementation != "PyPy") and extra == 'testing'
-Requires-Dist: pytest-mypy (>=0.9.1) ; (platform_python_implementation != "PyPy") and extra == 'testing'
-
-.. image:: https://img.shields.io/pypi/v/nspektr.svg
- :target: `PyPI link`_
-
-.. image:: https://img.shields.io/pypi/pyversions/nspektr.svg
- :target: `PyPI link`_
-
-.. _PyPI link: https://pypi.org/project/nspektr
-
-.. image:: https://github.com/jaraco/nspektr/workflows/tests/badge.svg
- :target: https://github.com/jaraco/nspektr/actions?query=workflow%3A%22tests%22
- :alt: tests
-
-.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
- :target: https://github.com/psf/black
- :alt: Code style: Black
-
-.. .. image:: https://readthedocs.org/projects/skeleton/badge/?version=latest
-.. :target: https://skeleton.readthedocs.io/en/latest/?badge=latest
-
-.. image:: https://img.shields.io/badge/skeleton-2022-informational
- :target: https://blog.jaraco.com/skeleton
-
-
diff --git a/setuptools/_vendor/nspektr-0.3.0.dist-info/RECORD b/setuptools/_vendor/nspektr-0.3.0.dist-info/RECORD
deleted file mode 100644
index 5e5de5eb..00000000
--- a/setuptools/_vendor/nspektr-0.3.0.dist-info/RECORD
+++ /dev/null
@@ -1,11 +0,0 @@
-nspektr-0.3.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
-nspektr-0.3.0.dist-info/LICENSE,sha256=2z8CRrH5J48VhFuZ_sR4uLUG63ZIeZNyL4xuJUKF-vg,1050
-nspektr-0.3.0.dist-info/METADATA,sha256=X0stV4vwFBDBxvzhBl4kAHVdGWPIjEitqAuTJItcQH0,2162
-nspektr-0.3.0.dist-info/RECORD,,
-nspektr-0.3.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
-nspektr-0.3.0.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
-nspektr-0.3.0.dist-info/top_level.txt,sha256=uEA20Ixo04XS3wOIt5-Jk5ZuMkBrtlleFipRr8Y1SjQ,8
-nspektr/__init__.py,sha256=d6-d-ZlGAQQP-MEi_NZMiyn2vLbq8Hw3HxICgm3X0Q8,3949
-nspektr/__pycache__/__init__.cpython-310.pyc,,
-nspektr/__pycache__/_compat.cpython-310.pyc,,
-nspektr/_compat.py,sha256=2QoozYhuhgow_NMUATmhoM-yppBV3jiZYQgdiP-ww0s,582
diff --git a/setuptools/_vendor/nspektr-0.3.0.dist-info/REQUESTED b/setuptools/_vendor/nspektr-0.3.0.dist-info/REQUESTED
deleted file mode 100644
index e69de29b..00000000
--- a/setuptools/_vendor/nspektr-0.3.0.dist-info/REQUESTED
+++ /dev/null
diff --git a/setuptools/_vendor/nspektr-0.3.0.dist-info/WHEEL b/setuptools/_vendor/nspektr-0.3.0.dist-info/WHEEL
deleted file mode 100644
index becc9a66..00000000
--- a/setuptools/_vendor/nspektr-0.3.0.dist-info/WHEEL
+++ /dev/null
@@ -1,5 +0,0 @@
-Wheel-Version: 1.0
-Generator: bdist_wheel (0.37.1)
-Root-Is-Purelib: true
-Tag: py3-none-any
-
diff --git a/setuptools/_vendor/nspektr-0.3.0.dist-info/top_level.txt b/setuptools/_vendor/nspektr-0.3.0.dist-info/top_level.txt
deleted file mode 100644
index b10ef50a..00000000
--- a/setuptools/_vendor/nspektr-0.3.0.dist-info/top_level.txt
+++ /dev/null
@@ -1 +0,0 @@
-nspektr
diff --git a/setuptools/_vendor/nspektr/__init__.py b/setuptools/_vendor/nspektr/__init__.py
deleted file mode 100644
index 938bbdb9..00000000
--- a/setuptools/_vendor/nspektr/__init__.py
+++ /dev/null
@@ -1,145 +0,0 @@
-import itertools
-import functools
-import contextlib
-
-from setuptools.extern.packaging.requirements import Requirement
-from setuptools.extern.packaging.version import Version
-from setuptools.extern.more_itertools import always_iterable
-from setuptools.extern.jaraco.context import suppress
-from setuptools.extern.jaraco.functools import apply
-
-from ._compat import metadata, repair_extras
-
-
-def resolve(req: Requirement) -> metadata.Distribution:
- """
- Resolve the requirement to its distribution.
-
- Ignore exception detail for Python 3.9 compatibility.
-
- >>> resolve(Requirement('pytest<3')) # doctest: +IGNORE_EXCEPTION_DETAIL
- Traceback (most recent call last):
- ...
- importlib.metadata.PackageNotFoundError: No package metadata was found for pytest<3
- """
- dist = metadata.distribution(req.name)
- if not req.specifier.contains(Version(dist.version), prereleases=True):
- raise metadata.PackageNotFoundError(str(req))
- dist.extras = req.extras # type: ignore
- return dist
-
-
-@apply(bool)
-@suppress(metadata.PackageNotFoundError)
-def is_satisfied(req: Requirement):
- return resolve(req)
-
-
-unsatisfied = functools.partial(itertools.filterfalse, is_satisfied)
-
-
-class NullMarker:
- @classmethod
- def wrap(cls, req: Requirement):
- return req.marker or cls()
-
- def evaluate(self, *args, **kwargs):
- return True
-
-
-def find_direct_dependencies(dist, extras=None):
- """
- Find direct, declared dependencies for dist.
- """
- simple = (
- req
- for req in map(Requirement, always_iterable(dist.requires))
- if NullMarker.wrap(req).evaluate(dict(extra=None))
- )
- extra_deps = (
- req
- for req in map(Requirement, always_iterable(dist.requires))
- for extra in always_iterable(getattr(dist, 'extras', extras))
- if NullMarker.wrap(req).evaluate(dict(extra=extra))
- )
- return itertools.chain(simple, extra_deps)
-
-
-def traverse(items, visit):
- """
- Given an iterable of items, traverse the items.
-
- For each item, visit is called to return any additional items
- to include in the traversal.
- """
- while True:
- try:
- item = next(items)
- except StopIteration:
- return
- yield item
- items = itertools.chain(items, visit(item))
-
-
-def find_req_dependencies(req):
- with contextlib.suppress(metadata.PackageNotFoundError):
- dist = resolve(req)
- yield from find_direct_dependencies(dist)
-
-
-def find_dependencies(dist, extras=None):
- """
- Find all reachable dependencies for dist.
-
- dist is an importlib.metadata.Distribution (or similar).
- TODO: create a suitable protocol for type hint.
-
- >>> deps = find_dependencies(resolve(Requirement('nspektr')))
- >>> all(isinstance(dep, Requirement) for dep in deps)
- True
- >>> not any('pytest' in str(dep) for dep in deps)
- True
- >>> test_deps = find_dependencies(resolve(Requirement('nspektr[testing]')))
- >>> any('pytest' in str(dep) for dep in test_deps)
- True
- """
-
- def visit(req, seen=set()):
- if req in seen:
- return ()
- seen.add(req)
- return find_req_dependencies(req)
-
- return traverse(find_direct_dependencies(dist, extras), visit)
-
-
-class Unresolved(Exception):
- def __iter__(self):
- return iter(self.args[0])
-
-
-def missing(ep):
- """
- Generate the unresolved dependencies (if any) of ep.
- """
- return unsatisfied(find_dependencies(ep.dist, repair_extras(ep.extras)))
-
-
-def check(ep):
- """
- >>> ep, = metadata.entry_points(group='console_scripts', name='pip')
- >>> check(ep)
- >>> dist = metadata.distribution('nspektr')
-
- Since 'docs' extras are not installed, requesting them should fail.
-
- >>> ep = metadata.EntryPoint(
- ... group=None, name=None, value='nspektr [docs]')._for(dist)
- >>> check(ep)
- Traceback (most recent call last):
- ...
- nspektr.Unresolved: [...]
- """
- missed = list(missing(ep))
- if missed:
- raise Unresolved(missed)
diff --git a/setuptools/_vendor/nspektr/_compat.py b/setuptools/_vendor/nspektr/_compat.py
deleted file mode 100644
index 3278379a..00000000
--- a/setuptools/_vendor/nspektr/_compat.py
+++ /dev/null
@@ -1,21 +0,0 @@
-import contextlib
-import sys
-
-
-if sys.version_info >= (3, 10):
- import importlib.metadata as metadata
-else:
- import setuptools.extern.importlib_metadata as metadata # type: ignore # noqa: F401
-
-
-def repair_extras(extras):
- """
- Repair extras that appear as match objects.
-
- python/importlib_metadata#369 revealed a flaw in the EntryPoint
- implementation. This function wraps the extras to ensure
- they are proper strings even on older implementations.
- """
- with contextlib.suppress(AttributeError):
- return list(item.group(0) for item in extras)
- return extras
diff --git a/setuptools/_vendor/vendored.txt b/setuptools/_vendor/vendored.txt
index 95de2dc5..84c4006c 100644
--- a/setuptools/_vendor/vendored.txt
+++ b/setuptools/_vendor/vendored.txt
@@ -5,7 +5,6 @@ more_itertools==8.8.0
jaraco.text==3.7.0
importlib_resources==5.4.0
importlib_metadata==4.11.1
-nspektr==0.3.0
# required for importlib_metadata on older Pythons
typing_extensions==4.0.1
# required for importlib_resources and _metadata on older Pythons
diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py
index c37ab81f..42a0178f 100644
--- a/setuptools/command/egg_info.py
+++ b/setuptools/command/egg_info.py
@@ -296,7 +296,6 @@ class egg_info(InfoCommon, Command):
self.mkpath(self.egg_info)
os.utime(self.egg_info, None)
for ep in metadata.entry_points(group='egg_info.writers'):
- self.distribution._install_dependencies(ep)
writer = ep.load()
writer(self, ep.name, os.path.join(self.egg_info, ep.name))
diff --git a/setuptools/dist.py b/setuptools/dist.py
index c1ad3008..82423548 100644
--- a/setuptools/dist.py
+++ b/setuptools/dist.py
@@ -30,7 +30,6 @@ from distutils.util import rfc822_escape
from setuptools.extern import packaging
from setuptools.extern import ordered_set
from setuptools.extern.more_itertools import unique_everseen, partition
-from setuptools.extern import nspektr
from ._importlib import metadata
@@ -918,18 +917,8 @@ class Distribution(_Distribution):
for ep in metadata.entry_points(group='distutils.setup_keywords'):
value = getattr(self, ep.name, None)
if value is not None:
- self._install_dependencies(ep)
ep.load()(self, ep.name, value)
- def _install_dependencies(self, ep):
- """
- Given an entry point, ensure that any declared extras for
- its distribution are installed.
- """
- for req in nspektr.missing(ep):
- # fetch_build_egg expects pkg_resources.Requirement
- self.fetch_build_egg(pkg_resources.Requirement(str(req)))
-
def get_egg_cache_dir(self):
egg_cache_dir = os.path.join(os.curdir, '.eggs')
if not os.path.exists(egg_cache_dir):
@@ -962,7 +951,6 @@ class Distribution(_Distribution):
eps = metadata.entry_points(group='distutils.commands', name=command)
for ep in eps:
- self._install_dependencies(ep)
self.cmdclass[command] = cmdclass = ep.load()
return cmdclass
else:
diff --git a/setuptools/extern/__init__.py b/setuptools/extern/__init__.py
index 192e55f6..d3a6dc99 100644
--- a/setuptools/extern/__init__.py
+++ b/setuptools/extern/__init__.py
@@ -71,6 +71,6 @@ class VendorImporter:
names = (
'packaging', 'pyparsing', 'ordered_set', 'more_itertools', 'importlib_metadata',
- 'zipp', 'importlib_resources', 'jaraco', 'typing_extensions', 'nspektr', 'tomli',
+ 'zipp', 'importlib_resources', 'jaraco', 'typing_extensions', 'tomli',
)
VendorImporter(__name__, names, 'setuptools._vendor').install()
diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py
index 246d634f..d102e586 100644
--- a/setuptools/tests/test_easy_install.py
+++ b/setuptools/tests/test_easy_install.py
@@ -846,9 +846,11 @@ class TestSetupRequires:
def test_setup_requires_with_transitive_extra_dependency(
self, monkeypatch):
- # Use case: installing a package with a build dependency on
- # an already installed `dep[extra]`, which in turn depends
- # on `extra_dep` (whose is not already installed).
+ '''
+ Use case: installing a package with a build dependency on
+ an already installed `dep[extra]`, which in turn depends
+ on `extra_dep` (whose is not already installed).
+ '''
with contexts.save_pkg_resources_state():
with contexts.tempdir() as temp_dir:
# Create source distribution for `extra_dep`.
@@ -890,6 +892,75 @@ class TestSetupRequires:
monkeypatch.setenv(str('PIP_TIMEOUT'), str('0'))
run_setup(test_setup_py, [str('--version')])
+ def test_setup_requires_with_distutils_command_dep(self, monkeypatch):
+ '''
+ Use case: ensure build requirements' extras
+ are properly installed and activated.
+ '''
+ with contexts.save_pkg_resources_state():
+ with contexts.tempdir() as temp_dir:
+ # Create source distribution for `extra_dep`.
+ make_sdist(os.path.join(temp_dir, 'extra_dep-1.0.tar.gz'), [
+ ('setup.py',
+ DALS("""
+ import setuptools
+ setuptools.setup(
+ name='extra_dep',
+ version='1.0',
+ py_modules=['extra_dep'],
+ )
+ """)),
+ ('setup.cfg', ''),
+ ('extra_dep.py', ''),
+ ])
+ # Create source tree for `epdep`.
+ dep_pkg = os.path.join(temp_dir, 'epdep')
+ os.mkdir(dep_pkg)
+ path.build({
+ 'setup.py':
+ DALS("""
+ import setuptools
+ setuptools.setup(
+ name='dep', version='2.0',
+ py_modules=['epcmd'],
+ extras_require={'extra': ['extra_dep']},
+ entry_points='''
+ [distutils.commands]
+ epcmd = epcmd:epcmd [extra]
+ ''',
+ )
+ """),
+ 'setup.cfg': '',
+ 'epcmd.py': DALS("""
+ from distutils.command.build_py import build_py
+
+ import extra_dep
+
+ class epcmd(build_py):
+ pass
+ """),
+ }, prefix=dep_pkg)
+ # "Install" dep.
+ run_setup(
+ os.path.join(dep_pkg, 'setup.py'), [str('dist_info')])
+ working_set.add_entry(dep_pkg)
+ # Create source tree for test package.
+ test_pkg = os.path.join(temp_dir, 'test_pkg')
+ test_setup_py = os.path.join(test_pkg, 'setup.py')
+ os.mkdir(test_pkg)
+ with open(test_setup_py, 'w') as fp:
+ fp.write(DALS(
+ '''
+ from setuptools import installer, setup
+ setup(setup_requires='dep[extra]')
+ '''))
+ # Check...
+ monkeypatch.setenv(str('PIP_FIND_LINKS'), str(temp_dir))
+ monkeypatch.setenv(str('PIP_NO_INDEX'), str('1'))
+ monkeypatch.setenv(str('PIP_RETRIES'), str('0'))
+ monkeypatch.setenv(str('PIP_TIMEOUT'), str('0'))
+ run_setup(test_setup_py, ['epcmd'])
+
def make_trivial_sdist(dist_path, distname, version):
"""
diff --git a/tools/vendored.py b/tools/vendored.py
index cd15adbf..8a122ad7 100644
--- a/tools/vendored.py
+++ b/tools/vendored.py
@@ -89,16 +89,6 @@ def rewrite_more_itertools(pkg_files: Path):
more_file.write_text(text)
-def rewrite_nspektr(pkg_files: Path, new_root):
- for file in pkg_files.glob('*.py'):
- text = file.read_text()
- text = re.sub(r' (more_itertools)', rf' {new_root}.\1', text)
- text = re.sub(r' (jaraco\.\w+)', rf' {new_root}.\1', text)
- text = re.sub(r' (packaging)', rf' {new_root}.\1', text)
- text = re.sub(r' (importlib_metadata)', rf' {new_root}.\1', text)
- file.write_text(text)
-
-
def clean(vendor):
"""
Remove all files out of the vendor directory except the meta
@@ -143,7 +133,6 @@ def update_setuptools():
rewrite_importlib_resources(vendor / 'importlib_resources', 'setuptools.extern')
rewrite_importlib_metadata(vendor / 'importlib_metadata', 'setuptools.extern')
rewrite_more_itertools(vendor / "more_itertools")
- rewrite_nspektr(vendor / "nspektr", 'setuptools.extern')
__name__ == '__main__' and update_vendored()