Skip to content

fix(python): resolve module-level functions in get_method; truthful callers/callees - #250

Merged
rahlk merged 2 commits into
mainfrom
fix/issue-246
Jul 14, 2026
Merged

fix(python): resolve module-level functions in get_method; truthful callers/callees#250
rahlk merged 2 commits into
mainfrom
fix/issue-246

Conversation

@rahlk

Copy link
Copy Markdown
Collaborator

Closes#246.

What

get_method only searched class scope, so module-level functions were unreachable and get_all_callers/get_all_callees returned a silent false-empty ({"caller_details": []}) for them even when the call graph had the edges. Fixed on both backends:

  • Local: get_method(scope, name) now resolves module-level functions when scope is a module name, mirroring get_all_methods_in_application's keying; short-name fallback preserved.
  • Neo4j: same semantics via a scoped module-functions query (no whole-table fan-out).
  • get_all_callers / get_all_callees / get_method_parameters / get_comments_in_a_method inherit the fix through get_method.
  • Docs: facade + ABC docstrings now state the module-name semantics; local-backend docstring notes the pathological class-signature==module-name resolution-order asymmetry.

Miss shapes are deliberately unchanged (a genuine miss still returns None / empty) — #249 owns miss discrimination.

Tests

New tests/analysis/python/test_python_method_lookup.py (11 tests): module-level lookup + callers/callees on a pkg.mod.entry -> pkg.mod.helper call-edge fixture, both backends, plus genuine-miss regression pins. TDD (RED on unfixed code, GREEN after).

Gate on head 0385257: tests/analysis/python35 passed, 6 skipped (skips = live-Neo4j gating, no server in the dev sandbox).

Notes for reviewers

  • The live-Neo4j parity assertions extended in test_python_neo4j_backend.py need a live-DB run (CI or local Neo4j) to execute; the offline stub tests cover the dispatch logic.
  • Accepted lookup key forms after this fix: qualified class name OR module name as scope + short name or full signature as member. (Languages differ in accepted key forms — relevant when the cross-language contract suite lands.)

rahlk added 2 commits July 14, 2026 10:23
get_method(scope, name) delegated straight to get_all_methods_in_class,
so any scope naming a module rather than a class came back empty. Since
get_all_callers/get_all_callees call get_method internally, they
silently reported the false-empty {"caller_details": []} /
{"callee_details": []} for module-level functions even when the call
graph knew the true edge.
Local backend: resolve scope the same way get_all_methods_in_application
already does (class signature or module name as the outer key).
Neo4j backend: try the class path first (get_class), and fall back to a
new targeted _get_module_functions query scoped by module_name so the
fix stays as cheap as the existing class lookup instead of paying a
whole-symbol-table fan-out per call.
Miss-shape semantics (None / empty caller_details) are unchanged.
@rahlk
rahlk merged commit 7eef456 into mainJul 14, 2026
@rahlk
rahlk deleted the fix/issue-246 branch July 14, 2026 15:59
@rahlkrahlk added the fix Bug fixes label Jul 14, 2026
@rahlkrahlk mentioned this pull request Jul 14, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fixBug fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(python): get_method blind to module-level functions — get_callers/get_callees silent false-empty (local + Neo4j)

1 participant

@rahlk