diff --git a/newsfragments/931.removal.rst b/newsfragments/931.removal.rst new file mode 100644 index 0000000000..cffc7456d5 --- /dev/null +++ b/newsfragments/931.removal.rst @@ -0,0 +1 @@ +The test command has been removed. Users relying on 'setup.py test' will need to migrate to another test runner or pin setuptools before this version. \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 2d8d49d184..41889d9854 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -141,7 +141,6 @@ rotate = "setuptools.command.rotate:rotate" saveopts = "setuptools.command.saveopts:saveopts" sdist = "setuptools.command.sdist:sdist" setopt = "setuptools.command.setopt:setopt" -test = "setuptools.command.test:test" upload_docs = "setuptools.command.upload_docs:upload_docs" [project.entry-points."setuptools.finalize_distribution_options"] @@ -153,19 +152,15 @@ eager_resources = "setuptools.dist:assert_string_list" namespace_packages = "setuptools.dist:check_nsp" extras_require = "setuptools.dist:check_extras" install_requires = "setuptools.dist:check_requirements" -tests_require = "setuptools.dist:check_requirements" setup_requires = "setuptools.dist:check_requirements" python_requires = "setuptools.dist:check_specifier" entry_points = "setuptools.dist:check_entry_points" -test_suite = "setuptools.dist:check_test_suite" zip_safe = "setuptools.dist:assert_bool" package_data = "setuptools.dist:check_package_data" exclude_package_data = "setuptools.dist:check_package_data" include_package_data = "setuptools.dist:assert_bool" packages = "setuptools.dist:check_packages" dependency_links = "setuptools.dist:assert_string_list" -test_loader = "setuptools.dist:check_importable" -test_runner = "setuptools.dist:check_importable" use_2to3 = "setuptools.dist:invalid_unless_false" [project.entry-points."egg_info.writers"] diff --git a/setuptools/_path.py b/setuptools/_path.py index fb8ef0e198..d00db25464 100644 --- a/setuptools/_path.py +++ b/setuptools/_path.py @@ -1,7 +1,11 @@ +import contextlib import os import sys from typing import Union +from more_itertools import unique_everseen + + if sys.version_info >= (3, 9): StrPath = Union[str, os.PathLike[str]] # Same as _typeshed.StrPath else: @@ -38,3 +42,41 @@ def normpath(filename: StrPath) -> str: # See pkg_resources.normalize_path for notes about cygwin file = os.path.abspath(filename) if sys.platform == 'cygwin' else filename return os.path.normcase(os.path.realpath(os.path.normpath(file))) + + +@contextlib.contextmanager +def paths_on_pythonpath(paths): + """ + Add the indicated paths to the head of the PYTHONPATH environment + variable so that subprocesses will also see the packages at + these paths. + + Do this in a context that restores the value on exit. + + >>> getfixture('monkeypatch').setenv('PYTHONPATH', 'anything') + >>> with paths_on_pythonpath(['foo', 'bar']): + ... assert 'foo' in os.environ['PYTHONPATH'] + ... assert 'anything' in os.environ['PYTHONPATH'] + >>> os.environ['PYTHONPATH'] + 'anything' + + >>> getfixture('monkeypatch').delenv('PYTHONPATH') + >>> with paths_on_pythonpath(['foo', 'bar']): + ... assert 'foo' in os.environ['PYTHONPATH'] + >>> os.environ.get('PYTHONPATH') + """ + nothing = object() + orig_pythonpath = os.environ.get('PYTHONPATH', nothing) + current_pythonpath = os.environ.get('PYTHONPATH', '') + try: + prefix = os.pathsep.join(unique_everseen(paths)) + to_join = filter(None, [prefix, current_pythonpath]) + new_path = os.pathsep.join(to_join) + if new_path: + os.environ['PYTHONPATH'] = new_path + yield + finally: + if orig_pythonpath is nothing: + os.environ.pop('PYTHONPATH', None) + else: + os.environ['PYTHONPATH'] = orig_pythonpath diff --git a/setuptools/command/test.py b/setuptools/command/test.py deleted file mode 100644 index fbdf9fb942..0000000000 --- a/setuptools/command/test.py +++ /dev/null @@ -1,250 +0,0 @@ -import os -import operator -import sys -import contextlib -import itertools -import unittest -from distutils.errors import DistutilsError, DistutilsOptionError -from distutils import log -from unittest import TestLoader - -from pkg_resources import ( - resource_listdir, - resource_exists, - normalize_path, - working_set, - evaluate_marker, - add_activation_listener, - require, -) -from .._importlib import metadata -from setuptools import Command -from more_itertools import unique_everseen -from jaraco.functools import pass_none - - -class ScanningLoader(TestLoader): - def __init__(self): - TestLoader.__init__(self) - self._visited = set() - - def loadTestsFromModule(self, module, pattern=None): - """Return a suite of all tests cases contained in the given module - - If the module is a package, load tests from all the modules in it. - If the module has an ``additional_tests`` function, call it and add - the return value to the tests. - """ - if module in self._visited: - return None - self._visited.add(module) - - tests = [] - tests.append(TestLoader.loadTestsFromModule(self, module)) - - if hasattr(module, "additional_tests"): - tests.append(module.additional_tests()) - - if hasattr(module, '__path__'): - for file in resource_listdir(module.__name__, ''): - if file.endswith('.py') and file != '__init__.py': - submodule = module.__name__ + '.' + file[:-3] - else: - if resource_exists(module.__name__, file + '/__init__.py'): - submodule = module.__name__ + '.' + file - else: - continue - tests.append(self.loadTestsFromName(submodule)) - - if len(tests) != 1: - return self.suiteClass(tests) - else: - return tests[0] # don't create a nested suite for only one return - - -# adapted from jaraco.classes.properties:NonDataProperty -class NonDataProperty: - def __init__(self, fget): - self.fget = fget - - def __get__(self, obj, objtype=None): - if obj is None: - return self - return self.fget(obj) - - -class test(Command): - """Command to run unit tests after in-place build""" - - description = "run unit tests after in-place build (deprecated)" - - user_options = [ - ('test-module=', 'm', "Run 'test_suite' in specified module"), - ( - 'test-suite=', - 's', - "Run single test, case or suite (e.g. 'module.test_suite')", - ), - ('test-runner=', 'r', "Test runner to use"), - ] - - def initialize_options(self): - self.test_suite = None - self.test_module = None - self.test_loader = None - self.test_runner = None - - def finalize_options(self): - if self.test_suite and self.test_module: - msg = "You may specify a module or a suite, but not both" - raise DistutilsOptionError(msg) - - if self.test_suite is None: - if self.test_module is None: - self.test_suite = self.distribution.test_suite - else: - self.test_suite = self.test_module + ".test_suite" - - if self.test_loader is None: - self.test_loader = getattr(self.distribution, 'test_loader', None) - if self.test_loader is None: - self.test_loader = "setuptools.command.test:ScanningLoader" - if self.test_runner is None: - self.test_runner = getattr(self.distribution, 'test_runner', None) - - @NonDataProperty - def test_args(self): - return list(self._test_args()) - - def _test_args(self): - if not self.test_suite: - yield 'discover' - if self.verbose: - yield '--verbose' - if self.test_suite: - yield self.test_suite - - def with_project_on_sys_path(self, func): - """ - Backward compatibility for project_on_sys_path context. - """ - with self.project_on_sys_path(): - func() - - @contextlib.contextmanager - def project_on_sys_path(self, include_dists=()): - self.run_command('egg_info') - - # Build extensions in-place - self.reinitialize_command('build_ext', inplace=True) - self.run_command('build_ext') - - ei_cmd = self.get_finalized_command("egg_info") - - old_path = sys.path[:] - old_modules = sys.modules.copy() - - try: - project_path = normalize_path(ei_cmd.egg_base) - sys.path.insert(0, project_path) - working_set.__init__() - add_activation_listener(lambda dist: dist.activate()) - require('%s==%s' % (ei_cmd.egg_name, ei_cmd.egg_version)) - with self.paths_on_pythonpath([project_path]): - yield - finally: - sys.path[:] = old_path - sys.modules.clear() - sys.modules.update(old_modules) - working_set.__init__() - - @staticmethod - @contextlib.contextmanager - def paths_on_pythonpath(paths): - """ - Add the indicated paths to the head of the PYTHONPATH environment - variable so that subprocesses will also see the packages at - these paths. - - Do this in a context that restores the value on exit. - """ - nothing = object() - orig_pythonpath = os.environ.get('PYTHONPATH', nothing) - current_pythonpath = os.environ.get('PYTHONPATH', '') - try: - prefix = os.pathsep.join(unique_everseen(paths)) - to_join = filter(None, [prefix, current_pythonpath]) - new_path = os.pathsep.join(to_join) - if new_path: - os.environ['PYTHONPATH'] = new_path - yield - finally: - if orig_pythonpath is nothing: - os.environ.pop('PYTHONPATH', None) - else: - os.environ['PYTHONPATH'] = orig_pythonpath - - @staticmethod - def install_dists(dist): - """ - Install the requirements indicated by self.distribution and - return an iterable of the dists that were built. - """ - ir_d = dist.fetch_build_eggs(dist.install_requires) - tr_d = dist.fetch_build_eggs(dist.tests_require or []) - er_d = dist.fetch_build_eggs( - v - for k, v in dist.extras_require.items() - if k.startswith(':') and evaluate_marker(k[1:]) - ) - return itertools.chain(ir_d, tr_d, er_d) - - def run(self): - self.announce( - "WARNING: Testing via this command is deprecated and will be " - "removed in a future version. Users looking for a generic test " - "entry point independent of test runner are encouraged to use " - "tox.", - log.WARN, - ) - - installed_dists = self.install_dists(self.distribution) - - cmd = ' '.join(self._argv) - if self.dry_run: - self.announce('skipping "%s" (dry run)' % cmd) - return - - self.announce('running "%s"' % cmd) - - paths = map(operator.attrgetter('location'), installed_dists) - with self.paths_on_pythonpath(paths): - with self.project_on_sys_path(): - self.run_tests() - - def run_tests(self): - test = unittest.main( - None, - None, - self._argv, - testLoader=self._resolve_as_ep(self.test_loader), - testRunner=self._resolve_as_ep(self.test_runner), - exit=False, - ) - if not test.result.wasSuccessful(): - msg = 'Test failed: %s' % test.result - self.announce(msg, log.ERROR) - raise DistutilsError(msg) - - @property - def _argv(self): - return ['unittest'] + self.test_args - - @staticmethod - @pass_none - def _resolve_as_ep(val): - """ - Load the indicated attribute value, called, as a as if it were - specified as an entry point. - """ - return metadata.EntryPoint(value=val, name=None, group=None).load()() diff --git a/setuptools/config/setupcfg.py b/setuptools/config/setupcfg.py index 772b8d00e0..5a3b7478a0 100644 --- a/setuptools/config/setupcfg.py +++ b/setuptools/config/setupcfg.py @@ -649,7 +649,6 @@ def parsers(self): self._parse_requirements_list, "install_requires" ), 'setup_requires': self._parse_list_semicolon, - 'tests_require': self._parse_list_semicolon, 'packages': self._parse_packages, 'entry_points': self._parse_file_in_root, 'py_modules': parse_list, diff --git a/setuptools/dist.py b/setuptools/dist.py index b4496ab986..6a29b2b2b7 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -168,11 +168,6 @@ def check_entry_points(dist, attr, value): raise DistutilsSetupError(e) from e -def check_test_suite(dist, attr, value): - if not isinstance(value, str): - raise DistutilsSetupError("test_suite must be a string") - - def check_package_data(dist, attr, value): """Verify that value is a dictionary of package names to glob lists""" if not isinstance(value, dict): @@ -233,12 +228,6 @@ class Distribution(_Distribution): EasyInstall and requests one of your extras, the corresponding additional requirements will be installed if needed. - 'test_suite' -- the name of a test suite to run for the 'test' command. - If the user runs 'python setup.py test', the package will be installed, - and the named test suite will be run. The format is the same as - would be used on a 'unittest.py' command line. That is, it is the - dotted name of an object to import and call to generate a test suite. - 'package_data' -- a dictionary mapping package names to lists of filenames or globs to use to find data files contained in the named packages. If the dictionary has filenames or globs listed under '""' (the empty diff --git a/setuptools/tests/config/setupcfg_examples.txt b/setuptools/tests/config/setupcfg_examples.txt index 5db3565464..6aab887ff1 100644 --- a/setuptools/tests/config/setupcfg_examples.txt +++ b/setuptools/tests/config/setupcfg_examples.txt @@ -15,7 +15,6 @@ https://github.com/pallets/click/raw/6411f425fae545f42795665af4162006b36c5e4a/se https://github.com/sqlalchemy/sqlalchemy/raw/533f5718904b620be8d63f2474229945d6f8ba5d/setup.cfg https://github.com/pytest-dev/pluggy/raw/461ef63291d13589c4e21aa182cd1529257e9a0a/setup.cfg https://github.com/pytest-dev/pytest/raw/c7be96dae487edbd2f55b561b31b68afac1dabe6/setup.cfg -https://github.com/tqdm/tqdm/raw/fc69d5dcf578f7c7986fa76841a6b793f813df35/setup.cfg https://github.com/platformdirs/platformdirs/raw/7b7852128dd6f07511b618d6edea35046bd0c6ff/setup.cfg https://github.com/pandas-dev/pandas/raw/bc17343f934a33dc231c8c74be95d8365537c376/setup.cfg https://github.com/django/django/raw/4e249d11a6e56ca8feb4b055b681cec457ef3a3d/setup.cfg diff --git a/setuptools/tests/config/test_apply_pyprojecttoml.py b/setuptools/tests/config/test_apply_pyprojecttoml.py index ff9c5fc66e..6650a657d3 100644 --- a/setuptools/tests/config/test_apply_pyprojecttoml.py +++ b/setuptools/tests/config/test_apply_pyprojecttoml.py @@ -50,7 +50,6 @@ def test_apply_pyproject_equivalent_to_setupcfg(url, monkeypatch, tmp_path): dist_toml = pyprojecttoml.apply_configuration(makedist(tmp_path), pyproject_example) dist_cfg = setupcfg.apply_configuration(makedist(tmp_path), setupcfg_example) - _port_tests_require(dist_cfg) pkg_info_toml = core_metadata(dist_toml) pkg_info_cfg = core_metadata(dist_cfg) @@ -83,12 +82,6 @@ def test_apply_pyproject_equivalent_to_setupcfg(url, monkeypatch, tmp_path): assert set(dist_toml.install_requires) == set(dist_cfg.install_requires) if any(getattr(d, "extras_require", None) for d in (dist_toml, dist_cfg)): - if ( - "testing" in dist_toml.extras_require - and "testing" not in dist_cfg.extras_require - ): - # ini2toml can automatically convert `tests_require` to `testing` extra - dist_toml.extras_require.pop("testing") extra_req_toml = {(k, *sorted(v)) for k, v in dist_toml.extras_require.items()} extra_req_cfg = {(k, *sorted(v)) for k, v in dist_cfg.extras_require.items()} assert extra_req_toml == extra_req_cfg @@ -461,8 +454,6 @@ def core_metadata(dist) -> str: skip_prefixes += ("Project-URL: Homepage,", "Home-page:") # May be missing in original (relying on default) but backfilled in the TOML skip_prefixes += ("Description-Content-Type:",) - # ini2toml can automatically convert `tests_require` to `testing` extra - skip_lines.add("Provides-Extra: testing") # Remove empty lines skip_lines.add("") @@ -473,15 +464,3 @@ def core_metadata(dist) -> str: result.append(line + "\n") return "".join(result) - - -def _port_tests_require(dist): - """ - ``ini2toml`` "forward fix" deprecated tests_require definitions by moving - them into an extra called ``testing``. - """ - tests_require = getattr(dist, "tests_require", None) or [] - if tests_require: - dist.tests_require = [] - dist.extras_require.setdefault("testing", []).extend(tests_require) - dist._finalize_requires() diff --git a/setuptools/tests/config/test_setupcfg.py b/setuptools/tests/config/test_setupcfg.py index dc8a4f7f88..0074fe2308 100644 --- a/setuptools/tests/config/test_setupcfg.py +++ b/setuptools/tests/config/test_setupcfg.py @@ -465,7 +465,6 @@ def test_basic(self, tmpdir): 'scripts = bin/one.py, bin/two.py\n' 'eager_resources = bin/one.py, bin/two.py\n' 'install_requires = docutils>=0.3; pack ==1.1, ==1.3; hey\n' - 'tests_require = mock==0.7.2; pytest\n' 'setup_requires = docutils>=0.3; spack ==1.1, ==1.3; there\n' 'dependency_links = http://some.com/here/1, ' 'http://some.com/there/2\n' @@ -494,7 +493,6 @@ def test_basic(self, tmpdir): 'spack ==1.1, ==1.3', 'there', ]) - assert dist.tests_require == ['mock==0.7.2', 'pytest'] assert dist.python_requires == '>=1.0, !=2.8' assert dist.py_modules == ['module1', 'module2'] @@ -521,9 +519,6 @@ def test_multiline(self, tmpdir): ' docutils>=0.3\n' ' pack ==1.1, ==1.3\n' ' hey\n' - 'tests_require = \n' - ' mock==0.7.2\n' - ' pytest\n' 'setup_requires = \n' ' docutils>=0.3\n' ' spack ==1.1, ==1.3\n' @@ -552,7 +547,6 @@ def test_multiline(self, tmpdir): 'spack ==1.1, ==1.3', 'there', ]) - assert dist.tests_require == ['mock==0.7.2', 'pytest'] def test_package_dir_fail(self, tmpdir): fake_env(tmpdir, '[options]\npackage_dir = a b\n') diff --git a/setuptools/tests/test_bdist_wheel.py b/setuptools/tests/test_bdist_wheel.py index 7043d857d7..3ca277ba15 100644 --- a/setuptools/tests/test_bdist_wheel.py +++ b/setuptools/tests/test_bdist_wheel.py @@ -98,7 +98,6 @@ setup_requires=["setuptools"], install_requires=["quux", "splort"], extras_require={"simple": ["simple.dist"]}, - tests_require=["foo", "bar>=10.0.0"], entry_points={ "console_scripts": [ "complex-dist=complexdist:main", diff --git a/setuptools/tests/test_develop.py b/setuptools/tests/test_develop.py index d36447edbb..6f17beb703 100644 --- a/setuptools/tests/test_develop.py +++ b/setuptools/tests/test_develop.py @@ -6,12 +6,11 @@ import pathlib import platform -from setuptools.command import test - import pytest from setuptools.command.develop import develop from setuptools.dist import Distribution +from setuptools._path import paths_on_pythonpath from . import contexts from . import namespaces @@ -124,7 +123,7 @@ def install_develop(src_dir, target): str(target), ] with src_dir.as_cwd(): - with test.test.paths_on_pythonpath([str(target)]): + with paths_on_pythonpath([str(target)]): subprocess.check_call(develop_cmd) @pytest.mark.skipif( @@ -163,7 +162,7 @@ def test_namespace_package_importable(self, tmpdir): '-c', 'import myns.pkgA; import myns.pkgB', ] - with test.test.paths_on_pythonpath([str(target)]): + with paths_on_pythonpath([str(target)]): subprocess.check_call(try_import) # additionally ensure that pkg_resources import works @@ -172,5 +171,5 @@ def test_namespace_package_importable(self, tmpdir): '-c', 'import pkg_resources', ] - with test.test.paths_on_pythonpath([str(target)]): + with paths_on_pythonpath([str(target)]): subprocess.check_call(pkg_resources_imp) diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py index 8616f813c1..856dd127bc 100644 --- a/setuptools/tests/test_egg_info.py +++ b/setuptools/tests/test_egg_info.py @@ -395,17 +395,6 @@ def parametrize(*test_list, **format_dict): setup_requires = barbazquux; {mismatch_marker} - """, - """ - tests_require_with_markers - {'cmd': ['test'], 'output': "Ran 0 tests in"} - - tests_require=["barbazquux;{mismatch_marker}"], - - [options] - tests_require = - barbazquux; {mismatch_marker} - """, """ extras_require_with_extra diff --git a/setuptools/tests/test_namespaces.py b/setuptools/tests/test_namespaces.py index 76b5af296a..56689301da 100644 --- a/setuptools/tests/test_namespaces.py +++ b/setuptools/tests/test_namespaces.py @@ -1,8 +1,9 @@ import sys import subprocess +from setuptools._path import paths_on_pythonpath + from . import namespaces -from setuptools.command import test class TestNamespaces: @@ -45,7 +46,7 @@ def test_mixed_site_and_non_site(self, tmpdir): '-c', 'import myns.pkgA; import myns.pkgB', ] - with test.test.paths_on_pythonpath(map(str, targets)): + with paths_on_pythonpath(map(str, targets)): subprocess.check_call(try_import) def test_pkg_resources_import(self, tmpdir): @@ -65,7 +66,7 @@ def test_pkg_resources_import(self, tmpdir): str(target), str(pkg), ] - with test.test.paths_on_pythonpath([str(target)]): + with paths_on_pythonpath([str(target)]): subprocess.check_call(install_cmd) namespaces.make_site_dir(target) try_import = [ @@ -73,7 +74,7 @@ def test_pkg_resources_import(self, tmpdir): '-c', 'import pkg_resources', ] - with test.test.paths_on_pythonpath([str(target)]): + with paths_on_pythonpath([str(target)]): subprocess.check_call(try_import) def test_namespace_package_installed_and_cwd(self, tmpdir): @@ -102,7 +103,7 @@ def test_namespace_package_installed_and_cwd(self, tmpdir): '-c', 'import pkg_resources; import myns.pkgA', ] - with test.test.paths_on_pythonpath([str(target)]): + with paths_on_pythonpath([str(target)]): subprocess.check_call(pkg_resources_imp, cwd=str(pkg_A)) def test_packages_in_the_same_namespace_installed_and_cwd(self, tmpdir): @@ -133,5 +134,5 @@ def test_packages_in_the_same_namespace_installed_and_cwd(self, tmpdir): '-c', 'import pkg_resources; import myns.pkgA; import myns.pkgB', ] - with test.test.paths_on_pythonpath([str(target)]): + with paths_on_pythonpath([str(target)]): subprocess.check_call(pkg_resources_imp, cwd=str(pkg_B)) diff --git a/setuptools/tests/test_setuptools.py b/setuptools/tests/test_setuptools.py index 566af6980e..9865ee847c 100644 --- a/setuptools/tests/test_setuptools.py +++ b/setuptools/tests/test_setuptools.py @@ -5,7 +5,6 @@ import os import distutils.core import distutils.cmd -from distutils.errors import DistutilsOptionError from distutils.errors import DistutilsSetupError from distutils.core import Extension from zipfile import ZipFile @@ -222,43 +221,6 @@ def testInvalidIncludeExclude(self): self.dist.exclude(package_dir=['q']) -class TestCommandTests: - def testTestIsCommand(self): - test_cmd = makeSetup().get_command_obj('test') - assert isinstance(test_cmd, distutils.cmd.Command) - - def testLongOptSuiteWNoDefault(self): - ts1 = makeSetup(script_args=['test', '--test-suite=foo.tests.suite']) - ts1 = ts1.get_command_obj('test') - ts1.ensure_finalized() - assert ts1.test_suite == 'foo.tests.suite' - - def testDefaultSuite(self): - ts2 = makeSetup(test_suite='bar.tests.suite').get_command_obj('test') - ts2.ensure_finalized() - assert ts2.test_suite == 'bar.tests.suite' - - def testDefaultWModuleOnCmdLine(self): - ts3 = makeSetup( - test_suite='bar.tests', script_args=['test', '-m', 'foo.tests'] - ).get_command_obj('test') - ts3.ensure_finalized() - assert ts3.test_module == 'foo.tests' - assert ts3.test_suite == 'foo.tests.test_suite' - - def testConflictingOptions(self): - ts4 = makeSetup( - script_args=['test', '-m', 'bar.tests', '-s', 'foo.tests.suite'] - ).get_command_obj('test') - with pytest.raises(DistutilsOptionError): - ts4.ensure_finalized() - - def testNoSuite(self): - ts5 = makeSetup().get_command_obj('test') - ts5.ensure_finalized() - assert ts5.test_suite is None - - @pytest.fixture def example_source(tmpdir): tmpdir.mkdir('foo') diff --git a/setuptools/tests/test_test.py b/setuptools/tests/test_test.py deleted file mode 100644 index 989996f3ba..0000000000 --- a/setuptools/tests/test_test.py +++ /dev/null @@ -1,39 +0,0 @@ -import pytest -from jaraco import path - -from setuptools.command.test import test -from setuptools.dist import Distribution - -from .textwrap import DALS - - -@pytest.mark.usefixtures('tmpdir_cwd') -def test_tests_are_run_once(capfd): - params = dict( - packages=['dummy'], - ) - files = { - 'setup.py': 'from setuptools import setup; setup(' - + ','.join(f'{name}={params[name]!r}' for name in params) - + ')', - 'dummy': { - '__init__.py': '', - 'test_dummy.py': DALS( - """ - import unittest - class TestTest(unittest.TestCase): - def test_test(self): - print('Foo') - """ - ), - }, - } - path.build(files) - dist = Distribution(params) - dist.script_name = 'setup.py' - cmd = test(dist) - cmd.ensure_finalized() - cmd.run() - out, err = capfd.readouterr() - assert out.endswith('Foo\n') - assert len(out.split('Foo')) == 2 diff --git a/setuptools/tests/test_virtualenv.py b/setuptools/tests/test_virtualenv.py index b84702aa70..4554581ed0 100644 --- a/setuptools/tests/test_virtualenv.py +++ b/setuptools/tests/test_virtualenv.py @@ -4,14 +4,9 @@ from urllib.request import urlopen from urllib.error import URLError -import pathlib import pytest -from . import contexts -from .textwrap import DALS -from .test_easy_install import make_nspkg_sdist - @pytest.fixture(autouse=True) def pytest_virtualenv_works(venv): @@ -111,80 +106,6 @@ def test_pip_upgrade_from_source( venv.run(["pip", "install", "--no-cache-dir", "--upgrade", str(setuptools_sdist)]) -def _check_test_command_install_requirements(venv, tmpdir): - """ - Check the test command will install all required dependencies. - """ - - def sdist(distname, version): - dist_path = tmpdir.join('%s-%s.tar.gz' % (distname, version)) - make_nspkg_sdist(str(dist_path), distname, version) - return dist_path - - dependency_links = [ - pathlib.Path(str(dist_path)).as_uri() - for dist_path in ( - sdist('foobar', '2.4'), - sdist('bits', '4.2'), - sdist('bobs', '6.0'), - sdist('pieces', '0.6'), - ) - ] - with tmpdir.join('setup.py').open('w') as fp: - fp.write( - DALS( - ''' - from setuptools import setup - - setup( - dependency_links={dependency_links!r}, - install_requires=[ - 'barbazquux1; sys_platform in ""', - 'foobar==2.4', - ], - setup_requires='bits==4.2', - tests_require=""" - bobs==6.0 - """, - extras_require={{ - 'test': ['barbazquux2'], - ':"" in sys_platform': 'pieces==0.6', - ':python_version > "1"': """ - pieces - foobar - """, - }} - ) - '''.format(dependency_links=dependency_links) - ) - ) - with tmpdir.join('test.py').open('w') as fp: - fp.write( - DALS( - """ - import foobar - import bits - import bobs - import pieces - - open('success', 'w').close() - """ - ) - ) - - cmd = ["python", 'setup.py', 'test', '-s', 'test'] - venv.run(cmd, cwd=str(tmpdir)) - assert tmpdir.join('success').check() - - -def test_test_command_install_requirements(venv, tmpdir, tmpdir_cwd): - # Ensure pip is installed. - venv.run(["python", "-c", "import pip"]) - # disable index URL so bits and bobs aren't requested from PyPI - with contexts.environment(PYTHONPATH=None, PIP_NO_INDEX="1"): - _check_test_command_install_requirements(venv, tmpdir) - - def test_no_missing_dependencies(bare_venv, request): """ Quick and dirty test to ensure all external dependencies are vendored.