codegraphcontext 0.6.1__py3-none-any.whl → 0.6.2__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.
@@ -798,21 +798,32 @@ class EmbeddedSessionWrapper:
798
798
  translated_query, translated_params = self._translate_query(query, parameters)
799
799
  debug_log(f"Translated Query: {translated_query[:200]}")
800
800
  try:
801
- # Force loop fallback for relationship writes inside UNWIND to avoid Kuzu query planner bugs
802
- # which can incorrectly bind/corrupt relationship endpoints across rows in the batch.
803
- # Only force it for `UNWIND $param AS row`, the single shape the
804
- # recovery path below can rewrite into a per-row loop. Read queries
805
- # that unwind a bound list (`WITH relationships(p) AS rels UNWIND
806
- # rels AS r`, used by find_all_callers/find_all_callees and the
807
- # visualizer) matched this guard too, but no `$`-UNWIND for the
808
- # fallback to latch onto — so the fabricated exception fell through
809
- # every handler and surfaced to the caller as a hard failure.
801
+ # Force the per-row loop fallback ONLY for UNWIND batches containing a
802
+ # node-MERGE. Kùzu's MERGE pipeline mis-binds when a merged node's key
803
+ # value repeats NON-adjacently across the batch: in
804
+ # [(A,P), (B,X), (C,P)] the C row binds to X's node instead of
805
+ # re-matching P (reproduced on Kùzu 0.11.3; see #1605). Relationship-only
806
+ # MERGEs (MATCH … MATCH … MERGE (a)-[r]->(b)) do not exhibit the bug —
807
+ # verified with interleaved duplicate endpoint keys and duplicate pairs —
808
+ # so they now run batched, which removes the bulk of the per-row planner
809
+ # overhead (~2.4x on a full index of the Python sample project).
810
+ # Only `UNWIND $param AS row` shapes are guarded — that is the single
811
+ # shape the recovery path below can rewrite into a per-row loop. Read
812
+ # queries that unwind a bound list (`WITH relationships(p) AS rels
813
+ # UNWIND rels AS r`) must not match, or the fabricated exception would
814
+ # surface to the caller as a hard failure.
815
+ # Node-only UNWIND writes (`MERGE (n:Label {…}) SET n += row`, no
816
+ # relationship pattern) have always batched through the SET-expansion
817
+ # path and the per-row rewriter cannot handle their bare `SET n += row`,
818
+ # so the guard additionally requires a relationship pattern.
819
+ _has_node_merge = re.search(r"MERGE\s*\(\s*\w+\s*:", query)
810
820
  if (
811
821
  re.search(r"UNWIND\s+\$\w+\s+AS\s+\w+", query)
812
822
  and ("-[" in query or "]->" in query)
823
+ and _has_node_merge
813
824
  and not getattr(self, "_skip_unwind_fallback", False)
814
825
  ):
815
- raise Exception("unordered_map::at (forced fallback to avoid relationship UNWIND planner bugs)")
826
+ raise Exception("unordered_map::at (forced fallback: node-MERGE inside UNWIND mis-binds repeated keys)")
816
827
 
817
828
  # 2. Execute under the lock. _write_lock (name kept for backward
818
829
  # compat) now serializes ALL access, reads included: kuzu.Connection
@@ -1138,8 +1138,23 @@ class GraphWriter:
1138
1138
  batch_size = 500
1139
1139
  backend = get_backend_type(self.driver, self._db_manager)
1140
1140
  def _work(session):
1141
- internal_batch = [r for r in inheritance_batch if r.get("resolved_parent_file_path") != "__external__"]
1142
- external_batch = [r for r in inheritance_batch if r.get("resolved_parent_file_path") == "__external__"]
1141
+ # Dedupe identical rows first: parsers can emit the same
1142
+ # (child, parent) record more than once, and while Neo4j's MERGE
1143
+ # absorbs the repeat, the embedded backends' rewritten
1144
+ # node-MERGE+rel-MERGE shape has been observed writing a duplicate
1145
+ # INHERITS edge for it. Deduping is correct on every backend.
1146
+ seen_rows: set = set()
1147
+ deduped_batch: List[Dict[str, Any]] = []
1148
+ for r in inheritance_batch:
1149
+ key = (r.get("child_name"), r.get("path"), r.get("parent_name"),
1150
+ r.get("resolved_parent_file_path"))
1151
+ if key in seen_rows:
1152
+ continue
1153
+ seen_rows.add(key)
1154
+ deduped_batch.append(r)
1155
+
1156
+ internal_batch = [r for r in deduped_batch if r.get("resolved_parent_file_path") != "__external__"]
1157
+ external_batch = [r for r in deduped_batch if r.get("resolved_parent_file_path") == "__external__"]
1143
1158
 
