Skip to content

Commit

Permalink
fix: update implementation of PEP 639 (#120)
Browse files Browse the repository at this point in the history
  • Loading branch information
frostming authored Aug 29, 2022
1 parent 8d43250 commit aa7aecb
Show file tree
Hide file tree
Showing 10 changed files with 40 additions and 66 deletions.
1 change: 1 addition & 0 deletions news/120.bugfix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Update the implementation of PEP 639 according to the lastest changes.
10 changes: 4 additions & 6 deletions pdm/pep517/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""
from __future__ import annotations

import shutil
from pathlib import Path
from typing import Any, Mapping

Expand Down Expand Up @@ -48,12 +49,9 @@ def _prepare_metadata(builder: WheelBuilder, metadata_directory: str) -> str:
builder._write_metadata_file(f)

for license_file in builder.find_license_files():
(dist_info / "license_files" / license_file).parent.mkdir(
parents=True, exist_ok=True
)
(dist_info / "license_files" / license_file).write_bytes(
Path(license_file).read_bytes()
)
full_path = dist_info / "licenses" / license_file
full_path.parent.mkdir(exist_ok=True, parents=True)
shutil.copy2(license_file, full_path)

return dist_info.name

Expand Down
2 changes: 1 addition & 1 deletion pdm/pep517/license.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def normalize_expression(expression: str) -> str:
"""Normalize a SPDX license expression."""
validate_result = _licensing.validate(expression)
if validate_result.errors:
raise MetadataError("license-expression", validate_result.errors)
raise MetadataError("license", validate_result.errors)
result = validate_result.normalized_expression or expression
if result != expression:
warnings.warn(
Expand Down
46 changes: 20 additions & 26 deletions pdm/pep517/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

from pdm.pep517._vendor.packaging.requirements import Requirement
from pdm.pep517.exceptions import MetadataError, PDMWarning, ProjectError
from pdm.pep517.license import normalize_expression
from pdm.pep517.utils import (
cd,
ensure_pep440_req,
Expand Down Expand Up @@ -161,13 +160,6 @@ def classifiers(self) -> list[str]:
PDMWarning,
stacklevel=2,
)
# if any(line.startswith("License :: ") for line in classifers):
# show_warning(
# "License classifiers are deprecated in favor of PEP 639 "
# "'license-expression' field.",
# PDMWarning,
# stacklevel=2,
# )

return sorted(classifers)

Expand All @@ -176,32 +168,34 @@ def classifiers(self) -> list[str]:

@property
def license_expression(self) -> str | None:
if "license-expression" in self.data:
if "license" in self.data:
raise MetadataError(
"license-expression",
"Can't specify both 'license' and 'license-expression' fields",
)
return normalize_expression(self.data["license-expression"])
elif "license" in self.data and "text" in self.data["license"]:
if "license" in self.data:
if isinstance(self.data["license"], str):
return self.data["license"]
# show_warning(
# "'license' field is deprecated in favor of 'license-expression'",
# "'license.text' subtable is deprecated in favor of string 'license' "
# "value",
# PDMWarning,
# stacklevel=2,
# )
# TODO: do not validate legacy license text,
# remove this after PEP 639 is finalized
return self.data["license"]["text"]
elif "license-expression" not in (self.dynamic or []):
show_warning("'license-expression' is missing", PDMWarning, stacklevel=2)
if "text" in self.data["license"]:
return self.data["license"]["text"]
show_warning("'license' is missing", PDMWarning, stacklevel=2)
return None

@property
def license_files(self) -> dict[str, list[str]]:
subtable_files = None
if (
"license" in self.data
and isinstance(self.data["license"], dict)
and "files" in self.data["license"]
):
subtable_files = self.data["license"]["files"]
if "license-files" not in self.data:
if self.data.get("license", {}).get("file"):
if subtable_files is not None:
# show_warning(
# "'license.file' field is deprecated in favor of 'license-files'",
# "'license.files' subtable is deprecated in favor of "
# "'license-files'",
# PDMWarning,
# stacklevel=2,
# )
Expand All @@ -215,10 +209,10 @@ def license_files(self) -> dict[str, list[str]]:
"AUTHORS*",
]
}
if "license" in self.data:
if subtable_files is not None:
raise MetadataError(
"license-files",
"Can't specify both 'license' and 'license-files' fields",
"Can't specify both 'license.files' and 'license-files' fields",
)
rv = self.data["license-files"]
valid_keys = {"globs", "paths"} & set(rv)
Expand Down
2 changes: 1 addition & 1 deletion pdm/pep517/validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
]

LICENSE_RULE = [
{"type": "string"},
{"type": "dict", "schema": {"file": {"type": "string", "required": True}}},
{"type": "dict", "schema": {"text": {"type": "string", "required": True}}},
]
Expand Down Expand Up @@ -53,7 +54,6 @@
"readme": {"oneof": README_RULE},
"requires-python": {"type": "string"},
"license": {"oneof": LICENSE_RULE},
"license-expression": {"type": "string"},
"license-files": {"oneof": LICENSE_FILE_RULE},
"authors": AUTHOR_RULE,
"maintainers": AUTHOR_RULE,
Expand Down
2 changes: 1 addition & 1 deletion pdm/pep517/wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ def _write_metadata(self) -> None:

