Skip to content

Commit

Permalink
Back-fill Description-Content-Type according to readme suffix
Browse files Browse the repository at this point in the history
According to PEP 621, the backend should fill-in the content-type if the
`readme` field is passed as a string. The value is derived from the
extension of the file (an error should be raised when that is not
possible).

Previously all READMEs were wrongly assumed rst.
This error was reported in:

https://discuss.python.org/t/help-testing-experimental-features-in-setuptools/13821/4
  • Loading branch information
abravalheri committed Feb 23, 2022
1 parent 19b6ce2 commit 979596a
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 5 deletions.
25 changes: 23 additions & 2 deletions setuptools/config/_apply_pyprojecttoml.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,39 @@ def _set_config(dist: "Distribution", field: str, value: Any):
setattr(dist, field, value)


_CONTENT_TYPES = {
".md": "text/markdown",
".rst": "text/x-rst",
".txt": "text/plain",
}


def _guess_content_type(file: str) -> Optional[str]:
_, ext = os.path.splitext(file.lower())
if not ext:
return None

if ext in _CONTENT_TYPES:
return _CONTENT_TYPES[ext]

valid = ", ".join(f"{k} ({v})" for k, v in _CONTENT_TYPES.items())
msg = f"only the following file extensions are recognized: {valid}."
raise ValueError(f"Undefined content type for {file}, {msg}")


def _long_description(dist: "Distribution", val: _DictOrStr, root_dir: _Path):
from setuptools.config import expand

if isinstance(val, str):
text = expand.read_files(val, root_dir)
ctype = "text/x-rst"
ctype = _guess_content_type(val)
else:
text = val.get("text") or expand.read_files(val.get("file", []), root_dir)
ctype = val["content-type"]

_set_config(dist, "long_description", text)
_set_config(dist, "long_description_content_type", ctype)
if ctype:
_set_config(dist, "long_description_content_type", ctype)


def _license(dist: "Distribution", val: Union[str, dict], _root_dir):
Expand Down
41 changes: 38 additions & 3 deletions setuptools/tests/config/test_apply_pyprojecttoml.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,18 +129,53 @@ def main_tomatoes(): pass
"""


def test_pep621_example(tmp_path):
"""Make sure the example in PEP 621 works"""
def _pep621_example_project(tmp_path, readme="README.rst"):
pyproject = tmp_path / "pyproject.toml"
pyproject.write_text(PEP621_EXAMPLE)
text = PEP621_EXAMPLE
replacements = {'readme = "README.rst"': f'readme = "{readme}"'}
for orig, subst in replacements.items():
text = text.replace(orig, subst)
pyproject.write_text(text)

(tmp_path / "README.rst").write_text("hello world")
(tmp_path / "LICENSE.txt").write_text("--- LICENSE stub ---")
(tmp_path / "spam.py").write_text(PEP621_EXAMPLE_SCRIPT)
return pyproject


def test_pep621_example(tmp_path):
"""Make sure the example in PEP 621 works"""
pyproject = _pep621_example_project(tmp_path)
dist = pyprojecttoml.apply_configuration(Distribution(), pyproject)
assert set(dist.metadata.license_files) == {"LICENSE.txt"}


@pytest.mark.parametrize(
"readme, ctype",
[
("Readme.txt", "text/plain"),
("readme.md", "text/markdown"),
("text.rst", "text/x-rst"),
]
)
def test_readme_content_type(tmp_path, readme, ctype):
pyproject = _pep621_example_project(tmp_path, readme)
dist = pyprojecttoml.apply_configuration(Distribution(), pyproject)
assert dist.metadata.long_description_content_type == ctype


def test_undefined_content_type(tmp_path):
pyproject = _pep621_example_project(tmp_path, "README.tex")
with pytest.raises(ValueError, match="Undefined content type for README.tex"):
pyprojecttoml.apply_configuration(Distribution(), pyproject)


def test_no_explicit_content_type_for_missing_extension(tmp_path):
pyproject = _pep621_example_project(tmp_path, "README")
dist = pyprojecttoml.apply_configuration(Distribution(), pyproject)
assert dist.metadata.long_description_content_type is None


# --- Auxiliary Functions ---


Expand Down

0 comments on commit 979596a

Please sign in to comment.