Files
MeshTerm/tests/test_spdx.py
T
Jean-Pierre MartineauandClaude Opus 5.5 b6e7cd5c16 The handhelds are named for their variant: picocalc-lyra and cardputer-zero
M5Stack makes three Cardputers and only the Zero runs Linux; the PicoCalc
takes several cores and only the Luckfox Lyra runs MeshTerm. So the bare
names were ambiguous, and every reference to the two devices now carries
the variant: the --platform values and MESHTERM_PLATFORM, the Platform
constants (PICOCALC_LYRA, CARDPUTER_ZERO), their lane decks and every
screen's picocalc_lyra_lane / cardputer_zero_lane, the font inventories,
the lane chips' theme styles, the scripts/ folders, the two chrome test
files, and the docs and CLAUDE.md that name them.

There is no alias: --platform picocalc is refused with the three real
choices listed, rather than falling back to the desktop layout. The
PicoCalc is auto-detected from its device tree, so it needs nothing.
What names hardware or a user's data keeps its name: the PicoCalc
keyboard's input-device name, its battery's sysfs supply, and the serial
profile the Lyra setup script writes. .gitignore follows the firmware's
folder, and the changelog keeps the words each release used.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-04 11:52:41 -04:00

47 lines
2.0 KiB
Python

# SPDX-License-Identifier: Apache-2.0
"""Enforce SPDX license identifiers on all Python files.
Every Python source file in the MeshTerm project must declare its license with
a SPDX-License-Identifier comment on line 1 (or line 2 if it starts with a
shebang). This test walks the entire codebase and asserts the identifier is
present. A file lifted out of the repository carries no license marking
otherwise, so this gate ensures no file lands unmarked.
"""
from pathlib import Path
def test_spdx_headers():
"""Every Python file must have an SPDX-License-Identifier header."""
repo_root = Path(__file__).parent.parent
python_files = []
# Collect all Python files from the required 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 both .py files and .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 check the extensionless scripts/uconsole/meshterm-spi-bridge script
spi_bridge = repo_root / "scripts" / "uconsole" / "meshterm-spi-bridge"
if spi_bridge.exists():
python_files.append(spi_bridge)
missing_spdx = []
for filepath in sorted(python_files):
# A file that cannot be read as UTF-8 is a finding, not something to skip: every
# source file here is UTF-8, and a silent skip would let an unmarked file through.
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)
)