py-flow-mapper 0.1.0b4.dev0__tar.gz → 0.1.0b5.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.
Files changed (16) hide show
  1. {py_flow_mapper-0.1.0b4.dev0/src/py_flow_mapper.egg-info → py_flow_mapper-0.1.0b5.dev0}/PKG-INFO +1 -1
  2. {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b5.dev0}/setup.py +1 -1
  3. {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b5.dev0}/src/py_flow_mapper/__init__.py +1 -1
  4. {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b5.dev0}/src/py_flow_mapper/analyzer.py +5 -2
  5. {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b5.dev0}/src/py_flow_mapper/mermaid_generator.py +24 -38
  6. {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b5.dev0/src/py_flow_mapper.egg-info}/PKG-INFO +1 -1
  7. {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b5.dev0}/LICENSE +0 -0
  8. {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b5.dev0}/README.md +0 -0
  9. {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b5.dev0}/setup.cfg +0 -0
  10. {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b5.dev0}/src/py_flow_mapper/cli.py +0 -0
  11. {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b5.dev0}/src/py_flow_mapper/utils.py +0 -0
  12. {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b5.dev0}/src/py_flow_mapper.egg-info/SOURCES.txt +0 -0
  13. {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b5.dev0}/src/py_flow_mapper.egg-info/dependency_links.txt +0 -0
  14. {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b5.dev0}/src/py_flow_mapper.egg-info/entry_points.txt +0 -0
  15. {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b5.dev0}/src/py_flow_mapper.egg-info/requires.txt +0 -0
  16. {py_flow_mapper-0.1.0b4.dev0 → py_flow_mapper-0.1.0b5.dev0}/src/py_flow_mapper.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: py-flow-mapper
3
- Version: 0.1.0b4.dev0
3
+ Version: 0.1.0b5.dev0
4
4
  Summary: Python project analyzer and visualization tool
5
5
  Home-page: https://github.com/ArunKoundinya/py-flow-mapper
6
6
  Author: Arun Koundinya Parasa
@@ -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.0b4.dev",
8
+ version="0.1.0b5.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.0b4.dev"
5
+ __version__ = "0.1.0b5.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
- self.return_assignments.setdefault(var_name, []).append(call_info["func_name"])
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)
@@ -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(current_module_ctx, {}) or {}).get("import_mapping", {}) or {}
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,42 +92,35 @@ 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
- # forced external always wins
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
- # NEW: module-specific import mapping
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:
@@ -174,7 +160,7 @@ class MermaidGenerator:
174
160
 
175
161
  info = function_map.get(fn_key, {})
176
162
  current_module = info.get("module", "") or ""
177
- current_module_ctx = current_module
163
+ #current_module_ctx = current_module
178
164
  for c in (info.get("calls") or []):
179
165
  target = self._find_function_full_name(c, current_module)
180
166
  if target and target in function_map:
@@ -210,15 +196,15 @@ class MermaidGenerator:
210
196
 
211
197
  for _, info in function_map.items():
212
198
  current_module = info.get("module", "") or ""
213
- current_module_ctx = current_module
199
+ #current_module_ctx = current_module
214
200
 
215
201
  # prefer call_arguments keys
216
202
  call_args = info.get("call_arguments", {}) or {}
217
203
  for callee in call_args.keys():
218
204
  if resolve_internal(callee, current_module):
219
205
  continue
220
- if keep_external(callee):
221
- external_nodes.add(external_root_name(callee) or callee)
206
+ if keep_external(callee, current_module):
207
+ external_nodes.add(external_root_name(callee, current_module) or callee)
222
208
 
223
209
  # scan raw calls for Done + missed externals
224
210
  for callee in (info.get("calls") or []):
@@ -227,8 +213,8 @@ class MermaidGenerator:
227
213
 
228
214
  if resolve_internal(callee, current_module):
229
215
  continue
