From 1cfa27c05bd6753c7a7c5fa4cb498c85ce088392 Mon Sep 17 00:00:00 2001 From: wim glenn Date: Fri, 29 Apr 2022 22:34:27 -0500 Subject: [PATCH] do not backfill Project-URL: homepage into Home-page: field (causes duplicates on PyPI). prevent "UNKNOWN" vals from appearing in summary, license, platform. prevent an extra newline getting added in long description --- setuptools/config/_apply_pyprojecttoml.py | 16 +------------ setuptools/dist.py | 22 +++++++++++++----- .../tests/config/test_apply_pyprojecttoml.py | 23 ++++++++++++------- 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/setuptools/config/_apply_pyprojecttoml.py b/setuptools/config/_apply_pyprojecttoml.py index fce5c40e34..a580b63f6f 100644 --- a/setuptools/config/_apply_pyprojecttoml.py +++ b/setuptools/config/_apply_pyprojecttoml.py @@ -171,21 +171,7 @@ def _people(dist: "Distribution", val: List[dict], _root_dir: _Path, kind: str): def _project_urls(dist: "Distribution", val: dict, _root_dir): - special = {"downloadurl": "download_url", "homepage": "url"} - for key, url in val.items(): - norm_key = json_compatible_key(key).replace("_", "") - _set_config(dist, special.get(norm_key, key), url) - # If `homepage` is missing, distutils will warn the following message: - # "warning: check: missing required meta-data: url" - # In the context of PEP 621, users might ask themselves: "which url?". - # Let's add a warning before distutils check to help users understand the problem: - if not dist.metadata.url: - msg = ( - "Missing `Homepage` url.\nIt is advisable to link some kind of reference " - "for your project (e.g. source code or documentation).\n" - ) - _logger.warning(msg) - _set_config(dist, "project_urls", val.copy()) + _set_config(dist, "project_urls", val) def _python_requires(dist: "Distribution", val: dict, _root_dir): diff --git a/setuptools/dist.py b/setuptools/dist.py index 215c88e3a8..5507167d30 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -102,7 +102,7 @@ def _read_list_from_msg(msg: "Message", field: str) -> Optional[List[str]]: def _read_payload_from_msg(msg: "Message") -> Optional[str]: value = msg.get_payload().strip() - if value == 'UNKNOWN': + if value == 'UNKNOWN' or not value: return None return value @@ -174,7 +174,10 @@ def write_field(key, value): write_field('Metadata-Version', str(version)) write_field('Name', self.get_name()) write_field('Version', self.get_version()) - write_field('Summary', single_line(self.get_description())) + + summary = self.get_description() + if summary: + write_field('Summary', single_line(summary)) optional_fields = ( ('Home-page', 'url'), @@ -190,8 +193,10 @@ def write_field(key, value): if attr_val is not None: write_field(field, attr_val) - license = rfc822_escape(self.get_license()) - write_field('License', license) + license = self.get_license() + if license: + write_field('License', rfc822_escape(license)) + for project_url in self.project_urls.items(): write_field('Project-URL', '%s, %s' % project_url) @@ -199,7 +204,8 @@ def write_field(key, value): if keywords: write_field('Keywords', keywords) - for platform in self.get_platforms(): + platforms = self.get_platforms() or [] + for platform in platforms: write_field('Platform', platform) self._write_list(file, 'Classifier', self.get_classifiers()) @@ -222,7 +228,11 @@ def write_field(key, value): self._write_list(file, 'License-File', self.license_files or []) - file.write("\n%s\n\n" % self.get_long_description()) + long_description = self.get_long_description() + if long_description: + file.write("\n%s" % long_description) + if not long_description.endswith("\n"): + file.write("\n") sequence = tuple, list diff --git a/setuptools/tests/config/test_apply_pyprojecttoml.py b/setuptools/tests/config/test_apply_pyprojecttoml.py index 045d7f40b6..4f541697aa 100644 --- a/setuptools/tests/config/test_apply_pyprojecttoml.py +++ b/setuptools/tests/config/test_apply_pyprojecttoml.py @@ -298,19 +298,26 @@ def test_example_file_not_in_wheel(self, setuptools_wheel): def core_metadata(dist) -> str: with io.StringIO() as buffer: dist.metadata.write_pkg_file(buffer) - value = "\n".join(buffer.getvalue().strip().splitlines()) + pkg_file_txt = buffer.getvalue() + skip_prefixes = () + skip_lines = set() # ---- DIFF NORMALISATION ---- # PEP 621 is very particular about author/maintainer metadata conversion, so skip - value = re.sub(r"^(Author|Maintainer)(-email)?:.*$", "", value, flags=re.M) + skip_prefixes += ("Author:", "Author-email:", "Maintainer:", "Maintainer-email:") # May be redundant with Home-page - value = re.sub(r"^Project-URL: Homepage,.*$", "", value, flags=re.M) + skip_prefixes += ("Project-URL: Homepage,", "Home-page:") # May be missing in original (relying on default) but backfilled in the TOML - value = re.sub(r"^Description-Content-Type:.*$", "", value, flags=re.M) + skip_prefixes += ("Description-Content-Type:",) # ini2toml can automatically convert `tests_require` to `testing` extra - value = value.replace("Provides-Extra: testing\n", "") + skip_lines.add("Provides-Extra: testing") # Remove empty lines - value = re.sub(r"^\s*$", "", value, flags=re.M) - value = re.sub(r"^\n", "", value, flags=re.M) + skip_lines.add("") - return value + result = [] + for line in pkg_file_txt.splitlines(): + if line.startswith(skip_prefixes) or line in skip_lines: + continue + result.append(line + "\n") + + return "".join(result)