py-flow-mapper 0.1.0b4.dev0__tar.gz → 0.1.0b6.dev0__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.
- {py_flow_mapper-0.1.0b4.dev0/src/py_flow_mapper.egg-info → py_flow_mapper-0.1.0b6.dev0}/PKG-INFO +1 -1
- {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b6.dev0}/setup.py +1 -1
- {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b6.dev0}/src/py_flow_mapper/__init__.py +1 -1
- {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b6.dev0}/src/py_flow_mapper/analyzer.py +5 -2
- {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b6.dev0}/src/py_flow_mapper/mermaid_generator.py +56 -41
- {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b6.dev0}/src/py_flow_mapper/utils.py +1 -1
- {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b6.dev0/src/py_flow_mapper.egg-info}/PKG-INFO +1 -1
- {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b6.dev0}/LICENSE +0 -0
- {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b6.dev0}/README.md +0 -0
- {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b6.dev0}/setup.cfg +0 -0
- {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b6.dev0}/src/py_flow_mapper/cli.py +0 -0
- {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b6.dev0}/src/py_flow_mapper.egg-info/SOURCES.txt +0 -0
- {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b6.dev0}/src/py_flow_mapper.egg-info/dependency_links.txt +0 -0
- {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b6.dev0}/src/py_flow_mapper.egg-info/entry_points.txt +0 -0
- {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b6.dev0}/src/py_flow_mapper.egg-info/requires.txt +0 -0
- {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b6.dev0}/src/py_flow_mapper.egg-info/top_level.txt +0 -0
|
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
|
|
|
5
5
|
|
|
6
6
|
setup(
|
|
7
7
|
name="py-flow-mapper",
|
|
8
|
-
version="0.1.
|
|
8
|
+
version="0.1.0b6.dev",
|
|
9
9
|
author="Arun Koundinya Parasa",
|
|
10
10
|
author_email="parasa.arunkoundinya@gmail.com",
|
|
11
11
|
description="Python project analyzer and visualization tool",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
PyFlowMapper - A Python project analyzer and visualization tool.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
__version__ = "0.1.
|
|
5
|
+
__version__ = "0.1.0b6.dev"
|
|
6
6
|
__author__ = "Arun Koundinya Parasa"
|
|
7
7
|
__description__ = "Analyze Python projects and generate dependency graphs"
|
|
8
8
|
__github__ = "https://github.com/ArunKoundinya/py-flow-mapper"
|
|
@@ -527,13 +527,16 @@ class DataFlowAnalyzer(ast.NodeVisitor):
|
|
|
527
527
|
if isinstance(node.value, ast.Call):
|
|
528
528
|
call_info = self._extract_call_info(node.value)
|
|
529
529
|
if call_info:
|
|
530
|
-
|
|
530
|
+
func_name = call_info["func_name"]
|
|
531
|
+
|
|
532
|
+
if func_name not in self.calls:
|
|
533
|
+
self.calls.append(func_name)
|
|
534
|
+
self.return_assignments.setdefault(var_name, []).append(func_name)
|
|
531
535
|
|
|
532
536
|
elif isinstance(node.value, ast.Name):
|
|
533
537
|
pass
|
|
534
538
|
|
|
535
539
|
self.generic_visit(node)
|
|
536
|
-
|
|
537
540
|
|
|
538
541
|
def visit_Call(self, node):
|
|
539
542
|
call_info = self._extract_call_info(node)
|
{py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b6.dev0}/src/py_flow_mapper/mermaid_generator.py
RENAMED
|
@@ -71,23 +71,16 @@ class MermaidGenerator:
|
|
|
71
71
|
return ""
|
|
72
72
|
return ",".join(sorted(set(cleaned)))
|
|
73
73
|
|
|
74
|
-
current_module_ctx = ""
|
|
75
74
|
|
|
76
|
-
def module_import_mapping() -> dict:
|
|
77
|
-
return (modules.get(
|
|
75
|
+
def module_import_mapping(mod: str) -> dict:
|
|
76
|
+
return (modules.get(mod, {}) or {}).get("import_mapping", {}) or {}
|
|
78
77
|
|
|
79
|
-
def external_root_name(call_name: str) -> str:
|
|
78
|
+
def external_root_name(call_name: str, current_module: str) -> str:
|
|
80
79
|
if not call_name:
|
|
81
80
|
return ""
|
|
82
|
-
|
|
83
81
|
root = call_name.split(".")[0]
|
|
84
|
-
|
|
85
|
-
# module-specific import mapping (from analyzer)
|
|
86
|
-
imp_map = module_import_mapping() or {}
|
|
87
|
-
|
|
88
|
-
# merge common aliases (module imports override defaults)
|
|
82
|
+
imp_map = module_import_mapping(current_module)
|
|
89
83
|
merged_map = {**COMMON_ALIAS_MAP, **imp_map}
|
|
90
|
-
|
|
91
84
|
return merged_map.get(root, root)
|
|
92
85
|
|
|
93
86
|
# Keep the graph clean: ignore common builtins + attribute-noise
|
|
@@ -99,52 +92,74 @@ class MermaidGenerator:
|
|
|
99
92
|
"Path",
|
|
100
93
|
}
|
|
101
94
|
|
|
102
|
-
def keep_external(call_name: str) -> bool:
|
|
95
|
+
def keep_external(call_name: str, current_module: str) -> bool:
|
|
103
96
|
if not call_name:
|
|
104
97
|
return False
|
|
105
98
|
|
|
106
99
|
base = short_label(call_name)
|
|
107
100
|
|
|
108
|
-
|
|
109
|
-
root = external_root_name(call_name)
|
|
101
|
+
root = external_root_name(call_name, current_module)
|
|
110
102
|
if root and root in self.force_external:
|
|
111
103
|
return True
|
|
112
104
|
if base in self.force_external:
|
|
113
105
|
return True
|
|
114
106
|
|
|
115
|
-
|
|
116
|
-
imp_map = module_import_mapping() or {}
|
|
107
|
+
imp_map = module_import_mapping(current_module)
|
|
117
108
|
if base in imp_map:
|
|
118
109
|
mapped = imp_map[base]
|
|
119
110
|
mapped_module = ".".join(mapped.split(".")[:-1])
|
|
120
|
-
|
|
121
111
|
if mapped_module in modules:
|
|
122
112
|
return False
|
|
123
|
-
|
|
124
113
|
return True
|
|
125
114
|
|
|
126
|
-
# internal class => NOT external
|
|
127
115
|
if base in internal_classes:
|
|
128
116
|
return False
|
|
129
117
|
|
|
130
118
|
if base in NOISY_EXTERNAL:
|
|
131
119
|
return False
|
|
132
120
|
|
|
133
|
-
# dotted calls like obj.method: too noisy at this level
|
|
134
121
|
if "." in call_name:
|
|
135
122
|
return False
|
|
136
123
|
|
|
137
|
-
# keep CamelCase (tool-ish classes / constructors)
|
|
138
124
|
return is_camel_case(base)
|
|
139
125
|
|
|
140
126
|
def resolve_internal(call: str, current_module: str) -> str:
|
|
141
|
-
|
|
127
|
+
call = call or ""
|
|
128
|
+
|
|
129
|
+
# 1) existing resolver
|
|
142
130
|
target = self._find_function_full_name(call, current_module)
|
|
143
131
|
if target and target in internal_funcs:
|
|
144
132
|
return target
|
|
145
133
|
|
|
146
|
-
|
|
147
|
-
|
|
134
|
+
imp_map = module_import_mapping(current_module)
|
|
135
|
+
|
|
136
|
+
# 2) If call is a bare name imported via "from X import name"
|
|
137
|
+
# import_mapping might contain: name -> "pkg.mod.name"
|
|
138
|
+
if call in imp_map:
|
|
139
|
+
mapped = imp_map[call]
|
|
140
|
+
if mapped in internal_funcs:
|
|
141
|
+
return mapped
|
|
142
|
+
# if mapped is "pkg.mod.name", try resolving it (or its tail)
|
|
143
|
+
target = self._find_function_full_name(mapped, current_module)
|
|
144
|
+
if target and target in internal_funcs:
|
|
145
|
+
return target
|
|
146
|
+
|
|
147
|
+
# 3) If call is "alias.something", rewrite alias using import_mapping
|
|
148
|
+
# import_mapping might contain: alias -> "pkg.mod"
|
|
149
|
+
if "." in call:
|
|
150
|
+
root, rest = call.split(".", 1)
|
|
151
|
+
if root in imp_map:
|
|
152
|
+
mapped_root = imp_map[root]
|
|
153
|
+
# If mapping is to a specific object like "pkg.mod.func",
|
|
154
|
+
# treat it as root too (best-effort)
|
|
155
|
+
candidate = f"{mapped_root}.{rest}"
|
|
156
|
+
if candidate in internal_funcs:
|
|
157
|
+
return candidate
|
|
158
|
+
target = self._find_function_full_name(candidate, current_module)
|
|
159
|
+
if target and target in internal_funcs:
|
|
160
|
+
return target
|
|
161
|
+
|
|
162
|
+
# 4) your existing "obj.method" heuristic
|
|
148
163
|
method = call.split(".")[-1]
|
|
149
164
|
matches = [k for k in internal_funcs if k.endswith("." + method)]
|
|
150
165
|
if len(matches) == 1:
|
|
@@ -174,7 +189,7 @@ class MermaidGenerator:
|
|
|
174
189
|
|
|
175
190
|
info = function_map.get(fn_key, {})
|
|
176
191
|
current_module = info.get("module", "") or ""
|
|
177
|
-
current_module_ctx = current_module
|
|
192
|
+
#current_module_ctx = current_module
|
|
178
193
|
for c in (info.get("calls") or []):
|
|
179
194
|
target = self._find_function_full_name(c, current_module)
|
|
180
195
|
if target and target in function_map:
|
|
@@ -210,15 +225,15 @@ class MermaidGenerator:
|
|
|
210
225
|
|
|
211
226
|
for _, info in function_map.items():
|
|
212
227
|
current_module = info.get("module", "") or ""
|
|
213
|
-
current_module_ctx = current_module
|
|
228
|
+
#current_module_ctx = current_module
|
|
214
229
|
|
|
215
230
|
# prefer call_arguments keys
|
|
216
231
|
call_args = info.get("call_arguments", {}) or {}
|
|
217
232
|
for callee in call_args.keys():
|
|
218
233
|
if resolve_internal(callee, current_module):
|
|
219
234
|
continue
|
|
220
|
-
if keep_external(callee):
|
|
221
|
-
external_nodes.add(external_root_name(callee) or callee)
|
|
235
|
+
if keep_external(callee, current_module):
|
|
236
|
+
external_nodes.add(external_root_name(callee, current_module) or callee)
|
|
222
237
|
|
|
223
238
|
# scan raw calls for Done + missed externals
|
|
224
239
|
for callee in (info.get("calls") or []):
|
|
@@ -227,8 +242,8 @@ class MermaidGenerator:
|
|
|
227
242
|
|
|
228
243
|
if resolve_internal(callee, current_module):
|
|
229
244
|
continue
|
|
230
|
-
if keep_external(callee):
|
|
231
|
-
external_nodes.add(external_root_name(callee) or callee)
|
|
245
|
+
if keep_external(callee, current_module):
|
|
246
|
+
external_nodes.add(external_root_name(callee, current_module) or callee)
|
|
232
247
|
|
|
233
248
|
if external_nodes or uses_done:
|
|
234
249
|
lines.append(" subgraph External [External]")
|
|
@@ -247,7 +262,7 @@ class MermaidGenerator:
|
|
|
247
262
|
|
|
248
263
|
info = function_map[caller]
|
|
249
264
|
current_module = info.get("module", "") or ""
|
|
250
|
-
current_module_ctx = current_module
|
|
265
|
+
#current_module_ctx = current_module
|
|
251
266
|
src = nid(caller)
|
|
252
267
|
|
|
253
268
|
call_args = info.get("call_arguments", {}) or {}
|
|
@@ -274,8 +289,8 @@ class MermaidGenerator:
|
|
|
274
289
|
else:
|
|
275
290
|
lines.append(f" {src} --> {nid(target_internal)}")
|
|
276
291
|
else:
|
|
277
|
-
if keep_external(callee):
|
|
278
|
-
ext = external_root_name(callee) or callee
|
|
292
|
+
if keep_external(callee, current_module):
|
|
293
|
+
ext = external_root_name(callee, current_module) or callee
|
|
279
294
|
edge_key = (src, nid("ext:" + callee), label)
|
|
280
295
|
if edge_key in seen:
|
|
281
296
|
continue
|
|
@@ -294,7 +309,7 @@ class MermaidGenerator:
|
|
|
294
309
|
info = function_map[fn]
|
|
295
310
|
dst = nid(fn)
|
|
296
311
|
current_module = info.get("module", "") or ""
|
|
297
|
-
current_module_ctx = current_module
|
|
312
|
+
#current_module_ctx = current_module
|
|
298
313
|
|
|
299
314
|
return_assignments = info.get("return_assignments", {}) or {}
|
|
300
315
|
for var_name, producers in return_assignments.items():
|
|
@@ -303,20 +318,20 @@ class MermaidGenerator:
|
|
|
303
318
|
if internal_p:
|
|
304
319
|
lines.append(f" {nid(internal_p)} -.->|{var_name}| {dst}")
|
|
305
320
|
else:
|
|
306
|
-
if keep_external(p):
|
|
307
|
-
ext = external_root_name(p) or p
|
|
321
|
+
if keep_external(p, current_module):
|
|
322
|
+
ext = external_root_name(p,current_module) or p
|
|
308
323
|
lines.append(f" {nid('ext:' + ext)} -.->|{var_name}| {dst}")
|
|
309
324
|
|
|
310
325
|
# ---------- pipeline heuristic: external tool A -> external tool B ----------
|
|
311
326
|
for _, info in function_map.items():
|
|
312
327
|
current_module = info.get("module", "") or ""
|
|
313
|
-
current_module_ctx = current_module
|
|
328
|
+
#current_module_ctx = current_module
|
|
314
329
|
calls = info.get("calls") or []
|
|
315
330
|
call_args = info.get("call_arguments") or {}
|
|
316
331
|
|
|
317
332
|
meaningful = []
|
|
318
333
|
for c in calls:
|
|
319
|
-
if c and keep_external(c) and not resolve_internal(c, current_module):
|
|
334
|
+
if c and keep_external(c,current_module) and not resolve_internal(c, current_module):
|
|
320
335
|
if c not in meaningful:
|
|
321
336
|
meaningful.append(c)
|
|
322
337
|
|
|
@@ -325,7 +340,7 @@ class MermaidGenerator:
|
|
|
325
340
|
|
|
326
341
|
fileish_callee = None
|
|
327
342
|
for callee, args in call_args.items():
|
|
328
|
-
if keep_external(callee) and any(is_fileish_arg(a) for a in (args or []) if isinstance(a, str)):
|
|
343
|
+
if keep_external(callee, current_module) and any(is_fileish_arg(a) for a in (args or []) if isinstance(a, str)):
|
|
329
344
|
fileish_callee = callee
|
|
330
345
|
break
|
|
331
346
|
|
|
@@ -338,8 +353,8 @@ class MermaidGenerator:
|
|
|
338
353
|
|
|
339
354
|
vars_passed = call_args.get(fileish_callee, []) or []
|
|
340
355
|
label = normalize_vars(vars_passed) or "value"
|
|
341
|
-
prod_ext = external_root_name(producer) or producer
|
|
342
|
-
file_ext = external_root_name(fileish_callee) or fileish_callee
|
|
356
|
+
prod_ext = external_root_name(producer,current_module) or producer
|
|
357
|
+
file_ext = external_root_name(fileish_callee,current_module) or fileish_callee
|
|
343
358
|
lines.append(f" {nid('ext:' + prod_ext)} -->|{label}| {nid('ext:' + file_ext)}")
|
|
344
359
|
|
|
345
360
|
# ---------- Done edge ----------
|
|
@@ -130,7 +130,7 @@ def get_project_structure(base_path: Path, exclude_dirs: List[str] = None) -> Di
|
|
|
130
130
|
"node_modules", "site-packages",
|
|
131
131
|
"docs", "doc", "notebooks", ".ipynb_checkpoints",
|
|
132
132
|
"models", "outputs", "results",
|
|
133
|
-
"logs", "tmp", "temp",
|
|
133
|
+
"logs", "tmp", "temp","log","cache"
|
|
134
134
|
]
|
|
135
135
|
|
|
136
136
|
exclude_set = set(exclude_dirs)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b6.dev0}/src/py_flow_mapper.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b6.dev0}/src/py_flow_mapper.egg-info/requires.txt
RENAMED
|
File without changes
|
|
File without changes
|