230
- if keep_external(callee):
231
- external_nodes.add(external_root_name(callee) or callee)
216
+ if keep_external(callee, current_module):
217
+ external_nodes.add(external_root_name(callee, current_module) or callee)
232
218
 
233
219
  if external_nodes or uses_done:
234
220
  lines.append(" subgraph External [External]")
@@ -247,7 +233,7 @@ class MermaidGenerator:
247
233
 
248
234
  info = function_map[caller]
249
235
  current_module = info.get("module", "") or ""
250
- current_module_ctx = current_module
236
+ #current_module_ctx = current_module
251
237
  src = nid(caller)
252
238
 
253
239
  call_args = info.get("call_arguments", {}) or {}
@@ -274,8 +260,8 @@ class MermaidGenerator:
274
260
  else:
275
261
  lines.append(f" {src} --> {nid(target_internal)}")
276
262
  else:
277
- if keep_external(callee):
278
- ext = external_root_name(callee) or callee
263
+ if keep_external(callee, current_module):
264
+ ext = external_root_name(callee, current_module) or callee
279
265
  edge_key = (src, nid("ext:" + callee), label)
280
266
  if edge_key in seen:
281
267
  continue
@@ -294,7 +280,7 @@ class MermaidGenerator:
294
280
  info = function_map[fn]
295
281
  dst = nid(fn)
296
282
  current_module = info.get("module", "") or ""
297
- current_module_ctx = current_module
283
+ #current_module_ctx = current_module
298
284
 
299
285
  return_assignments = info.get("return_assignments", {}) or {}
300
286
  for var_name, producers in return_assignments.items():
@@ -303,20 +289,20 @@ class MermaidGenerator:
303
289
  if internal_p:
304
290
  lines.append(f" {nid(internal_p)} -.->|{var_name}| {dst}")
305
291
  else:
306
- if keep_external(p):
307
- ext = external_root_name(p) or p
292
+ if keep_external(p, current_module):
293
+ ext = external_root_name(p,current_module) or p
308
294
  lines.append(f" {nid('ext:' + ext)} -.->|{var_name}| {dst}")
309
295
 
310
296
  # ---------- pipeline heuristic: external tool A -> external tool B ----------
311
297
  for _, info in function_map.items():
312
298
  current_module = info.get("module", "") or ""
313
- current_module_ctx = current_module
299
+ #current_module_ctx = current_module
314
300
  calls = info.get("calls") or []
315
301
  call_args = info.get("call_arguments") or {}
316
302
 
317
303
  meaningful = []
318
304
  for c in calls:
319
- if c and keep_external(c) and not resolve_internal(c, current_module):
305
+ if c and keep_external(c,current_module) and not resolve_internal(c, current_module):
320
306
  if c not in meaningful:
321
307
  meaningful.append(c)
322
308
 
@@ -325,7 +311,7 @@ class MermaidGenerator:
325
311
 
326
312
  fileish_callee = None
327
313
  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)):
314
+ if keep_external(callee, current_module) and any(is_fileish_arg(a) for a in (args or []) if isinstance(a, str)):
329
315
  fileish_callee = callee
330
316
  break
331
317
 
@@ -338,8 +324,8 @@ class MermaidGenerator:
338
324
 
339
325
  vars_passed = call_args.get(fileish_callee, []) or []
340
326
  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
327
+ prod_ext = external_root_name(producer,current_module) or producer
328
+ file_ext = external_root_name(fileish_callee,current_module) or fileish_callee
343
329
  lines.append(f" {nid('ext:' + prod_ext)} -->|{label}| {nid('ext:' + file_ext)}")
344
330
 
345
331
  # ---------- Done edge ----------
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: py-flow-mapper
3
- Version: 0.1.0b4.dev0
3
+ Version: 0.1.0b5.dev0
4
4
  Summary: Python project analyzer and visualization tool
5
5
  Home-page: https://github.com/ArunKoundinya/py-flow-mapper
6
6
  Author: Arun Koundinya Parasa