ra8-firmware
0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
check_no_unsafe_python_install.py
Go to the documentation of this file.
1
#!/usr/bin/env python3
2
# SPDX-License-Identifier: MIT
3
# Copyright (c) 2026 Brighton Sikarskie
4
"""Reject first-party attempts to override PEP 668 package ownership.
5
6
Python-managed repository tools belong in a virtual environment. A system-pip
7
override can mutate apt-owned files, while a user-site fallback makes the
8
interpreter and PATH depend on whichever account happened to provision a host.
9
Scan every authored tracked or untracked file so the unsafe option cannot
10
return in workflows, images, provisioning, documentation, or error hints.
11
"""
12
13
from
__future__
import
annotations
14
15
import
shutil
16
import
subprocess
17
import
sys
18
from
pathlib
import
Path
19
20
REPO_ROOT = Path(__file__).resolve().parents[2]
21
SELF =
"scripts/checks/check_no_unsafe_python_install.py"
22
FORBIDDEN =
"--break-"
+
"system-packages"
23
EXCLUDED_PREFIXES = (
24
"docs/sbom/upstream/"
,
25
"libs/third_party/"
,
26
"apps/shared_libs/third_party/"
,
27
"port/netxduo/"
,
28
"port/nimble/"
,
29
"port/threadx/"
,
30
"port/usbx/"
,
31
"tests/fixtures/"
,
32
)
33
MIN_SCOPED_FILES = 4000
34
35
36
def
scoped_files() -> list[str]:
37
"""Return all first-party files known to Git, including new files."""
38
git_bin = shutil.which(
"git"
)
or
"git"
39
proc = subprocess.run(
# noqa: S603 -- resolved Git executable; fixed arguments
40
[git_bin,
"ls-files"
,
"--cached"
,
"--others"
,
"--exclude-standard"
,
"-z"
],
41
cwd=REPO_ROOT,
42
check=
True
,
43
capture_output=
True
,
44
)
45
rels = proc.stdout.decode(
"utf-8"
, errors=
"strict"
).split(
"\0"
)
46
selected = {
47
rel
48
for
rel
in
rels
49
if
rel
and
not
rel.startswith(EXCLUDED_PREFIXES)
and
(REPO_ROOT / rel).is_file()
50
}
51
if
(REPO_ROOT / SELF).is_file():
52
selected.add(SELF)
53
return
sorted(selected)
54
55
56
def
scan_text(text: str) -> list[int]:
57
"""Return one-based line numbers containing the unsafe pip option."""
58
return
[number
for
number, line
in
enumerate(text.splitlines(), start=1)
if
FORBIDDEN
in
line]
59
60
61
def
scan(rels: list[str]) -> list[str]:
62
"""Return path/line findings, skipping non-text tracked assets."""
63
findings: list[str] = []
64
for
rel
in
rels:
65
try
:
66
text = (REPO_ROOT / rel).read_text(encoding=
"utf-8"
)
67
except
UnicodeDecodeError:
68
continue
69
findings.extend(f
"{rel}:{line}"
for
line
in
scan_text(text))
70
return
findings
71
72
73
def
selftest() -> int:
74
"""Prove the detector fires and accepts isolated installation guidance."""
75
unsafe =
"python3 -m pip install "
+ FORBIDDEN +
" libclang"
76
cases = (
77
(unsafe, [1],
"an unsafe active install fires"
),
78
(
"hint: "
+ unsafe, [1],
"an unsafe documentation hint fires"
),
79
(
"python3 -m venv .venv\n.venv/bin/pip install libclang"
, [],
"a venv passes"
),
80
(
"python3 -m pip --version"
, [],
"a non-mutating pip probe passes"
),
81
)
82
failures = [label
for
text, expected, label
in
cases
if
scan_text(text) != expected]
83
if
failures:
84
for
failure
in
failures:
85
print(f
"check_no_unsafe_python_install.py --selftest: FAIL: {failure}"
, file=sys.stderr)
86
return
1
87
print(f
"check_no_unsafe_python_install.py --selftest: PASS ({len(cases)} cases)"
)
88
return
0
89
90
91
def
main
() -> int:
92
"""Run detector self-tests or scan the live first-party tree."""
93
if
sys.argv[1:] == [
"--selftest"
]:
94
return
selftest()
95
if
sys.argv[1:]:
96
print(
"usage: check_no_unsafe_python_install.py [--selftest]"
, file=sys.stderr)
97
return
2
98
try
:
99
rels = scoped_files()
100
except
(OSError, subprocess.CalledProcessError, UnicodeError)
as
exc:
101
print(f
"cannot enumerate first-party files: {exc}"
, file=sys.stderr)
102
return
2
103
if
len(rels) < MIN_SCOPED_FILES
or
SELF
not
in
rels:
104
print(
105
f
"scope collapsed to {len(rels)} files; expected at least "
106
f
"{MIN_SCOPED_FILES} including {SELF}"
,
107
file=sys.stderr,
108
)
109
return
2
110
findings = scan(rels)
111
if
findings:
112
print(
"unsafe system-Python package override found:"
, file=sys.stderr)
113
for
finding
in
findings:
114
print(f
" {finding}"
, file=sys.stderr)
115
print(
"Create a venv and wire its interpreter/PATH explicitly."
, file=sys.stderr)
116
return
1
117
print(f
"check_no_unsafe_python_install.py: clean ({len(rels)} first-party files)"
)
118
return
0
119
120
121
if
__name__ ==
"__main__"
:
122
raise
SystemExit(
main
())
main
void main(void)
The application entry point Reset_Handler hands control to.
Definition
main.c:298
scripts
checks
check_no_unsafe_python_install.py
Generated by
1.16.1