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
10 changes: 6 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ jobs:
name: standardize thyself
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: '3.10'
- uses: pre-commit/action@v3.0.1
- run: python -m pip install pre-commit
shell: bash
- run: python -m pip freeze --local
shell: bash
- run: pre-commit run --show-diff-on-failure --color=always
shell: bash

pytest:
runs-on: ubuntu-latest
Expand Down
274 changes: 201 additions & 73 deletions LICENSE

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion polymath_code_standard/checkers/copyright.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,10 @@ def run(self, args: argparse.Namespace) -> list[Result]:
except OSError:
pass

results.append(self._check_license_file(args.license_id, args.copyright_year, args.copyright_org or ''))
if args.wildcard_copyright_org:
results.append(Result(name='LICENSE file', passed=True, skipped=True))
else:
results.append(self._check_license_file(args.license_id, args.copyright_year, args.copyright_org or ''))
return results

@staticmethod
Expand Down
3 changes: 2 additions & 1 deletion polymath_code_standard/insert_license.py
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,8 @@ def find_license_header_index(

def _is_copyright_line(stripped_line: str) -> bool:
"""Return True if a stripped line is a copyright attribution (any comment style)."""
return stripped_line.lstrip('/#').lstrip().lower().startswith('copyright')
normalized = stripped_line.lstrip('/#').lstrip().lower()
return normalized.startswith('copyright') or normalized.startswith('spdx-filecopyrighttext')


def copyright_sentinel_found(src_file_content, top_lines_count):
Expand Down
24 changes: 24 additions & 0 deletions tests/test_copyright.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# SPDX-License-Identifier: Apache-2.0
"""Tests for CopyrightGroup._check_license_file and _strip_leading_comment_block."""

import argparse
from unittest.mock import patch

from polymath_code_standard.checkers.copyright import CopyrightGroup
Expand Down Expand Up @@ -74,6 +75,29 @@ def test_fetch_error_returns_failed(self, tmp_path, monkeypatch):
assert 'BOGUS' in result.output


class TestWildcardOrgSkipsLicenseFile:
def test_license_file_not_modified_with_wildcard_org(self, tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
license_file = tmp_path / 'LICENSE'
original_content = 'Apache License 2.0\n\nCopyright Acme Corp\n'
license_file.write_text(original_content)

args = argparse.Namespace(
license_id='Apache-2.0',
copyright_year='2026',
copyright_org=None,
wildcard_copyright_org=True,
reuse_style=True,
relicense=False,
files=[],
)
with patch.object(CopyrightGroup, '_check_license_file') as mock_check:
CopyrightGroup().run(args)
mock_check.assert_not_called()

assert license_file.read_text() == original_content


_strip = CopyrightGroup._strip_leading_comment_block


Expand Down
37 changes: 37 additions & 0 deletions tests/test_insert_license_wildcard.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ def test_non_copyright(self):
def test_blank_comment(self):
assert not _is_copyright_line('#')

def test_reuse_spdx_hash_style(self):
assert _is_copyright_line('# SPDX-FileCopyrightText: 2026 Acme Corp')

def test_reuse_spdx_slash_style(self):
assert _is_copyright_line('// SPDX-FileCopyrightText: 2026 Acme Corp')

def test_reuse_spdx_license_identifier_is_not_copyright(self):
assert not _is_copyright_line('# SPDX-License-Identifier: Apache-2.0')


# ---------------------------------------------------------------------------
# _license_line_matches — wildcard_copyright_org
Expand Down Expand Up @@ -228,6 +237,34 @@ def test_no_header_inserts_sentinel(self, tmp_path):
assert ret == 1
assert COPYRIGHT_ORG_SENTINEL in src.read_text()

def test_reuse_style_replaced_org_not_duplicated(self, tmp_path):
"""After replacing the sentinel in a REUSE-style header, re-running should not insert a duplicate."""
reuse_license_text = (
f'SPDX-FileCopyrightText: 2026 {COPYRIGHT_ORG_SENTINEL}\nSPDX-License-Identifier: Apache-2.0\n'
)
lf = tmp_path / 'license.txt'
lf.write_text(reuse_license_text, encoding='utf-8')

# File already has the sentinel replaced with a real org
src = self._write(
tmp_path,
'f.py',
'# SPDX-FileCopyrightText: 2026 My Org\n# SPDX-License-Identifier: Apache-2.0\nimport foo\n',
)
original = src.read_text()
ret = main([
'--license-filepath',
str(lf),
'--comment-style',
'#',
'--allow-past-years',
'--no-extra-eol',
'--wildcard-copyright-org',
str(src),
])
assert ret == 0
assert src.read_text() == original

def test_without_wildcard_rejects_different_org(self, tmp_path):
src = self._write(tmp_path, 'f.py', ''.join(_file_with_header('Contributor Corp.')))
lf = self._license_file(tmp_path, org='Polymath Robotics, Inc.')
Expand Down