interlinked-mapper 0.3.12__tar.gz → 0.3.13__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.
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/PKG-INFO +1 -1
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/analyzer/graph.py +11 -1
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked_mapper.egg-info/PKG-INFO +1 -1
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/pyproject.toml +1 -1
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/tests/test_accuracy.py +61 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/__init__.py +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/analyzer/__init__.py +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/analyzer/dead_code.py +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/analyzer/embeddings.py +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/analyzer/parser.py +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/analyzer/similarity.py +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/cli.py +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/commander/__init__.py +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/commander/llm.py +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/commander/query.py +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/commander/repl.py +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/mcp_server.py +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/models.py +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/__init__.py +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/dist/assets/index-CyhrxsQU.css +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/dist/assets/index-Dh01aXoE.js +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/dist/index.html +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/index.html +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/index.html.d3-legacy +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/package-lock.json +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/package.json +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/src/App.tsx +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/src/graph/GraphCanvas.tsx +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/src/graph/nodePrograms.ts +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/src/index.css +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/src/main.tsx +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/src/state/graphStore.ts +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/src/state/sseClient.ts +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/src/theme.ts +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/src/types.ts +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/src/vite-env.d.ts +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/tsconfig.json +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/vite.config.ts +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/layouts.py +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/server.py +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked_mapper.egg-info/SOURCES.txt +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked_mapper.egg-info/dependency_links.txt +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked_mapper.egg-info/entry_points.txt +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked_mapper.egg-info/requires.txt +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked_mapper.egg-info/top_level.txt +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/setup.cfg +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/tests/test_query_completeness.py +0 -0
- {interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/tests/test_watcher.py +0 -0
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
from itertools import islice
|
|
5
6
|
from typing import Any, Iterator
|
|
6
7
|
|
|
7
8
|
import networkx as nx
|
|
@@ -445,17 +446,26 @@ class CodeGraph:
|
|
|
445
446
|
if k not in ("contains", "inherits")]
|
|
446
447
|
)
|
|
447
448
|
|
|
449
|
+
_MAX_PAIRS = 50
|
|
450
|
+
_MAX_PATHS_PER_PAIR = 10
|
|
451
|
+
pairs_checked = 0
|
|
448
452
|
for w in writers:
|
|
449
453
|
for r in readers:
|
|
450
454
|
if w == r:
|
|
451
455
|
continue
|
|
456
|
+
if pairs_checked >= _MAX_PAIRS:
|
|
457
|
+
break
|
|
452
458
|
for src, tgt in [(w, r), (r, w)]:
|
|
453
459
|
if src in flow_graph and tgt in flow_graph:
|
|
454
460
|
try:
|
|
455
|
-
for path in nx.all_simple_paths(flow_graph, src, tgt, cutoff=5):
|
|
461
|
+
for path in islice(nx.all_simple_paths(flow_graph, src, tgt, cutoff=5), _MAX_PATHS_PER_PAIR):
|
|
456
462
|
path_nodes.update(path)
|
|
457
463
|
except nx.NetworkXError:
|
|
458
464
|
pass
|
|
465
|
+
pairs_checked += 1
|
|
466
|
+
else:
|
|
467
|
+
continue
|
|
468
|
+
break
|
|
459
469
|
|
|
460
470
|
# Also add ancestors/descendants of each writer/reader within the trace
|
|
461
471
|
for nid in list(trace_func_ids):
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "interlinked-mapper"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.13"
|
|
8
8
|
description = "A Python program topology explorer — visualize the shape of your codebase"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
@@ -1399,6 +1399,67 @@ class TestFalsePositiveEdges:
|
|
|
1399
1399
|
f"calls_shared_helper resolved to foreign _shared_helper: {foreign_match}"
|
|
1400
1400
|
|
|
1401
1401
|
|
|
1402
|
+
# ══════════════════════════════════════════════════════════════════════
|
|
1403
|
+
# REGRESSION: trace_variable must not hang on ubiquitous variables
|
|
1404
|
+
# ══════════════════════════════════════════════════════════════════════
|
|
1405
|
+
|
|
1406
|
+
|
|
1407
|
+
class TestTraceVariable:
|
|
1408
|
+
"""Regression test for trace_variable combinatorial explosion.
|
|
1409
|
+
|
|
1410
|
+
trace_variable previously called nx.all_simple_paths for every
|
|
1411
|
+
(writer, reader) pair with no cap on path count. For common
|
|
1412
|
+
variables with many readers/writers this caused an infinite loop.
|
|
1413
|
+
"""
|
|
1414
|
+
|
|
1415
|
+
@pytest.fixture(autouse=True)
|
|
1416
|
+
def setup(self):
|
|
1417
|
+
self.graph, self.engine, _, _ = _build(FIXTURES)
|
|
1418
|
+
|
|
1419
|
+
def test_trace_common_variable_terminates(self):
|
|
1420
|
+
"""Tracing a variable that appears in many scopes must complete quickly."""
|
|
1421
|
+
import signal
|
|
1422
|
+
|
|
1423
|
+
class _Timeout(Exception):
|
|
1424
|
+
pass
|
|
1425
|
+
|
|
1426
|
+
def _handler(signum, frame):
|
|
1427
|
+
raise _Timeout("trace_variable did not terminate within timeout")
|
|
1428
|
+
|
|
1429
|
+
# Pick a variable with many readers/writers across fixtures
|
|
1430
|
+
# 'result' appears in 13+ read/write edges — enough to trigger
|
|
1431
|
+
# the old combinatorial explosion in all_simple_paths
|
|
1432
|
+
old = signal.signal(signal.SIGALRM, _handler)
|
|
1433
|
+
signal.alarm(30) # 30 second hard limit
|
|
1434
|
+
try:
|
|
1435
|
+
nodes, edges, node_roles, edge_roles = self.graph.trace_variable("result")
|
|
1436
|
+
except _Timeout:
|
|
1437
|
+
pytest.fail("trace_variable('result') hung — combinatorial explosion regression")
|
|
1438
|
+
finally:
|
|
1439
|
+
signal.alarm(0)
|
|
1440
|
+
signal.signal(signal.SIGALRM, old)
|
|
1441
|
+
|
|
1442
|
+
assert len(nodes) > 0, "trace_variable('result') should find nodes"
|
|
1443
|
+
|
|
1444
|
+
def test_trace_returns_valid_roles(self):
|
|
1445
|
+
"""trace_variable must return well-formed role dicts."""
|
|
1446
|
+
nodes, edges, node_roles, edge_roles = self.graph.trace_variable("result")
|
|
1447
|
+
valid_node_roles = {"origin", "mutator", "passthrough", "destination"}
|
|
1448
|
+
for nid, role in node_roles.items():
|
|
1449
|
+
assert role in valid_node_roles, f"Invalid node role '{role}' for {nid}"
|
|
1450
|
+
valid_edge_roles = {"read", "write", "flow"}
|
|
1451
|
+
for key, role in edge_roles.items():
|
|
1452
|
+
assert role in valid_edge_roles, f"Invalid edge role '{role}' for {key}"
|
|
1453
|
+
|
|
1454
|
+
def test_trace_nonexistent_variable_returns_empty(self):
|
|
1455
|
+
"""Tracing a variable that doesn't exist should return empty, not crash."""
|
|
1456
|
+
nodes, edges, node_roles, edge_roles = self.graph.trace_variable("zzz_no_such_var_zzz")
|
|
1457
|
+
assert nodes == []
|
|
1458
|
+
assert edges == []
|
|
1459
|
+
assert node_roles == {}
|
|
1460
|
+
assert edge_roles == {}
|
|
1461
|
+
|
|
1462
|
+
|
|
1402
1463
|
class TestMCPFidelity:
|
|
1403
1464
|
"""Verify MCP dispatch produces the same results as direct engine calls."""
|
|
1404
1465
|
|
|
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
|
{interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/index.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/package.json
RENAMED
|
File without changes
|
{interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/src/App.tsx
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/src/main.tsx
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/src/theme.ts
RENAMED
|
File without changes
|
{interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked/visualizer/frontend/src/types.ts
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked_mapper.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked_mapper.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked_mapper.egg-info/requires.txt
RENAMED
|
File without changes
|
{interlinked_mapper-0.3.12 → interlinked_mapper-0.3.13}/interlinked_mapper.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|