diff options
| -rw-r--r-- | setuptools/dist.py | 21 | ||||
| -rw-r--r-- | setuptools/tests/test_dist.py | 40 |
2 files changed, 60 insertions, 1 deletions
diff --git a/setuptools/dist.py b/setuptools/dist.py index 8b687af7..c7af35dc 100644 --- a/setuptools/dist.py +++ b/setuptools/dist.py @@ -16,6 +16,7 @@ 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 @@ -71,6 +72,16 @@ def get_metadata_version(self): return mv +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] @@ -79,6 +90,14 @@ def _read_field_from_msg(msg: "Message", field: str) -> Optional[str]: return value +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_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) @@ -108,7 +127,7 @@ def read_pkg_file(self, file): else: self.download_url = None - self.long_description = _read_field_from_msg(msg, 'description') + self.long_description = _read_field_unescaped_from_msg(msg, 'description') self.description = _read_field_from_msg(msg, 'summary') if 'keywords' in msg: 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)) |
