Skip to content

Commit

Permalink
Store license-files in licenses subfolder
Browse files Browse the repository at this point in the history
  • Loading branch information
cdce8p committed Nov 24, 2024
1 parent bf2ced2 commit c47ade2
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 9 deletions.
1 change: 1 addition & 0 deletions newsfragments/4728.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Store ``License-File``s in ``.dist-info/licenses`` subfolder and added support for recursive globs for ``license_files`` (`PEP 639 <https://peps.python.org/pep-0639/#add-license-expression-field>`_). -- by :user:`cdce8p`
6 changes: 4 additions & 2 deletions setuptools/command/bdist_wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -592,9 +592,11 @@ def adios(p: str) -> None:
metadata_path = os.path.join(distinfo_path, "METADATA")
shutil.copy(pkginfo_path, metadata_path)

licenses_folder_path = os.path.join(distinfo_path, "licenses")
for license_path in self.license_paths:
filename = os.path.basename(license_path)
shutil.copy(license_path, os.path.join(distinfo_path, filename))
dist_info_license_path = os.path.join(licenses_folder_path, license_path)
os.makedirs(os.path.dirname(dist_info_license_path), exist_ok=True)
shutil.copy(license_path, dist_info_license_path)

adios(egginfo_path)

Expand Down
7 changes: 5 additions & 2 deletions setuptools/dist.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,10 @@ def _finalize_license_files(self) -> None:
patterns = ['LICEN[CS]E*', 'COPYING*', 'NOTICE*', 'AUTHORS*']

self.metadata.license_files = list(
unique_everseen(self._expand_patterns(patterns))
map(
lambda path: path.replace("\\", "/"),
unique_everseen(self._expand_patterns(patterns)),
)
)

@staticmethod
Expand All @@ -427,7 +430,7 @@ def _expand_patterns(patterns):
return (
path
for pattern in patterns
for path in sorted(iglob(pattern))
for path in sorted(iglob(pattern, recursive=True))
if not path.endswith('~') and os.path.isfile(path)
)

Expand Down
46 changes: 43 additions & 3 deletions setuptools/tests/test_bdist_wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,20 @@
),
"README.rst": "UTF-8 描述 説明",
},
"licenses-dist": {
"setup.cfg": cleandoc(
"""
[metadata]
name = licenses-dist
version = 1.0
license_files = **/LICENSE
"""
),
"LICENSE": "",
"src": {
"vendor": {"LICENSE": ""},
},
},
}


Expand Down Expand Up @@ -238,6 +252,11 @@ def dummy_dist(tmp_path_factory):
return mkexample(tmp_path_factory, "dummy-dist")


@pytest.fixture
def licenses_dist(tmp_path_factory):
return mkexample(tmp_path_factory, "licenses-dist")


def test_no_scripts(wheel_paths):
"""Make sure entry point scripts are not generated."""
path = next(path for path in wheel_paths if "complex_dist" in path)
Expand Down Expand Up @@ -297,7 +316,8 @@ def test_licenses_default(dummy_dist, monkeypatch, tmp_path):
bdist_wheel_cmd(bdist_dir=str(tmp_path)).run()
with ZipFile("dist/dummy_dist-1.0-py3-none-any.whl") as wf:
license_files = {
"dummy_dist-1.0.dist-info/" + fname for fname in DEFAULT_LICENSE_FILES
"dummy_dist-1.0.dist-info/licenses/" + fname
for fname in DEFAULT_LICENSE_FILES
}
assert set(wf.namelist()) == DEFAULT_FILES | license_files

Expand All @@ -311,7 +331,7 @@ def test_licenses_deprecated(dummy_dist, monkeypatch, tmp_path):
bdist_wheel_cmd(bdist_dir=str(tmp_path)).run()

with ZipFile("dist/dummy_dist-1.0-py3-none-any.whl") as wf:
license_files = {"dummy_dist-1.0.dist-info/DUMMYFILE"}
license_files = {"dummy_dist-1.0.dist-info/licenses/licenses/DUMMYFILE"}
assert set(wf.namelist()) == DEFAULT_FILES | license_files


