diff options
author | Jason R. Coombs <jaraco@jaraco.com> | 2021-04-14 19:04:50 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-14 19:04:50 -0400 |
commit | 07eda18d6c4cf987ea57a2f9cf3deff9f0bf0105 (patch) | |
tree | 5b8a940400c3c5e408edf6d2e974cc3e51b3b542 | |
parent | 1d330f9daded60f0d7721b51d8027494c5bf11d3 (diff) | |
parent | c18ed8706d759e11d7bb7e9070a1897ee2f1e979 (diff) | |
download | python-setuptools-git-07eda18d6c4cf987ea57a2f9cf3deff9f0bf0105.tar.gz |
Merge pull request #2635 from cdce8p/refactor-dist
Refactor ``read_pkg_file``
-rw-r--r-- | setuptools/dist.py | 83 | ||||
-rw-r--r-- | setuptools/tests/test_dist.py | 40 |
2 files changed, 95 insertions, 28 deletions
diff --git a/setuptools/dist.py b/setuptools/dist.py index 7cebcb37..c7af35dc 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -16,6 +16,8 @@ from distutils.util import strtobool from distutils.debug import DEBUG from distutils.fancy_getopt import translate_longopt import itertools +import textwrap +from typing import List, Optional, TYPE_CHECKING from collections import defaultdict from email import message_from_file @@ -36,6 +38,9 @@ from setuptools.monkey import get_unpatched from setuptools.config import parse_configuration import pkg_resources +if TYPE_CHECKING: + from email.message import Message + __import__('setuptools.extern.packaging.specifiers') __import__('setuptools.extern.packaging.version') @@ -67,53 +72,75 @@ def get_metadata_version(self): return mv -def read_pkg_file(self, file): - """Reads the metadata values from a file object.""" - msg = message_from_file(file) +def rfc822_unescape(content: str) -> str: + """Reverse RFC-822 escaping by removing leading whitespaces from content.""" + lines = content.splitlines() + if len(lines) == 1: + return lines[0].lstrip() + return '\n'.join( + (lines[0].lstrip(), + textwrap.dedent('\n'.join(lines[1:])))) + + +def _read_field_from_msg(msg: "Message", field: str) -> Optional[str]: + """Read Message header field.""" + value = msg[field] + if value == 'UNKNOWN': + return None + return value + - def _read_field(name): - value = msg[name] - if value == 'UNKNOWN': - return None +def _read_field_unescaped_from_msg(msg: "Message", field: str) -> Optional[str]: + """Read Message header field and apply rfc822_unescape.""" + value = _read_field_from_msg(msg, field) + if value is None: return value + return rfc822_unescape(value) - def _read_list(name): - values = msg.get_all(name, None) - if values == []: - return None - return values + +def _read_list_from_msg(msg: "Message", field: str) -> Optional[List[str]]: + """Read Message header field and return all results as list.""" + values = msg.get_all(field, None) + if values == []: + return None + return values + + +def read_pkg_file(self, file): + """Reads the metadata values from a file object.""" + msg = message_from_file(file) self.metadata_version = StrictVersion(msg['metadata-version']) - self.name = _read_field('name') - self.version = _read_field('version') - self.description = _read_field('summary') + self.name = _read_field_from_msg(msg, 'name') + self.version = _read_field_from_msg(msg, 'version') + self.description = _read_field_from_msg(msg, 'summary') # we are filling author only. - self.author = _read_field('author') + self.author = _read_field_from_msg(msg, 'author') self.maintainer = None - self.author_email = _read_field('author-email') + self.author_email = _read_field_from_msg(msg, 'author-email') self.maintainer_email = None - self.url = _read_field('home-page') - self.license = _read_field('license') + self.url = _read_field_from_msg(msg, 'home-page') + self.license = _read_field_from_msg(msg, 'license') if 'download-url' in msg: - self.download_url = _read_field('download-url') + self.download_url = _read_field_from_msg(msg, 'download-url') else: self.download_url = None - self.long_description = _read_field('description') - self.description = _read_field('summary') + self.long_description = _read_field_unescaped_from_msg(msg, 'description') + self.description = _read_field_from_msg(msg, 'summary') if 'keywords' in msg: - self.keywords = _read_field('keywords').split(',') + self.keywords = _read_field_from_msg(msg, 'keywords').split(',') - self.platforms = _read_list('platform') - self.classifiers = _read_list('classifier') + self.platforms = _read_list_from_msg(msg, 'platform') + self.classifiers = _read_list_from_msg(msg, 'classifier') # PEP 314 - these fields only exist in 1.1 if self.metadata_version == StrictVersion('1.1'): - self.requires = _read_list('requires') - self.provides = _read_list('provides') - self.obsoletes = _read_list('obsoletes') + self.requires = _read_list_from_msg(msg, 'requires') + self.provides = _read_list_from_msg(msg, 'provides') + self.obsoletes = _read_list_from_msg(msg, 'obsoletes') else: self.requires = None self.provides = None diff --git a/setuptools/tests/test_dist.py b/setuptools/tests/test_dist.py index e4bba47b..dcec1734 100644 --- a/setuptools/tests/test_dist.py +++ b/setuptools/tests/test_dist.py @@ -10,6 +10,8 @@ from setuptools.dist import ( check_package_data, DistDeprecationWarning, check_specifier, + rfc822_escape, + rfc822_unescape, ) from setuptools import sic from setuptools import Distribution @@ -85,6 +87,9 @@ def __read_test_cases(): ('Metadata version 1.1: Provides', params( provides=['package'], )), + ('Metadata Version 1.0: Short long description', params( + long_description='Short long description', + )), ('Metadata version 1.1: Obsoletes', params( obsoletes=['foo'], )), @@ -162,6 +167,7 @@ def test_read_metadata(name, attrs): ('metadata_version', dist_class.get_metadata_version), ('provides', dist_class.get_provides), ('description', dist_class.get_description), + ('long_description', dist_class.get_long_description), ('download_url', dist_class.get_download_url), ('keywords', dist_class.get_keywords), ('platforms', dist_class.get_platforms), @@ -336,3 +342,37 @@ def test_check_specifier(): attrs = {'name': 'foo', 'python_requires': ['>=3.0', '!=3.1']} with pytest.raises(DistutilsSetupError): dist = Distribution(attrs) + + +@pytest.mark.parametrize( + 'content, result', + ( + pytest.param( + "Just a single line", + None, + id="single_line", + ), + pytest.param( + "Multiline\nText\nwithout\nextra indents\n", + None, + id="multiline", + ), + pytest.param( + "Multiline\n With\n\nadditional\n indentation", + None, + id="multiline_with_indentation", + ), + pytest.param( + " Leading whitespace", + "Leading whitespace", + id="remove_leading_whitespace", + ), + pytest.param( + " Leading whitespace\nIn\n Multiline comment", + "Leading whitespace\nIn\n Multiline comment", + id="remove_leading_whitespace_multiline", + ), + ) +) +def test_rfc822_unescape(content, result): + assert (result or content) == rfc822_unescape(rfc822_escape(content)) |