Skip to content

Latest commit

 

History

History
98 lines (88 loc) · 6.03 KB

File metadata and controls

98 lines (88 loc) · 6.03 KB

Python analysis in Trellis

Trellis audits .py files alongside TypeScript and TSX with the same scoring, reporting, comparison, policy, history and fleet pipeline. Python is parsed in process with pinned @lezer/python 1.1.18; no Python interpreter, project import, install or subprocess is needed for the native audit. The audited project is never executed. The parser accepts Python 3 grammar forms tested here, including async def, decorators, comprehensions and match. Newer or interpreter-specific syntax is only covered when the pinned grammar accepts it; Trellis does not emulate Python's runtime semantics. Python source must be UTF-8; invalid byte sequences are reported as an incomplete parse rather than silently decoded with replacement characters.

Discovery includes root packages, src/ layouts and nested projects. Test paths and test_*.py / *_test.py basenames enter the test source set. Environment/cache directories, including .venv, venv, __pycache__, .pytest_cache, .mypy_cache, .ruff_cache and directories bearing pyvenv.cfg, are skipped. Existing source.exclude and source.classify rules also apply to Python files.

The native adapter measures named, async, decorated and nested functions, methods, and anonymous lambdas. It counts if/elif, loops, except, non-default case, guards, boolean short-circuit operators, conditional expressions and comprehension clauses. Nested function and lambda decisions belong to their own function. Python functions feed the same erosion formula and hotspot ranking as TypeScript. Clone detection shares the bounded native engine and its 100-token / 3-line thresholds, with Python-specific lexical normalization and suite boundaries. Python and TypeScript tokens cannot clone across languages.

Advisory duplication.candidate.* metrics count independent executable copies from those raw groups. Python import statements, type declarations, literal collections and calls with entirely literal arguments receive separate syntax roles; mixed spans remain visible without an automatic implementation-copy claim. Candidate intervals are selected on tokens, so copies sharing a line can still be independent. These metrics never enter the current index.

Confirmed typing.overload declarations, including imported aliases and qualified decorators on methods and async methods, count as signatures rather than executable functions. Their following implementation retains its scoped identity and records the signature count. A declaration without a matching implementation produces an unscored python.orphan-overload finding. Rebound decorator names do not receive overload treatment, and genuinely repeated implementations retain ambiguous identities. Analyzer 0.7.0 and scoring 0.7.0-provisional mark this corrected function population; re-audit saved baselines before using regression policy.

Static imports resolve only against discovered local Python files. Trellis supports dotted absolute imports, package __init__.py, src/ module roots, and relative from imports. from pkg import child targets the child module when present, otherwise the package containing the imported symbol. A top level name absent locally is external; a missing descendant of a known local package or failed relative import is unresolved. Ambiguous module owners are unresolved. Binding-confirmed literal importlib.import_module calls, including a literal relative package, and supported one-argument absolute __import__ calls can resolve to discovered local modules. Runtime-selected calls remain located unresolved evidence; ambiguous local module owners still make cycle coverage incomplete. Arbitrary dataflow, sys.path mutation, installed packages and imports between Python and TypeScript are not resolved. Confirmed typing.TYPE_CHECKING guards, including imported aliases, qualified typing aliases, nested guards and negation, mark their guarded imports as type-only. The complementary else branch remains runtime when provable. Rebound and shadowed names receive no type-only inference. These edges remain in graph evidence and form a separate cycle subgraph; a type-only/runtime pair is not a runtime cycle. This is a static binding classification, not Python execution. Deferred function bodies reconfirm typing aliases imported locally; a module alias used from a deferred body is treated as unknown because it could be rebound before the body runs. .pyi files remain unsupported.

First-statement module, class and function docstrings retain physical SLOC but are excluded from executable function mass and clone tokens, covered lines and density denominators. Other multiline strings remain executable source. Native advisory documentation review flags a docstring only when its physical content exceeds 40 nonblank lines or 300 Unicode-whitespace-separated words. The finding carries the original range, owner when known and effective thresholds; it never changes the index. trellis.yaml can disable the review or set positive integer thresholds under documentation.

Reports include languageCoverage rows with discovered/analyzed files, parse failures, source lines, unresolved imports and dynamic imports. An unresolved import remains visible even when its absent or runtime-selected target cannot join the declared-source graph. Parser recovery and ambiguous local targets still make required dimensions incomplete. Schema 1.5.0 carries production-only cycle metrics beside workspace cycle evidence. Analyzer 0.7.0 and scoring 0.7.0-provisional score cycles only over production modules and their imports; unrelated test files cannot dilute the cycle density or withhold its score. Recreate baselines made by older analyzer versions before using regression policy. Historical reports remain readable.

The external evidence providers remain optional, unscored and scoped to TypeScript. They do not claim coverage of Python files. The native Python adapter is the authoritative Python measurement path.

The implementation report records the acceptance tests, CLI smoke runs, TypeScript parity and Trellis self-audit.