exonware-xwnode 0.0.1.12__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 (132) hide show
  1. exonware/__init__.py +14 -0
  2. exonware/xwnode/__init__.py +127 -0
  3. exonware/xwnode/base.py +676 -0
  4. exonware/xwnode/config.py +178 -0
  5. exonware/xwnode/contracts.py +730 -0
  6. exonware/xwnode/errors.py +503 -0
  7. exonware/xwnode/facade.py +460 -0
  8. exonware/xwnode/strategies/__init__.py +158 -0
  9. exonware/xwnode/strategies/advisor.py +463 -0
  10. exonware/xwnode/strategies/edges/__init__.py +32 -0
  11. exonware/xwnode/strategies/edges/adj_list.py +227 -0
  12. exonware/xwnode/strategies/edges/adj_matrix.py +391 -0
  13. exonware/xwnode/strategies/edges/base.py +169 -0
  14. exonware/xwnode/strategies/flyweight.py +328 -0
  15. exonware/xwnode/strategies/impls/__init__.py +13 -0
  16. exonware/xwnode/strategies/impls/_base_edge.py +403 -0
  17. exonware/xwnode/strategies/impls/_base_node.py +307 -0
  18. exonware/xwnode/strategies/impls/edge_adj_list.py +353 -0
  19. exonware/xwnode/strategies/impls/edge_adj_matrix.py +445 -0
  20. exonware/xwnode/strategies/impls/edge_bidir_wrapper.py +455 -0
  21. exonware/xwnode/strategies/impls/edge_block_adj_matrix.py +539 -0
  22. exonware/xwnode/strategies/impls/edge_coo.py +533 -0
  23. exonware/xwnode/strategies/impls/edge_csc.py +447 -0
  24. exonware/xwnode/strategies/impls/edge_csr.py +492 -0
  25. exonware/xwnode/strategies/impls/edge_dynamic_adj_list.py +503 -0
  26. exonware/xwnode/strategies/impls/edge_flow_network.py +555 -0
  27. exonware/xwnode/strategies/impls/edge_hyperedge_set.py +516 -0
  28. exonware/xwnode/strategies/impls/edge_neural_graph.py +650 -0
  29. exonware/xwnode/strategies/impls/edge_octree.py +574 -0
  30. exonware/xwnode/strategies/impls/edge_property_store.py +655 -0
  31. exonware/xwnode/strategies/impls/edge_quadtree.py +519 -0
  32. exonware/xwnode/strategies/impls/edge_rtree.py +820 -0
  33. exonware/xwnode/strategies/impls/edge_temporal_edgeset.py +558 -0
  34. exonware/xwnode/strategies/impls/edge_tree_graph_basic.py +271 -0
  35. exonware/xwnode/strategies/impls/edge_weighted_graph.py +411 -0
  36. exonware/xwnode/strategies/manager.py +775 -0
  37. exonware/xwnode/strategies/metrics.py +538 -0
  38. exonware/xwnode/strategies/migration.py +432 -0
  39. exonware/xwnode/strategies/nodes/__init__.py +50 -0
  40. exonware/xwnode/strategies/nodes/_base_node.py +307 -0
  41. exonware/xwnode/strategies/nodes/adjacency_list.py +267 -0
  42. exonware/xwnode/strategies/nodes/aho_corasick.py +345 -0
  43. exonware/xwnode/strategies/nodes/array_list.py +209 -0
  44. exonware/xwnode/strategies/nodes/base.py +247 -0
  45. exonware/xwnode/strategies/nodes/deque.py +200 -0
  46. exonware/xwnode/strategies/nodes/hash_map.py +135 -0
  47. exonware/xwnode/strategies/nodes/heap.py +307 -0
  48. exonware/xwnode/strategies/nodes/linked_list.py +232 -0
  49. exonware/xwnode/strategies/nodes/node_aho_corasick.py +520 -0
  50. exonware/xwnode/strategies/nodes/node_array_list.py +175 -0
  51. exonware/xwnode/strategies/nodes/node_avl_tree.py +371 -0
  52. exonware/xwnode/strategies/nodes/node_b_plus_tree.py +542 -0
  53. exonware/xwnode/strategies/nodes/node_bitmap.py +420 -0
  54. exonware/xwnode/strategies/nodes/node_bitset_dynamic.py +513 -0
  55. exonware/xwnode/strategies/nodes/node_bloom_filter.py +347 -0
  56. exonware/xwnode/strategies/nodes/node_btree.py +357 -0
  57. exonware/xwnode/strategies/nodes/node_count_min_sketch.py +470 -0
  58. exonware/xwnode/strategies/nodes/node_cow_tree.py +473 -0
  59. exonware/xwnode/strategies/nodes/node_cuckoo_hash.py +392 -0
  60. exonware/xwnode/strategies/nodes/node_fenwick_tree.py +301 -0
  61. exonware/xwnode/strategies/nodes/node_hash_map.py +269 -0
  62. exonware/xwnode/strategies/nodes/node_heap.py +191 -0
  63. exonware/xwnode/strategies/nodes/node_hyperloglog.py +407 -0
  64. exonware/xwnode/strategies/nodes/node_linked_list.py +409 -0
  65. exonware/xwnode/strategies/nodes/node_lsm_tree.py +400 -0
  66. exonware/xwnode/strategies/nodes/node_ordered_map.py +390 -0
  67. exonware/xwnode/strategies/nodes/node_ordered_map_balanced.py +565 -0
  68. exonware/xwnode/strategies/nodes/node_patricia.py +512 -0
  69. exonware/xwnode/strategies/nodes/node_persistent_tree.py +378 -0
  70. exonware/xwnode/strategies/nodes/node_radix_trie.py +452 -0
  71. exonware/xwnode/strategies/nodes/node_red_black_tree.py +497 -0
  72. exonware/xwnode/strategies/nodes/node_roaring_bitmap.py +570 -0
  73. exonware/xwnode/strategies/nodes/node_segment_tree.py +289 -0
  74. exonware/xwnode/strategies/nodes/node_set_hash.py +354 -0
  75. exonware/xwnode/strategies/nodes/node_set_tree.py +480 -0
  76. exonware/xwnode/strategies/nodes/node_skip_list.py +316 -0
  77. exonware/xwnode/strategies/nodes/node_splay_tree.py +393 -0
  78. exonware/xwnode/strategies/nodes/node_suffix_array.py +487 -0
  79. exonware/xwnode/strategies/nodes/node_treap.py +387 -0
  80. exonware/xwnode/strategies/nodes/node_tree_graph_hybrid.py +1434 -0
  81. exonware/xwnode/strategies/nodes/node_trie.py +252 -0
  82. exonware/xwnode/strategies/nodes/node_union_find.py +187 -0
  83. exonware/xwnode/strategies/nodes/node_xdata_optimized.py +369 -0
  84. exonware/xwnode/strategies/nodes/priority_queue.py +209 -0
  85. exonware/xwnode/strategies/nodes/queue.py +161 -0
  86. exonware/xwnode/strategies/nodes/sparse_matrix.py +206 -0
  87. exonware/xwnode/strategies/nodes/stack.py +152 -0
  88. exonware/xwnode/strategies/nodes/trie.py +274 -0
  89. exonware/xwnode/strategies/nodes/union_find.py +283 -0
  90. exonware/xwnode/strategies/pattern_detector.py +603 -0
  91. exonware/xwnode/strategies/performance_monitor.py +487 -0
  92. exonware/xwnode/strategies/queries/__init__.py +24 -0
  93. exonware/xwnode/strategies/queries/base.py +236 -0
  94. exonware/xwnode/strategies/queries/cql.py +201 -0
  95. exonware/xwnode/strategies/queries/cypher.py +181 -0
  96. exonware/xwnode/strategies/queries/datalog.py +70 -0
  97. exonware/xwnode/strategies/queries/elastic_dsl.py +70 -0
  98. exonware/xwnode/strategies/queries/eql.py +70 -0
  99. exonware/xwnode/strategies/queries/flux.py +70 -0
  100. exonware/xwnode/strategies/queries/gql.py +70 -0
  101. exonware/xwnode/strategies/queries/graphql.py +240 -0
  102. exonware/xwnode/strategies/queries/gremlin.py +181 -0
  103. exonware/xwnode/strategies/queries/hiveql.py +214 -0
  104. exonware/xwnode/strategies/queries/hql.py +70 -0
  105. exonware/xwnode/strategies/queries/jmespath.py +219 -0
  106. exonware/xwnode/strategies/queries/jq.py +66 -0
  107. exonware/xwnode/strategies/queries/json_query.py +66 -0
  108. exonware/xwnode/strategies/queries/jsoniq.py +248 -0
  109. exonware/xwnode/strategies/queries/kql.py +70 -0
  110. exonware/xwnode/strategies/queries/linq.py +238 -0
  111. exonware/xwnode/strategies/queries/logql.py +70 -0
  112. exonware/xwnode/strategies/queries/mql.py +68 -0
  113. exonware/xwnode/strategies/queries/n1ql.py +210 -0
  114. exonware/xwnode/strategies/queries/partiql.py +70 -0
  115. exonware/xwnode/strategies/queries/pig.py +215 -0
  116. exonware/xwnode/strategies/queries/promql.py +70 -0
  117. exonware/xwnode/strategies/queries/sparql.py +220 -0
  118. exonware/xwnode/strategies/queries/sql.py +275 -0
  119. exonware/xwnode/strategies/queries/xml_query.py +66 -0
  120. exonware/xwnode/strategies/queries/xpath.py +223 -0
  121. exonware/xwnode/strategies/queries/xquery.py +258 -0
  122. exonware/xwnode/strategies/queries/xwnode_executor.py +332 -0
  123. exonware/xwnode/strategies/queries/xwquery_strategy.py +424 -0
  124. exonware/xwnode/strategies/registry.py +604 -0
  125. exonware/xwnode/strategies/simple.py +273 -0
  126. exonware/xwnode/strategies/utils.py +532 -0
  127. exonware/xwnode/types.py +912 -0
  128. exonware/xwnode/version.py +78 -0
  129. exonware_xwnode-0.0.1.12.dist-info/METADATA +169 -0
  130. exonware_xwnode-0.0.1.12.dist-info/RECORD +132 -0
  131. exonware_xwnode-0.0.1.12.dist-info/WHEEL +4 -0
  132. exonware_xwnode-0.0.1.12.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,730 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Contract interfaces for XWNode Strategy Pattern.
