-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpython_api.py
More file actions
57 lines (42 loc) · 2.12 KB
/
Copy pathpython_api.py
File metadata and controls
57 lines (42 loc) · 2.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#!/usr/bin/env python3
"""Use Stowaway as a Python library.
Runs a full scan of the bundled inert sample project and inspects the resulting
`Report` object — the same object the CLI renders. Everything here is offline,
static (scanned code is never executed), and deterministic.
python examples/python_api.py
Zero third-party dependencies; standard library only.
"""
from __future__ import annotations
from pathlib import Path
from stowaway.core.corpus import load_corpus
from stowaway.core.engine import scan
SAMPLE = Path(__file__).parent / "sample_project"
def main() -> None:
# 1. Load the popularity corpus. Passing internal_prefixes turns on
# high-confidence dependency-confusion detection for your namespace.
corpus = load_corpus(internal_prefixes=("@acme/",))
# 2. Scan a directory. `generated_at` is the single point of nondeterminism;
# pinning it (as tests do) makes the whole Report byte-reproducible.
report = scan(SAMPLE, corpus)
# 3. Inspect the Report — a plain, typed dataclass (see core/models.py).
print(f"target: {report.target}")
print(f"ecosystems: {', '.join(report.ecosystems_scanned) or 'none'}")
print(f"score: {report.project_score}/100 ({report.score_formula})")
print(f"priorities: {report.priority_counts()}")
print(f"findings: {len(report.findings)}")
print()
# 4. Every finding is traceable to a file:line with an inert snippet, and
# carries a confidence because heuristics are probabilistic.
for f in report.findings:
loc = f.evidence.file_path + (f":{f.evidence.line}" if f.evidence.line else "")
print(f"[{f.rule_id}] {f.package.name} ({f.severity}/{f.confidence})")
print(f" where: {loc}")
print(f" why: {f.message}")
print(f" remediation: {f.remediation}")
print(f" fingerprint: {f.fingerprint()}")
print()
# 5. Per-package risk assessments carry the priority and its justification.
for a in report.assessments:
print(f"{a.priority} {a.package.name:20} — {a.justification}")
if __name__ == "__main__":
main()