Skip to content

Commit 74b262f

Browse files
Fix Windows call graph traversal for flows helper modules
Resolve PyCG graph keys such as utils.xx to flows\utils.xx on Windows so extract/build pick up OneCode elements defined in imported helper modules under flows/. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent dfa8e73 commit 74b262f

2 files changed

Lines changed: 70 additions & 2 deletions

File tree

onecode/cli/utils.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,31 @@ def run():
130130
json.dump(flows, f, indent=4)
131131

132132

133+
def _resolve_graph_key(name: str, graph: Dict) -> str:
134+
"""
135+
Resolve a PyCG graph key across platform naming differences.
136+
137+
On Windows, relative imports inside ``flows/`` are often keyed as ``utils.xx``
138+
while the analyzed module lives under ``flows\\utils.xx``.
139+
"""
140+
if name in graph:
141+
return name
142+
143+
candidates = []
144+
module_name = name[len('flows.'):] if name.startswith('flows.') else name
145+
146+
if not name.startswith('flows.'):
147+
candidates.append(f'flows.{module_name}')
148+
candidates.append(name)
149+
candidates.append(f'flows\\{module_name}')
150+
151+
for candidate in candidates:
152+
if candidate in graph:
153+
return candidate
154+
155+
return name
156+
157+
133158
# check_type decorator not compatible with recursive calls
134159
def extract_calls(
135160
entry_point: str,
@@ -164,7 +189,9 @@ def extract_calls(
164189

165190
# PyCG is not exactly equivalent on Windows vs Linux wrt to graph keys
166191
if os.name == 'nt' and not entry_point.startswith('flows\\'):
167-
entry_point = f'flows\\{entry_point}'
192+
entry_point = f'flows\\{entry_point.replace(".", "\\")}'
193+
194+
entry_point = _resolve_graph_key(entry_point, graph)
168195

169196
if entry_point in graph:
170197
for fn in graph[entry_point]:
@@ -183,7 +210,8 @@ def extract_calls(
183210
if verbose:
184211
print(f" >> ({entry_point}) function {fn['normed']} ⏩")
185212

186-
extract_calls(fn['normed'], graph, calls)
213+
next_point = _resolve_graph_key(fn['normed'], graph)
214+
extract_calls(next_point, graph, calls)
187215

188216

189217
@check_type

tests/unit/cli/test_utils.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,46 @@
55

66
from onecode import Project, register_ext_module
77
from onecode.cli import process_call_graph
8+
from onecode.cli.utils import _resolve_graph_key, extract_calls
9+
10+
11+
def test_resolve_graph_key_windows_style():
12+
graph = {
13+
'flows\\step2.run': [],
14+
'flows\\utils.xx': [
15+
{
16+
'normed': 'onecode.slider',
17+
'code': "onecode.slider('My slider\"1', 0.5, max=6)",
18+
}
19+
],
20+
}
21+
22+
assert _resolve_graph_key('utils.xx', graph) == 'flows\\utils.xx'
23+
assert _resolve_graph_key('flows\\step2.run', graph) == 'flows\\step2.run'
24+
25+
26+
def test_extract_calls_resolves_windows_helper_modules():
27+
graph = {
28+
'flows\\step2.run': [
29+
{
30+
'normed': 'utils.xx',
31+
'code': 'xx()',
32+
}
33+
],
34+
'flows\\utils.xx': [
35+
{
36+
'normed': 'onecode.slider',
37+
'code': "onecode.slider('My slider\"1', 0.5, max=6)",
38+
}
39+
],
40+
}
41+
42+
Project().reset()
43+
calls = []
44+
extract_calls('flows\\step2.run', graph, calls)
45+
46+
assert len(calls) == 1
47+
assert calls[0]['func'] == 'onecode.slider'
848

949

1050
def test_invalid_call_graph():

0 commit comments

Comments
 (0)