victor-codegraph 0.10.1__tar.gz → 0.10.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/PKG-INFO +7 -3
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/README.md +6 -2
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/pyproject.toml +1 -1
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/tests/test_relations_v2.py +36 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph/__init__.py +1 -1
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph/python_parser.py +39 -17
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph/repository_index.py +16 -8
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph/resolution.py +9 -1
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph.egg-info/PKG-INFO +7 -3
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/setup.cfg +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/tests/test_adapter.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/tests/test_adapter_validation_v2.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/tests/test_chunk_contract_v2.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/tests/test_diagnostics_v2.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/tests/test_embedding_contract.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/tests/test_identity_v2.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/tests/test_line_base_contract.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/tests/test_manifest.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/tests/test_python_parser.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/tests/test_repo.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/tests/test_repository_delta_v2.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/tests/test_sizing_and_chunk.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/tests/test_sizing_overlap.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/tests/test_symbol_oid_contract.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/tests/test_symbol_oid_parity.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/tests/test_treesitter_jsts.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/tests/test_treesitter_languages.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/tests/test_treesitter_relations.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph/adapter.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph/config.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph/embeddings.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph/javascript_repository.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph/languages.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph/manifest.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph/model.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph/parser.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph/py.typed +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph/repo.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph/rust_repository.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph/sizing.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph/treesitter_parser.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph/treesitter_tables.py +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph.egg-info/SOURCES.txt +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph.egg-info/dependency_links.txt +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph.egg-info/requires.txt +0 -0
- {victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: victor-codegraph
|
|
3
|
-
Version: 0.10.
|
|
3
|
+
Version: 0.10.2
|
|
4
4
|
Summary: Repository-to-Code-Semantic-Graph compiler with stable identity, bounded chunks, incremental deltas, and ProximaRecord projection.
|
|
5
5
|
Author-email: Vijaykumar Singh <vijay@anvaiops.com>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -56,7 +56,11 @@ gaps:
|
|
|
56
56
|
## Install
|
|
57
57
|
|
|
58
58
|
Published on PyPI as [`victor-codegraph`](https://pypi.org/project/victor-codegraph/).
|
|
59
|
-
This source tree is version **0.10.
|
|
59
|
+
This source tree is version **0.10.2**; consumers should use a compatible `<1.0` pin.
|
|
60
|
+
It repairs nested Python definition/import shadowing: proven local definitions
|
|
61
|
+
retain their targets, while unmodeled conditional bindings stay unresolved.
|
|
62
|
+
Rebuild derived graphs when adopting the new parser; unchanged source hashes do
|
|
63
|
+
not invalidate old semantic results automatically. Publication is a separate gate.
|
|
60
64
|
|
|
61
65
|
```bash
|
|
62
66
|
# from PyPI
|
|
@@ -128,7 +132,7 @@ records = to_proxima_records(repository, repo_graph_id="myrepo")
|
|
|
128
132
|
|
|
129
133
|
## Status
|
|
130
134
|
|
|
131
|
-
`0.10.
|
|
135
|
+
`0.10.2` source version. Python (`ast`) is the full, offline frontend. JS/TS, Go, Rust,
|
|
132
136
|
Java, C, and C++ have conformance fixtures; other mapped tree-sitter languages report
|
|
133
137
|
symbols-tier or fallback status rather than implying full fidelity.
|
|
134
138
|
|
|
@@ -25,7 +25,11 @@ gaps:
|
|
|
25
25
|
## Install
|
|
26
26
|
|
|
27
27
|
Published on PyPI as [`victor-codegraph`](https://pypi.org/project/victor-codegraph/).
|
|
28
|
-
This source tree is version **0.10.
|
|
28
|
+
This source tree is version **0.10.2**; consumers should use a compatible `<1.0` pin.
|
|
29
|
+
It repairs nested Python definition/import shadowing: proven local definitions
|
|
30
|
+
retain their targets, while unmodeled conditional bindings stay unresolved.
|
|
31
|
+
Rebuild derived graphs when adopting the new parser; unchanged source hashes do
|
|
32
|
+
not invalidate old semantic results automatically. Publication is a separate gate.
|
|
29
33
|
|
|
30
34
|
```bash
|
|
31
35
|
# from PyPI
|
|
@@ -97,7 +101,7 @@ records = to_proxima_records(repository, repo_graph_id="myrepo")
|
|
|
97
101
|
|
|
98
102
|
## Status
|
|
99
103
|
|
|
100
|
-
`0.10.
|
|
104
|
+
`0.10.2` source version. Python (`ast`) is the full, offline frontend. JS/TS, Go, Rust,
|
|
101
105
|
Java, C, and C++ have conformance fixtures; other mapped tree-sitter languages report
|
|
102
106
|
symbols-tier or fallback status rather than implying full fidelity.
|
|
103
107
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "victor-codegraph"
|
|
7
|
-
version = "0.10.
|
|
7
|
+
version = "0.10.2"
|
|
8
8
|
description = "Repository-to-Code-Semantic-Graph compiler with stable identity, bounded chunks, incremental deltas, and ProximaRecord projection."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
3
5
|
import pytest
|
|
4
6
|
|
|
5
7
|
from victor_codegraph import CodeRelationType, parse, parse_repo, to_proxima_records
|
|
@@ -319,6 +321,40 @@ def test_python_enclosing_and_capture_bindings_block_import_guess(tmp_path, body
|
|
|
319
321
|
assert calls and all(r.target_ref for r in calls)
|
|
320
322
|
|
|
321
323
|
|
|
324
|
+
@pytest.mark.parametrize(
|
|
325
|
+
("body", "target_scope"),
|
|
326
|
+
[
|
|
327
|
+
("def caller():\n def target(): return 2\n return target()", ["caller"]),
|
|
328
|
+
("async def caller():\n async def target(): return 2\n return await target()", ["caller"]),
|
|
329
|
+
("def caller():\n class target: pass\n return target()", ["caller"]),
|
|
330
|
+
("def outer():\n def target(): return 2\n def caller(): return target()", ["outer"]),
|
|
331
|
+
("def caller(flag):\n if flag:\n def target(): return 2\n return target()", None),
|
|
332
|
+
(
|
|
333
|
+
"def outer():\n def target(): return 2\n def caller(flag):\n if flag:\n def target(): return 3\n return target()",
|
|
334
|
+
None,
|
|
335
|
+
),
|
|
336
|
+
("def caller(): return target()", []),
|
|
337
|
+
],
|
|
338
|
+
)
|
|
339
|
+
def test_python_nearest_definition_precedes_import(
|
|
340
|
+
tmp_path: Path, body: str, target_scope: list[str] | None
|
|
341
|
+
) -> None:
|
|
342
|
+
(tmp_path / "a.py").write_text("def target(): return 1\n")
|
|
343
|
+
(tmp_path / "b.py").write_text("from a import target\n" + body)
|
|
344
|
+
graph = parse_repo(tmp_path)
|
|
345
|
+
calls = [r for r in graph.relations if r.relation_type == CodeRelationType.CALLS]
|
|
346
|
+
assert len(calls) == 1
|
|
347
|
+
call = calls[0]
|
|
348
|
+
if target_scope is None:
|
|
349
|
+
assert call.target_ref is not None
|
|
350
|
+
assert call.confidence < 1.0
|
|
351
|
+
else:
|
|
352
|
+
target = next(s for s in graph.symbols if s.id == call.to_symbol_id)
|
|
353
|
+
assert call.target_ref is None
|
|
354
|
+
assert target.scope_chain == target_scope
|
|
355
|
+
assert target.location.file_path == ("b.py" if target_scope else "a.py")
|
|
356
|
+
|
|
357
|
+
|
|
322
358
|
def test_python_reassigned_self_is_not_a_proven_receiver():
|
|
323
359
|
parsed = parse(
|
|
324
360
|
"class A:\n def target(self): pass\n def caller(self):\n self = external\n self.target()\n",
|
|
@@ -8,6 +8,8 @@ signatures, docstrings, decorators, parameters, cyclomatic complexity, and CALLS
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
10
|
import ast
|
|
11
|
+
from collections.abc import Iterator, Sequence
|
|
12
|
+
from typing import NotRequired, TypedDict
|
|
11
13
|
|
|
12
14
|
from .model import (
|
|
13
15
|
CodeRelation,
|
|
@@ -47,13 +49,20 @@ def _cyclomatic(node: ast.AST) -> dict[str, int]:
|
|
|
47
49
|
return {"cyclomatic": count, "lines": end - lineno + 1}
|
|
48
50
|
|
|
49
51
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
class _Parameter(TypedDict):
|
|
53
|
+
name: str
|
|
54
|
+
type: NotRequired[str]
|
|
55
|
+
is_variadic: NotRequired[bool]
|
|
56
|
+
is_kwonly: NotRequired[bool]
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _params(args: ast.arguments) -> list[_Parameter]:
|
|
60
|
+
out: list[_Parameter] = []
|
|
52
61
|
posonly = getattr(args, "posonlyargs", [])
|
|
53
62
|
for a in [*posonly, *args.args]:
|
|
54
63
|
if a.arg in ("self", "cls"):
|
|
55
64
|
continue
|
|
56
|
-
p:
|
|
65
|
+
p: _Parameter = {"name": a.arg}
|
|
57
66
|
if a.annotation is not None:
|
|
58
67
|
p["type"] = ast.unparse(a.annotation)
|
|
59
68
|
out.append(p)
|
|
@@ -109,7 +118,7 @@ def _callee_ref(call: ast.Call) -> SymbolReference | None:
|
|
|
109
118
|
return None
|
|
110
119
|
|
|
111
120
|
|
|
112
|
-
def _calls_owned_by(node: ast.AST):
|
|
121
|
+
def _calls_owned_by(node: ast.AST) -> Iterator[ast.Call]:
|
|
113
122
|
"""Yield calls owned by ``node`` without stealing calls from nested definitions."""
|
|
114
123
|
|
|
115
124
|
stack = list(ast.iter_child_nodes(node))
|
|
@@ -122,13 +131,15 @@ def _calls_owned_by(node: ast.AST):
|
|
|
122
131
|
stack.extend(ast.iter_child_nodes(child))
|
|
123
132
|
|
|
124
133
|
|
|
125
|
-
def
|
|
126
|
-
"""
|
|
134
|
+
def _lexical_bindings(nodes: Sequence[ast.AST]) -> tuple[set[str], set[str]]:
|
|
135
|
+
"""Collect writes and definition bindings without entering nested namespaces."""
|
|
127
136
|
names: set[str] = set()
|
|
137
|
+
definitions: set[str] = set()
|
|
128
138
|
stack = list(nodes)
|
|
129
139
|
while stack:
|
|
130
140
|
node = stack.pop()
|
|
131
141
|
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)):
|
|
142
|
+
definitions.add(node.name)
|
|
132
143
|
continue
|
|
133
144
|
if isinstance(node, ast.arg):
|
|
134
145
|
names.add(node.arg)
|
|
@@ -141,7 +152,7 @@ def _bound_names(nodes: list[ast.AST]) -> set[str]:
|
|
|
141
152
|
if isinstance(node, (ast.Import, ast.ImportFrom)):
|
|
142
153
|
names.update(a.asname or a.name.split(".")[0] for a in node.names)
|
|
143
154
|
stack.extend(ast.iter_child_nodes(node))
|
|
144
|
-
return names
|
|
155
|
+
return names, definitions
|
|
145
156
|
|
|
146
157
|
|
|
147
158
|
class _Visitor:
|
|
@@ -152,6 +163,7 @@ class _Visitor:
|
|
|
152
163
|
self.relations: list[CodeRelation] = []
|
|
153
164
|
self.imports: list[str] = []
|
|
154
165
|
self._enclosing_bindings: list[set[str]] = []
|
|
166
|
+
self._definition_scopes: list[dict[str, list[str]]] = [{}]
|
|
155
167
|
self._import_names: set[str] = set()
|
|
156
168
|
self._wildcard_import = False
|
|
157
169
|
self._fqn_prefix = file_path.replace("/", ".").replace("\\", ".")
|
|
@@ -190,7 +202,7 @@ class _Visitor:
|
|
|
190
202
|
symbol_type: CodeSymbolType,
|
|
191
203
|
scope: list[str],
|
|
192
204
|
signature: str | None = None,
|
|
193
|
-
params: list[
|
|
205
|
+
params: list[_Parameter] | None = None,
|
|
194
206
|
return_type: str | None = None,
|
|
195
207
|
modifiers: list[str] | None = None,
|
|
196
208
|
) -> CodeSymbol:
|
|
@@ -220,7 +232,7 @@ class _Visitor:
|
|
|
220
232
|
signature=signature,
|
|
221
233
|
modifiers=modifiers or [],
|
|
222
234
|
scope_chain=list(scope),
|
|
223
|
-
parameters=params or [],
|
|
235
|
+
parameters=[dict(parameter) for parameter in params or []],
|
|
224
236
|
return_type=return_type,
|
|
225
237
|
complexity=_cyclomatic(node),
|
|
226
238
|
)
|
|
@@ -254,10 +266,16 @@ class _Visitor:
|
|
|
254
266
|
bound.add(node.args.vararg.arg)
|
|
255
267
|
if node.args.kwarg:
|
|
256
268
|
bound.add(node.args.kwarg.arg)
|
|
257
|
-
writes =
|
|
269
|
+
writes, definitions = _lexical_bindings(node.body)
|
|
270
|
+
inner = [*scope, name]
|
|
271
|
+
definition_scopes = {
|
|
272
|
+
**self._definition_scopes[-1],
|
|
273
|
+
**{definition: inner for definition in definitions},
|
|
274
|
+
}
|
|
258
275
|
enclosing = set().union(*self._enclosing_bindings)
|
|
259
276
|
sym.metadata["python_bound_names"] = sorted(bound | writes | enclosing)
|
|
260
277
|
sym.metadata["python_rebound_names"] = sorted(writes | enclosing)
|
|
278
|
+
sym.metadata["python_definition_scopes"] = definition_scopes
|
|
261
279
|
sym.metadata["python_import_names"] = sorted(self._import_names)
|
|
262
280
|
sym.metadata["python_wildcard_import"] = self._wildcard_import
|
|
263
281
|
sym.metadata["python_receiver"] = (
|
|
@@ -275,10 +293,10 @@ class _Visitor:
|
|
|
275
293
|
# and otherwise keeps it as a bare name (so cross-file/external calls — e.g.
|
|
276
294
|
# a CPG's blast radius — are not silently dropped). ``call_site`` records the
|
|
277
295
|
# call line for consumers that need it.
|
|
278
|
-
for
|
|
279
|
-
ref = _callee_ref(
|
|
296
|
+
for call in _calls_owned_by(node):
|
|
297
|
+
ref = _callee_ref(call)
|
|
280
298
|
if ref:
|
|
281
|
-
line, col, end_line, end_col, offset, length = self._span(
|
|
299
|
+
line, col, end_line, end_col, offset, length = self._span(call)
|
|
282
300
|
self.relations.append(
|
|
283
301
|
CodeRelation(
|
|
284
302
|
from_symbol_id=sym.id,
|
|
@@ -297,8 +315,8 @@ class _Visitor:
|
|
|
297
315
|
),
|
|
298
316
|
)
|
|
299
317
|
)
|
|
300
|
-
inner = [*scope, name]
|
|
301
318
|
self._enclosing_bindings.append(bound | writes)
|
|
319
|
+
self._definition_scopes.append(definition_scopes)
|
|
302
320
|
for child in node.body:
|
|
303
321
|
nested: CodeSymbol | None = None
|
|
304
322
|
if isinstance(child, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
@@ -314,6 +332,7 @@ class _Visitor:
|
|
|
314
332
|
)
|
|
315
333
|
)
|
|
316
334
|
self._enclosing_bindings.pop()
|
|
335
|
+
self._definition_scopes.pop()
|
|
317
336
|
return sym
|
|
318
337
|
|
|
319
338
|
def visit_class(self, node: ast.ClassDef, scope: list[str]) -> CodeSymbol:
|
|
@@ -322,6 +341,7 @@ class _Visitor:
|
|
|
322
341
|
if bases:
|
|
323
342
|
mods.append(f"extends({','.join(bases)})")
|
|
324
343
|
cls = self._make_symbol(node, node.name, CodeSymbolType.CLASS, scope, modifiers=mods)
|
|
344
|
+
cls.metadata["python_definition_scopes"] = self._definition_scopes[-1]
|
|
325
345
|
cls.metadata["python_rebound_names"] = sorted(set().union(*self._enclosing_bindings))
|
|
326
346
|
self.symbols.append(cls)
|
|
327
347
|
for base in bases:
|
|
@@ -356,9 +376,11 @@ class _Visitor:
|
|
|
356
376
|
return cls
|
|
357
377
|
|
|
358
378
|
def run(self, tree: ast.Module) -> None:
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
379
|
+
module_writes, _ = _lexical_bindings(
|
|
380
|
+
[n for n in tree.body if not isinstance(n, (ast.Import, ast.ImportFrom))]
|
|
381
|
+
)
|
|
382
|
+
self._enclosing_bindings = [module_writes]
|
|
383
|
+
self._definition_scopes = [{}]
|
|
362
384
|
self._import_names = set()
|
|
363
385
|
for declaration in tree.body:
|
|
364
386
|
if isinstance(declaration, (ast.Import, ast.ImportFrom)):
|
|
@@ -7,6 +7,10 @@ import hashlib
|
|
|
7
7
|
import os
|
|
8
8
|
from dataclasses import asdict, dataclass, field, replace
|
|
9
9
|
from pathlib import Path
|
|
10
|
+
from typing import TYPE_CHECKING
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from .rust_repository import RustBinding
|
|
10
14
|
|
|
11
15
|
from .model import (
|
|
12
16
|
CodeRelation,
|
|
@@ -67,7 +71,7 @@ def _resolve_across_files(
|
|
|
67
71
|
symbols: list[CodeSymbol],
|
|
68
72
|
relations: list[CodeRelation],
|
|
69
73
|
files: dict[str, ParsedCode],
|
|
70
|
-
rust_bindings: dict[str, list] | None = None,
|
|
74
|
+
rust_bindings: dict[str, list[RustBinding]] | None = None,
|
|
71
75
|
javascript: JavaScriptRepository | None = None,
|
|
72
76
|
) -> list[CodeRelation]:
|
|
73
77
|
"""Resolve only unambiguous repository targets; ambiguity remains explicit."""
|
|
@@ -147,11 +151,15 @@ def _resolve_across_files(
|
|
|
147
151
|
if source.language == "python":
|
|
148
152
|
text = ref.text or ref.name
|
|
149
153
|
root, *tail = text.split(".")
|
|
150
|
-
if
|
|
151
|
-
"python_wildcard_import"
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
154
|
+
if (
|
|
155
|
+
not source.metadata.get("python_wildcard_import")
|
|
156
|
+
and root not in source.metadata.get("python_bound_names", [])
|
|
157
|
+
and root not in source.metadata.get("python_definition_scopes", {})
|
|
158
|
+
):
|
|
159
|
+
for import_name, targets in python_bindings.get(
|
|
160
|
+
source.location.file_path, {}
|
|
161
|
+
).items():
|
|
162
|
+
prefix = import_name.split(".")
|
|
155
163
|
parts = text.split(".")
|
|
156
164
|
if parts[: len(prefix)] != prefix:
|
|
157
165
|
continue
|
|
@@ -198,7 +206,7 @@ def _python_bindings(
|
|
|
198
206
|
if isinstance(node, ast.ImportFrom):
|
|
199
207
|
module = "." * node.level + (node.module or "")
|
|
200
208
|
name = alias.asname or alias.name
|
|
201
|
-
target = (alias.name,)
|
|
209
|
+
target: tuple[str, ...] = (alias.name,)
|
|
202
210
|
options = [
|
|
203
211
|
(module, target),
|
|
204
212
|
(module + ("." if node.module else "") + alias.name, ()),
|
|
@@ -347,7 +355,7 @@ def parse_repo(
|
|
|
347
355
|
|
|
348
356
|
rust = RustRepository(root_path, resolution_files)
|
|
349
357
|
javascript = JavaScriptRepository(resolution_files)
|
|
350
|
-
rust_bindings: dict[str, list] = {}
|
|
358
|
+
rust_bindings: dict[str, list[RustBinding]] = {}
|
|
351
359
|
for relative, parsed in resolution_files.items():
|
|
352
360
|
owner = file_symbols[relative]
|
|
353
361
|
for symbol in parsed.symbols:
|
|
@@ -72,6 +72,7 @@ def resolve_relations(
|
|
|
72
72
|
if source is not None and source.language == "rust":
|
|
73
73
|
candidates = _rust_candidates(source, ref, candidates, symbols)
|
|
74
74
|
elif source is not None and source.language == "python":
|
|
75
|
+
definition_scope = source.metadata.get("python_definition_scopes", {}).get(ref.name)
|
|
75
76
|
if source.metadata.get("python_wildcard_import"):
|
|
76
77
|
candidates = []
|
|
77
78
|
elif ref.qualifier in {"self", "cls"}:
|
|
@@ -87,7 +88,10 @@ def resolve_relations(
|
|
|
87
88
|
elif (
|
|
88
89
|
ref.qualifier
|
|
89
90
|
or ref.name in source.metadata.get("python_bound_names", [])
|
|
90
|
-
or
|
|
91
|
+
or (
|
|
92
|
+
ref.name in source.metadata.get("python_import_names", [])
|
|
93
|
+
and definition_scope is None
|
|
94
|
+
)
|
|
91
95
|
):
|
|
92
96
|
candidates = []
|
|
93
97
|
else:
|
|
@@ -104,6 +108,10 @@ def resolve_relations(
|
|
|
104
108
|
and [*source.scope_chain, source.simple_name][: len(c.scope_chain)]
|
|
105
109
|
== c.scope_chain
|
|
106
110
|
]
|
|
111
|
+
# A lexical definition shadows imports and outer definitions even
|
|
112
|
+
# when its conditional body is not represented by this parser.
|
|
113
|
+
if definition_scope is not None:
|
|
114
|
+
candidates = [c for c in candidates if c.scope_chain == definition_scope]
|
|
107
115
|
nearest = max((len(c.scope_chain) for c in candidates), default=-1)
|
|
108
116
|
candidates = [c for c in candidates if len(c.scope_chain) == nearest]
|
|
109
117
|
elif source is not None and source.language in {"javascript", "typescript", "tsx"}:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: victor-codegraph
|
|
3
|
-
Version: 0.10.
|
|
3
|
+
Version: 0.10.2
|
|
4
4
|
Summary: Repository-to-Code-Semantic-Graph compiler with stable identity, bounded chunks, incremental deltas, and ProximaRecord projection.
|
|
5
5
|
Author-email: Vijaykumar Singh <vijay@anvaiops.com>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -56,7 +56,11 @@ gaps:
|
|
|
56
56
|
## Install
|
|
57
57
|
|
|
58
58
|
Published on PyPI as [`victor-codegraph`](https://pypi.org/project/victor-codegraph/).
|
|
59
|
-
This source tree is version **0.10.
|
|
59
|
+
This source tree is version **0.10.2**; consumers should use a compatible `<1.0` pin.
|
|
60
|
+
It repairs nested Python definition/import shadowing: proven local definitions
|
|
61
|
+
retain their targets, while unmodeled conditional bindings stay unresolved.
|
|
62
|
+
Rebuild derived graphs when adopting the new parser; unchanged source hashes do
|
|
63
|
+
not invalidate old semantic results automatically. Publication is a separate gate.
|
|
60
64
|
|
|
61
65
|
```bash
|
|
62
66
|
# from PyPI
|
|
@@ -128,7 +132,7 @@ records = to_proxima_records(repository, repo_graph_id="myrepo")
|
|
|
128
132
|
|
|
129
133
|
## Status
|
|
130
134
|
|
|
131
|
-
`0.10.
|
|
135
|
+
`0.10.2` source version. Python (`ast`) is the full, offline frontend. JS/TS, Go, Rust,
|
|
132
136
|
Java, C, and C++ have conformance fixtures; other mapped tree-sitter languages report
|
|
133
137
|
symbols-tier or fallback status rather than implying full fidelity.
|
|
134
138
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph/javascript_repository.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{victor_codegraph-0.10.1 → victor_codegraph-0.10.2}/victor_codegraph.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|