Browse Source

Merge branch 'deprecated'

uncommentable2
carmenbianca 2 weeks ago
parent
commit
8de9d26e26
Signed by: Carmen Bianca Bakker <carmenbianca@fsfe.org> GPG Key ID: 76EBA6F6B6EA2EC9
7 changed files with 88 additions and 13 deletions
  1. 3
    0
      CHANGELOG.md
  2. 7
    0
      docs/usage.rst
  3. 2
    8
      src/reuse/_licenses.py
  4. 32
    0
      src/reuse/lint.py
  5. 9
    5
      src/reuse/report.py
  6. 23
    0
      tests/test_lint.py
  7. 12
    0
      tests/test_report.py

+ 3
- 0
CHANGELOG.md View File

@@ -44,6 +44,9 @@ The versions follow [semantic versioning](https://semver.org).

- The linter will complain about licenses without file extensions.

- Deprecated licenses are now recognised. `lint` will complain about deprecated
licenses.

### Changed

- The linter output has been very slightly re-ordered to be more internally

+ 7
- 0
docs/usage.rst View File

@@ -192,6 +192,7 @@ This is some example output of ``reuse lint``:
# SUMMARY

* Bad licenses: bad-license
* Deprecated licenses:
* Licenses without file extension:
* Missing licenses:
* Unused licenses: bad-license
@@ -222,6 +223,12 @@ Bad licenses
Licenses that are found in ``LICENSES/`` that are not found in the SPDX License
List or do not start with ``LicenseRef-`` are bad licenses.

Deprecated licenses
+++++++++++++++++++

If a license has an SPDX License Identifier that has been deprecated by SPDX,
the license will show up here.

Licenses without file extension
+++++++++++++++++++++++++++++++


+ 2
- 8
src/reuse/_licenses.py View File

@@ -31,11 +31,8 @@ def _load_license_list(file_name):
licenses = json.load(lics)
version = licenses["licenseListVersion"].split(".")
for lic in licenses["licenses"]:
if lic.get("isDeprecatedLicenseId"):
continue
name = lic["name"]
identifier = lic["licenseId"]
licenses_map[identifier] = name
licenses_map[identifier] = lic
return version, licenses_map


@@ -49,11 +46,8 @@ def _load_exception_list(file_name):
exceptions = json.load(excs)
version = exceptions["licenseListVersion"].split(".")
for exc in exceptions["exceptions"]:
if exc.get("isDeprecatedLicenseId"):
continue
name = exc["name"]
identifier = exc["licenseExceptionId"]
exceptions_map[identifier] = name
exceptions_map[identifier] = exc
return version, exceptions_map



+ 32
- 0
src/reuse/lint.py View File

@@ -24,6 +24,7 @@ def _write_element(element, out=sys.stdout):
def lint(report: ProjectReport, out=sys.stdout) -> bool:
"""Lint the entire project."""
bad_licenses_result = lint_bad_licenses(report, out)
deprecated_result = lint_deprecated_licenses(report, out)
extensionless = lint_licenses_without_extension(report, out)
missing_licenses_result = lint_missing_licenses(report, out)
unused_licenses_result = lint_unused_licenses(report, out)
@@ -38,6 +39,7 @@ def lint(report: ProjectReport, out=sys.stdout) -> bool:
any(result)
for result in (
bad_licenses_result,
deprecated_result,
extensionless,
missing_licenses_result,
unused_licenses_result,
@@ -88,6 +90,26 @@ def lint_bad_licenses(report: ProjectReport, out=sys.stdout) -> Iterable[str]:
return bad_files


def lint_deprecated_licenses(
report: ProjectReport, out=sys.stdout
) -> Iterable[str]:
"""Lint for deprecated licenses."""
deprecated = []

if report.deprecated_licenses:
out.write("# ")
out.write(_("DEPRECATED LICENSES"))
out.write("\n\n")
out.write(_("The following licenses are deprecated by SPDX:"))
out.write("\n")
for lic in sorted(report.deprecated_licenses):
deprecated.append(lic)
_write_element(lic, out=out)
out.write("\n\n")

return deprecated


def lint_licenses_without_extension(
report: ProjectReport, out=sys.stdout
) -> Iterable[str]:
@@ -216,6 +238,7 @@ def lint_files_without_copyright_and_licensing(

def lint_summary(report: ProjectReport, out=sys.stdout) -> None:
"""Print a summary for linting."""
# pylint: disable=too-many-statements
out.write("# ")
out.write(_("SUMMARY"))
out.write("\n\n")
@@ -231,6 +254,15 @@ def lint_summary(report: ProjectReport, out=sys.stdout) -> None:
out.write(lic)
out.write("\n")

out.write("* ")
out.write(_("Deprecated licenses:"))
for i, lic in enumerate(sorted(report.deprecated_licenses)):
if i:
out.write(",")
out.write(" ")
out.write(lic)
out.write("\n")

out.write("* ")
out.write(_("Licenses without file extension:"))
for i, lic in enumerate(sorted(report.licenses_without_extension)):

+ 9
- 5
src/reuse/report.py View File

@@ -39,6 +39,7 @@ class ProjectReport: # pylint: disable=too-many-instance-attributes
self.licenses = dict()
self.missing_licenses = dict()
self.bad_licenses = dict()
self.deprecated_licenses = set()
self.read_errors = set()
self.file_reports = set()
self.licenses_without_extension = dict()
@@ -53,14 +54,15 @@ class ProjectReport: # pylint: disable=too-many-instance-attributes
"""Turn the report into a json-like dictionary."""
return {
"path": str(Path(self.path).resolve()),
"bad_licenses": {
lic: [str(file_) for file_ in files]
for lic, files in self.bad_licenses.items()
},
"licenses": {
identifier: str(path)
for identifier, path in self.licenses.items()
},
"bad_licenses": {
lic: [str(file_) for file_ in files]
for lic, files in self.bad_licenses.items()
},
"deprecated_licenses": sorted(self.deprecated_licenses),
"licenses_without_extension": {
identifier: str(path)
for identifier, path in self.licenses_without_extension.items()
@@ -187,10 +189,12 @@ class ProjectReport: # pylint: disable=too-many-instance-attributes
lint_file_info.file_report.path
)

# More bad licenses
# More bad licenses, and also deprecated licenses
for name, path in project.licenses.items():
if name not in project.license_map:
project_report.bad_licenses.setdefault(name, set()).add(path)
elif project.license_map[name]["isDeprecatedLicenseId"]:
project_report.deprecated_licenses.add(name)

return project_report


+ 23
- 0
tests/test_lint.py View File

@@ -4,6 +4,8 @@

"""All tests for reuse.lint"""

import shutil

from reuse.lint import (
lint,
lint_bad_licenses,
@@ -58,6 +60,27 @@ def test_lint_empty_directory(empty_directory):
assert result


def test_lint_deprecated(fake_repository, stringio):
"""If a repo has a deprecated license, detect it."""
shutil.copy(
fake_repository / "LICENSES/GPL-3.0-or-later.txt",
fake_repository / "LICENSES/GPL-3.0.txt",
)
(fake_repository / "foo.py").write_text(
"SPDX"
"-License-Identifier: GPL-3.0\n"
"SPDX"
"-FileCopyrightText: Jane Doe"
)

project = Project(fake_repository)
report = ProjectReport.generate(project)
result = lint(report, out=stringio)

assert not result
assert "GPL-3.0" in stringio.getvalue()


def test_lint_bad_license(fake_repository, stringio):
"""A bad license is detected."""
(fake_repository / "foo.py").write_text(

+ 12
- 0
tests/test_report.py View File

@@ -141,6 +141,18 @@ def test_generate_project_report_bad_license_in_file(fake_repository):
assert "bad" in result.bad_licenses


def test_generate_project_report_deprecated_license(fake_repository):
"""Deprecated licenses are detected."""
(fake_repository / "LICENSES/GPL-3.0-or-later.txt").rename(
fake_repository / "LICENSES/GPL-3.0.txt"
)

project = Project(fake_repository)
result = ProjectReport.generate(project)

assert "GPL-3.0" in result.deprecated_licenses


def test_generate_project_report_read_error(fake_repository):
"""Files that cannot be read are added to the read error list."""
(fake_repository / "bad").symlink_to("does_not_exist")

Loading…
Cancel
Save