diff options
| author | Paul Ganssle <pganssle@users.noreply.github.com> | 2018-12-31 17:27:40 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-12-31 17:27:40 -0500 |
| commit | f5c04b1bb6c2f97305d7a92ce401194c5195197e (patch) | |
| tree | edeb927b51212a57e785b8f6a06b7f61b3599f48 /setuptools | |
| parent | 0c9624fd5ee5abe3fb0d1e3dfa68a9cbaf261aed (diff) | |
| parent | 3db95bcc3dcc72dbb47d7dfc987ae646b249addd (diff) | |
| download | python-setuptools-git-f5c04b1bb6c2f97305d7a92ce401194c5195197e.tar.gz | |
Merge pull request #1559 from RajdeepRao/BUG-1551
Disallow files for license inputs
Diffstat (limited to 'setuptools')
| -rw-r--r-- | setuptools/config.py | 22 | ||||
| -rw-r--r-- | setuptools/tests/test_config.py | 20 | ||||
| -rw-r--r-- | setuptools/tests/test_egg_info.py | 35 |
3 files changed, 73 insertions, 4 deletions
diff --git a/setuptools/config.py b/setuptools/config.py index d1ac6734..3a6da20f 100644 --- a/setuptools/config.py +++ b/setuptools/config.py @@ -247,6 +247,24 @@ class ConfigHandler: return value in ('1', 'true', 'yes') @classmethod + def _exclude_files_parser(cls, key): + """Returns a parser function to make sure field inputs + are not files. + + Parses a value after getting the key so error messages are + more informative. + + :param key: + :rtype: callable + """ + def parser(value): + exclude_directive = 'file:' + if value.startswith(exclude_directive): + raise ValueError('Only strings are accepted for the {0} field, files are not accepted'.format(key)) + return value + return parser + + @classmethod def _parse_file(cls, value): """Represents value as a string, allowing including text from nearest files using `file:` directive. @@ -255,7 +273,6 @@ class ConfigHandler: directory with setup.py. Examples: - file: LICENSE file: README.rst, CHANGELOG.md, src/file.txt :param str value: @@ -449,6 +466,7 @@ class ConfigMetadataHandler(ConfigHandler): parse_list = self._parse_list parse_file = self._parse_file parse_dict = self._parse_dict + exclude_files_parser = self._exclude_files_parser return { 'platforms': parse_list, @@ -460,7 +478,7 @@ class ConfigMetadataHandler(ConfigHandler): DeprecationWarning), 'obsoletes': parse_list, 'classifiers': self._get_parser_compound(parse_file, parse_list), - 'license': parse_file, + 'license': exclude_files_parser('license'), 'description': parse_file, 'long_description': parse_file, 'version': self._parse_version, diff --git a/setuptools/tests/test_config.py b/setuptools/tests/test_config.py index 736c184d..53b8a956 100644 --- a/setuptools/tests/test_config.py +++ b/setuptools/tests/test_config.py @@ -1,10 +1,12 @@ import contextlib import pytest + from distutils.errors import DistutilsOptionError, DistutilsFileError from mock import patch from setuptools.dist import Distribution, _Distribution from setuptools.config import ConfigHandler, read_configuration from . import py2_only, py3_only +from .textwrap import DALS class ErrConfigHandler(ConfigHandler): """Erroneous handler. Fails to implement required methods.""" @@ -146,6 +148,24 @@ class TestMetadata: assert metadata.download_url == 'http://test.test.com/test/' assert metadata.maintainer_email == 'test@test.com' + def test_license_cfg(self, tmpdir): + fake_env( + tmpdir, + DALS(""" + [metadata] + name=foo + version=0.0.1 + license=Apache 2.0 + """) + ) + + with get_dist(tmpdir) as dist: + metadata = dist.metadata + + assert metadata.name == "foo" + assert metadata.version == "0.0.1" + assert metadata.license == "Apache 2.0" + def test_file_mixed(self, tmpdir): fake_env( diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py index f97b3f1d..979ff18e 100644 --- a/setuptools/tests/test_egg_info.py +++ b/setuptools/tests/test_egg_info.py @@ -148,6 +148,37 @@ class TestEggInfo: ] assert sorted(actual) == expected + def test_license_is_a_string(self, tmpdir_cwd, env): + setup_config = DALS(""" + [metadata] + name=foo + version=0.0.1 + license=file:MIT + """) + + setup_script = DALS(""" + from setuptools import setup + + setup() + """) + + build_files({'setup.py': setup_script, + 'setup.cfg': setup_config}) + + # This command should fail with a ValueError, but because it's + # currently configured to use a subprocess, the actual traceback + # object is lost and we need to parse it from stderr + with pytest.raises(AssertionError) as exc: + self._run_egg_info_command(tmpdir_cwd, env) + + # Hopefully this is not too fragile: the only argument to the + # assertion error should be a traceback, ending with: + # ValueError: .... + # + # assert not 1 + tb = exc.value.args[0].split('\n') + assert tb[-3].lstrip().startswith('ValueError') + def test_rebuilt(self, tmpdir_cwd, env): """Ensure timestamps are updated when the command is re-run.""" self._create_project() @@ -597,8 +628,8 @@ class TestEggInfo: data_stream=1, env=environ, ) - if code: - raise AssertionError(data) + assert not code, data + if output: assert output in data |
