Commit Graph
9 Commits
Author SHA1 Message Date
Martin Vogel 8a0afb5fed feat(resolver): recover Python edges a project's layout and ordinary writes had voided
CALLS recall against SCIP on six repositories rises from 80.7% to 95.5%, precision holding at 99.5%. A manifest now states source roots, so a src layout reaches its own package. A write blocks only the name it spells, not a whole package. Decorators keep the declaration unless the source proves the function dropped. Three false edges the baseline also had are fixed: a conditional star's first arm, t.x = make() reading the declared x, and a descriptor read as the instance.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-11-02 18:07:57 +01:00
Martin Vogel d614236668 test(resolver): forge a C include list, and split the Python suite for the Windows cap
C writes no binding list to alter now, so the authority test forges one: a property naming a wrong target must still carry no authority. The Python suite ran about 500 full indexes through both drivers and passed the 900 s per-suite cap on Windows, so it is three suites, and rows of one fixture share its index. No assertion changes.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-11-02 18:07:01 +01:00
Martin Vogel 456bdbb30c resolver: an external base keeps what a class body assigned
The class-body rule also withheld under any opaque base. Whole django lost 1,071
CALLS occurrences to it, and read against source nearly all were true: rf =
RequestFactory() in a unittest.TestCase is what it says. Only about 16 of them
were the wrong edges the rule exists for, a field read through a model class.

A metaclass we can see and __init_subclass__ still withhold, and so do Enum and
NamedTuple, known from the stdlib through the import. A base that resolves to
nothing at all still does too. A project class named Enum does not.

The field reads stay withheld. So do the true reads through django's own
ModelBase, such as ContentType.objects.get_for_model, since nothing static tells
a manager from a field: 13 of 10,506 CALLS on dj-core. tests/middleware: self.rf.get
back on all 40 sites.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-11-01 17:52:38 +01:00
Martin Vogel ecfe0b3dc5 test: pin Python search path, spelling and class-body rules
Each rule with its decoy, on both drivers: search path, ambiguity and shadowing,
Optional and unions through the import, shadowed super and type, subscripted
bases, class-body values under a metaclass, Enum and opaque bases, class
comprehensions, the first written base, and every form that rebinds a receiver.

Corrected, each with the reason:
- python_route_edges hard-coded main.py as the source, so a test written from any
  other file passed its negatives vacuously. It takes the source file now.
- plain read control: a function read in an assignment is a CALL_REFERENCE, the
  bare return form is the USAGE, as `return decorator` is in django/test/utils.py.
- local rebound to another class: both candidates shared one file and name, so
  the count could not tell them apart. It now separates them, which is stricter:
  the last assignment selects, a branch selects neither.
- property read: a getter and setter share one node with the setter's span, so a
  read abstains. Pinned as a known gap at the case, with a getter alone as positive.
- single chain: Multi(Middle, Base) now proves self.mid through its first base.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-11-01 17:21:27 +01:00
Martin Vogel 154251af1e resolver: a conditional wrapper pair must both be proven
Either arm of a conditional def can be the one bound at run time. The
decorator shape looked at the first def of the name only, so a second arm
that never calls the function still counted as keeping its identity.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-11-01 16:22:58 +01:00
Martin Vogel 0417b0c0b0 resolver: more decorator forms proven from source
wraps(fn)(g) and update_wrapper(g, fn) keep identity when g calls fn. A
decorator that hands the function to another decorator keeps identity when
that one does. A classmethod or staticmethod subclass binds the same function.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-11-01 16:15:52 +01:00
Martin Vogel 41527834f2 resolver: Python package roots, line continuations, proven INHERITS
- import a.b and import a.c bind one package, not two competing values, and
  a.other reads through that package
- a backslash line continuation no longer voids the file
- bases proven through reexports and star imports become INHERITS edges on
  both drivers, so the hierarchy no longer stops where the registry stops
- a binder is only annotated once add_name actually recorded it

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-11-01 16:10:03 +01:00
Martin Vogel 9d39c6576e test: pin the Python binding and member rules
Forms taken from django, each with its decoy or shadow, on both drivers:
ordinary syntax, real dynamic effects, member spellings, deferred bodies,
conditional defs, import forms, star imports, C3 order, super, receiver type
facts, module instances, decorators and properties.

Flipped pins, each now a true rule:
- f-string values and no-value annotations are reads, so they no longer void
  the file
- setattr, delattr, __dict__ and __import__ cannot rebind an audited name
- PEP 695 declarations bind inside their own scope

test_incremental.c pinned IMPORTS occurrences at span 0/0; they now carry the
exact clause span, so fastapi_physical_import checks that span.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-11-01 14:11:13 +01:00
Martin Vogel 75f45ba248 Add shared semantic resolution with explicit proof admission
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-10-25 18:20:22 +01:00