Both tests walk scripts/ with rglob, so they also read the MeshCore checkout that build-firmware.sh makes in scripts/picocalc-lyra/ xiao-radio/_meshcore-build. Its third-party code and libraries have contractions and no SPDX lines, and every developer who followed the PicoCalc guide got three failures. conftest.not_ignored asks git check-ignore which paths it ignores and removes them; a tracked file is never ignored, and without git the tests examine everything, as before. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
50 lines
2.2 KiB
Python
50 lines
2.2 KiB
Python
# SPDX-License-Identifier: Apache-2.0
|
|
"""Make sure that all Python files have an SPDX licence identifier.
|
|
|
|
Each Python source file in the MeshTerm project must declare its licence with a
|
|
SPDX-License-Identifier comment on line 1 (or on line 2 if the file starts with a shebang).
|
|
This test examines the entire code base and asserts that the identifier is there. If
|
|
someone copies a file out of the repository, the file has no licence marking without this
|
|
identifier. Thus this gate makes sure that no file has no marking.
|
|
"""
|
|
|
|
from pathlib import Path
|
|
|
|
from tests.conftest import not_ignored
|
|
|
|
|
|
def test_spdx_headers():
|
|
"""Each Python file must have an SPDX-License-Identifier header."""
|
|
repo_root = Path(__file__).parent.parent
|
|
python_files = []
|
|
|
|
# Collect all the Python files from the necessary directories
|
|
for directory in ["meshterm", "tests", "packaging", "scripts/picocalc-lyra/xiao-radio"]:
|
|
dir_path = repo_root / directory
|
|
if dir_path.exists():
|
|
if directory == "packaging":
|
|
# For packaging, include the .py files and the .spec files
|
|
python_files.extend(dir_path.glob("*.py"))
|
|
python_files.extend(dir_path.glob("*.spec"))
|
|
else:
|
|
python_files.extend(dir_path.rglob("*.py"))
|
|
|
|
# Also examine the script scripts/uconsole/meshterm-spi-bridge, which has no extension
|
|
spi_bridge = repo_root / "scripts" / "uconsole" / "meshterm-spi-bridge"
|
|
if spi_bridge.exists():
|
|
python_files.append(spi_bridge)
|
|
|
|
missing_spdx = []
|
|
for filepath in not_ignored(sorted(python_files)):
|
|
# A file that MeshTerm cannot read as UTF-8 is a finding. The test must not skip it.
|
|
# Each source file here is UTF-8, and a skip with no message lets a file with no
|
|
# marking pass.
|
|
head = filepath.read_text(encoding="utf-8").split("\n", 2)[:2]
|
|
if not any("SPDX-License-Identifier:" in line for line in head):
|
|
missing_spdx.append(str(filepath.relative_to(repo_root)))
|
|
|
|
assert not missing_spdx, (
|
|
f"Found {len(missing_spdx)} Python file(s) without SPDX-License-Identifier:\n"
|
|
+ "\n".join(f" {f}" for f in missing_spdx)
|
|
)
|