pviz-parser 0.1.0__py3-none-any.whl

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 (169) hide show
  1. adapters/__init__.py +0 -0
  2. adapters/analyzer_bridge/__init__.py +26 -0
  3. adapters/analyzer_bridge/bridge_payloads.py +259 -0
  4. adapters/analyzer_bridge/core.py +668 -0
  5. adapters/analyzer_bridge/internals.py +260 -0
  6. adapters/analyzer_bridge/provenance.py +135 -0
  7. adapters/canonical.py +340 -0
  8. adapters/payloads.py +253 -0
  9. analyzer/__init__.py +172 -0
  10. analyzer/analyzer_types.py +216 -0
  11. analyzer/ast_common.py +1098 -0
  12. analyzer/build_classic.py +373 -0
  13. analyzer/config.py +288 -0
  14. analyzer/dead_code.py +635 -0
  15. analyzer/discovery_manifest.py +936 -0
  16. analyzer/duplicate_code.py +400 -0
  17. analyzer/extract_crosstalk.py +414 -0
  18. analyzer/followup_python.py +0 -0
  19. analyzer/fs.py +259 -0
  20. analyzer/go/__init__.py +26 -0
  21. analyzer/go/go_build_artifacts.py +614 -0
  22. analyzer/go/go_canonical.py +315 -0
  23. analyzer/go/go_config.py +155 -0
  24. analyzer/go/go_folder_index.py +976 -0
  25. analyzer/go/go_nodefacts_symbols.py +172 -0
  26. analyzer/go/go_parse.py +319 -0
  27. analyzer/go/go_parse_dispatch.py +284 -0
  28. analyzer/go/go_run.py +535 -0
  29. analyzer/imports_lex.py +167 -0
  30. analyzer/index.py +428 -0
  31. analyzer/java/__init__.py +0 -0
  32. analyzer/java/java_build_artifacts.py +1164 -0
  33. analyzer/java/java_canonical.py +329 -0
  34. analyzer/java/java_config.py +75 -0
  35. analyzer/java/java_folder_index.py +1142 -0
  36. analyzer/java/java_nodefacts_symbols.py +445 -0
  37. analyzer/java/java_parse/__init__.py +19 -0
  38. analyzer/java/java_parse/engine.py +48 -0
  39. analyzer/java/java_parse/javaparser_engine.py +336 -0
  40. analyzer/java/java_parse/models.py +58 -0
  41. analyzer/java/java_parse/regex_engine.py +372 -0
  42. analyzer/java/java_parse_dispatch.py +238 -0
  43. analyzer/java/java_run.py +488 -0
  44. analyzer/kotlin/__init__.py +1 -0
  45. analyzer/kotlin/kotlin_build_artifacts.py +508 -0
  46. analyzer/kotlin/kotlin_canonical.py +147 -0
  47. analyzer/kotlin/kotlin_config.py +37 -0
  48. analyzer/kotlin/kotlin_folder_index.py +1144 -0
  49. analyzer/kotlin/kotlin_nodefacts_symbols.py +123 -0
  50. analyzer/kotlin/kotlin_parse_dispatch.py +20 -0
  51. analyzer/kotlin/kotlin_run.py +299 -0
  52. analyzer/kotlin/parse_kotlin/__init__.py +15 -0
  53. analyzer/kotlin/parse_kotlin/engine.py +104 -0
  54. analyzer/kotlin/parse_kotlin/models.py +143 -0
  55. analyzer/l2_method_usage.py +196 -0
  56. analyzer/module_map.py +170 -0
  57. analyzer/module_resolve.py +420 -0
  58. analyzer/parse.py +306 -0
  59. analyzer/py/__init__.py +0 -0
  60. analyzer/py/py_run.py +120 -0
  61. analyzer/rust/__init__.py +0 -0
  62. analyzer/rust/rust_build_artifacts.py +1347 -0
  63. analyzer/rust/rust_canonical.py +392 -0
  64. analyzer/rust/rust_config.py +133 -0
  65. analyzer/rust/rust_folder_index.py +1234 -0
  66. analyzer/rust/rust_nodefacts_symbols.py +483 -0
  67. analyzer/rust/rust_parse/__init__.py +44 -0
  68. analyzer/rust/rust_parse/engine.py +282 -0
  69. analyzer/rust/rust_parse/models.py +438 -0
  70. analyzer/rust/rust_parse_dispatch.py +218 -0
  71. analyzer/rust/rust_run.py +489 -0
  72. analyzer/ts/__init__.py +7 -0
  73. analyzer/ts/build_artifacts.py +690 -0
  74. analyzer/ts/canonical_web.py +422 -0
  75. analyzer/ts/config.py +53 -0
  76. analyzer/ts/discover.py +54 -0
  77. analyzer/ts/extract_crosstalk.py +344 -0
  78. analyzer/ts/extract_imports.py +188 -0
  79. analyzer/ts/model.py +24 -0
  80. analyzer/ts/parser_runtime.py +91 -0
  81. analyzer/ts/resolve_imports.py +266 -0
  82. analyzer/ts/run.py +979 -0
  83. analyzer/ts/symbols_js.py +319 -0
  84. analyzer/ts/tsconfig_paths.py +548 -0
  85. analyzer/ts/write_artifacts.py +12 -0
  86. analyzer_store/__init__.py +1 -0
  87. analyzer_store/coverage.py +73 -0
  88. analyzer_store/edge_pass.py +536 -0
  89. analyzer_store/folder_index.py +931 -0
  90. analyzer_store/followup_assess.py +50 -0
  91. analyzer_store/integration.py +727 -0
  92. analyzer_store/io_utils.py +128 -0
  93. analyzer_store/nodefacts.py +1256 -0
  94. analyzer_store/types.py +138 -0
  95. analyzer_store/validators.py +72 -0
  96. contracts/__init__.py +0 -0
  97. contracts/types.py +184 -0
  98. core/artifact_sets_merge/__init__.py +5 -0
  99. core/artifact_sets_merge/api.py +176 -0
  100. core/artifact_sets_merge/config.py +86 -0
  101. core/artifact_sets_merge/crosstalk.py +225 -0
  102. core/artifact_sets_merge/discovery.py +44 -0
  103. core/artifact_sets_merge/edges.py +53 -0
  104. core/artifact_sets_merge/folder_index.py +125 -0
  105. core/artifact_sets_merge/io.py +52 -0
  106. core/artifact_sets_merge/meta.py +112 -0
  107. core/artifact_sets_merge/metrics.py +115 -0
  108. core/artifact_sets_merge/nodes.py +205 -0
  109. core/artifact_sets_merge/normalize.py +33 -0
  110. core/artifact_sets_merge/publish.py +156 -0
  111. core/artifact_sets_merge/scc.py +245 -0
  112. core/artifacts.py +204 -0
  113. core/artifacts_headless.py +50 -0
  114. core/build_context.py +91 -0
  115. core/build_pipeline/JS_P_Crosstalk.py +845 -0
  116. core/build_pipeline/P_JS_Crosstalk.py +1023 -0
  117. core/build_pipeline/__init__.py +32 -0
  118. core/build_pipeline/buckets.py +955 -0
  119. core/build_pipeline/followups.py +108 -0
  120. core/build_pipeline/json_io.py +18 -0
  121. core/build_pipeline/normalize.py +82 -0
  122. core/build_pipeline/pipeline.py +556 -0
  123. core/build_pipeline/types.py +87 -0
  124. core/json_export.py +541 -0
  125. core/pkgzones/builder.py +437 -0
  126. core/pkgzones/contracts.py +91 -0
  127. core/pkgzones/placement.py +114 -0
  128. core/pkgzones/state.py +32 -0
  129. core/store_root.py +79 -0
  130. core/workspace_core.py +150 -0
  131. core/zones_ctx.py +313 -0
  132. core/zones_headless.py +71 -0
  133. diagnostics/__init__.py +0 -0
  134. diagnostics/events.py +52 -0
  135. diagnostics/logging.py +360 -0
  136. i_o/__init__.py +55 -0
  137. i_o/diagnostics_export.py +51 -0
  138. i_o/export_json.py +361 -0
  139. i_o/export_llm_json/__init__.py +4 -0
  140. i_o/export_llm_json/artifacts.py +65 -0
  141. i_o/export_llm_json/builders_discovery.py +119 -0
  142. i_o/export_llm_json/builders_folders.py +356 -0
  143. i_o/export_llm_json/builders_node_order.py +15 -0
  144. i_o/export_llm_json/builders_nodes_edges.py +251 -0
  145. i_o/export_llm_json/builders_zones.py +41 -0
  146. i_o/export_llm_json/errors.py +5 -0
  147. i_o/export_llm_json/export.py +573 -0
  148. i_o/export_llm_json/json_compression/__init__.py +16 -0
  149. i_o/export_llm_json/json_compression/edge_codecs.py +157 -0
  150. i_o/export_llm_json/json_compression/format_guide.py +215 -0
  151. i_o/export_llm_json/json_compression/node_codecs.py +328 -0
  152. i_o/export_llm_json/json_compression/nodes.py +165 -0
  153. i_o/export_llm_json/json_compression/path_legend.py +230 -0
  154. i_o/export_llm_json/json_compression/run.py +136 -0
  155. i_o/export_llm_json/json_compression/types.py +130 -0
  156. i_o/export_llm_json/json_compression/util.py +60 -0
  157. i_o/export_llm_json/summary.py +649 -0
  158. i_o/export_llm_json/utils.py +62 -0
  159. i_o/export_pdf.py +97 -0
  160. i_o/layout_store.py +455 -0
  161. i_o/path_utils.py +23 -0
  162. i_o/workspace_io.py +295 -0
  163. i_o/workspace_manager.py +171 -0
  164. pviz_parser-0.1.0.dist-info/METADATA +123 -0
  165. pviz_parser-0.1.0.dist-info/RECORD +169 -0
  166. pviz_parser-0.1.0.dist-info/WHEEL +5 -0
  167. pviz_parser-0.1.0.dist-info/entry_points.txt +2 -0
  168. pviz_parser-0.1.0.dist-info/licenses/LICENSE +21 -0
  169. pviz_parser-0.1.0.dist-info/top_level.txt +7 -0
