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,371 @@
1
+ #exonware\xnode\strategies\impls\node_avl_tree.py
2
+ """
3
+ AVL Tree Node Strategy Implementation
4
+
5
+ This module implements the AVL_TREE strategy for strictly balanced binary
6
+ search trees with guaranteed O(log n) height and operations.
7
+ """
8
+
9
+ from typing import Any, Iterator, List, Dict, Optional, Tuple
10
+ from .base import ANodeTreeStrategy
11
+ from ...types import NodeMode, NodeTrait
12
+
13
+
14
+ class AVLTreeNode:
15
+ """Node in the AVL tree."""
16
+
17
+ def __init__(self, key: str, value: Any = None, height: int = 1):
18
+ self.key = key
19
+ self.value = value
20
+ self.height = height
21
+ self.left: Optional['AVLTreeNode'] = None
22
+ self.right: Optional['AVLTreeNode'] = None
23
+ self._hash = None
24
+
25
+ def __hash__(self) -> int:
26
+ """Cache hash for performance."""
27
+ if self._hash is None:
28
+ self._hash = hash((self.key, self.value, self.height))
29
+ return self._hash
30
+
31
+ def __eq__(self, other) -> bool:
32
+ """Structural equality."""
33
+ if not isinstance(other, AVLTreeNode):
34
+ return False
35
+ return (self.key == other.key and
36
+ self.value == other.value and
37
+ self.height == other.height)
38
+
39
+
40
+ class AVLTreeStrategy(ANodeTreeStrategy):
41
+ """
42
+ AVL tree node strategy for strictly balanced binary search trees.
43
+
44
+ Provides guaranteed O(log n) height and operations through height-based
45
+ balancing rules and rotations.
46
+ """
47
+
48
+ def __init__(self, traits: NodeTrait = NodeTrait.NONE, **options):
49
+ """Initialize the AVL tree strategy."""
50
+ super().__init__(NodeMode.AVL_TREE, traits, **options)
51
+
52
+ self.case_sensitive = options.get('case_sensitive', True)
53
+
54
+ # Core AVL tree
55
+ self._root: Optional[AVLTreeNode] = None
56
+ self._size = 0
57
+
58
+ # Statistics
59
+ self._total_insertions = 0
60
+ self._total_deletions = 0
61
+ self._total_rotations = 0
62
+ self._max_height = 0
63
+
64
+ def get_supported_traits(self) -> NodeTrait:
65
+ """Get the traits supported by the AVL tree strategy."""
66
+ return (NodeTrait.ORDERED | NodeTrait.INDEXED)
67
+
68
+ def _normalize_key(self, key: str) -> str:
69
+ """Normalize key based on case sensitivity."""
70
+ return key if self.case_sensitive else key.lower()
71
+
72
+ def _get_height(self, node: Optional[AVLTreeNode]) -> int:
73
+ """Get height of node."""
74
+ return node.height if node else 0
75
+
76
+ def _get_balance(self, node: Optional[AVLTreeNode]) -> int:
77
+ """Get balance factor of node."""
78
+ if not node:
79
+ return 0
80
+ return self._get_height(node.left) - self._get_height(node.right)
81
+
82
+ def _update_height(self, node: AVLTreeNode) -> None:
83
+ """Update height of node."""
84
+ node.height = 1 + max(self._get_height(node.left), self._get_height(node.right))
85
+
86
+ def _rotate_right(self, node: AVLTreeNode) -> AVLTreeNode:
87
+ """Right rotation around node."""
88
+ left_child = node.left
89
+ if not left_child:
90
+ return node
91
+
92
+ # Perform rotation
93
+ node.left = left_child.right
94
+ left_child.right = node
95
+
96
+ # Update heights
97
+ self._update_height(node)
98
+ self._update_height(left_child)
99
+
100
+ self._total_rotations += 1
101
+ return left_child
102
+
103
+ def _rotate_left(self, node: AVLTreeNode) -> AVLTreeNode:
104
+ """Left rotation around node."""
105
+ right_child = node.right
106
+ if not right_child:
107
+ return node
108
+
109
+ # Perform rotation
110
+ node.right = right_child.left
111
+ right_child.left = node
112
+
113
+ # Update heights
114
+ self._update_height(node)
115
+ self._update_height(right_child)
116
+
117
+ self._total_rotations += 1
118
+ return right_child
119
+
120
+ def _balance_node(self, node: AVLTreeNode) -> AVLTreeNode:
121
+ """Balance node using AVL rotations."""
122
+ # Update height
123
+ self._update_height(node)
124
+
125
+ # Get balance factor
126
+ balance = self._get_balance(node)
127
+
128
+ # Left heavy
129
+ if balance > 1:
130
+ if self._get_balance(node.left) < 0:
131
+ # Left-Right case
132
+ node.left = self._rotate_left(node.left)
133
+ return self._rotate_right(node)
134
+ else:
135
+ # Left-Left case
136
+ return self._rotate_right(node)
137
+
138
+ # Right heavy
139
+ if balance < -1:
140
+ if self._get_balance(node.right) > 0:
141
+ # Right-Left case
142
+ node.right = self._rotate_right(node.right)
143
+ return self._rotate_left(node)
144
+ else:
145
+ # Right-Right case
146
+ return self._rotate_left(node)
147
+
148
+ return node
149
+
150
+ def _insert_node(self, node: Optional[AVLTreeNode], key: str, value: Any) -> Tuple[AVLTreeNode, bool]:
151
+ """Insert node with given key and value."""
152
+ if not node:
153
+ new_node = AVLTreeNode(key, value)
154
+ return new_node, True
155
+
156
+ normalized_key = self._normalize_key(key)
157
+ node_key = self._normalize_key(node.key)
158
+
159
+ if normalized_key < node_key:
160
+ node.left, inserted = self._insert_node(node.left, key, value)
161
+ elif normalized_key > node_key:
162
+ node.right, inserted = self._insert_node(node.right, key, value)
163
+ else:
164
+ # Key already exists, update value
165
+ node.value = value
166
+ return node, False
167
+
168
+ # Balance the node
169
+ balanced_node = self._balance_node(node)
170
+ return balanced_node, inserted
171
+
172
+ def _find_node(self, node: Optional[AVLTreeNode], key: str) -> Optional[AVLTreeNode]:
173
+ """Find node with given key."""
174
+ if not node:
175
+ return None
176
+
177
+ normalized_key = self._normalize_key(key)
178
+ node_key = self._normalize_key(node.key)
179
+
180
+ if normalized_key < node_key:
181
+ return self._find_node(node.left, key)
182
+ elif normalized_key > node_key:
183
+ return self._find_node(node.right, key)
184
+ else:
185
+ return node
186
+
187
+ def _find_min(self, node: AVLTreeNode) -> AVLTreeNode:
188
+ """Find minimum node in subtree."""
189
+ while node.left:
190
+ node = node.left
191
+ return node
192
+
193
+ def _find_max(self, node: AVLTreeNode) -> AVLTreeNode:
194
+ """Find maximum node in subtree."""
195
+ while node.right:
196
+ node = node.right
197
+ return node
198
+
199
+ def _delete_node(self, node: Optional[AVLTreeNode], key: str) -> Tuple[Optional[AVLTreeNode], bool]:
200
+ """Delete node with given key."""
201
+ if not node:
202
+ return None, False
203
+
204
+ normalized_key = self._normalize_key(key)
205
+ node_key = self._normalize_key(node.key)
206
+
207
+ if normalized_key < node_key:
208
+ node.left, deleted = self._delete_node(node.left, key)
209
+ elif normalized_key > node_key:
210
+ node.right, deleted = self._delete_node(node.right, key)
211
+ else:
212
+ # Found node to delete
213
+ if not node.left:
214
+ return node.right, True
215
+ elif not node.right:
216
+ return node.left, True
217
+ else:
218
+ # Node has both children, find successor
219
+ successor = self._find_min(node.right)
220
+ node.key = successor.key
221
+ node.value = successor.value
222
+ node.right, _ = self._delete_node(node.right, successor.key)
223
+ deleted = True
224
+
225
+ if not deleted:
226
+ return node, False
227
+
228
+ # Balance the node
229
+ balanced_node = self._balance_node(node)
230
+ return balanced_node, True
231
+
232
+ def _inorder_traversal(self, node: Optional[AVLTreeNode]) -> Iterator[Tuple[str, Any]]:
233
+ """In-order traversal of tree."""
234
+ if node:
235
+ yield from self._inorder_traversal(node.left)
236
+ yield (node.key, node.value)
237
+ yield from self._inorder_traversal(node.right)
238
+
239
+ # ============================================================================
240
+ # CORE OPERATIONS
241
+ # ============================================================================
242
+
243
+ def put(self, key: Any, value: Any = None) -> None:
244
+ """Store a key-value pair."""
245
+ if not isinstance(key, str):
246
+ key = str(key)
247
+
248
+ self._root, inserted = self._insert_node(self._root, key, value)
249
+ if inserted:
250
+ self._size += 1
251
+ self._total_insertions += 1
252
+ self._max_height = max(self._max_height, self._get_height(self._root))
253
+
254
+ def get(self, key: Any, default: Any = None) -> Any:
255
+ """Retrieve a value by key."""
256
+ if not isinstance(key, str):
257
+ key = str(key)
258
+
259
+ node = self._find_node(self._root, key)
260
+ return node.value if node else default
261
+
262
+ def delete(self, key: Any) -> bool:
263
+ """Remove a key-value pair."""
264
+ if not isinstance(key, str):
265
+ key = str(key)
266
+
267
+ self._root, deleted = self._delete_node(self._root, key)
268
+ if deleted:
269
+ self._size -= 1
270
+ self._total_deletions += 1
271
+ return deleted
272
+
273
+ def has(self, key: Any) -> bool:
274
+ """Check if key exists."""
275
+ if not isinstance(key, str):
276
+ key = str(key)
277
+
278
+ return self._find_node(self._root, key) is not None
279
+
280
+ def clear(self) -> None:
281
+ """Clear all data."""
282
+ self._root = None
283
+ self._size = 0
284
+
285
+ def size(self) -> int:
286
+ """Get number of key-value pairs."""
287
+ return self._size
288
+
289
+ def is_empty(self) -> bool:
290
+ """Check if tree is empty."""
291
+ return self._root is None
292
+
293
+ # ============================================================================
294
+ # ITERATION
295
+ # ============================================================================
296
+
297
+ def keys(self) -> Iterator[str]:
298
+ """Iterate over keys in sorted order."""
299
+ for key, _ in self._inorder_traversal(self._root):
300
+ yield key
301
+
302
+ def values(self) -> Iterator[Any]:
303
+ """Iterate over values in key order."""
304
+ for _, value in self._inorder_traversal(self._root):
305
+ yield value
306
+
307
+ def items(self) -> Iterator[Tuple[str, Any]]:
308
+ """Iterate over key-value pairs in sorted order."""
309
+ yield from self._inorder_traversal(self._root)
310
+
311
+ def __iter__(self) -> Iterator[str]:
312
+ """Iterate over keys."""
313
+ yield from self.keys()
314
+
315
+ # ============================================================================
316
+ # AVL TREE SPECIFIC OPERATIONS
317
+ # ============================================================================
318
+
319
+ def get_min(self) -> Optional[Tuple[str, Any]]:
320
+ """Get the minimum key-value pair."""
321
+ if not self._root:
322
+ return None
323
+
324
+ min_node = self._find_min(self._root)
325
+ return (min_node.key, min_node.value)
326
+
327
+ def get_max(self) -> Optional[Tuple[str, Any]]:
328
+ """Get the maximum key-value pair."""
329
+ if not self._root:
330
+ return None
331
+
332
+ max_node = self._find_max(self._root)
333
+ return (max_node.key, max_node.value)
334
+
335
+ def get_height(self) -> int:
336
+ """Get the height of the tree."""
337
+ return self._get_height(self._root)
338
+
339
+ def is_balanced(self) -> bool:
340
+ """Check if tree is AVL balanced."""
341
+ def check_balance(node: Optional[AVLTreeNode]) -> bool:
342
+ if not node:
343
+ return True
344
+
345
+ balance = self._get_balance(node)
346
+ if abs(balance) > 1:
347
+ return False
348
+
349
+ return check_balance(node.left) and check_balance(node.right)
350
+
351
+ return check_balance(self._root)
352
+
353
+ def get_balance_factor(self, key: str) -> Optional[int]:
354
+ """Get balance factor of node with given key."""
355
+ node = self._find_node(self._root, key)
356
+ return self._get_balance(node) if node else None
357
+
358
+ def get_stats(self) -> Dict[str, Any]:
359
+ """Get performance statistics."""
360
+ return {
361
+ 'size': self._size,
362
+ 'height': self._get_height(self._root),
363
+ 'max_height': self._max_height,
364
+ 'total_insertions': self._total_insertions,
365
+ 'total_deletions': self._total_deletions,
366
+ 'total_rotations': self._total_rotations,
367
+ 'is_balanced': self.is_balanced(),
368
+ 'strategy': 'AVL_TREE',
369
+ 'backend': 'Strictly balanced AVL tree with guaranteed O(log n) height',
370
+ 'traits': [trait.name for trait in NodeTrait if self.has_trait(trait)]
371
+ }