Skip to content

fix(python): avoid false edges for pytest decorators - #2739

Open
aayush598 wants to merge 1 commit into
Graphify-Labs:v8from
aayush598:fix/2732-decorator-noise
Open

fix(python): avoid false edges for pytest decorators#2739
aayush598 wants to merge 1 commit into
Graphify-Labs:v8from
aayush598:fix/2732-decorator-noise

Conversation

@aayush598

Copy link
Copy Markdown

Problem

Python decorator extraction currently resolves decorator names using the bare symbol name. This causes third-party pytest decorators such as @pytest.fixture and @pytest.mark.parametrize to be treated as references to same-named functions in the corpus.

When a project contains a local fixture() or parametrize() function, repeated pytest decorators can therefore collapse onto that local node and create spurious references edges, producing misleading high-degree/"God Node" results.

Fixes #2732.

Fix

  • Track pytest bindings at module scope in source order.
  • Recognize import pytest and aliased imports such as import pytest as pt.
  • Recognize decorator-capable direct imports such as from pytest import fixture and from pytest import mark.
  • Suppress known pytest decorators only when the decorator is actually bound to pytest at that location.
  • Preserve normal decorator edges for corpus-owned decorators such as bare @fixture.
  • Respect later rebinding and del statements so shadowed pytest names are not incorrectly suppressed.
  • Handle pytest.mark.* decorators without fabricating nodes for marker names.
  • Keep the existing bare-name decorator noise handling unchanged.

Tests

Adds regression coverage for:

  • @pytest.fixture
  • @pytest.mark.parametrize
  • aliased pytest imports
  • direct pytest decorator imports and aliases
  • local decorator shadowing
  • source-order rebinding
  • with/for/walrus rebinding
  • del unbinding
  • nested functions and class methods
  • stacked pytest and custom decorators
  • unimported @pytest.fixture remaining a normal corpus reference

Also updates the changelog for the fix.

Result

Pytest decorators are treated as external test-framework vocabulary when their binding proves they refer to pytest, preventing false cross-file decorator edges and spurious God Nodes while preserving legitimate project-owned decorators.

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

This PR adds pytest-decorator filtering to the Python extractor to prevent false decorator edges. It introduces an ordered module-level binding tracker (_python_pytest_bindings / _PythonBindingEvent) and an _is_pytest_decorator_noise check that classifies decorators like @pytest.fixture, @pytest.mark.*, and rebound @fixture names by qualified path or import binding in force at the decorator's location, rather than by bare tail name. It wires this check into the generic decorator extraction branch, adds supporting constants and a changelog entry, and includes a corresponding test.

No blocking issues surfaced. 4 lower-confidence candidates did not survive cross-model review.

Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 818 functions depend on the 423 functions this change touches.

Health — this change adds coupling hotspots:

  • worse: _extract_generic() — 18 callers, 24 callees
  • worse: walk() — 1 callers, 56 callees

Verification — 818 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 759 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify \_extract\_generic.

The verifier did not have enough to check \_extract\_generic, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `path` is annotated `Path` — outside the synthesizable primitive/collection set

Could not verify: Could not verify \_python\_decorator\_name.

The verifier did not have enough to check \_python\_decorator\_name, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: not verifiable: all 182 sampled inputs raised on both versions — the function never executed, so 'no divergence' would be vacuous (mostly AttributeError — names the real obstacle, not a sampling gap)

· 2 more finding(s) on lines outside this diff (see the check run).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant