Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions pyproject_metadata/project_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,9 @@ def _(prefix: str, data: object, error_collector: SimpleErrorCollector) -> None:
if "content-type" not in data:
msg = f'Field "{prefix}" is missing required key "content-type"'
error_collector.error(ConfigurationError(msg, key=prefix))
elif data["content-type"] == "":
msg = f'Field "{prefix}.content-type" must not be empty'
error_collector.error(ConfigurationError(msg, key=f"{prefix}.content-type"))


@validate_via_prefix.register(r"project\.version")
Expand Down
10 changes: 6 additions & 4 deletions pyproject_metadata/pyproject.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,11 @@ def get_license(
filename = _license.get("file")
text = _license.get("text")

if (filename and text) or (not filename and not text):
# Reported by the project.license validator
if (filename is None) == (text is None):
return None

if filename:
if filename is not None:
file = project_dir.joinpath(filename)
if not file.is_file():
msg = "License file not found ({filename!r})"
Expand Down Expand Up @@ -212,14 +213,15 @@ def get_readme( # noqa: C901
if text is None:
return None

if (filename and text) or (not filename and not text):
# Reported by the project.readme validator
if (filename is None) == (text is None):
return None
if not content_type:
return None
else:
return None

if filename:
if filename is not None:
file = project_dir.joinpath(filename)
if not file.is_file():
msg = "Readme file not found ({filename!r})"
Expand Down
42 changes: 39 additions & 3 deletions tests/test_standard_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,16 @@ def all_errors(request: pytest.FixtureRequest, monkeypatch: pytest.MonkeyPatch)
'Field "project.readme" is missing required key "content-type"',
id="Missing content-type for readme (text only)",
),
pytest.param(
"""
[project]
name = "test"
version = "0.1.0"
readme = { text = "...", content-type = "" }
""",
'Field "project.readme.content-type" must not be empty',
id="Empty content-type for readme",
),
pytest.param(
"""
[project]
Expand Down Expand Up @@ -1430,18 +1440,44 @@ def test_as_json(monkeypatch: pytest.MonkeyPatch) -> None:
}


def test_readme_text() -> None:
@pytest.mark.parametrize("text", ["onetwothree", ""])
def test_readme_text(text: str) -> None:
pyproject = pyproject_metadata.StandardMetadata.from_pyproject(
{
"project": {
"name": "foo",
"version": "1.2.3",
"readme": {"text": "onetwothree", "content-type": "text/plain"},
"readme": {"text": text, "content-type": "text/plain"},
}
}
)
assert pyproject.readme
assert pyproject.readme.text == "onetwothree"
assert pyproject.readme.text == text
assert pyproject.readme.content_type == "text/plain"
assert pyproject.as_rfc822()["Description-Content-Type"] == "text/plain"
assert pyproject.as_json()["description"] == text


def test_empty_license_text() -> None:
pyproject = pyproject_metadata.StandardMetadata.from_pyproject(
{"project": {"name": "x", "version": "1.0", "license": {"text": ""}}}
)
assert pyproject.license == pyproject_metadata.License("", file=None)
assert pyproject.as_rfc822()["License"] == ""


@pytest.mark.parametrize(
("field", "value"),
[
("readme", {"file": "", "content-type": "text/plain"}),
("license", {"file": ""}),
],
)
def test_empty_metadata_filename(field: str, value: dict[str, str]) -> None:
with pytest.raises(pyproject_metadata.ConfigurationError, match="file not found"):
pyproject_metadata.StandardMetadata.from_pyproject(
{"project": {"name": "x", "version": "1.0", field: value}}
)


def test_as_rfc822(monkeypatch: pytest.MonkeyPatch) -> None:
Expand Down
Loading