Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for file comments in spdx #625

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
6 changes: 5 additions & 1 deletion src/reuse/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,11 @@
#: The two iterables MUST be sets.
SpdxInfo = NamedTuple(
"SpdxInfo",
[("spdx_expressions", Set[Expression]), ("copyright_lines", Set[str])],
[
("spdx_expressions", Set[Expression]),
("copyright_lines", Set[str]),
("comment", str)
],
)


Expand Down
5 changes: 3 additions & 2 deletions src/reuse/_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,11 +204,12 @@ def _copyright_from_dep5(path: PathLike, dep5_copyright: Copyright) -> SpdxInfo:
result = dep5_copyright.find_files_paragraph(Path(path).as_posix())

if result is None:
return SpdxInfo(set(), set())
return SpdxInfo(set(), set(), "")

return SpdxInfo(
set(map(_LICENSING.parse, [result.license.synopsis])),
set(map(str.strip, result.copyright.splitlines())),
" ".join(result.comment.split()) if result.comment else ""
)


Expand Down Expand Up @@ -302,7 +303,7 @@ def extract_spdx_info(text: str) -> SpdxInfo:
copyright_matches.add(match.groupdict()["copyright"].strip())
break

return SpdxInfo(expressions, copyright_matches)
return SpdxInfo(expressions, copyright_matches, "")


def find_license_identifiers(text: str) -> Iterator[str]:
Expand Down
3 changes: 2 additions & 1 deletion src/reuse/header.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ def create_header(
spdx_info = SpdxInfo(
spdx_info.spdx_expressions.union(existing_spdx.spdx_expressions),
spdx_copyrights,
""
)

new_header += _create_new_header(
Expand Down Expand Up @@ -703,7 +704,7 @@ def run(args, project: Project, out=sys.stdout) -> int:
else set()
)

spdx_info = SpdxInfo(expressions, copyright_lines)
spdx_info = SpdxInfo(expressions, copyright_lines, "")

result = 0
for path in paths:
Expand Down
5 changes: 3 additions & 2 deletions src/reuse/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,8 @@ def spdx_info_of(self, path: PathLike) -> SpdxInfo:
path = _determine_license_path(path)
_LOGGER.debug(f"searching '{path}' for SPDX information")

dep5_result = SpdxInfo(set(), set())
file_result = SpdxInfo(set(), set())
dep5_result = SpdxInfo(set(), set(), "")
file_result = SpdxInfo(set(), set(), "")

# Search the .reuse/dep5 file for SPDX information.
if self._copyright:
Expand Down Expand Up @@ -172,6 +172,7 @@ def spdx_info_of(self, path: PathLike) -> SpdxInfo:
return SpdxInfo(
dep5_result.spdx_expressions.union(file_result.spdx_expressions),
dep5_result.copyright_lines.union(file_result.copyright_lines),
dep5_result.comment
)

def relative_from_root(self, path: Path) -> Path:
Expand Down
11 changes: 10 additions & 1 deletion src/reuse/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from pathlib import Path
from typing import Iterable, List, NamedTuple, Optional, Set
from uuid import uuid4
from textwrap import fill

from . import __version__
from ._util import _LICENSING, _checksum
Expand Down Expand Up @@ -158,6 +159,12 @@ def bill_of_materials(self) -> str:
)
else:
out.write("FileCopyrightText: NONE\n")
if report.spdxfile.comment:
out.write(
f"FileComment: <text>\n"
f"{fill(report.spdxfile.comment, width=72)}\n"
f"</text>\n"
)

# Licenses
for lic, path in sorted(self.licenses.items()):
Expand Down Expand Up @@ -307,6 +314,7 @@ def __init__(self, name, spdx_id=None, chk_sum=None):
self.chk_sum: str = chk_sum
self.licenses_in_file: List[str] = []
self.copyright: str = None
self.comment: str = None