1144
1159
  labels = ("Class", "Trait", "Interface", "Struct", "Enum", "Union", "Record", "Mixin", "Extension", "Module", "Object", "Variable")
1145
1160
 
@@ -201,10 +201,32 @@ async def run_tree_sitter_index_async(
201
201
  # it to this file's path string turned a single recoverable write
202
202
  # failure into an AttributeError that aborted the whole job.
203
203
  failed_path = file_data.get("path")
204
- write_failures.append({"path": failed_path, "error": str(exc)})
205
- error_logger(f"Failed to write {failed_path} to the graph: {exc}")
206
- file_data["error"] = str(exc)
207
- file_data["parse_failed"] = True
204
+ # Retry once before giving up: writes are MERGE-idempotent, and a
205
+ # transient failure under runner load silently costs the graph the
206
+ # whole file's edges (observed as LadybugDB intermittently writing
207
+ # ~51 fewer CONTAINS edges in the parity run, #1612).
208
+ retried_ok = False
209
+ if "error" not in file_data:
210
+ try:
211
+ await asyncio.sleep(0.2)
212
+ await asyncio.to_thread(
213
+ writer.add_file_to_graph,
214
+ file_data,
215
+ repo_name,
216
+ imports_map,
217
+ repo_path_str=resolved_repo_path_str,
218
+ )
219
+ retried_ok = True
220
+ warning_logger(
221
+ f"Write for {failed_path} succeeded on retry after: {exc}"
222
+ )
223
+ except Exception as retry_exc: # noqa: BLE001
224
+ exc = retry_exc
225
+ if not retried_ok:
226
+ write_failures.append({"path": failed_path, "error": str(exc)})
227
+ error_logger(f"Failed to write {failed_path} to the graph: {exc}")
228
+ file_data["error"] = str(exc)
229
+ file_data["parse_failed"] = True
208
230
 
209
231
  if write_failures:
210
232
  warning_logger(
@@ -519,11 +519,7 @@ class CppTreeSitterParser:
519
519
  if lambda_node is None or lambda_node.type != 'lambda_expression':
520
520
  continue
521
521
 
522
- params_node = lambda_node.child_by_field_name('declarator')
523
- if params_node:
524
- params_node = params_node.child_by_field_name('parameters')
525
522
  name = self._get_node_text(node)
526
- params_node = lambda_node.child_by_field_name('parameters')
527
523
 
528
524
  context, context_type, _ = self._get_parent_context(assignment_node)
529
525
  class_context, _, _ = self._get_parent_context(assignment_node, types=('class_specifier',))
@@ -532,7 +528,15 @@ class CppTreeSitterParser:
532
528
  "name": name,
533
529
  "line_number": node.start_point[0] + 1,
534
530
  "end_line": assignment_node.end_point[0] + 1,
535
- "args": [p for p in [self._get_node_text(p) for p in params_node.children if p.type == 'identifier'] if p] if params_node else [],
531
+ # lambda_expression carries the same declarator→parameters
532
+ # field chain as a function_definition, so the shared
533
+ # extractor handles parameter_declaration unwrapping
534
+ # (pointers/refs included). The old inline version first
535
+ # clobbered its correctly-walked parameter_list with a
536
+ # nonexistent field and then filtered for bare identifiers
537
+ # over parameter_declaration nodes — every lambda got
538
+ # args: [] (#1527, case 5).
539
+ "args": self._extract_function_params(lambda_node),
536
540
 
537
541
  "docstring": None,
538
542
  "cyclomatic_complexity": 1,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codegraphcontext
3
- Version: 0.6.1
3
+ Version: 0.6.2
4
4
  Summary: An MCP server that indexes local code into a graph database to provide context to AI assistants.
5
5
  Author-email: Shashank Shekhar Singh <shashankshekharsingh1205@gmail.com>
6
6
  License: MIT License
@@ -26,7 +26,7 @@ codegraphcontext/core/bundle_registry.py,sha256=xlVBe-fmvEOLY9xDq7w0vXFlTPzeFVIw
26
26
  codegraphcontext/core/cgc_bundle.py,sha256=X2aOji754UyjvCEJc3hOQCP6KF_H4OJNQMfUunrYY5I,74714
27
27
  codegraphcontext/core/cgcignore.py,sha256=x50FOG04kmR12LqixTlfiHW4ka05jf6_jaRA-5yiqis,10847
28
28
  codegraphcontext/core/database.py,sha256=ZLOHXv46hVxWiPYQala0Co7_Z8vqj5juaenudwq6DTU,14893
29
- codegraphcontext/core/database_embedded_kuzu.py,sha256=xa3hpCJcV4mcigmJf0RkafZULOzOxhkZtZD4Y0h0CcQ,81677
29
+ codegraphcontext/core/database_embedded_kuzu.py,sha256=85J43enxfPgEAR9lu2HflaD-Pmfcx4Mc5vCka_Vho5o,82482
30
30
  codegraphcontext/core/database_falkordb.py,sha256=8TSFfgKoaNdTzSx7P4qXMMs2kTNBzrcW5tZxR8JV4bY,35834
31
31
  codegraphcontext/core/database_falkordb_remote.py,sha256=HdkcmwgUxPy1bwiFqqcU8yMQYib7B3JarYQ1LlTwfJ8,7957
32
32
  codegraphcontext/core/database_kuzu.py,sha256=5I31dGm7wRo3YjIWeWGRVcX1eYRXYc7fPWnT7zHFjf0,1123
@@ -61,7 +61,7 @@ codegraphcontext/tools/indexing/__init__.py,sha256=exCNeB4UYhKhNSoEBNta_EZ51Kdze
61
61
  codegraphcontext/tools/indexing/constants.py,sha256=-ZiD5tdX95efNo2gOFrTNlmDnY4TALMN4GT0jOGPbcQ,742
62
62
  codegraphcontext/tools/indexing/discovery.py,sha256=l0uoCCPRWClXPbHzbExrkC2RRjhN8u5KX6gOhQZliII,5326
63
63
  codegraphcontext/tools/indexing/embeddings.py,sha256=Iny1K1HZaHtgApWpw88RLy1T10Rk4yJ8G6LNt5OcKfg,11406
64
- codegraphcontext/tools/indexing/pipeline.py,sha256=oDx3l65OC5lwqtkJ5ImaquaCfnpyZ4DNNEAXQhvAvto,18602
64
+ codegraphcontext/tools/indexing/pipeline.py,sha256=1JFgIj5VYjtzPQOERdFJqunh4CFjH7QJNiqbsYPspjo,19653
65
65
  codegraphcontext/tools/indexing/pre_scan.py,sha256=St7Hc3-NFTMYF39vWneJL6iIRIc78vyKEWABJstFM3c,6956
66
66
  codegraphcontext/tools/indexing/sanitize.py,sha256=lh78GDdYHxsd5fXlhS-bdOaOlMGD0Z2t8xALy9gX9fQ,3870
67
67
  codegraphcontext/tools/indexing/schema.py,sha256=3iIX6ToqGyZ41hkDmxJnETLSl98FXOqBM5dz8tRkQmg,8910
@@ -70,13 +70,13 @@ codegraphcontext/tools/indexing/scip_pipeline.py,sha256=OLbf0rhs1XU4LTQ6B3mS1-ng
70
70
  codegraphcontext/tools/indexing/vector_resolver.py,sha256=0D0QClro7nx9Wx6hbbFlOsO4dqgcTrwPMqE0CsJK01o,5477
71
71
  codegraphcontext/tools/indexing/persistence/__init__.py,sha256=hFRlNgiYS7uN9X4e4xfP3c1BvcYSxpmq0k_uaDRn2Fg,121
72
72
  codegraphcontext/tools/indexing/persistence/utils.py,sha256=OtndHpE_R14mPz5i-Bo9mA7NsoIuYnCNER-oIwxDOYA,2028
73
- codegraphcontext/tools/indexing/persistence/writer.py,sha256=j55lOTg422A7MRsxX1bf3GtILFw3axYcIrDfhWU-p2Q,111514
73
+ codegraphcontext/tools/indexing/persistence/writer.py,sha256=qh8-QHiUtIKUBbzNqzbEqmiHESmJ8FfCCrDmSxFVHoY,112282
74
74
  codegraphcontext/tools/indexing/resolution/__init__.py,sha256=BR57mVydpzjOnFSbGbwIIrPEWp1eHjLPAq6oUq_jutw,567
75
75
  codegraphcontext/tools/indexing/resolution/calls.py,sha256=q2YFGc0PACvCJn-Vr4pUwM4_IZwWm9Spof_4IpUpvo4,131656
76
76
  codegraphcontext/tools/indexing/resolution/inheritance.py,sha256=wS3fczEPcUkCDc-H7ON7YXm32EaDteuukK_Quq1I8dg,35772
77
77
  codegraphcontext/tools/indexing/resolution/post_resolution.py,sha256=OzmbbmLwIbKb5wm1RodoyvDST3d35A2e35ruDKBQDF4,10859
78
78
  codegraphcontext/tools/languages/c.py,sha256=quo2j0PCTlSOJctqqF_5zKeisERvTDyKuPtz_qvFgQA,31618
79
- codegraphcontext/tools/languages/cpp.py,sha256=lEErpGUSOlQzRn7NxK58JUF41OFj12sYdWMoLeUISxE,34521
79
+ codegraphcontext/tools/languages/cpp.py,sha256=s6dZsb2uiW2Spe0TVs37A8GzDeiLQG-yROUZCg4k1tM,34761
80
80
  codegraphcontext/tools/languages/csharp.py,sha256=_Kmpz1gqqkBCzhuHVyDJ5MsD2yI1Vh6PMGp0Ser_xjA,27170
81
81
  codegraphcontext/tools/languages/css.py,sha256=aN1Nm8vHmfV0J0jQ-_q5x0YDTOtLV2IW-5lp7WtGG5o,3789
82
82
  codegraphcontext/tools/languages/dart.py,sha256=yjqVA6XwoADrZab95p6wva0jT-PAGw_x90LR-cp2BDk,27160
@@ -174,9 +174,9 @@ codegraphcontext/viz/dist/wasm/tree-sitter-typescript.wasm,sha256=hRVATc7tOOHthq
174
174
  codegraphcontext/viz/dist/wasm/tree-sitter.wasm,sha256=CCeVuI_hXktkBD-DW01xYPv5XoAYVRIqzJUJI5te-RY,196763
175
175
  codegraphcontext/viz/dist/wasm/web-tree-sitter.js,sha256=DIaCNqRylrT_PBVw8g4ImeSnhP9uXNe_ycOlUiVGPko,153666
176
176
  codegraphcontext/viz/dist/wasm/web-tree-sitter.wasm,sha256=CCeVuI_hXktkBD-DW01xYPv5XoAYVRIqzJUJI5te-RY,196763
177
- codegraphcontext-0.6.1.dist-info/licenses/LICENSE,sha256=rh8M-bJpQYJnw2vtRVgt0t7piMZXh5QzaKeNEI0vqqA,1061
178
- codegraphcontext-0.6.1.dist-info/METADATA,sha256=nBcEmRNjpr0p4qu4-umRhZlF79XICLP4VzvwQ1FQO0E,33422
179
- codegraphcontext-0.6.1.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
180
- codegraphcontext-0.6.1.dist-info/entry_points.txt,sha256=LCxWCWMshdvYGoHBPuQZ8C-e4CiNSHCLXofrNSGHkoE,103
181
- codegraphcontext-0.6.1.dist-info/top_level.txt,sha256=CBgc6LAPZIO5FS0nSYYkylDifHsZTIqw3Gf5UwDxeGI,17
182
- codegraphcontext-0.6.1.dist-info/RECORD,,
177
+ codegraphcontext-0.6.2.dist-info/licenses/LICENSE,sha256=rh8M-bJpQYJnw2vtRVgt0t7piMZXh5QzaKeNEI0vqqA,1061
178
+ codegraphcontext-0.6.2.dist-info/METADATA,sha256=PDwab-ix3AJJeGpZY6MBVK5TBc-clvKlMPGblbwnrVE,33422
179
+ codegraphcontext-0.6.2.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
180
+ codegraphcontext-0.6.2.dist-info/entry_points.txt,sha256=LCxWCWMshdvYGoHBPuQZ8C-e4CiNSHCLXofrNSGHkoE,103
181
+ codegraphcontext-0.6.2.dist-info/top_level.txt,sha256=CBgc6LAPZIO5FS0nSYYkylDifHsZTIqw3Gf5UwDxeGI,17
182
+ codegraphcontext-0.6.2.dist-info/RECORD,,