diff options
| author | Anderson Bravalheri <andersonbravalheri@gmail.com> | 2022-03-16 15:51:11 +0000 |
|---|---|---|
| committer | Anderson Bravalheri <andersonbravalheri@gmail.com> | 2022-03-16 15:51:11 +0000 |
| commit | a70240af2c4eade71f2900cc0fba9369939b2cd4 (patch) | |
| tree | 04c260eedf6599056bb0c37061b9ee1086b7cd96 | |
| parent | 4d3b445d5a53bda3424aac273e80e51e92a08b2c (diff) | |
| parent | 02f3821b9af91feadae2326b78a814ac2fbbe520 (diff) | |
| download | python-setuptools-git-a70240af2c4eade71f2900cc0fba9369939b2cd4.tar.gz | |
Merge branch 'main' into experimental/support-pyproject
31 files changed, 387 insertions, 83 deletions
diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 79260da6..fd32042d 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 60.9.3 +current_version = 60.10.0 commit = True tag = True diff --git a/CHANGES.rst b/CHANGES.rst index a24cd2ad..3c724e47 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,39 @@ +v60.10.0 +-------- + + +Changes +^^^^^^^ +* #2971: Deprecated upload_docs command, to be removed in the future. +* #3137: Use samefile from stdlib, supported on Windows since Python 3.2. +* #3170: Adopt nspektr (vendored) to implement Distribution._install_dependencies. + +Documentation changes +^^^^^^^^^^^^^^^^^^^^^ +* #3144: Added documentation on using console_scripts from setup.py, which was previously only shown in setup.cfg -- by :user:`xhlulu` +* #3148: Added clarifications about ``MANIFEST.in``, that include links to PyPUG docs + and more prominent mentions to using a revision control system plugin as an + alternative. +* #3148: Removed mention to ``pkg_resources`` as the recommended way of accessing data + files, in favour of :doc:`importlib.resources`. + Additionally more emphasis was put on the fact that *package data files* reside + **inside** the *package directory* (and therefore should be *read-only*). + +Misc +^^^^ +* #3120: Added workaround for intermittent failures of backend tests on PyPy. + These tests now are marked with `XFAIL + <https://docs.pytest.org/en/stable/how-to/skipping.html>`_, instead of erroring + out directly. +* #3124: Improved configuration for :pypi:`rst-linker` (extension used to build the + changelog). +* #3133: Enhanced isolation of tests using virtual environments - PYTHONPATH is not leaking to spawned subprocesses -- by :user:`befeleme` +* #3147: Added options to provide a pre-built ``setuptools`` wheel or sdist for being + used during tests with virtual environments. + Paths for these pre-built distribution files can now be set via the environment + variables: ``PRE_BUILT_SETUPTOOLS_SDIST`` and ``PRE_BUILT_SETUPTOOLS_WHEEL``. + + v60.9.3 ------- diff --git a/changelog.d/2971.change.rst b/changelog.d/2971.change.rst deleted file mode 100644 index b9a093b4..00000000 --- a/changelog.d/2971.change.rst +++ /dev/null @@ -1 +0,0 @@ -Deprecated upload_docs command, to be removed in the future. diff --git a/changelog.d/3120.misc.rst b/changelog.d/3120.misc.rst deleted file mode 100644 index 3531a0ab..00000000 --- a/changelog.d/3120.misc.rst +++ /dev/null @@ -1,4 +0,0 @@ -Added workaround for intermittent failures of backend tests on PyPy. -These tests now are marked with `XFAIL -<https://docs.pytest.org/en/stable/how-to/skipping.html>`_, instead of erroring -out directly. diff --git a/changelog.d/3124.misc.rst b/changelog.d/3124.misc.rst deleted file mode 100644 index aba19b80..00000000 --- a/changelog.d/3124.misc.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improved configuration for :pypi:`rst-linker` (extension used to build the -changelog). diff --git a/changelog.d/3133.misc.rst b/changelog.d/3133.misc.rst deleted file mode 100644 index 3377e061..00000000 --- a/changelog.d/3133.misc.rst +++ /dev/null @@ -1 +0,0 @@ -Enhanced isolation of tests using virtual environments - PYTHONPATH is not leaking to spawned subprocesses -- by :user:`befeleme` diff --git a/changelog.d/3137.change.rst b/changelog.d/3137.change.rst deleted file mode 100644 index e4186054..00000000 --- a/changelog.d/3137.change.rst +++ /dev/null @@ -1 +0,0 @@ -Use samefile from stdlib, supported on Windows since Python 3.2. diff --git a/changelog.d/3148.doc.1.rst b/changelog.d/3148.doc.1.rst deleted file mode 100644 index af89bde2..00000000 --- a/changelog.d/3148.doc.1.rst +++ /dev/null @@ -1,3 +0,0 @@ -Added clarifications about ``MANIFEST.in``, that include links to PyPUG docs -and more prominent mentions to using a revision control system plugin as an -alternative. diff --git a/changelog.d/3148.doc.2.rst b/changelog.d/3148.doc.2.rst deleted file mode 100644 index f46fb248..00000000 --- a/changelog.d/3148.doc.2.rst +++ /dev/null @@ -1,4 +0,0 @@ -Removed mention to ``pkg_resources`` as the recommended way of accessing data -files, in favour of :doc:`importlib.resources`. -Additionally more emphasis was put on the fact that *package data files* reside -**inside** the *package directory* (and therefore should be *read-only*). diff --git a/docs/conf.py b/docs/conf.py index 7f66483a..9b4841d1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -206,6 +206,7 @@ favicons = [ intersphinx_mapping['pip'] = 'https://pip.pypa.io/en/latest', None intersphinx_mapping['PyPUG'] = ('https://packaging.python.org/en/latest/', None) +intersphinx_mapping['packaging'] = ('https://packaging.pypa.io/en/latest/', None) intersphinx_mapping['importlib-resources'] = ( 'https://importlib-resources.readthedocs.io/en/latest', None ) diff --git a/docs/deprecated/distutils-legacy.rst b/docs/deprecated/distutils-legacy.rst index 148dc259..e73cdff5 100644 --- a/docs/deprecated/distutils-legacy.rst +++ b/docs/deprecated/distutils-legacy.rst @@ -3,11 +3,10 @@ Porting from Distutils Setuptools and the PyPA have a `stated goal <https://github.com/pypa/packaging-problems/issues/127>`_ to make Setuptools the reference API for distutils. -Since the 49.1.2 release, Setuptools includes a local, vendored copy of distutils (from late copies of CPython) that is disabled by default. To enable the use of this copy of distutils when invoking setuptools, set the enviroment variable: +Since the 60.0.0 release, Setuptools includes a local, vendored copy of distutils (from late copies of CPython) that is enabled by default. To disable the use of this copy of distutils when invoking setuptools, set the enviroment variable: - SETUPTOOLS_USE_DISTUTILS=local + SETUPTOOLS_USE_DISTUTILS=stdlib -This behavior is planned to become the default. Prefer Setuptools ----------------- @@ -20,12 +19,15 @@ As Distutils is deprecated, any usage of functions or objects from distutils is ``distutils.command.{build_clib,build_ext,build_py,sdist}`` → ``setuptools.command.*`` -``distutils.log`` → (no replacement yet) +``distutils.log`` → :mod:`logging` (standard library) -``distutils.version.*`` → ``packaging.version.*`` +``distutils.version.*`` → :doc:`packaging.version.* <packaging:version>` ``distutils.errors.*`` → ``setuptools.errors.*`` [#errors]_ + +Migration advice is also provided by :pep:`PEP 632 <632#migration-advice>`. + If a project relies on uses of ``distutils`` that do not have a suitable replacement above, please search the `Setuptools issue tracker <https://github.com/pypa/setuptools/issues/>`_ and file a request, describing the use-case so that Setuptools' maintainers can investigate. Please provide enough detail to help the maintainers understand how distutils is used, what value it provides, and why that behavior should be supported. diff --git a/docs/userguide/entry_point.rst b/docs/userguide/entry_point.rst index 21edc697..ea73bb5e 100644 --- a/docs/userguide/entry_point.rst +++ b/docs/userguide/entry_point.rst @@ -54,11 +54,32 @@ above example, to create a command ``hello-world`` that invokes ``timmins.hello_world``, add a console script entry point to ``setup.cfg``: -.. code-block:: ini +.. tab:: setup.cfg + + .. code-block:: ini + + [options.entry_points] + console_scripts = + hello-world = timmins:hello_world + +.. tab:: setup.py + + .. code-block:: python + + from setuptools import setup + + setup( + name='timmins', + version='0.0.1', + packages=['timmins'], + # ... + entry_points={ + 'console_scripts': [ + 'hello-world=timmins:hello_world', + ] + } + ) - [options.entry_points] - console_scripts = - hello-world = timmins:hello_world After installing the package, a user may invoke that function by simply calling ``hello-world`` on the command line. @@ -1,6 +1,6 @@ [metadata] name = setuptools -version = 60.9.3 +version = 60.10.0 author = Python Packaging Authority author_email = distutils-sig@python.org description = Easily download, build, install, upgrade, and uninstall Python packages diff --git a/setuptools/_vendor/nspektr-0.3.0.dist-info/INSTALLER b/setuptools/_vendor/nspektr-0.3.0.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/setuptools/_vendor/nspektr-0.3.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/setuptools/_vendor/nspektr-0.3.0.dist-info/LICENSE b/setuptools/_vendor/nspektr-0.3.0.dist-info/LICENSE new file mode 100644 index 00000000..353924be --- /dev/null +++ b/setuptools/_vendor/nspektr-0.3.0.dist-info/LICENSE @@ -0,0 +1,19 @@ +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 new file mode 100644 index 00000000..aadc3749 --- /dev/null +++ b/setuptools/_vendor/nspektr-0.3.0.dist-info/METADATA @@ -0,0 +1,57 @@ +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 new file mode 100644 index 00000000..5e5de5eb --- /dev/null +++ b/setuptools/_vendor/nspektr-0.3.0.dist-info/RECORD @@ -0,0 +1,11 @@ +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 new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/setuptools/_vendor/nspektr-0.3.0.dist-info/REQUESTED diff --git a/setuptools/_vendor/nspektr-0.3.0.dist-info/WHEEL b/setuptools/_vendor/nspektr-0.3.0.dist-info/WHEEL new file mode 100644 index 00000000..becc9a66 --- /dev/null +++ b/setuptools/_vendor/nspektr-0.3.0.dist-info/WHEEL @@ -0,0 +1,5 @@ +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 new file mode 100644 index 00000000..b10ef50a --- /dev/null +++ b/setuptools/_vendor/nspektr-0.3.0.dist-info/top_level.txt @@ -0,0 +1 @@ +nspektr diff --git a/setuptools/_vendor/nspektr/__init__.py b/setuptools/_vendor/nspektr/__init__.py new file mode 100644 index 00000000..938bbdb9 --- /dev/null +++ b/setuptools/_vendor/nspektr/__init__.py @@ -0,0 +1,145 @@ +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 new file mode 100644 index 00000000..3278379a --- /dev/null +++ b/setuptools/_vendor/nspektr/_compat.py @@ -0,0 +1,21 @@ +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 21054883..cf0e531d 100644 --- a/setuptools/_vendor/vendored.txt +++ b/setuptools/_vendor/vendored.txt @@ -5,6 +5,7 @@ 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/dist.py b/setuptools/dist.py index 8c995aca..1cdb7472 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -29,7 +29,8 @@ 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, always_iterable, partition +from setuptools.extern.more_itertools import unique_everseen, partition +from setuptools.extern import nspektr from ._importlib import metadata @@ -43,7 +44,7 @@ from setuptools.config import setupcfg, pyprojecttoml from setuptools.discovery import ConfigDiscovery import pkg_resources -from setuptools.extern.packaging import version, requirements +from setuptools.extern.packaging import version from . import _reqs from . import _entry_points @@ -892,25 +893,10 @@ class Distribution(_Distribution): Given an entry point, ensure that any declared extras for its distribution are installed. """ - reqs = { - req - for req in map(requirements.Requirement, always_iterable(ep.dist.requires)) - for extra in ep.extras - if extra in req.extras - } - missing = itertools.filterfalse(self._is_installed, reqs) - for req in missing: + for req in nspektr.missing(ep): # fetch_build_egg expects pkg_resources.Requirement self.fetch_build_egg(pkg_resources.Requirement(str(req))) - def _is_installed(self, req): - try: - dist = metadata.distribution(req.name) - except metadata.PackageNotFoundError: - return False - found_ver = packaging.version.Version(dist.version()) - return found_ver in req.specifier - def get_egg_cache_dir(self): egg_cache_dir = os.path.join(os.curdir, '.eggs') if not os.path.exists(egg_cache_dir): diff --git a/setuptools/extern/__init__.py b/setuptools/extern/__init__.py index 90736e21..f09b7faa 100644 --- a/setuptools/extern/__init__.py +++ b/setuptools/extern/__init__.py @@ -71,7 +71,7 @@ class VendorImporter: names = ( 'packaging', 'pyparsing', 'ordered_set', 'more_itertools', 'importlib_metadata', - 'zipp', 'importlib_resources', 'jaraco', 'typing_extensions', 'tomli', - '_validate_pyproject', + 'zipp', 'importlib_resources', 'jaraco', 'typing_extensions', 'nspektr', + 'tomli', '_validate_pyproject', ) VendorImporter(__name__, names, 'setuptools._vendor').install() diff --git a/setuptools/tests/fixtures.py b/setuptools/tests/fixtures.py index e912399d..25ab49fd 100644 --- a/setuptools/tests/fixtures.py +++ b/setuptools/tests/fixtures.py @@ -1,6 +1,8 @@ +import os import contextlib import sys import subprocess +from pathlib import Path import pytest import path @@ -64,6 +66,9 @@ def sample_project(tmp_path): @pytest.fixture(scope="session") def setuptools_sdist(tmp_path_factory, request): + if os.getenv("PRE_BUILT_SETUPTOOLS_SDIST"): + return Path(os.getenv("PRE_BUILT_SETUPTOOLS_SDIST")).resolve() + with contexts.session_locked_tmp_dir( request, tmp_path_factory, "sdist_build") as tmp: dist = next(tmp.glob("*.tar.gz"), None) @@ -79,6 +84,9 @@ def setuptools_sdist(tmp_path_factory, request): @pytest.fixture(scope="session") def setuptools_wheel(tmp_path_factory, request): + if os.getenv("PRE_BUILT_SETUPTOOLS_WHEEL"): + return Path(os.getenv("PRE_BUILT_SETUPTOOLS_WHEEL")).resolve() + with contexts.session_locked_tmp_dir( request, tmp_path_factory, "wheel_build") as tmp: dist = next(tmp.glob("*.whl"), None) diff --git a/setuptools/tests/test_build_meta.py b/setuptools/tests/test_build_meta.py index dfbe8379..628d601e 100644 --- a/setuptools/tests/test_build_meta.py +++ b/setuptools/tests/test_build_meta.py @@ -21,6 +21,13 @@ TIMEOUT = int(os.getenv("TIMEOUT_BACKEND_TEST", "180")) # in seconds IS_PYPY = '__pypy__' in sys.builtin_module_names +pytestmark = pytest.mark.skipif( + sys.platform == "win32" and IS_PYPY, + reason="The combination of PyPy + Windows + pytest-xdist + ProcessPoolExecutor " + "is flaky and problematic" +) + + class BuildBackendBase: def __init__(self, cwd='.', env={}, backend_name='setuptools.build_meta'): self.cwd = cwd diff --git a/setuptools/tests/test_virtualenv.py b/setuptools/tests/test_virtualenv.py index 0ba89643..65358543 100644 --- a/setuptools/tests/test_virtualenv.py +++ b/setuptools/tests/test_virtualenv.py @@ -1,7 +1,8 @@ import os import sys -import itertools import subprocess +from urllib.request import urlopen +from urllib.error import URLError import pathlib @@ -31,56 +32,39 @@ def test_clean_env_install(venv_without_setuptools, setuptools_wheel): venv_without_setuptools.run(cmd) -def _get_pip_versions(): - # This fixture will attempt to detect if tests are being run without - # network connectivity and if so skip some tests - - network = True +def access_pypi(): + # Detect if tests are being run without connectivity if not os.environ.get('NETWORK_REQUIRED', False): # pragma: nocover try: - from urllib.request import urlopen - from urllib.error import URLError - except ImportError: - from urllib2 import urlopen, URLError # Python 2.7 compat - - try: urlopen('https://pypi.org', timeout=1) except URLError: # No network, disable most of these tests - network = False + return False - def mark(param, *marks): - if not isinstance(param, type(pytest.param(''))): - param = pytest.param(param) - return param._replace(marks=param.marks + marks) + return True - def skip_network(param): - return param if network else mark(param, pytest.mark.skip(reason="no network")) - network_versions = [ - mark('pip<20', pytest.mark.xfail(reason='pypa/pip#6599')), +@pytest.mark.skipif( + 'platform.python_implementation() == "PyPy"', + reason="https://github.com/pypa/setuptools/pull/2865#issuecomment-965834995", +) +@pytest.mark.skipif(not access_pypi(), reason="no network") +# ^-- Even when it is not necessary to install a different version of `pip` +# the build process will still try to download `wheel`, see #3147 and #2986. +@pytest.mark.parametrize( + 'pip_version', + [ + None, + pytest.param('pip<20', marks=pytest.mark.xfail(reason='pypa/pip#6599')), 'pip<20.1', 'pip<21', 'pip<22', - mark( + pytest.param( 'https://github.com/pypa/pip/archive/main.zip', - pytest.mark.xfail(reason='#2975'), + marks=pytest.mark.xfail(reason='#2975'), ), ] - - versions = itertools.chain( - [None], - map(skip_network, network_versions) - ) - - return list(versions) - - -@pytest.mark.skipif( - 'platform.python_implementation() == "PyPy"', - reason="https://github.com/pypa/setuptools/pull/2865#issuecomment-965834995", ) -@pytest.mark.parametrize('pip_version', _get_pip_versions()) def test_pip_upgrade_from_source(pip_version, venv_without_setuptools, setuptools_wheel, setuptools_sdist): """ diff --git a/tools/finalize.py b/tools/finalize.py index e4f65543..5a4df5df 100644 --- a/tools/finalize.py +++ b/tools/finalize.py @@ -42,6 +42,7 @@ def update_changelog(): cmd = [ sys.executable, '-m', 'towncrier', + 'build', '--version', get_version(), '--yes', ] diff --git a/tools/vendored.py b/tools/vendored.py index 83ab200f..dc1b0c07 100644 --- a/tools/vendored.py +++ b/tools/vendored.py @@ -92,6 +92,16 @@ 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 @@ -137,6 +147,7 @@ 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') def install_validate_pyproject(vendor): @@ -14,6 +14,8 @@ usedevelop = True extras = testing passenv = SETUPTOOLS_USE_DISTUTILS + PRE_BUILT_SETUPTOOLS_WHEEL + PRE_BUILT_SETUPTOOLS_SDIST TIMEOUT_BACKEND_TEST # timeout (in seconds) for test_build_meta windir # required for test_pkg_resources # honor git config in pytest-perf |