4
+
5
+ This module defines the contracts that all node and edge strategies must implement.
6
+ """
7
+
8
+ from abc import ABC, abstractmethod
9
+ from typing import Any, Iterator, Optional, Dict, List, Union, Callable
10
+ from enum import Enum, Flag
11
+
12
+ # Import all enums from types.py to avoid circular references
13
+ from .types import (
14
+ NodeMode, EdgeMode, NodeTrait, EdgeTrait, QueryMode, QueryTrait
15
+ )
16
+
17
+
18
+ class iNodeStrategy(ABC):
19
+ """
20
+ Abstract interface for node strategies.
21
+
22
+ All node strategies must implement this interface to ensure
23
+ compatibility with the XWNode facade.
24
+ """
25
+
26
+ @abstractmethod
27
+ def create_from_data(self, data: Any) -> 'iNodeStrategy':
28
+ """Create a new strategy instance from data."""
29
+ pass
30
+
31
+ @abstractmethod
32
+ def to_native(self) -> Any:
33
+ """Convert to native Python object."""
34
+ pass
35
+
36
+ @abstractmethod
37
+ def get(self, path: str, default: Any = None) -> Optional['iNodeStrategy']:
38
+ """Get a child node by path."""
39
+ pass
40
+
41
+ @abstractmethod
42
+ def put(self, path: str, value: Any) -> 'iNodeStrategy':
43
+ """Set a value at path."""
44
+ pass
45
+
46
+ @abstractmethod
47
+ def delete(self, path: str) -> bool:
48
+ """Delete a node at path."""
49
+ pass
50
+
51
+ @abstractmethod
52
+ def exists(self, path: str) -> bool:
53
+ """Check if path exists."""
54
+ pass
55
+
56
+ @abstractmethod
57
+ def keys(self) -> Iterator[str]:
58
+ """Get keys (for dict-like nodes)."""
59
+ pass
60
+
61
+ @abstractmethod
62
+ def values(self) -> Iterator['iNodeStrategy']:
63
+ """Get values (for dict-like nodes)."""
64
+ pass
65
+
66
+ @abstractmethod
67
+ def items(self) -> Iterator[tuple[str, 'iNodeStrategy']]:
68
+ """Get items (for dict-like nodes)."""
69
+ pass
70
+
71
+ @abstractmethod
72
+ def __len__(self) -> int:
73
+ """Get length."""
74
+ pass
75
+
76
+ @abstractmethod
77
+ def __iter__(self) -> Iterator['iNodeStrategy']:
78
+ """Iterate over children."""
79
+ pass
80
+
81
+ @abstractmethod
82
+ def __getitem__(self, key: Union[str, int]) -> 'iNodeStrategy':
83
+ """Get child by key or index."""
84
+ pass
85
+
86
+ @abstractmethod
87
+ def __setitem__(self, key: Union[str, int], value: Any) -> None:
88
+ """Set child by key or index."""
89
+ pass
90
+
91
+ @abstractmethod
92
+ def __contains__(self, key: Union[str, int]) -> bool:
93
+ """Check if key exists."""
94
+ pass
95
+
96
+ # Type checking properties
97
+ @property
98
+ @abstractmethod
99
+ def is_leaf(self) -> bool:
100
+ """Check if this is a leaf node."""
101
+ pass
102
+
103
+ @property
104
+ @abstractmethod
105
+ def is_list(self) -> bool:
106
+ """Check if this is a list node."""
107
+ pass
108
+
109
+ @property
110
+ @abstractmethod
111
+ def is_dict(self) -> bool:
112
+ """Check if this is a dict node."""
113
+ pass
114
+
115
+ @property
116
+ @abstractmethod
117
+ def is_reference(self) -> bool:
118
+ """Check if this is a reference node."""
119
+ pass
120
+
121
+ @property
122
+ @abstractmethod
123
+ def is_object(self) -> bool:
124
+ """Check if this is an object node."""
125
+ pass
126
+
127
+ @property
128
+ @abstractmethod
129
+ def type(self) -> str:
130
+ """Get the type of this node."""
131
+ pass
132
+
133
+ @property
134
+ @abstractmethod
135
+ def value(self) -> Any:
136
+ """Get the value of this node."""
137
+ pass
138
+
139
+ # Optional properties with default implementations
140
+ @property
141
+ def uri(self) -> Optional[str]:
142
+ """Get URI (for reference/object nodes)."""
143
+ return None
144
+
145
+ @property
146
+ def reference_type(self) -> Optional[str]:
147
+ """Get reference type (for reference nodes)."""
148
+ return None
149
+
150
+ @property
151
+ def object_type(self) -> Optional[str]:
152
+ """Get object type (for object nodes)."""
153
+ return None
154
+
155
+ @property
156
+ def mime_type(self) -> Optional[str]:
157
+ """Get MIME type (for object nodes)."""
158
+ return None
159
+
160
+ @property
161
+ def metadata(self) -> Optional[Dict[str, Any]]:
162
+ """Get metadata (for reference/object nodes)."""
163
+ return None
164
+
165
+ # Strategy information
166
+ @property
167
+ @abstractmethod
168
+ def strategy_name(self) -> str:
169
+ """Get the name of this strategy."""
170
+ pass
171
+
172
+ @property
173
+ @abstractmethod
174
+ def supported_traits(self) -> List[NodeTrait]:
175
+ """Get supported traits for this strategy."""
176
+ pass
177
+
178
+
179
+ class iEdgeStrategy(ABC):
180
+ """
181
+ Abstract interface for edge strategies.
182
+
183
+ All edge strategies must implement this interface to ensure
184
+ compatibility with the XWNode graph operations, including advanced
185
+ features like edge types, weights, properties, and graph algorithms.
186
+ """
187
+
188
+ @abstractmethod
189
+ def add_edge(self, source: str, target: str, edge_type: str = "default",
190
+ weight: float = 1.0, properties: Optional[Dict[str, Any]] = None,
191
+ is_bidirectional: bool = False, edge_id: Optional[str] = None) -> str:
192
+ """Add an edge between source and target with advanced properties."""
193
+ pass
194
+
195
+ @abstractmethod
196
+ def remove_edge(self, source: str, target: str, edge_id: Optional[str] = None) -> bool:
197
+ """Remove an edge between source and target."""
198
+ pass
199
+
200
+ @abstractmethod
201
+ def has_edge(self, source: str, target: str) -> bool:
202
+ """Check if edge exists between source and target."""
203
+ pass
204
+
205
+ @abstractmethod
206
+ def get_neighbors(self, node: str, edge_type: Optional[str] = None, direction: str = "outgoing") -> List[str]:
207
+ """Get neighbors of a node with optional filtering."""
208
+ pass
209
+
210
+ @abstractmethod
211
+ def get_edges(self, edge_type: Optional[str] = None, direction: str = "both") -> List[Dict[str, Any]]:
212
+ """Get all edges with metadata."""
213
+ pass
214
+
215
+ @abstractmethod
216
+ def get_edge_data(self, source: str, target: str, edge_id: Optional[str] = None) -> Optional[Dict[str, Any]]:
217
+ """Get edge data/properties."""
218
+ pass
219
+
220
+ @abstractmethod
221
+ def shortest_path(self, source: str, target: str, edge_type: Optional[str] = None) -> List[str]:
222
+ """Find shortest path between nodes."""
223
+ pass
224
+
225
+ @abstractmethod
226
+ def find_cycles(self, start_node: str, edge_type: Optional[str] = None, max_depth: int = 10) -> List[List[str]]:
227
+ """Find cycles in the graph."""
228
+ pass
229
+
230
+ @abstractmethod
231
+ def traverse_graph(self, start_node: str, strategy: str = "bfs", max_depth: int = 100,
232
+ edge_type: Optional[str] = None) -> Iterator[str]:
233
+ """Traverse the graph with cycle detection."""
234
+ pass
235
+
236
+ @abstractmethod
237
+ def is_connected(self, source: str, target: str, edge_type: Optional[str] = None) -> bool:
238
+ """Check if nodes are connected."""
239
+ pass
240
+
241
+ @abstractmethod
242
+ def __len__(self) -> int:
243
+ """Get number of edges."""
244
+ pass
245
+
246
+ @abstractmethod
247
+ def __iter__(self) -> Iterator[Dict[str, Any]]:
248
+ """Iterate over edges with full metadata."""
249
+ pass
250
+
251
+ @property
252
+ @abstractmethod
253
+ def strategy_name(self) -> str:
254
+ """Get the name of this strategy."""
255
+ pass
256
+
257
+ @property
258
+ @abstractmethod
259
+ def supported_traits(self) -> List[EdgeTrait]:
260
+ """Get supported traits for this strategy."""
261
+ pass
262
+
263
+
264
+ class iEdge(ABC):
265
+ """
266
+ Abstract interface for edge facade.
267
+
268
+ This defines the public interface for edge operations with advanced features
269
+ including edge types, weights, properties, and graph algorithms.
270
+ """
271
+
272
+ @abstractmethod
273
+ def add_edge(self, source: str, target: str, edge_type: str = "default",
274
+ weight: float = 1.0, properties: Optional[Dict[str, Any]] = None,
275
+ is_bidirectional: bool = False, edge_id: Optional[str] = None) -> str:
276
+ """Add an edge between source and target with advanced properties."""
277
+ pass
278
+
279
+ @abstractmethod
280
+ def remove_edge(self, source: str, target: str, edge_id: Optional[str] = None) -> bool:
281
+ """Remove an edge between source and target."""
282
+ pass
283
+
284
+ @abstractmethod
285
+ def has_edge(self, source: str, target: str) -> bool:
286
+ """Check if edge exists between source and target."""
287
+ pass
288
+
289
+ @abstractmethod
290
+ def get_neighbors(self, node: str, edge_type: Optional[str] = None, direction: str = "outgoing") -> List[str]:
291
+ """Get neighbors of a node with optional filtering."""
292
+ pass
293
+
294
+ @abstractmethod
295
+ def get_edges(self, edge_type: Optional[str] = None, direction: str = "both") -> List[Dict[str, Any]]:
296
+ """Get all edges with metadata."""
297
+ pass
298
+
299
+ @abstractmethod
300
+ def get_edge_data(self, source: str, target: str, edge_id: Optional[str] = None) -> Optional[Dict[str, Any]]:
301
+ """Get edge data/properties."""
302
+ pass
303
+
304
+ @abstractmethod
305
+ def shortest_path(self, source: str, target: str, edge_type: Optional[str] = None) -> List[str]:
306
+ """Find shortest path between nodes."""
307
+ pass
308
+
309
+ @abstractmethod
310
+ def find_cycles(self, start_node: str, edge_type: Optional[str] = None, max_depth: int = 10) -> List[List[str]]:
311
+ """Find cycles in the graph."""
312
+ pass
313
+
314
+ @abstractmethod
315
+ def traverse_graph(self, start_node: str, strategy: str = "bfs", max_depth: int = 100,
316
+ edge_type: Optional[str] = None) -> Iterator[str]:
317
+ """Traverse the graph with cycle detection."""
318
+ pass
319
+
320
+ @abstractmethod
321
+ def is_connected(self, source: str, target: str, edge_type: Optional[str] = None) -> bool:
322
+ """Check if nodes are connected."""
323
+ pass
324
+
325
+ @abstractmethod
326
+ def __len__(self) -> int:
327
+ """Get number of edges."""
328
+ pass
329
+
330
+ @abstractmethod
331
+ def __iter__(self) -> Iterator[Dict[str, Any]]:
332
+ """Iterate over edges with full metadata."""
333
+ pass
334
+
335
+ @abstractmethod
336
+ def to_native(self) -> Any:
337
+ """Convert to native Python object."""
338
+ pass
339
+
340
+ @abstractmethod
341
+ def copy(self) -> 'iEdge':
342
+ """Create a deep copy."""
343
+ pass
344
+
345
+
346
+ class iNodeFacade(ABC):
347
+ """
348
+ Abstract interface for the XWNode facade.
349
+
350
+ This defines the public interface that XWNode must implement.
351
+ """
352
+
353
+ @abstractmethod
354
+ def get(self, path: str, default: Any = None) -> Optional['iNodeFacade']:
355
+ """Get a node by path."""
356
+ pass
357
+
358
+ @abstractmethod
359
+ def set(self, path: str, value: Any, in_place: bool = True) -> 'iNodeFacade':
360
+ """Set a value at path."""
361
+ pass
362
+
363
+ @abstractmethod
364
+ def delete(self, path: str, in_place: bool = True) -> 'iNodeFacade':
365
+ """Delete a node at path."""
366
+ pass
367
+
368
+ @abstractmethod
369
+ def exists(self, path: str) -> bool:
370
+ """Check if path exists."""
371
+ pass
372
+
373
+ @abstractmethod
374
+ def find(self, path: str, in_place: bool = False) -> Optional['iNodeFacade']:
375
+ """Find a node by path."""
376
+ pass
377
+
378
+ @abstractmethod
379
+ def to_native(self) -> Any:
380
+ """Convert to native Python object."""
381
+ pass
382
+
383
+ @abstractmethod
384
+ def copy(self) -> 'iNodeFacade':
385
+ """Create a deep copy."""
386
+ pass
387
+
388
+ @abstractmethod
389
+ def count(self, path: str = ".") -> int:
390
+ """Count nodes at path."""
391
+ pass
392
+
393
+ @abstractmethod
394
+ def flatten(self, separator: str = ".") -> Dict[str, Any]:
395
+ """Flatten to dictionary."""
396
+ pass
397
+
398
+ @abstractmethod
399
+ def merge(self, other: 'iNodeFacade', strategy: str = "replace") -> 'iNodeFacade':
400
+ """Merge with another node."""
401
+ pass
402
+
403
+ @abstractmethod
404
+ def diff(self, other: 'iNodeFacade') -> Dict[str, Any]:
405
+ """Get differences with another node."""
406
+ pass
407
+
408
+ @abstractmethod
409
+ def transform(self, transformer: callable) -> 'iNodeFacade':
410
+ """Transform using a function."""
411
+ pass
412
+
413
+ @abstractmethod
414
+ def select(self, *paths: str) -> Dict[str, 'iNodeFacade']:
415
+ """Select multiple paths."""
416
+ pass
417
+
418
+ # Container methods
419
+ @abstractmethod
420
+ def __len__(self) -> int:
421
+ """Get length."""
422
+ pass
423
+
424
+ @abstractmethod
425
+ def __iter__(self) -> Iterator['iNodeFacade']:
426
+ """Iterate over children."""
427
+ pass
428
+
429
+ @abstractmethod
430
+ def __getitem__(self, key: Union[str, int]) -> 'iNodeFacade':
431
+ """Get child by key or index."""
432
+ pass
433
+
434
+ @abstractmethod
435
+ def __setitem__(self, key: Union[str, int], value: Any) -> None:
436
+ """Set child by key or index."""
437
+ pass
438
+
439
+ @abstractmethod
440
+ def __contains__(self, key: Union[str, int]) -> bool:
441
+ """Check if key exists."""
442
+ pass
443
+
444
+ # Type checking properties
445
+ @property
446
+ @abstractmethod
447
+ def is_leaf(self) -> bool:
448
+ """Check if this is a leaf node."""
449
+ pass
450
+
451
+ @property
452
+ @abstractmethod
453
+ def is_list(self) -> bool:
454
+ """Check if this is a list node."""
455
+ pass
456
+
457
+ @property
458
+ @abstractmethod
459
+ def is_dict(self) -> bool:
460
+ """Check if this is a dict node."""
461
+ pass
462
+
463
+ @property
464
+ @abstractmethod
465
+ def type(self) -> str:
466
+ """Get the type of this node."""
467
+ pass
468
+
469
+ @property
470
+ @abstractmethod
471
+ def value(self) -> Any:
472
+ """Get the value of this node."""
473
+ pass
474
+
475
+ # ============================================================================
476
+ # QUERY INTERFACES
477
+ # ============================================================================
478
+
479
+ # QueryMode and QueryTrait are now imported from types.py
480
+
481
+
482
+ class IQueryStrategy(ABC):
483
+ """
484
+ Abstract interface for query strategies.
485
+
486
+ All query strategies must implement this interface to ensure
487
+ compatibility with the XWQuery facade and automatic query detection.
488
+ """
489
+
490
+ @abstractmethod
491
+ def execute(self, query_string: str, context: Dict[str, Any] = None) -> 'iQueryResult':
492
+ """Execute a query and return results."""
493
+ pass
494
+
495
+ @abstractmethod
496
+ def validate_query(self, query_string: str) -> bool:
497
+ """Validate if the query string is valid for this strategy."""
498
+ pass
499
+
500
+ @abstractmethod
501
+ def get_query_plan(self, query_string: str) -> Dict[str, Any]:
502
+ """Get the execution plan for a query."""
503
+ pass
504
+
505
+ @abstractmethod
506
+ def get_mode(self) -> QueryMode:
507
+ """Get the query mode this strategy handles."""
508
+ pass
509
+
510
+ @abstractmethod
511
+ def get_traits(self) -> QueryTrait:
512
+ """Get the traits/capabilities this strategy supports."""
513
+ pass
514
+
515
+ @abstractmethod
516
+ def can_handle(self, query_string: str) -> bool:
517
+ """Check if this strategy can handle the given query string."""
518
+ pass
519
+
520
+ @abstractmethod
521
+ def get_supported_operations(self) -> List[str]:
522
+ """Get list of supported query operations."""
523
+ pass
524
+
525
+ @abstractmethod
526
+ def estimate_complexity(self, query_string: str) -> Dict[str, Any]:
527
+ """Estimate query complexity and resource requirements."""
528
+ pass
529
+
530
+
531
+ # ============================================================================
532
+ # QUERY ERROR CLASSES
533
+ # ============================================================================
534
+
535
+ class XWQueryError(Exception):
536
+ """Base exception for all query-related errors."""
537
+
538
+ def __init__(self, message: str, query_string: str = None, cause: Exception = None):
539
+ super().__init__(message)
540
+ self.query_string = query_string
541
+ self.cause = cause
542
+
543
+ def __str__(self):
544
+ base_msg = super().__str__()
545
+ if self.query_string:
546
+ return f"{base_msg} (Query: {self.query_string[:100]}...)"
547
+ return base_msg
548
+
549
+
550
+ class XWQueryValidationError(XWQueryError):
551
+ """Raised when query validation fails."""
552
+ pass
553
+
554
+
555
+ class XWQueryExecutionError(XWQueryError):
556
+ """Raised when query execution fails."""
557
+ pass
558
+
559
+
560
+ class XWQueryParseError(XWQueryError):
561
+ """Raised when query parsing fails."""
562
+ pass
563
+
564
+
565
+ class XWQueryTimeoutError(XWQueryError):
566
+ """Raised when query execution times out."""
567
+ pass
568
+
569
+
570
+ class XWQueryNotSupportedError(XWQueryError):
571
+ """Raised when a query operation is not supported."""
572
+ pass
573
+
574
+
575
+ class XWQueryStrategyNotFoundError(XWQueryError):
576
+ """Raised when no suitable query strategy is found."""
577
+ pass
578
+
579
+
580
+ class XWQueryContextError(XWQueryError):
581
+ """Raised when query context is invalid or missing."""
582
+ pass
583
+
584
+ class iQueryResult(ABC):
585
+ """Interface for query results."""
586
+
587
+ @property
588
+ @abstractmethod
589
+ def nodes(self) -> List['iNodeFacade']:
590
+ """Get result nodes."""
591
+ pass
592
+
593
+ @property
594
+ @abstractmethod
595
+ def metadata(self) -> Dict[str, Any]:
596
+ """Get result metadata."""
597
+ pass
598
+
599
+ @abstractmethod
600
+ def first(self) -> Optional['iNodeFacade']:
601
+ """Get first result."""
602
+ pass
603
+
604
+ @abstractmethod
605
+ def count(self) -> int:
606
+ """Get result count."""
607
+ pass
608
+
609
+ @abstractmethod
610
+ def filter(self, predicate: Callable[['iNodeFacade'], bool]) -> 'iQueryResult':
611
+ """Filter results."""
612
+ pass
613
+
614
+ @abstractmethod
615
+ def limit(self, limit: int) -> 'iQueryResult':
616
+ """Limit results."""
617
+ pass
618
+
619
+ @abstractmethod
620
+ def offset(self, offset: int) -> 'iQueryResult':
621
+ """Offset results."""
622
+ pass
623
+
624
+
625
+ class iQueryEngine(ABC):
626
+ """Interface for query engines."""
627
+
628
+ @abstractmethod
629
+ def execute_query(self, query_string: str, context: Dict[str, Any]) -> iQueryResult:
630
+ """Execute query and return results."""
631
+ pass
632
+
633
+ @abstractmethod
634
+ def parse_query(self, query_string: str) -> Dict[str, Any]:
635
+ """Parse query string into structured format."""
636
+ pass
637
+
638
+ @abstractmethod
639
+ def validate_query(self, query_string: str) -> bool:
640
+ """Validate query string."""
641
+ pass
642
+
643
+
644
+ class iQuery(ABC):
645
+ """Interface for query capabilities."""
646
+
647
+ @abstractmethod
648
+ def query(self, query_string: str, query_type: str = "hybrid", **kwargs) -> iQueryResult:
649
+ """Execute a query."""
650
+ pass
651
+
652
+ @abstractmethod
653
+ def find_nodes(self, predicate: Callable[['iNodeFacade'], bool], max_results: Optional[int] = None) -> iQueryResult:
654
+ """Find nodes matching predicate."""
655
+ pass
656
+
657
+ @abstractmethod
658
+ def find_by_path(self, path_pattern: str) -> iQueryResult:
659
+ """Find nodes by path pattern."""
660
+ pass
661
+
662
+ @abstractmethod
663
+ def find_by_value(self, value: Any, exact_match: bool = True) -> iQueryResult:
664
+ """Find nodes by value."""
665
+ pass
666
+
667
+ @abstractmethod
668
+ def count_nodes(self, predicate: Optional[Callable[['iNodeFacade'], bool]] = None) -> int:
669
+ """Count nodes matching predicate."""
670
+ pass
671
+
672
+ @abstractmethod
673
+ def select(self, selector: str, **kwargs) -> List['iNodeFacade']:
674
+ """Select nodes using a selector expression."""
675
+ pass
676
+
677
+ @abstractmethod
678
+ def filter(self, condition: str, **kwargs) -> List['iNodeFacade']:
679
+ """Filter nodes based on a condition."""
680
+ pass
681
+
682
+ @abstractmethod
683
+ def where(self, condition: str) -> List['iNodeFacade']:
684
+ """Filter nodes using a where condition."""
685
+ pass
686
+
687
+ @abstractmethod
688
+ def sort(self, key: str = None, reverse: bool = False) -> List['iNodeFacade']:
689
+ """Sort nodes by a key."""
690
+ pass
691
+
692
+ @abstractmethod
693
+ def limit(self, count: int) -> List['iNodeFacade']:
694
+ """Limit the number of results."""
695
+ pass
696
+
697
+ @abstractmethod
698
+ def skip(self, count: int) -> List['iNodeFacade']:
699
+ """Skip a number of results."""
700
+ pass
701
+
702
+ @abstractmethod
703
+ def first(self) -> Optional['iNodeFacade']:
704
+ """Get the first result."""
705
+ pass
706
+
707
+ @abstractmethod
708
+ def last(self) -> Optional['iNodeFacade']:
709
+ """Get the last result."""
710
+ pass
711
+
712
+ @abstractmethod
713
+ def group_by(self, key: str) -> Dict[str, List['iNodeFacade']]:
714
+ """Group nodes by a key."""
715
+ pass
716
+
717
+ @abstractmethod
718
+ def distinct(self, key: str = None) -> List['iNodeFacade']:
719
+ """Get distinct values."""
720
+ pass
721
+
722
+ @abstractmethod
723
+ def clear_query_cache(self):
724
+ """Clear the query cache."""
725
+ pass
726
+
727
+ @abstractmethod
728
+ def get_query_stats(self) -> Dict[str, Any]:
729
+ """Get query execution statistics."""
730
+ pass