summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bumpversion.cfg2
-rw-r--r--CHANGES.rst18
-rw-r--r--changelog.d/2459.change.rst1
-rw-r--r--pyproject.toml3
-rw-r--r--setup.cfg5
-rw-r--r--setuptools/dist.py4
-rw-r--r--setuptools/tests/fixtures.py37
-rw-r--r--setuptools/tests/test_build_meta.py6
-rw-r--r--setuptools/tests/test_distutils_adoption.py6
-rw-r--r--setuptools/tests/test_virtualenv.py25
10 files changed, 83 insertions, 24 deletions
diff --git a/.bumpversion.cfg b/.bumpversion.cfg
index 2cb50290..debcfeeb 100644
--- a/.bumpversion.cfg
+++ b/.bumpversion.cfg
@@ -1,5 +1,5 @@
[bumpversion]
-current_version = 51.3.1
+current_version = 51.3.3
commit = True
tag = True
diff --git a/CHANGES.rst b/CHANGES.rst
index 2be5fa2f..c094960f 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,3 +1,21 @@
+v51.3.3
+-------
+
+
+Misc
+^^^^
+* #2539: Fix AttributeError in Description validation.
+
+
+v51.3.2
+-------
+
+
+Misc
+^^^^
+* #1390: Validation of Description field now is more lenient, emitting a warning and mangling the value to be valid (replacing newlines with spaces).
+
+
v51.3.1
-------
diff --git a/changelog.d/2459.change.rst b/changelog.d/2459.change.rst
new file mode 100644
index 00000000..3b8d11a9
--- /dev/null
+++ b/changelog.d/2459.change.rst
@@ -0,0 +1 @@
+Tests now run in parallel via pytest-xdist, completing in about half the time. Special thanks to :user:`webknjaz` for hard work implementing test isolation. To run without parallelization, disable the plugin with ``tox -- -p no:xdist``.
diff --git a/pyproject.toml b/pyproject.toml
index 0bc2a46f..4e80bdc1 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -24,6 +24,9 @@ addopts = "--flake8"
[pytest.enabler.cov]
addopts = "--cov"
+[pytest.enabler.xdist]
+addopts = "-n auto"
+
[tool.towncrier]
package = "setuptools"
package_dir = "setuptools"
diff --git a/setup.cfg b/setup.cfg
index aead4346..36c7daee 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -2,7 +2,7 @@
license_files =
LICENSE
name = setuptools
-version = 51.3.1
+version = 51.3.3
author = Python Packaging Authority
author_email = distutils-sig@python.org
description = Easily download, build, install, upgrade, and uninstall Python packages
@@ -47,7 +47,7 @@ testing =
pytest-black >= 0.3.7; python_implementation != "PyPy"
pytest-cov
pytest-mypy; python_implementation != "PyPy"
- pytest-enabler
+ pytest-enabler >= 1.0.1
# local
mock
@@ -58,6 +58,7 @@ testing =
paver
pip>=19.1 # For proper file:// URLs support.
jaraco.envs
+ pytest-xdist
docs =
# Keep these in sync with docs/requirements.txt
diff --git a/setuptools/dist.py b/setuptools/dist.py
index 2d0aac33..050388de 100644
--- a/setuptools/dist.py
+++ b/setuptools/dist.py
@@ -121,7 +121,9 @@ def read_pkg_file(self, file):
def single_line(val):
# quick and dirty validation for description pypa/setuptools#1390
if '\n' in val:
- raise ValueError("newlines not allowed")
+ # TODO after 2021-07-31: Replace with `raise ValueError("newlines not allowed")`
+ warnings.warn("newlines not allowed and will break in the future")
+ val = val.replace('\n', ' ')
return val
diff --git a/setuptools/tests/fixtures.py b/setuptools/tests/fixtures.py
index e8cb7f52..d74b5f03 100644
--- a/setuptools/tests/fixtures.py
+++ b/setuptools/tests/fixtures.py
@@ -1,3 +1,7 @@
+import contextlib
+import sys
+import shutil
+
import pytest
from . import contexts
@@ -21,3 +25,36 @@ def user_override(monkeypatch):
def tmpdir_cwd(tmpdir):
with tmpdir.as_cwd() as orig:
yield orig
+
+
+@pytest.fixture
+def tmp_src(request, tmp_path):
+ """Make a copy of the source dir under `$tmp/src`.
+
+ This fixture is useful whenever it's necessary to run `setup.py`
+ or `pip install` against the source directory when there's no
+ control over the number of simultaneous invocations. Such
+ concurrent runs create and delete directories with the same names
+ under the target directory and so they influence each other's runs
+ when they are not being executed sequentially.
+ """
+ tmp_src_path = tmp_path / 'src'
+ shutil.copytree(request.config.rootdir, tmp_src_path)
+ return tmp_src_path
+
+
+@pytest.fixture(autouse=True, scope="session")
+def workaround_xdist_376(request):
+ """
+ Workaround pytest-dev/pytest-xdist#376
+
+ ``pytest-xdist`` tends to inject '' into ``sys.path``,
+ which may break certain isolation expectations.
+ Remove the entry so the import
+ machinery behaves the same irrespective of xdist.
+ """
+ if not request.config.pluginmanager.has_plugin('xdist'):
+ return
+
+ with contextlib.suppress(ValueError):
+ sys.path.remove('')
diff --git a/setuptools/tests/test_build_meta.py b/setuptools/tests/test_build_meta.py
index 6d3a997e..e117d8e6 100644
--- a/setuptools/tests/test_build_meta.py
+++ b/setuptools/tests/test_build_meta.py
@@ -11,7 +11,7 @@ from .textwrap import DALS
class BuildBackendBase:
- def __init__(self, cwd=None, env={}, backend_name='setuptools.build_meta'):
+ def __init__(self, cwd='.', env={}, backend_name='setuptools.build_meta'):
self.cwd = cwd
self.env = env
self.backend_name = backend_name
@@ -126,7 +126,7 @@ class TestBuildMetaBackend:
backend_name = 'setuptools.build_meta'
def get_build_backend(self):
- return BuildBackend(cwd='.', backend_name=self.backend_name)
+ return BuildBackend(backend_name=self.backend_name)
@pytest.fixture(params=defns)
def build_backend(self, tmpdir, request):
@@ -337,7 +337,7 @@ class TestBuildMetaBackend:
def test_build_sdist_relative_path_import(self, tmpdir_cwd):
build_files(self._relative_path_import_files)
build_backend = self.get_build_backend()
- with pytest.raises(ImportError):
+ with pytest.raises(ImportError, match="^No module named 'hello'$"):
build_backend.build_sdist("temp")
@pytest.mark.parametrize('setup_literal, requirements', [
diff --git a/setuptools/tests/test_distutils_adoption.py b/setuptools/tests/test_distutils_adoption.py
index a53773df..0e89921c 100644
--- a/setuptools/tests/test_distutils_adoption.py
+++ b/setuptools/tests/test_distutils_adoption.py
@@ -21,10 +21,10 @@ class VirtualEnv(jaraco.envs.VirtualEnv):
@pytest.fixture
-def venv(tmpdir):
+def venv(tmp_path, tmp_src):
env = VirtualEnv()
- env.root = path.Path(tmpdir)
- env.req = os.getcwd()
+ env.root = path.Path(tmp_path / 'venv')
+ env.req = str(tmp_src)
return env.create()
diff --git a/setuptools/tests/test_virtualenv.py b/setuptools/tests/test_virtualenv.py
index 8681ed27..fcd5da5d 100644
--- a/setuptools/tests/test_virtualenv.py
+++ b/setuptools/tests/test_virtualenv.py
@@ -40,14 +40,11 @@ def bare_virtualenv():
yield venv
-SOURCE_DIR = os.path.join(os.path.dirname(__file__), '../..')
-
-
-def test_clean_env_install(bare_virtualenv):
+def test_clean_env_install(bare_virtualenv, tmp_src):
"""
Check setuptools can be installed in a clean environment.
"""
- bare_virtualenv.run(['python', 'setup.py', 'install'], cd=SOURCE_DIR)
+ bare_virtualenv.run(['python', 'setup.py', 'install'], cd=tmp_src)
def _get_pip_versions():
@@ -85,7 +82,7 @@ def _get_pip_versions():
@pytest.mark.parametrize('pip_version', _get_pip_versions())
-def test_pip_upgrade_from_source(pip_version, virtualenv):
+def test_pip_upgrade_from_source(pip_version, tmp_src, virtualenv):
"""
Check pip can upgrade setuptools from source.
"""
@@ -104,7 +101,7 @@ def test_pip_upgrade_from_source(pip_version, virtualenv):
virtualenv.run(' && '.join((
'python setup.py -q sdist -d {dist}',
'python setup.py -q bdist_wheel -d {dist}',
- )).format(dist=dist_dir), cd=SOURCE_DIR)
+ )).format(dist=dist_dir), cd=tmp_src)
sdist = glob.glob(os.path.join(dist_dir, '*.zip'))[0]
wheel = glob.glob(os.path.join(dist_dir, '*.whl'))[0]
# Then update from wheel.
@@ -113,12 +110,12 @@ def test_pip_upgrade_from_source(pip_version, virtualenv):
virtualenv.run('pip install --no-cache-dir --upgrade ' + sdist)
-def _check_test_command_install_requirements(virtualenv, tmpdir):
+def _check_test_command_install_requirements(virtualenv, tmpdir, cwd):
"""
Check the test command will install all required dependencies.
"""
# Install setuptools.
- virtualenv.run('python setup.py develop', cd=SOURCE_DIR)
+ virtualenv.run('python setup.py develop', cd=cwd)
def sdist(distname, version):
dist_path = tmpdir.join('%s-%s.tar.gz' % (distname, version))
@@ -175,7 +172,7 @@ def _check_test_command_install_requirements(virtualenv, tmpdir):
assert tmpdir.join('success').check()
-def test_test_command_install_requirements(virtualenv, tmpdir):
+def test_test_command_install_requirements(virtualenv, tmpdir, request):
# Ensure pip/wheel packages are installed.
virtualenv.run(
"python -c \"__import__('pkg_resources').require(['pip', 'wheel'])\"")
@@ -183,13 +180,13 @@ def test_test_command_install_requirements(virtualenv, tmpdir):
virtualenv.run("python -m pip uninstall -y setuptools")
# disable index URL so bits and bobs aren't requested from PyPI
virtualenv.env['PIP_NO_INDEX'] = '1'
- _check_test_command_install_requirements(virtualenv, tmpdir)
+ _check_test_command_install_requirements(virtualenv, tmpdir, request.config.rootdir)
-def test_no_missing_dependencies(bare_virtualenv):
+def test_no_missing_dependencies(bare_virtualenv, request):
"""
Quick and dirty test to ensure all external dependencies are vendored.
"""
for command in ('upload',): # sorted(distutils.command.__all__):
- bare_virtualenv.run(
- ['python', 'setup.py', command, '-h'], cd=SOURCE_DIR)
+ cmd = ['python', 'setup.py', command, '-h']
+ bare_virtualenv.run(cmd, cd=request.config.rootdir)