Expand All @@ -334,9 +354,29 @@ def test_licenses_override(dummy_dist, monkeypatch, tmp_path, config_file, confi
bdist_wheel_cmd(bdist_dir=str(tmp_path)).run()
with ZipFile("dist/dummy_dist-1.0-py3-none-any.whl") as wf:
license_files = {
"dummy_dist-1.0.dist-info/" + fname for fname in {"DUMMYFILE", "LICENSE"}
"dummy_dist-1.0.dist-info/licenses/" + fname
for fname in {"licenses/DUMMYFILE", "LICENSE"}
}
assert set(wf.namelist()) == DEFAULT_FILES | license_files
metadata = wf.read("dummy_dist-1.0.dist-info/METADATA").decode("utf8")
assert "License-File: licenses/DUMMYFILE" in metadata
assert "License-File: LICENSE" in metadata


def test_licenses_preserve_folder_structure(licenses_dist, monkeypatch, tmp_path):
monkeypatch.chdir(licenses_dist)
bdist_wheel_cmd(bdist_dir=str(tmp_path)).run()
print(os.listdir("dist"))
with ZipFile("dist/licenses_dist-1.0-py3-none-any.whl") as wf:
default_files = {name.replace("dummy_", "licenses_") for name in DEFAULT_FILES}
license_files = {
"licenses_dist-1.0.dist-info/licenses/LICENSE",
"licenses_dist-1.0.dist-info/licenses/src/vendor/LICENSE",
}
assert set(wf.namelist()) == default_files | license_files
metadata = wf.read("licenses_dist-1.0.dist-info/METADATA").decode("utf8")
assert "License-File: src/vendor/LICENSE" in metadata
assert "License-File: LICENSE" in metadata


def test_licenses_disabled(dummy_dist, monkeypatch, tmp_path):
Expand Down
7 changes: 5 additions & 2 deletions setuptools/tests/test_build_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,9 @@ def test_build_with_pyproject_config(self, tmpdir, setup_script):
with ZipFile(os.path.join(tmpdir, "temp", wheel_file)) as zipfile:
wheel_contents = set(zipfile.namelist())
metadata = str(zipfile.read("foo-0.1.dist-info/METADATA"), "utf-8")
license = str(zipfile.read("foo-0.1.dist-info/LICENSE.txt"), "utf-8")
license = str(
zipfile.read("foo-0.1.dist-info/licenses/LICENSE.txt"), "utf-8"
)
epoints = str(zipfile.read("foo-0.1.dist-info/entry_points.txt"), "utf-8")

assert sdist_contents - {"foo-0.1/setup.py"} == {
Expand Down Expand Up @@ -426,7 +428,7 @@ def test_build_with_pyproject_config(self, tmpdir, setup_script):
"foo/cli.py",
"foo/data.txt", # include_package_data defaults to True
"foo/py.typed", # include type information by default
"foo-0.1.dist-info/LICENSE.txt",
"foo-0.1.dist-info/licenses/LICENSE.txt",
"foo-0.1.dist-info/METADATA",
"foo-0.1.dist-info/WHEEL",
"foo-0.1.dist-info/entry_points.txt",
Expand All @@ -438,6 +440,7 @@ def test_build_with_pyproject_config(self, tmpdir, setup_script):
for line in (
"Summary: This is a Python package",
"License: MIT",
"License-File: LICENSE.txt",
"Classifier: Intended Audience :: Developers",
"Requires-Dist: appdirs",
"Requires-Dist: " + str(Requirement('tomli>=1 ; extra == "all"')),
Expand Down
20 changes: 20 additions & 0 deletions setuptools/tests/test_egg_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,22 @@ def test_setup_cfg_license_file(self, tmpdir_cwd, env, files, license_in_sources
[],
id="files_only_added_once",
),
pytest.param(
{
'setup.cfg': DALS(
"""
[metadata]
license_files = **/LICENSE
"""
),
'LICENSE': "ABC license",
'LICENSE-OTHER': "Don't include",
'vendor': {'LICENSE': "Vendor license"},
},
['LICENSE', 'vendor/LICENSE'],
['LICENSE-OTHER'],
id="recursive_glob",
),
],
)
def test_setup_cfg_license_files(
Expand Down Expand Up @@ -1032,12 +1048,14 @@ def test_license_file_attr_pkg_info(self, tmpdir_cwd, env):
license_files =
NOTICE*
LICENSE*
**/LICENSE
"""
),
"LICENSE-ABC": "ABC license",
"LICENSE-XYZ": "XYZ license",
"NOTICE": "included",
"IGNORE": "not include",
"vendor": {'LICENSE': "Vendor license"},
})

environment.run_setup_py(
Expand All @@ -1053,9 +1071,11 @@ def test_license_file_attr_pkg_info(self, tmpdir_cwd, env):

# Only 'NOTICE', LICENSE-ABC', and 'LICENSE-XYZ' should have been matched
# Also assert that order from license_files is keeped
assert len(license_file_lines) == 4
assert "License-File: NOTICE" == license_file_lines[0]
assert "License-File: LICENSE-ABC" in license_file_lines[1:]
assert "License-File: LICENSE-XYZ" in license_file_lines[1:]
assert "License-File: vendor/LICENSE" in license_file_lines[3]

def test_metadata_version(self, tmpdir_cwd, env):
"""Make sure latest metadata version is used by default."""
Expand Down

0 comments on commit c47ade2

Please sign in to comment.