class FileReport:
Expand Down Expand Up @@ -378,8 +386,9 @@ def generate(
# Add license to report.
report.spdxfile.licenses_in_file.append(identifier)

# Copyright text
# Copyright text and comment
report.spdxfile.copyright = "\n".join(sorted(spdx_info.copyright_lines))
report.spdxfile.comment = spdx_info.comment

return report

Expand Down
34 changes: 17 additions & 17 deletions tests/test_header.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
def test_create_header_simple():
"""Create a super simple header."""
spdx_info = SpdxInfo(
{"GPL-3.0-or-later"}, {"SPDX-FileCopyrightText: Jane Doe"}
{"GPL-3.0-or-later"}, {"SPDX-FileCopyrightText: Jane Doe"}, ""
)
expected = cleandoc(
"""
Expand All @@ -37,7 +37,7 @@ def test_create_header_simple():
def test_create_header_template_simple(template_simple):
"""Create a header with a simple template."""
spdx_info = SpdxInfo(
{"GPL-3.0-or-later"}, {"SPDX-FileCopyrightText: Jane Doe"}
{"GPL-3.0-or-later"}, {"SPDX-FileCopyrightText: Jane Doe"}, ""
)
expected = cleandoc(
"""
Expand All @@ -57,7 +57,7 @@ def test_create_header_template_simple(template_simple):
def test_create_header_template_no_spdx(template_no_spdx):
"""Create a header with a template that does not have all SPDX info."""
spdx_info = SpdxInfo(
{"GPL-3.0-or-later"}, {"SPDX-FileCopyrightText: Jane Doe"}
{"GPL-3.0-or-later"}, {"SPDX-FileCopyrightText: Jane Doe"}, ""
)

with pytest.raises(MissingSpdxInfo):
Expand All @@ -67,7 +67,7 @@ def test_create_header_template_no_spdx(template_no_spdx):
def test_create_header_template_commented(template_commented):
"""Create a header with an already-commented template."""
spdx_info = SpdxInfo(
{"GPL-3.0-or-later"}, {"SPDX-FileCopyrightText: Jane Doe"}
{"GPL-3.0-or-later"}, {"SPDX-FileCopyrightText: Jane Doe"}, ""
)
expected = cleandoc(
"""
Expand All @@ -93,7 +93,7 @@ def test_create_header_template_commented(template_commented):
def test_create_header_already_contains_spdx():
"""Create a new header from a header that already contains SPDX info."""
spdx_info = SpdxInfo(
{"GPL-3.0-or-later"}, {"SPDX-FileCopyrightText: Jane Doe"}
{"GPL-3.0-or-later"}, {"SPDX-FileCopyrightText: Jane Doe"}, ""
)
existing = cleandoc(
"""
Expand All @@ -118,7 +118,7 @@ def test_create_header_already_contains_spdx():
def test_create_header_existing_is_wrong():
"""If the existing header contains errors, raise a CommentCreateError."""
spdx_info = SpdxInfo(
{"GPL-3.0-or-later"}, {"SPDX-FileCopyrightText: Jane Doe"}
{"GPL-3.0-or-later"}, {"SPDX-FileCopyrightText: Jane Doe"}, ""
)
existing = cleandoc(
"""
Expand All @@ -134,7 +134,7 @@ def test_create_header_existing_is_wrong():

def test_create_header_old_syntax():
"""Old copyright syntax is preserved when creating a new header."""
spdx_info = SpdxInfo({"GPL-3.0-or-later"}, set())
spdx_info = SpdxInfo({"GPL-3.0-or-later"}, set(), "")
existing = cleandoc(
"""
# Copyright John Doe
Expand All @@ -153,7 +153,7 @@ def test_create_header_old_syntax():

def test_create_header_remove_fluff():
"""Any stuff that isn't SPDX info is removed when using create_header."""
spdx_info = SpdxInfo({"GPL-3.0-or-later"}, set())
spdx_info = SpdxInfo({"GPL-3.0-or-later"}, set(), "")
existing = cleandoc(
"""
# SPDX-FileCopyrightText: John Doe
Expand All @@ -177,7 +177,7 @@ def test_create_header_remove_fluff():
def test_find_and_replace_no_header():
"""Given text without header, add a header."""
spdx_info = SpdxInfo(
{"GPL-3.0-or-later"}, {"SPDX-FileCopyrightText: Jane Doe"}
{"GPL-3.0-or-later"}, {"SPDX-FileCopyrightText: Jane Doe"}, ""
)
text = "pass"
expected = cleandoc(
Expand All @@ -195,7 +195,7 @@ def test_find_and_replace_no_header():

def test_find_and_replace_verbatim():
"""Replace a header with itself."""
spdx_info = SpdxInfo(set(), set())
spdx_info = SpdxInfo(set(), set(), "")
text = cleandoc(
"""
# SPDX-FileCopyrightText: Jane Doe
Expand All @@ -214,7 +214,7 @@ def test_find_and_replace_newline_before_header():
preceding whitespace.
"""
spdx_info = SpdxInfo(
{"GPL-3.0-or-later"}, {"SPDX-FileCopyrightText: John Doe"}
{"GPL-3.0-or-later"}, {"SPDX-FileCopyrightText: John Doe"}, ""
)
text = cleandoc(
"""
Expand All @@ -241,7 +241,7 @@ def test_find_and_replace_newline_before_header():
def test_find_and_replace_preserve_preceding():
"""When the SPDX header is in the middle of the file, keep it there."""
spdx_info = SpdxInfo(
{"GPL-3.0-or-later"}, {"SPDX-FileCopyrightText: John Doe"}
{"GPL-3.0-or-later"}, {"SPDX-FileCopyrightText: John Doe"}, ""
)
text = cleandoc(
"""
Expand Down Expand Up @@ -279,7 +279,7 @@ def test_find_and_replace_keep_shebang():
it.
"""
spdx_info = SpdxInfo(
{"GPL-3.0-or-later"}, {"SPDX-FileCopyrightText: John Doe"}
{"GPL-3.0-or-later"}, {"SPDX-FileCopyrightText: John Doe"}, ""
)
text = cleandoc(
"""
Expand Down Expand Up @@ -310,7 +310,7 @@ def test_find_and_replace_separate_shebang():
"""When the shebang is part of the same comment as the SPDX comment,
separate the two.
"""
spdx_info = SpdxInfo({"GPL-3.0-or-later"}, set())
spdx_info = SpdxInfo({"GPL-3.0-or-later"}, set(), "")
text = cleandoc(
"""
#!/usr/bin/env python3
Expand Down Expand Up @@ -338,7 +338,7 @@ def test_find_and_replace_separate_shebang():

def test_find_and_replace_only_shebang():
"""When the file only contains a shebang, keep it at the top of the file."""
spdx_info = SpdxInfo({"GPL-3.0-or-later"}, set())
spdx_info = SpdxInfo({"GPL-3.0-or-later"}, set(), "")
text = cleandoc(
"""
#!/usr/bin/env python3
Expand Down Expand Up @@ -368,7 +368,7 @@ def test_find_and_replace_keep_old_comment():
licensing information, preserve it below the REUSE header.
"""
spdx_info = SpdxInfo(
{"GPL-3.0-or-later"}, {"SPDX-FileCopyrightText: Jane Doe"}
{"GPL-3.0-or-later"}, {"SPDX-FileCopyrightText: Jane Doe"}, ""
)
text = cleandoc(
"""
Expand All @@ -395,7 +395,7 @@ def test_find_and_replace_keep_old_comment():
def test_find_and_replace_preserve_newline():
"""If the file content ends with a newline, don't remove it."""

spdx_info = SpdxInfo(set(), set())
spdx_info = SpdxInfo(set(), set(), "")
text = (
cleandoc(
"""
Expand Down
2 changes: 1 addition & 1 deletion tests/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def test_extract_no_info():
object.
"""
result = _util.extract_spdx_info("")
assert result == _util.SpdxInfo(set(), set())
assert result == _util.SpdxInfo(set(), set(), "")


def test_extract_tab():
Expand Down