diff options
author | Jason R. Coombs <jaraco@jaraco.com> | 2019-09-11 18:07:45 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-09-11 18:07:45 +0100 |
commit | b3ef77b2085dc8d66d178a2f7d2047a9ca207309 (patch) | |
tree | 59b29ad80ec61296572c53e38443fa91d71dd8bf /setuptools/tests | |
parent | 7f7780e5b572d6fcacd63bf99389dd9f48c5345c (diff) | |
parent | cb64d3a84fab15aacbdf31a0a5632690ca9f49b2 (diff) | |
download | external_python_setuptools-b3ef77b2085dc8d66d178a2f7d2047a9ca207309.tar.gz external_python_setuptools-b3ef77b2085dc8d66d178a2f7d2047a9ca207309.tar.bz2 external_python_setuptools-b3ef77b2085dc8d66d178a2f7d2047a9ca207309.zip |
Merge branch 'master' into feature/deterministic-provides-extras
Diffstat (limited to 'setuptools/tests')
-rw-r--r-- | setuptools/tests/test_build_meta.py | 100 | ||||
-rw-r--r-- | setuptools/tests/test_config.py | 38 | ||||
-rw-r--r-- | setuptools/tests/test_dist.py | 54 | ||||
-rw-r--r-- | setuptools/tests/test_egg_info.py | 1 | ||||
-rw-r--r-- | setuptools/tests/test_integration.py | 5 | ||||
-rw-r--r-- | setuptools/tests/test_packageindex.py | 2 | ||||
-rw-r--r-- | setuptools/tests/test_setopt.py | 36 | ||||
-rw-r--r-- | setuptools/tests/test_virtualenv.py | 52 |
8 files changed, 257 insertions, 31 deletions
diff --git a/setuptools/tests/test_build_meta.py b/setuptools/tests/test_build_meta.py index 74969322..e1efe561 100644 --- a/setuptools/tests/test_build_meta.py +++ b/setuptools/tests/test_build_meta.py @@ -28,7 +28,7 @@ class BuildBackend(BuildBackendBase): def __init__(self, *args, **kwargs): super(BuildBackend, self).__init__(*args, **kwargs) - self.pool = futures.ProcessPoolExecutor() + self.pool = futures.ProcessPoolExecutor(max_workers=1) def __getattr__(self, name): """Handles aribrary function invocations on the build backend.""" @@ -157,6 +157,53 @@ class TestBuildMetaBackend: assert os.path.isfile(os.path.join(dist_dir, wheel_name)) + @pytest.mark.parametrize('build_type', ('wheel', 'sdist')) + def test_build_with_existing_file_present(self, build_type, tmpdir_cwd): + # Building a sdist/wheel should still succeed if there's + # already a sdist/wheel in the destination directory. + files = { + 'setup.py': "from setuptools import setup\nsetup()", + 'VERSION': "0.0.1", + 'setup.cfg': DALS(""" + [metadata] + name = foo + version = file: VERSION + """), + 'pyproject.toml': DALS(""" + [build-system] + requires = ["setuptools", "wheel"] + build-backend = "setuptools.build_meta + """), + } + + build_files(files) + + dist_dir = os.path.abspath('preexisting-' + build_type) + + build_backend = self.get_build_backend() + build_method = getattr(build_backend, 'build_' + build_type) + + # Build a first sdist/wheel. + # Note: this also check the destination directory is + # successfully created if it does not exist already. + first_result = build_method(dist_dir) + + # Change version. + with open("VERSION", "wt") as version_file: + version_file.write("0.0.2") + + # Build a *second* sdist/wheel. + second_result = build_method(dist_dir) + + assert os.path.isfile(os.path.join(dist_dir, first_result)) + assert first_result != second_result + + # And if rebuilding the exact same sdist/wheel? + open(os.path.join(dist_dir, second_result), 'w').close() + third_result = build_method(dist_dir) + assert third_result == second_result + assert os.path.getsize(os.path.join(dist_dir, third_result)) > 0 + def test_build_sdist(self, build_backend): dist_dir = os.path.abspath('pip-sdist') os.makedirs(dist_dir) @@ -287,6 +334,57 @@ class TestBuildMetaBackend: with pytest.raises(ImportError): build_backend.build_sdist("temp") + @pytest.mark.parametrize('setup_literal, requirements', [ + ("'foo'", ['foo']), + ("['foo']", ['foo']), + (r"'foo\n'", ['foo']), + (r"'foo\n\n'", ['foo']), + ("['foo', 'bar']", ['foo', 'bar']), + (r"'# Has a comment line\nfoo'", ['foo']), + (r"'foo # Has an inline comment'", ['foo']), + (r"'foo \\\n >=3.0'", ['foo>=3.0']), + (r"'foo\nbar'", ['foo', 'bar']), + (r"'foo\nbar\n'", ['foo', 'bar']), + (r"['foo\n', 'bar\n']", ['foo', 'bar']), + ]) + @pytest.mark.parametrize('use_wheel', [True, False]) + def test_setup_requires(self, setup_literal, requirements, use_wheel, + tmpdir_cwd): + + files = { + 'setup.py': DALS(""" + from setuptools import setup + + setup( + name="qux", + version="0.0.0", + py_modules=["hello.py"], + setup_requires={setup_literal}, + ) + """).format(setup_literal=setup_literal), + 'hello.py': DALS(""" + def run(): + print('hello') + """), + } + + build_files(files) + + build_backend = self.get_build_backend() + + if use_wheel: + base_requirements = ['wheel'] + get_requires = build_backend.get_requires_for_build_wheel + else: + base_requirements = [] + get_requires = build_backend.get_requires_for_build_sdist + + # Ensure that the build requirements are properly parsed + expected = sorted(base_requirements + requirements) + actual = get_requires() + + assert expected == sorted(actual) + class TestBuildMetaLegacyBackend(TestBuildMetaBackend): backend_name = 'setuptools.build_meta:__legacy__' diff --git a/setuptools/tests/test_config.py b/setuptools/tests/test_config.py index 6b177709..bc97664d 100644 --- a/setuptools/tests/test_config.py +++ b/setuptools/tests/test_config.py @@ -8,8 +8,7 @@ from distutils.errors import DistutilsOptionError, DistutilsFileError from mock import patch from setuptools.dist import Distribution, _Distribution from setuptools.config import ConfigHandler, read_configuration -from setuptools.extern.six.moves.configparser import InterpolationMissingOptionError -from setuptools.tests import is_ascii +from setuptools.extern.six.moves import configparser from . import py2_only, py3_only from .textwrap import DALS @@ -29,7 +28,9 @@ def make_package_dir(name, base_dir, ns=False): return dir_package, init_file -def fake_env(tmpdir, setup_cfg, setup_py=None, encoding='ascii', package_path='fake_package'): +def fake_env( + tmpdir, setup_cfg, setup_py=None, + encoding='ascii', package_path='fake_package'): if setup_py is None: setup_py = ( @@ -440,13 +441,10 @@ class TestMetadata: '[metadata]\n' 'description = %(message)s\n' ) - with pytest.raises(InterpolationMissingOptionError): + with pytest.raises(configparser.InterpolationMissingOptionError): with get_dist(tmpdir): pass - skip_if_not_ascii = pytest.mark.skipif(not is_ascii, reason='Test not supported with this locale') - - @skip_if_not_ascii def test_non_ascii_1(self, tmpdir): fake_env( tmpdir, @@ -454,18 +452,8 @@ class TestMetadata: 'description = éàïôñ\n', encoding='utf-8' ) - with pytest.raises(UnicodeDecodeError): - with get_dist(tmpdir): - pass - - def test_non_ascii_2(self, tmpdir): - fake_env( - tmpdir, - '# -*- coding: invalid\n' - ) - with pytest.raises(LookupError): - with get_dist(tmpdir): - pass + with get_dist(tmpdir): + pass def test_non_ascii_3(self, tmpdir): fake_env( @@ -476,7 +464,6 @@ class TestMetadata: with get_dist(tmpdir): pass - @skip_if_not_ascii def test_non_ascii_4(self, tmpdir): fake_env( tmpdir, @@ -488,8 +475,10 @@ class TestMetadata: with get_dist(tmpdir) as dist: assert dist.metadata.description == 'éàïôñ' - @skip_if_not_ascii - def test_non_ascii_5(self, tmpdir): + def test_not_utf8(self, tmpdir): + """ + Config files encoded not in UTF-8 will fail + """ fake_env( tmpdir, '# vim: set fileencoding=iso-8859-15 :\n' @@ -497,8 +486,9 @@ class TestMetadata: 'description = éàïôñ\n', encoding='iso-8859-15' ) - with get_dist(tmpdir) as dist: - assert dist.metadata.description == 'éàïôñ' + with pytest.raises(UnicodeDecodeError): + with get_dist(tmpdir): + pass class TestOptions: diff --git a/setuptools/tests/test_dist.py b/setuptools/tests/test_dist.py index 0c0b9d66..36237f24 100644 --- a/setuptools/tests/test_dist.py +++ b/setuptools/tests/test_dist.py @@ -4,8 +4,13 @@ from __future__ import unicode_literals import io import collections - -from setuptools.dist import DistDeprecationWarning, _get_unpatched +import re +from distutils.errors import DistutilsSetupError +from setuptools.dist import ( + _get_unpatched, + check_package_data, + DistDeprecationWarning, +) from setuptools import Distribution from setuptools.extern.six.moves.urllib.request import pathname2url from setuptools.extern.six.moves.urllib_parse import urljoin @@ -278,3 +283,48 @@ def test_provides_extras_deterministic_order(): reversed(list(attrs['extras_require'].items()))) dist = Distribution(attrs) assert dist.metadata.provides_extras == ['b', 'a'] + + +CHECK_PACKAGE_DATA_TESTS = ( + # Valid. + ({ + '': ['*.txt', '*.rst'], + 'hello': ['*.msg'], + }, None), + # Not a dictionary. + (( + ('', ['*.txt', '*.rst']), + ('hello', ['*.msg']), + ), ( + "'package_data' must be a dictionary mapping package" + " names to lists of string wildcard patterns" + )), + # Invalid key type. + ({ + 400: ['*.txt', '*.rst'], + }, ( + "keys of 'package_data' dict must be strings (got 400)" + )), + # Invalid value type. + ({ + 'hello': str('*.msg'), + }, ( + "\"values of 'package_data' dict\" must be a list of strings (got '*.msg')" + )), + # Invalid value type (generators are single use) + ({ + 'hello': (x for x in "generator"), + }, ( + "\"values of 'package_data' dict\" must be a list of strings " + "(got <generator object" + )), +) + + +@pytest.mark.parametrize('package_data, expected_message', CHECK_PACKAGE_DATA_TESTS) +def test_check_package_data(package_data, expected_message): + if expected_message is None: + assert check_package_data(None, 'package_data', package_data) is None + else: + with pytest.raises(DistutilsSetupError, match=re.escape(expected_message)): + check_package_data(None, str('package_data'), package_data) diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py index db9c3873..316eb2ed 100644 --- a/setuptools/tests/test_egg_info.py +++ b/setuptools/tests/test_egg_info.py @@ -622,6 +622,7 @@ class TestEggInfo: assert expected_line in pkg_info_lines expected_line = 'Project-URL: Link Two, https://example.com/two/' assert expected_line in pkg_info_lines + assert 'Metadata-Version: 1.2' in pkg_info_lines def test_python_requires_egg_info(self, tmpdir_cwd, env): self._setup_script_with_requires( diff --git a/setuptools/tests/test_integration.py b/setuptools/tests/test_integration.py index e54f3209..1e132188 100644 --- a/setuptools/tests/test_integration.py +++ b/setuptools/tests/test_integration.py @@ -141,6 +141,7 @@ def test_build_deps_on_distutils(request, tmpdir_factory, build_dep): allowed_unknowns = [ 'test_suite', 'tests_require', + 'python_requires', 'install_requires', ] assert not match or match.group(1).strip('"\'') in allowed_unknowns @@ -149,8 +150,8 @@ def test_build_deps_on_distutils(request, tmpdir_factory, build_dep): def install(pkg_dir, install_dir): with open(os.path.join(pkg_dir, 'setuptools.py'), 'w') as breaker: breaker.write('raise ImportError()') - cmd = [sys.executable, 'setup.py', 'install', '--prefix', install_dir] - env = dict(os.environ, PYTHONPATH=pkg_dir) + cmd = [sys.executable, 'setup.py', 'install', '--prefix', str(install_dir)] + env = dict(os.environ, PYTHONPATH=str(pkg_dir)) output = subprocess.check_output( cmd, cwd=pkg_dir, env=env, stderr=subprocess.STDOUT) return output.decode('utf-8') diff --git a/setuptools/tests/test_packageindex.py b/setuptools/tests/test_packageindex.py index ab371884..60d968fd 100644 --- a/setuptools/tests/test_packageindex.py +++ b/setuptools/tests/test_packageindex.py @@ -249,7 +249,7 @@ class TestPackageIndex: first_call_args = os_system_mock.call_args_list[0][0] assert first_call_args == (expected,) - tmpl = '(cd {expected_dir} && git checkout --quiet master)' + tmpl = 'git -C {expected_dir} checkout --quiet master' expected = tmpl.format(**locals()) assert os_system_mock.call_args_list[1][0] == (expected,) assert result == expected_dir diff --git a/setuptools/tests/test_setopt.py b/setuptools/tests/test_setopt.py new file mode 100644 index 00000000..3fb04fb4 --- /dev/null +++ b/setuptools/tests/test_setopt.py @@ -0,0 +1,36 @@ +# coding: utf-8 + +from __future__ import unicode_literals + +import io + +import six + +from setuptools.command import setopt +from setuptools.extern.six.moves import configparser + + +class TestEdit: + @staticmethod + def parse_config(filename): + parser = configparser.ConfigParser() + with io.open(filename, encoding='utf-8') as reader: + (parser.read_file if six.PY3 else parser.readfp)(reader) + return parser + + @staticmethod + def write_text(file, content): + with io.open(file, 'wb') as strm: + strm.write(content.encode('utf-8')) + + def test_utf8_encoding_retained(self, tmpdir): + """ + When editing a file, non-ASCII characters encoded in + UTF-8 should be retained. + """ + config = tmpdir.join('setup.cfg') + self.write_text(str(config), '[names]\njaraco=джарако') + setopt.edit_config(str(config), dict(names=dict(other='yes'))) + parser = self.parse_config(str(config)) + assert parser.get('names', 'jaraco') == 'джарако' + assert parser.get('names', 'other') == 'yes' diff --git a/setuptools/tests/test_virtualenv.py b/setuptools/tests/test_virtualenv.py index 3d5c84b0..74a1284c 100644 --- a/setuptools/tests/test_virtualenv.py +++ b/setuptools/tests/test_virtualenv.py @@ -8,6 +8,8 @@ from pytest_fixture_config import yield_requires_config import pytest_virtualenv +from setuptools.extern import six + from .textwrap import DALS from .test_easy_install import make_nspkg_sdist @@ -52,10 +54,58 @@ def test_clean_env_install(bare_virtualenv): )).format(source=SOURCE_DIR)) -def test_pip_upgrade_from_source(virtualenv): +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 + 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 + + network_versions = [ + 'pip==9.0.3', + 'pip==10.0.1', + 'pip==18.1', + 'pip==19.0.1', + ] + + # Pip's master dropped support for 3.4. + if not six.PY34: + network_versions.append('https://github.com/pypa/pip/archive/master.zip') + + versions = [None] + [ + pytest.param(v, **({} if network else {'marks': pytest.mark.skip})) + for v in network_versions + ] + + return versions + + +@pytest.mark.parametrize('pip_version', _get_pip_versions()) +def test_pip_upgrade_from_source(pip_version, virtualenv): """ Check pip can upgrade setuptools from source. """ + # Install pip/wheel, and remove setuptools (as it + # should not be needed for bootstraping from source) + if pip_version is None: + upgrade_pip = () + else: + upgrade_pip = ('python -m pip install -U {pip_version} --retries=1',) + virtualenv.run(' && '.join(( + 'pip uninstall -y setuptools', + 'pip install -U wheel', + ) + upgrade_pip).format(pip_version=pip_version)) dist_dir = virtualenv.workspace # Generate source distribution / wheel. virtualenv.run(' && '.join(( |