diff options
-rw-r--r-- | docs/setuptools.txt | 1 | ||||
-rwxr-xr-x | setup.py | 5 | ||||
-rwxr-xr-x | setuptools/command/egg_info.py | 1 | ||||
-rw-r--r-- | setuptools/config.py | 2 | ||||
-rw-r--r-- | setuptools/dist.py | 11 | ||||
-rw-r--r-- | setuptools/tests/test_config.py | 16 | ||||
-rw-r--r-- | setuptools/tests/test_egg_info.py | 30 |
7 files changed, 65 insertions, 1 deletions
diff --git a/docs/setuptools.txt b/docs/setuptools.txt index c2822c4f..e3154b46 100644 --- a/docs/setuptools.txt +++ b/docs/setuptools.txt @@ -2406,6 +2406,7 @@ name str version attr:, str url home-page str download_url download-url str +project_urls dict author str author_email author-email str maintainer str @@ -98,6 +98,11 @@ setup_params = dict( long_description_content_type='text/x-rst; charset=UTF-8', keywords="CPAN PyPI distutils eggs package management", url="https://github.com/pypa/setuptools", + project_urls={ + "Bug Tracker": "https://github.com/pypa/setuptools/issues", + "Documentation": "http://setuptools.readthedocs.io/", + "Source Code": "https://github.com/pypa/setuptools", + }, src_root=None, packages=setuptools.find_packages(exclude=['*.tests']), package_data=package_data, diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py index a1d41b27..c8b2bd17 100755 --- a/setuptools/command/egg_info.py +++ b/setuptools/command/egg_info.py @@ -597,6 +597,7 @@ def write_pkg_info(cmd, basename, filename): metadata = cmd.distribution.metadata metadata.version, oldver = cmd.egg_version, metadata.version metadata.name, oldname = cmd.egg_name, metadata.name + metadata.project_urls = cmd.distribution.metadata.project_urls metadata.long_description_content_type = getattr( cmd.distribution, 'long_description_content_type' diff --git a/setuptools/config.py b/setuptools/config.py index 53828447..a70794a4 100644 --- a/setuptools/config.py +++ b/setuptools/config.py @@ -404,6 +404,7 @@ class ConfigMetadataHandler(ConfigHandler): """Metadata item name to parser function mapping.""" parse_list = self._parse_list parse_file = self._parse_file + parse_dict = self._parse_dict return { 'platforms': parse_list, @@ -416,6 +417,7 @@ class ConfigMetadataHandler(ConfigHandler): 'description': parse_file, 'long_description': parse_file, 'version': self._parse_version, + 'project_urls': parse_dict, } def _parse_version(self, value): diff --git a/setuptools/dist.py b/setuptools/dist.py index aa304500..fa03cd27 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -44,7 +44,7 @@ def write_pkg_file(self, file): self.classifiers or self.download_url): version = '1.1' # Setuptools specific for PEP 345 - if hasattr(self, 'python_requires'): + if hasattr(self, 'python_requires') or self.project_urls: version = '1.2' file.write('Metadata-Version: %s\n' % version) @@ -57,6 +57,8 @@ def write_pkg_file(self, file): file.write('License: %s\n' % self.get_license()) if self.download_url: file.write('Download-URL: %s\n' % self.download_url) + for project_url in self.project_urls.items(): + file.write('Project-URL: %s, %s\n' % project_url) long_desc_content_type = getattr( self, @@ -327,11 +329,18 @@ class Distribution(Distribution_parse_config_files, _Distribution): self.long_description_content_type = attrs.get( 'long_description_content_type' ) + self.project_urls = attrs.get('project_urls', {}) self.dependency_links = attrs.pop('dependency_links', []) self.setup_requires = attrs.pop('setup_requires', []) for ep in pkg_resources.iter_entry_points('distutils.setup_keywords'): vars(self).setdefault(ep.name, None) _Distribution.__init__(self, attrs) + + # The project_urls attribute may not be supported in distutils, so + # prime it here from our value if not automatically set + self.metadata.project_urls = getattr( + self.metadata, 'project_urls', self.project_urls) + if isinstance(self.metadata.version, numbers.Number): # Some people apparently take "version number" too literally :) self.metadata.version = str(self.metadata.version) diff --git a/setuptools/tests/test_config.py b/setuptools/tests/test_config.py index cdfa5af4..a69bca46 100644 --- a/setuptools/tests/test_config.py +++ b/setuptools/tests/test_config.py @@ -215,6 +215,22 @@ class TestMetadata: 'Programming Language :: Python :: 3.5', ] + def test_dict(self, tmpdir): + + fake_env( + tmpdir, + '[metadata]\n' + 'project_urls =\n' + ' Link One = https://example.com/one/\n' + ' Link Two = https://example.com/two/\n' + ) + with get_dist(tmpdir) as dist: + metadata = dist.metadata + assert metadata.project_urls == { + 'Link One': 'https://example.com/one/', + 'Link Two': 'https://example.com/two/', + } + def test_version(self, tmpdir): _, config = fake_env( diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py index a97d0c84..e05498b8 100644 --- a/setuptools/tests/test_egg_info.py +++ b/setuptools/tests/test_egg_info.py @@ -417,6 +417,36 @@ class TestEggInfo(object): expected_line = 'Description-Content-Type: text/markdown' assert expected_line in pkg_info_lines + def test_project_urls(self, tmpdir_cwd, env): + # Test that specifying a `project_urls` dict to the `setup` + # function results in writing multiple `Project-URL` lines to + # the `PKG-INFO` file in the `<distribution>.egg-info` + # directory. + # `Project-URL` is described at https://packaging.python.org + # /specifications/core-metadata/#project-url-multiple-use + + self._setup_script_with_requires( + """project_urls={ + 'Link One': 'https://example.com/one/', + 'Link Two': 'https://example.com/two/', + },""") + environ = os.environ.copy().update( + HOME=env.paths['home'], + ) + code, data = environment.run_setup_py( + cmd=['egg_info'], + pypath=os.pathsep.join([env.paths['lib'], str(tmpdir_cwd)]), + data_stream=1, + env=environ, + ) + egg_info_dir = os.path.join('.', 'foo.egg-info') + with open(os.path.join(egg_info_dir, 'PKG-INFO')) as pkginfo_file: + pkg_info_lines = pkginfo_file.read().split('\n') + expected_line = 'Project-URL: Link One, https://example.com/one/' + assert expected_line in pkg_info_lines + expected_line = 'Project-URL: Link Two, https://example.com/two/' + assert expected_line in pkg_info_lines + def test_python_requires_egg_info(self, tmpdir_cwd, env): self._setup_script_with_requires( """python_requires='>=2.7.12',""") |