adapters/__init__.py ADDED
File without changes
@@ -0,0 +1,26 @@
1
+ # adapters/analyzer_bridge/__init__.py
2
+ from __future__ import annotations
3
+
4
+ from typing import Any, Dict, Optional
5
+ from pathlib import Path
6
+
7
+ from .core import normalize_graph_for_contracts as normalize_graph_for_contracts
8
+ __all__ = [
9
+ "normalize_graph_for_contracts",
10
+ ]
11
+
12
+ def enrich_graph(graph: Any, *, repo_root: Optional[Path | str] = None) -> Dict[str, Any]:
13
+ g = graph if isinstance(graph, dict) else {"nodes": {}, "edges": []}
14
+ nodes = g.get("nodes") or {}
15
+ for _id, payload in nodes.items():
16
+ if not isinstance(payload, dict):
17
+ continue
18
+ defs_rows = payload.get("defs_rows") or []
19
+ extra = payload.setdefault("extra", {})
20
+ if "defs_rows" not in extra:
21
+ extra["defs_rows"] = list(defs_rows)
22
+ return g
23
+
24
+
25
+ # Backward-compatible alias
26
+ enrich_for_ui = enrich_graph
@@ -0,0 +1,259 @@
1
+ from __future__ import annotations
2
+ from typing import Any, Dict, List, Optional, Sequence
3
+ import os
4
+ from pathlib import Path
5
+
6
+ from .internals import build_import_row_annotations
7
+ from adapters.canonical import (
8
+ repo_rel,
9
+ to_posix,
10
+ canon_file_id,
11
+ canon_module_id,
12
+ )
13
+ from adapters.analyzer_bridge.internals import (
14
+ as_list,
15
+ attr_or_key,
16
+ )
17
+
18
+
19
+ def _dedupe_preserve_order(seq: Sequence[str]) -> List[str]:
20
+ seen: set[str] = set()
21
+ out: List[str] = []
22
+ for s in seq:
23
+ if s not in seen:
24
+ seen.add(s)
25
+ out.append(s)
26
+ return out
27
+
28
+
29
+ def _to_name(v) -> Optional[str]:
30
+ if v is None:
31
+ return None
32
+ if isinstance(v, str):
33
+ s = v.strip()
34
+ if s.startswith(("def ", "class ")):
35
+ s = s.split(" ", 1)[1].strip() or s
36
+ return s or None
37
+ if isinstance(v, dict):
38
+ name = v.get("name") or v.get("label") or v.get("id")
39
+ return str(name) if name else None
40
+ for attr in ("name", "label", "id"):
41
+ try:
42
+ name = getattr(v, attr, None)
43
+ if isinstance(name, str) and name:
44
+ return name
45
+ except Exception:
46
+ pass
47
+ try:
48
+ s = str(v)
49
+ if s and s != "(none)":
50
+ return s
51
+ except Exception:
52
+ pass
53
+ return None
54
+
55
+
56
+ def _clean_and_normalize_import_rows(rows_like) -> List[str]:
57
+ out: List[str] = []
58
+ for r in as_list(rows_like):
59
+ s = r if isinstance(r, str) else _to_name(r) or ""
60
+ s = (s or "").strip()
61
+ if not s:
62
+ continue
63
+ # strip trailing comments
64
+ i = s.find("#")
65
+ if i == 0:
66
+ continue
67
+ if i > 0:
68
+ s = s[:i].rstrip()
69
+ if not s:
70
+ continue
71
+ if s.startswith("from ") or s.startswith("import "):
72
+ out.append(s)
73
+ else:
74
+ out.append(f"import {s}")
75
+ return _dedupe_preserve_order(out)
76
+
77
+
78
+ def node_payload_from(node_id: str, n: Any, *, repo_root: Optional[Path | str]) -> Dict[str, Any]:
79
+ """
80
+ Authoritative payload builder used by analyzer.
81
+
82
+ Assumptions under the current contracts:
83
+ - `node_id` is a stable node identifier; for analyzer-backed graphs this
84
+ is a **module id** relative to the scan root (e.g. 'downloader',
85
+ 'scrapy.core.engine', 'ui.app.run_gui').
86
+ - The node record `n` may carry:
87
+ • path/file: repo-relative or absolute path
88
+ • module: dotted module id
89
+ """
90
+ root = to_posix(str(repo_root)) if repo_root else None
91
+
92
+ # ---------- Canonical file-id (repo-rel POSIX) ----------
93
+ # Prefer an explicit path/file on the node; fall back to id/module when needed.
94
+ raw_path_like = (
95
+ attr_or_key(n, "path")
96
+ or attr_or_key(n, "file")
97
+ or (str(node_id) if isinstance(node_id, str) else "")
98
+ )
99
+
100
+ canon_path = ""
101
+ try:
102
+ # canon_file_id knows how to handle both path-ish and dotted inputs;
103
+ # we pass scan_root so it will keep things repo-relative when possible.
104
+ canon_path = canon_file_id(raw_path_like, root, strict_suffix=False) or ""
105
+ except Exception:
106
+ canon_path = ""
107
+
108
+ if not canon_path:
109
+ # Retry from explicit module field if present
110
+ raw_mod = attr_or_key(n, "module") or ""
111
+ try:
112
+ if raw_mod:
113
+ canon_path = canon_file_id(raw_mod, root, strict_suffix=False) or ""
114
+ except Exception:
115
+ pass
116
+
117
+ canon_path = to_posix(canon_path) if canon_path else ""
118
+
119
+ # ---------- Canonical module (dotted) ----------
120
+ # Prefer node_id itself when it behaves like a module id (no slashes, no .py).
121
+ module = ""
122
+ if isinstance(node_id, str):
123
+ nid = node_id.strip()
124
+ if nid and "/" not in nid and "\\" not in nid and not nid.endswith(".py"):
125
+ module = nid
126
+
127
+ if not module and canon_path:
128
+ try:
129
+ module = canon_module_id(canon_path, root) or ""
130
+ except Exception:
131
+ module = ""
132
+
133
+ if not module:
134
+ raw_mod = attr_or_key(n, "module") or ""
135
+ try:
136
+ if raw_mod:
137
+ module = canon_module_id(raw_mod, root) or ""
138
+ except Exception:
139
+ # last resort: try making a module from the raw path-ish
140
+ try:
141
+ module = canon_module_id(raw_path_like, root) if raw_path_like else ""
142
+ except Exception:
143
+ module = ""
144
+
145
+ # ---------- Header path for UI (repo-rel POSIX) ----------
146
+ header_path = canon_path or repo_rel(
147
+ attr_or_key(n, "path") or attr_or_key(n, "file"),
148
+ repo_root,
149
+ )
150
+ if isinstance(header_path, str):
151
+ header_path = to_posix(header_path)
152
+
153
+ # ---------- Label: prefer module leaf; fall back to basename ----------
154
+ if module:
155
+ label = module.split(".")[-1]
156
+ else:
157
+ leaf = to_posix(str(header_path or node_id))
158
+ label = os.path.basename(leaf.rstrip("/")) if leaf else str(node_id)
159
+
160
+ # ---------- Imports ----------
161
+ pre_rows = attr_or_key(n, "imports_rows") or (
162
+ (attr_or_key(n, "extra") or {}).get("imports_rows")
163
+ if isinstance(n, dict)
164
+ else None
165
+ )
166
+ raw_imports = attr_or_key(n, "imports")
167
+ imp_rows = (
168
+ _clean_and_normalize_import_rows(pre_rows)
169
+ if pre_rows
170
+ else _clean_and_normalize_import_rows(raw_imports)
171
+ )
172
+
173
+ # Fallback: mine file only if still empty
174
+ if not imp_rows:
175
+ try:
176
+ abs_hint = attr_or_key(n, "file") or attr_or_key(n, "path") or ""
177
+ p: Optional[str] = None
178
+ if isinstance(abs_hint, str) and os.path.isabs(abs_hint):
179
+ p = abs_hint
180
+ elif isinstance(canon_path, str) and canon_path:
181
+ p = str(Path(root) / canon_path) if root else None
182
+ if p and p.endswith(".py") and os.path.exists(p):
183
+ with open(p, "r", encoding="utf-8", errors="ignore") as f:
184
+ text = f.read(64_000)
185
+ lines = (ln.strip() for ln in text.splitlines())
186
+ imp_rows = [
187
+ s
188
+ for s in lines
189
+ if s
190
+ and not s.startswith("#")
191
+ and (s.startswith("import ") or (s.startswith("from ") and " import " in s))
192
+ ]
193
+ imp_rows = _dedupe_preserve_order(imp_rows)
194
+ except Exception:
195
+ pass
196
+
197
+ # ---------- Defs / exports ----------
198
+ pre_defs = attr_or_key(n, "defs_rows") or (
199
+ (attr_or_key(n, "extra") or {}).get("defs_rows")
200
+ if isinstance(n, dict)
201
+ else None
202
+ )
203
+ classes = _dedupe_preserve_order(as_list(attr_or_key(n, "classes")))
204
+ functions = _dedupe_preserve_order(as_list(attr_or_key(n, "functions")))
205
+ globals_ = _dedupe_preserve_order(as_list(attr_or_key(n, "globals")))
206
+ raw_exports = attr_or_key(n, "exports")
207
+
208
+ if pre_defs:
209
+ def_rows = [
210
+ s
211
+ for s in _dedupe_preserve_order(as_list(pre_defs))
212
+ if s and s != "(none)"
213
+ ]
214
+ else:
215
+ seen: set[str] = set()
216
+ acc: List[str] = []
217
+ for s in [*classes, *functions, *globals_]:
218
+ if s not in seen:
219
+ seen.add(s)
220
+ acc.append(s)
221
+ def_rows = acc or ["(none)"]
222
+
223
+ parsed_for_tags = attr_or_key(n, "parsed")
224
+ import_rows_annotated, import_tag_counts = build_import_row_annotations(
225
+ imp_rows,
226
+ parsed_for_tags,
227
+ )
228
+
229
+ extra: Dict[str, Any] = {
230
+ "imports": imp_rows,
231
+ "imports_rows": imp_rows,
232
+ "imports_display": [a.get("row") for a in import_rows_annotated]
233
+ if import_rows_annotated
234
+ else imp_rows,
235
+ "defs_rows": def_rows,
236
+ "import_rows_annotated": import_rows_annotated,
237
+ "import_tag_counts": import_tag_counts,
238
+ }
239
+
240
+ # ---------- Final payload ----------
241
+ payload: Dict[str, Any] = {
242
+ "node_id": node_id,
243
+ "label": label,
244
+ "kind": "file",
245
+ "path": header_path or "",
246
+ "module": module or None,
247
+ "package": None,
248
+ "file": header_path or "",
249
+ "extra": extra,
250
+ "imports": imp_rows,
251
+ "imports_rows": imp_rows,
252
+ "imports_display": extra["imports_display"],
253
+ "defs_rows": def_rows,
254
+ "classes": classes,
255
+ "functions": functions,
256
+ "globals": globals_,
257
+ "exports": [e for e in as_list(raw_exports) if isinstance(e, str)],
258
+ }
259
+ return {k: v for k, v in payload.items() if v is not None}