Is your feature request related to a problem? Please describe.
The same checkout (odoo-slim-19, 2,364 files) analysed by codeanalyzer-python 1.4.1 under two different Python interpreters produces materially different graphs. Emitting into Neo4j from two runs:
|
run A |
run B |
PY_CALLS |
baseline |
+2,256 (3,125 new / 869 gone) |
PY_RESOLVES_TO |
baseline |
−40 |
PyBodyNode, L4 kinds only (actual_in −1,193, actual_out −568, formal_in −678, formal_out −285) |
baseline |
−2,724 |
PY_DDG |
baseline |
−5,360 (reaching-defs −6,993, points-to +1,633) |
every level-1 body kind (call 77,332, statement 55,169, …) |
identical |
identical |
The differences are systematic re-spellings of resolved targets:
werkzeug.exceptions/NotFound → werkzeug.exceptions.NotFound/__init__
_thread/allocate_lock → _thread.LockType/__init__
super().write → BaseModel.write in one run, builtins.super/write (a ghost) in the other
with downstream consequences: one call site in StockWarehouse.write loses 100 L4 vertices because its chain no longer reaches odoo.tools.translate.
- Two analyses of the same commit are not comparable across machines; a Neo4j graph's
PY_CALLS depends on who emitted it.
- The defuse linker's fan-out amplifies each unresolved call (companion issue): one changed resolution added 219 edges to a single hub in a consumer's bounded call graph.
:PyApplication records analyzer_version but not the interpreter or package set, so a consumer cannot detect the difference.
Describe the solution you'd like
- Record the analysis interpreter (
sys.version_info, platform) and ideally a hash of the resolved environment on :PyApplication and in analysis.json metadata.
- Document that resolution is environment-sensitive and recommend pinning the analysis interpreter for reproducible graphs.
- Consider spelling stdlib targets canonically regardless of interpreter (always the class, never the factory) so the stable cases agree.
Describe alternatives you've considered
Not stated in the original issue.
Additional context
Isolation
A controlled run over a small fixture shows this is not a 1.4.0→1.4.1 emitter change:
- 1.4.0 and 1.4.1 on the same interpreter give byte-identical call targets.
- The same fixture under Python 3.13 flips
Lock() to _thread.LockType/__init__ for both versions.
v1.4.0..v1.4.1 touches only entrypoints/, neo4j/, schema/; jedi is 0.19.2 in both.
The variable is the interpreter (and by implication its stdlib typeshed and installed packages) that Jedi inspects at analysis time.
Definition of done
- A consumer reading
analysis.json or the graph can determine which interpreter produced it.
- The docs state the sensitivity and the recommended practice.
Found while migrating the python-sdk Neo4j backend to 1.4.1 (python-sdk#327).
Is your feature request related to a problem? Please describe.
The same checkout (odoo-slim-19, 2,364 files) analysed by codeanalyzer-python 1.4.1 under two different Python interpreters produces materially different graphs. Emitting into Neo4j from two runs:
PY_CALLSPY_RESOLVES_TOPyBodyNode, L4 kinds only (actual_in−1,193,actual_out−568,formal_in−678,formal_out−285)PY_DDGreaching-defs−6,993,points-to+1,633)call77,332,statement55,169, …)The differences are systematic re-spellings of resolved targets:
werkzeug.exceptions/NotFound→werkzeug.exceptions.NotFound/__init___thread/allocate_lock→_thread.LockType/__init__super().write→BaseModel.writein one run,builtins.super/write(a ghost) in the otherwith downstream consequences: one call site in
StockWarehouse.writeloses 100 L4 vertices because its chain no longer reachesodoo.tools.translate.PY_CALLSdepends on who emitted it.:PyApplicationrecordsanalyzer_versionbut not the interpreter or package set, so a consumer cannot detect the difference.Describe the solution you'd like
sys.version_info, platform) and ideally a hash of the resolved environment on:PyApplicationand inanalysis.jsonmetadata.Describe alternatives you've considered
Not stated in the original issue.
Additional context
Isolation
A controlled run over a small fixture shows this is not a 1.4.0→1.4.1 emitter change:
Lock()to_thread.LockType/__init__for both versions.v1.4.0..v1.4.1touches onlyentrypoints/,neo4j/,schema/; jedi is 0.19.2 in both.The variable is the interpreter (and by implication its stdlib typeshed and installed packages) that Jedi inspects at analysis time.
Definition of done
analysis.jsonor the graph can determine which interpreter produced it.Found while migrating the python-sdk Neo4j backend to 1.4.1 (python-sdk#327).