for license_file in self.find_license_files():
self._add_file(
f"{dist_info}/license_files/{license_file}",
f"{dist_info}/licenses/{license_file}",
self.location / license_file,
)

Expand Down
2 changes: 1 addition & 1 deletion tests/fixtures/projects/demo-no-license/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ authors = [
]
dynamic = ["version"]
requires-python = ">=3.5"
license-expression = "MIT"
license = "MIT"
dependencies = []
description = ""
name = "demo-module"
Expand Down
4 changes: 2 additions & 2 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def test_build_single_module(tmp_path: Path) -> None:
for name in ("pyproject.toml", "LICENSE"):
assert name not in zip_names

assert "demo_module-0.1.0.dist-info/license_files/LICENSE" in zip_names
assert "demo_module-0.1.0.dist-info/licenses/LICENSE" in zip_names


def test_build_package(tmp_path: Path) -> None:
Expand Down Expand Up @@ -200,7 +200,7 @@ def test_build_editable(tmp_path: Path) -> None:
namelist = zf.namelist()
assert "demo_package.pth" in namelist
assert "__editables_demo_package.py" in namelist
assert "demo_package-0.1.0.dist-info/license_files/LICENSE" in namelist
assert "demo_package-0.1.0.dist-info/licenses/LICENSE" in namelist

metadata = email.message_from_bytes(
zf.read("demo_package-0.1.0.dist-info/METADATA")
Expand Down
31 changes: 6 additions & 25 deletions tests/test_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,24 +158,6 @@ def test_license_classifiers_warning(recwarn) -> None:
)


def test_both_license_and_license_expression_error() -> None:
metadata = make_metadata(
{
"description": "test package",
"name": "demo",
"version": "0.1.0",
"license": {"text": "MIT"},
"license-expression": "MIT",
}
)
with pytest.raises(
ValueError,
match="license-expression: Can't specify both 'license' and "
"'license-expression' fields",
):
metadata.license_expression


@pytest.mark.deprecation
@pytest.mark.xfail(reason="Don't emit warning until PEP 639 is accepted")
def test_deprecated_license_field_warning(recwarn) -> None:
Expand Down Expand Up @@ -204,9 +186,7 @@ def test_missing_license_expression_warning(recwarn) -> None:
)
assert not metadata.license_expression
assert len(recwarn) == 1
assert str(recwarn.pop(UserWarning).message).startswith(
"'license-expression' is missing"
)
assert str(recwarn.pop(UserWarning).message).startswith("'license' is missing")


@pytest.mark.deprecation
Expand All @@ -217,7 +197,6 @@ def test_deprecated_license_file_warning(recwarn) -> None:
"description": "test package",
"name": "demo",
"version": "0.1.0",
"license-expression": "MIT",
"license": {"file": "LICENSE"},
}
)
Expand All @@ -234,21 +213,22 @@ def test_default_license_files() -> None:
"description": "test package",
"name": "demo",
"version": "0.1.0",
"license-expression": "MIT",
"license": "MIT",
}
)
assert metadata.license_files == {
"globs": ["LICENSES/*", "LICEN[CS]E*", "COPYING*", "NOTICE*", "AUTHORS*"]
}


@pytest.mark.xfail(reason="Don't emit warning until PEP 639 is accepted")
def test_license_normalization() -> None:
metadata = make_metadata(
{
"description": "test package",
"name": "demo",
"version": "0.1.0",
"license-expression": "mIt",
"license": "mIt",
}
)
with pytest.warns(UserWarning) as record:
Expand All @@ -259,13 +239,14 @@ def test_license_normalization() -> None:
)


@pytest.mark.xfail(reason="Don't emit warning until PEP 639 is accepted")
def test_invalid_license_identifier() -> None:
metadata = make_metadata(
{
"description": "test package",
"name": "demo",
"version": "0.1.0",
"license-expression": "foo OR MIT",
"license": "foo OR MIT",
}
)
with pytest.raises(ValueError, match=r".*Unknown license key\(s\): foo"):
Expand Down
6 changes: 3 additions & 3 deletions tests/test_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@
},
{
"name": "foo",
"license-expression": "MIT",
"license": "MIT",
"license-files": {"paths": ["LICENSE"]},
},
{
"name": "foo",
"license-expression": "MIT",
"license": "MIT",
"license-files": {"globs": ["LICENSE*"]},
},
]
Expand All @@ -53,7 +53,7 @@
{"name": "foo", "version": {"from": "foo.py"}},
{
"name": "foo",
"license-expression": "MIT",
"license": "MIT",
"license-files": {"paths": ["LICENSE"], "globs": ["LICENSE*"]},
},
]
Expand Down

0 comments on commit aa7aecb

Please sign in to comment.