exonware-xwnode 0.0.1.21__py3-none-any.whl → 0.0.1.23__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 (250) hide show
  1. exonware/__init__.py +8 -1
  2. exonware/xwnode/__init__.py +18 -5
  3. exonware/xwnode/add_strategy_types.py +165 -0
  4. exonware/xwnode/base.py +7 -5
  5. exonware/xwnode/common/__init__.py +1 -1
  6. exonware/xwnode/common/graph/__init__.py +30 -0
  7. exonware/xwnode/common/graph/caching.py +131 -0
  8. exonware/xwnode/common/graph/contracts.py +100 -0
  9. exonware/xwnode/common/graph/errors.py +44 -0
  10. exonware/xwnode/common/graph/indexing.py +260 -0
  11. exonware/xwnode/common/graph/manager.py +568 -0
  12. exonware/xwnode/common/management/__init__.py +3 -5
  13. exonware/xwnode/common/management/manager.py +9 -9
  14. exonware/xwnode/common/management/migration.py +6 -6
  15. exonware/xwnode/common/monitoring/__init__.py +3 -5
  16. exonware/xwnode/common/monitoring/metrics.py +7 -3
  17. exonware/xwnode/common/monitoring/pattern_detector.py +2 -2
  18. exonware/xwnode/common/monitoring/performance_monitor.py +6 -2
  19. exonware/xwnode/common/patterns/__init__.py +3 -5
  20. exonware/xwnode/common/patterns/advisor.py +1 -1
  21. exonware/xwnode/common/patterns/flyweight.py +6 -2
  22. exonware/xwnode/common/patterns/registry.py +203 -184
  23. exonware/xwnode/common/utils/__init__.py +25 -11
  24. exonware/xwnode/common/utils/simple.py +1 -1
  25. exonware/xwnode/config.py +3 -8
  26. exonware/xwnode/contracts.py +4 -105
  27. exonware/xwnode/defs.py +413 -159
  28. exonware/xwnode/edges/strategies/__init__.py +86 -4
  29. exonware/xwnode/edges/strategies/_base_edge.py +2 -2
  30. exonware/xwnode/edges/strategies/adj_list.py +287 -121
  31. exonware/xwnode/edges/strategies/adj_matrix.py +316 -222
  32. exonware/xwnode/edges/strategies/base.py +1 -1
  33. exonware/xwnode/edges/strategies/{edge_bidir_wrapper.py → bidir_wrapper.py} +45 -4
  34. exonware/xwnode/edges/strategies/bitemporal.py +520 -0
  35. exonware/xwnode/edges/strategies/{edge_block_adj_matrix.py → block_adj_matrix.py} +77 -6
  36. exonware/xwnode/edges/strategies/bv_graph.py +664 -0
  37. exonware/xwnode/edges/strategies/compressed_graph.py +217 -0
  38. exonware/xwnode/edges/strategies/{edge_coo.py → coo.py} +46 -4
  39. exonware/xwnode/edges/strategies/{edge_csc.py → csc.py} +45 -4
  40. exonware/xwnode/edges/strategies/{edge_csr.py → csr.py} +94 -12
  41. exonware/xwnode/edges/strategies/{edge_dynamic_adj_list.py → dynamic_adj_list.py} +46 -4
  42. exonware/xwnode/edges/strategies/edge_list.py +168 -0
  43. exonware/xwnode/edges/strategies/edge_property_store.py +2 -2
  44. exonware/xwnode/edges/strategies/euler_tour.py +560 -0
  45. exonware/xwnode/edges/strategies/{edge_flow_network.py → flow_network.py} +2 -2
  46. exonware/xwnode/edges/strategies/graphblas.py +449 -0
  47. exonware/xwnode/edges/strategies/hnsw.py +637 -0
  48. exonware/xwnode/edges/strategies/hop2_labels.py +467 -0
  49. exonware/xwnode/edges/strategies/{edge_hyperedge_set.py → hyperedge_set.py} +2 -2
  50. exonware/xwnode/edges/strategies/incidence_matrix.py +250 -0
  51. exonware/xwnode/edges/strategies/k2_tree.py +613 -0
  52. exonware/xwnode/edges/strategies/link_cut.py +626 -0
  53. exonware/xwnode/edges/strategies/multiplex.py +532 -0
  54. exonware/xwnode/edges/strategies/{edge_neural_graph.py → neural_graph.py} +2 -2
  55. exonware/xwnode/edges/strategies/{edge_octree.py → octree.py} +69 -11
  56. exonware/xwnode/edges/strategies/{edge_quadtree.py → quadtree.py} +66 -10
  57. exonware/xwnode/edges/strategies/roaring_adj.py +438 -0
  58. exonware/xwnode/edges/strategies/{edge_rtree.py → rtree.py} +43 -5
  59. exonware/xwnode/edges/strategies/{edge_temporal_edgeset.py → temporal_edgeset.py} +24 -5
  60. exonware/xwnode/edges/strategies/{edge_tree_graph_basic.py → tree_graph_basic.py} +78 -7
  61. exonware/xwnode/edges/strategies/{edge_weighted_graph.py → weighted_graph.py} +188 -10
  62. exonware/xwnode/errors.py +3 -6
  63. exonware/xwnode/facade.py +20 -20
  64. exonware/xwnode/nodes/strategies/__init__.py +29 -9
  65. exonware/xwnode/nodes/strategies/adjacency_list.py +650 -177
  66. exonware/xwnode/nodes/strategies/aho_corasick.py +358 -183
  67. exonware/xwnode/nodes/strategies/array_list.py +36 -3
  68. exonware/xwnode/nodes/strategies/art.py +581 -0
  69. exonware/xwnode/nodes/strategies/{node_avl_tree.py → avl_tree.py} +77 -6
  70. exonware/xwnode/nodes/strategies/{node_b_plus_tree.py → b_plus_tree.py} +81 -40
  71. exonware/xwnode/nodes/strategies/{node_btree.py → b_tree.py} +79 -9
  72. exonware/xwnode/nodes/strategies/base.py +469 -98
  73. exonware/xwnode/nodes/strategies/{node_bitmap.py → bitmap.py} +12 -12
  74. exonware/xwnode/nodes/strategies/{node_bitset_dynamic.py → bitset_dynamic.py} +11 -11
  75. exonware/xwnode/nodes/strategies/{node_bloom_filter.py → bloom_filter.py} +15 -2
  76. exonware/xwnode/nodes/strategies/bloomier_filter.py +519 -0
  77. exonware/xwnode/nodes/strategies/bw_tree.py +531 -0
  78. exonware/xwnode/nodes/strategies/contracts.py +1 -1
  79. exonware/xwnode/nodes/strategies/{node_count_min_sketch.py → count_min_sketch.py} +3 -2
  80. exonware/xwnode/nodes/strategies/{node_cow_tree.py → cow_tree.py} +135 -13
  81. exonware/xwnode/nodes/strategies/crdt_map.py +629 -0
  82. exonware/xwnode/nodes/strategies/{node_cuckoo_hash.py → cuckoo_hash.py} +2 -2
  83. exonware/xwnode/nodes/strategies/{node_xdata_optimized.py → data_interchange_optimized.py} +21 -4
  84. exonware/xwnode/nodes/strategies/dawg.py +876 -0
  85. exonware/xwnode/nodes/strategies/deque.py +321 -153
  86. exonware/xwnode/nodes/strategies/extendible_hash.py +93 -0
  87. exonware/xwnode/nodes/strategies/{node_fenwick_tree.py → fenwick_tree.py} +111 -19
  88. exonware/xwnode/nodes/strategies/hamt.py +403 -0
  89. exonware/xwnode/nodes/strategies/hash_map.py +354 -67
  90. exonware/xwnode/nodes/strategies/heap.py +105 -5
  91. exonware/xwnode/nodes/strategies/hopscotch_hash.py +525 -0
  92. exonware/xwnode/nodes/strategies/{node_hyperloglog.py → hyperloglog.py} +6 -5
  93. exonware/xwnode/nodes/strategies/interval_tree.py +742 -0
  94. exonware/xwnode/nodes/strategies/kd_tree.py +703 -0
  95. exonware/xwnode/nodes/strategies/learned_index.py +533 -0
  96. exonware/xwnode/nodes/strategies/linear_hash.py +93 -0
  97. exonware/xwnode/nodes/strategies/linked_list.py +316 -119
  98. exonware/xwnode/nodes/strategies/{node_lsm_tree.py → lsm_tree.py} +219 -15
  99. exonware/xwnode/nodes/strategies/masstree.py +130 -0
  100. exonware/xwnode/nodes/strategies/{node_persistent_tree.py → persistent_tree.py} +149 -9
  101. exonware/xwnode/nodes/strategies/priority_queue.py +544 -132
  102. exonware/xwnode/nodes/strategies/queue.py +249 -120
  103. exonware/xwnode/nodes/strategies/{node_red_black_tree.py → red_black_tree.py} +183 -72
  104. exonware/xwnode/nodes/strategies/{node_roaring_bitmap.py → roaring_bitmap.py} +19 -6
  105. exonware/xwnode/nodes/strategies/rope.py +717 -0
  106. exonware/xwnode/nodes/strategies/{node_segment_tree.py → segment_tree.py} +106 -106
  107. exonware/xwnode/nodes/strategies/{node_set_hash.py → set_hash.py} +30 -29
  108. exonware/xwnode/nodes/strategies/{node_skip_list.py → skip_list.py} +74 -6
  109. exonware/xwnode/nodes/strategies/sparse_matrix.py +427 -131
  110. exonware/xwnode/nodes/strategies/{node_splay_tree.py → splay_tree.py} +55 -6
  111. exonware/xwnode/nodes/strategies/stack.py +244 -112
  112. exonware/xwnode/nodes/strategies/{node_suffix_array.py → suffix_array.py} +5 -1
  113. exonware/xwnode/nodes/strategies/t_tree.py +94 -0
  114. exonware/xwnode/nodes/strategies/{node_treap.py → treap.py} +75 -6
  115. exonware/xwnode/nodes/strategies/{node_tree_graph_hybrid.py → tree_graph_hybrid.py} +46 -5
  116. exonware/xwnode/nodes/strategies/trie.py +153 -9
  117. exonware/xwnode/nodes/strategies/union_find.py +111 -5
  118. exonware/xwnode/nodes/strategies/veb_tree.py +856 -0
  119. exonware/xwnode/strategies/__init__.py +5 -51
  120. exonware/xwnode/version.py +3 -3
  121. {exonware_xwnode-0.0.1.21.dist-info → exonware_xwnode-0.0.1.23.dist-info}/METADATA +23 -3
  122. exonware_xwnode-0.0.1.23.dist-info/RECORD +130 -0
  123. exonware/xwnode/edges/strategies/edge_adj_list.py +0 -353
  124. exonware/xwnode/edges/strategies/edge_adj_matrix.py +0 -445
  125. exonware/xwnode/nodes/strategies/_base_node.py +0 -307
  126. exonware/xwnode/nodes/strategies/node_aho_corasick.py +0 -525
  127. exonware/xwnode/nodes/strategies/node_array_list.py +0 -179
  128. exonware/xwnode/nodes/strategies/node_hash_map.py +0 -273
  129. exonware/xwnode/nodes/strategies/node_heap.py +0 -196
  130. exonware/xwnode/nodes/strategies/node_linked_list.py +0 -413
  131. exonware/xwnode/nodes/strategies/node_trie.py +0 -257
  132. exonware/xwnode/nodes/strategies/node_union_find.py +0 -192
  133. exonware/xwnode/queries/executors/__init__.py +0 -47
  134. exonware/xwnode/queries/executors/advanced/__init__.py +0 -37
  135. exonware/xwnode/queries/executors/advanced/aggregate_executor.py +0 -50
  136. exonware/xwnode/queries/executors/advanced/ask_executor.py +0 -50
  137. exonware/xwnode/queries/executors/advanced/construct_executor.py +0 -50
  138. exonware/xwnode/queries/executors/advanced/describe_executor.py +0 -50
  139. exonware/xwnode/queries/executors/advanced/for_loop_executor.py +0 -50
  140. exonware/xwnode/queries/executors/advanced/foreach_executor.py +0 -50
  141. exonware/xwnode/queries/executors/advanced/join_executor.py +0 -50
  142. exonware/xwnode/queries/executors/advanced/let_executor.py +0 -50
  143. exonware/xwnode/queries/executors/advanced/mutation_executor.py +0 -50
  144. exonware/xwnode/queries/executors/advanced/options_executor.py +0 -50
  145. exonware/xwnode/queries/executors/advanced/pipe_executor.py +0 -50
  146. exonware/xwnode/queries/executors/advanced/subscribe_executor.py +0 -50
  147. exonware/xwnode/queries/executors/advanced/subscription_executor.py +0 -50
  148. exonware/xwnode/queries/executors/advanced/union_executor.py +0 -50
  149. exonware/xwnode/queries/executors/advanced/window_executor.py +0 -51
  150. exonware/xwnode/queries/executors/advanced/with_cte_executor.py +0 -50
  151. exonware/xwnode/queries/executors/aggregation/__init__.py +0 -21
  152. exonware/xwnode/queries/executors/aggregation/avg_executor.py +0 -50
  153. exonware/xwnode/queries/executors/aggregation/count_executor.py +0 -38
  154. exonware/xwnode/queries/executors/aggregation/distinct_executor.py +0 -50
  155. exonware/xwnode/queries/executors/aggregation/group_executor.py +0 -50
  156. exonware/xwnode/queries/executors/aggregation/having_executor.py +0 -50
  157. exonware/xwnode/queries/executors/aggregation/max_executor.py +0 -50
  158. exonware/xwnode/queries/executors/aggregation/min_executor.py +0 -50
  159. exonware/xwnode/queries/executors/aggregation/sum_executor.py +0 -50
  160. exonware/xwnode/queries/executors/aggregation/summarize_executor.py +0 -50
  161. exonware/xwnode/queries/executors/array/__init__.py +0 -9
  162. exonware/xwnode/queries/executors/array/indexing_executor.py +0 -51
  163. exonware/xwnode/queries/executors/array/slicing_executor.py +0 -51
  164. exonware/xwnode/queries/executors/base.py +0 -257
  165. exonware/xwnode/queries/executors/capability_checker.py +0 -204
  166. exonware/xwnode/queries/executors/contracts.py +0 -166
  167. exonware/xwnode/queries/executors/core/__init__.py +0 -17
  168. exonware/xwnode/queries/executors/core/create_executor.py +0 -96
  169. exonware/xwnode/queries/executors/core/delete_executor.py +0 -99
  170. exonware/xwnode/queries/executors/core/drop_executor.py +0 -100
  171. exonware/xwnode/queries/executors/core/insert_executor.py +0 -39
  172. exonware/xwnode/queries/executors/core/select_executor.py +0 -152
  173. exonware/xwnode/queries/executors/core/update_executor.py +0 -102
  174. exonware/xwnode/queries/executors/data/__init__.py +0 -13
  175. exonware/xwnode/queries/executors/data/alter_executor.py +0 -50
  176. exonware/xwnode/queries/executors/data/load_executor.py +0 -50
  177. exonware/xwnode/queries/executors/data/merge_executor.py +0 -50
  178. exonware/xwnode/queries/executors/data/store_executor.py +0 -50
  179. exonware/xwnode/queries/executors/defs.py +0 -93
  180. exonware/xwnode/queries/executors/engine.py +0 -221
  181. exonware/xwnode/queries/executors/errors.py +0 -68
  182. exonware/xwnode/queries/executors/filtering/__init__.py +0 -25
  183. exonware/xwnode/queries/executors/filtering/between_executor.py +0 -80
  184. exonware/xwnode/queries/executors/filtering/filter_executor.py +0 -79
  185. exonware/xwnode/queries/executors/filtering/has_executor.py +0 -70
  186. exonware/xwnode/queries/executors/filtering/in_executor.py +0 -70
  187. exonware/xwnode/queries/executors/filtering/like_executor.py +0 -76
  188. exonware/xwnode/queries/executors/filtering/optional_executor.py +0 -76
  189. exonware/xwnode/queries/executors/filtering/range_executor.py +0 -80
  190. exonware/xwnode/queries/executors/filtering/term_executor.py +0 -77
  191. exonware/xwnode/queries/executors/filtering/values_executor.py +0 -71
  192. exonware/xwnode/queries/executors/filtering/where_executor.py +0 -44
  193. exonware/xwnode/queries/executors/graph/__init__.py +0 -15
  194. exonware/xwnode/queries/executors/graph/in_traverse_executor.py +0 -51
  195. exonware/xwnode/queries/executors/graph/match_executor.py +0 -51
  196. exonware/xwnode/queries/executors/graph/out_executor.py +0 -51
  197. exonware/xwnode/queries/executors/graph/path_executor.py +0 -51
  198. exonware/xwnode/queries/executors/graph/return_executor.py +0 -51
  199. exonware/xwnode/queries/executors/ordering/__init__.py +0 -9
  200. exonware/xwnode/queries/executors/ordering/by_executor.py +0 -50
  201. exonware/xwnode/queries/executors/ordering/order_executor.py +0 -51
  202. exonware/xwnode/queries/executors/projection/__init__.py +0 -9
  203. exonware/xwnode/queries/executors/projection/extend_executor.py +0 -50
  204. exonware/xwnode/queries/executors/projection/project_executor.py +0 -50
  205. exonware/xwnode/queries/executors/registry.py +0 -173
  206. exonware/xwnode/queries/parsers/__init__.py +0 -26
  207. exonware/xwnode/queries/parsers/base.py +0 -86
  208. exonware/xwnode/queries/parsers/contracts.py +0 -46
  209. exonware/xwnode/queries/parsers/errors.py +0 -53
  210. exonware/xwnode/queries/parsers/sql_param_extractor.py +0 -318
  211. exonware/xwnode/queries/strategies/__init__.py +0 -24
  212. exonware/xwnode/queries/strategies/base.py +0 -236
  213. exonware/xwnode/queries/strategies/cql.py +0 -201
  214. exonware/xwnode/queries/strategies/cypher.py +0 -181
  215. exonware/xwnode/queries/strategies/datalog.py +0 -70
  216. exonware/xwnode/queries/strategies/elastic_dsl.py +0 -70
  217. exonware/xwnode/queries/strategies/eql.py +0 -70
  218. exonware/xwnode/queries/strategies/flux.py +0 -70
  219. exonware/xwnode/queries/strategies/gql.py +0 -70
  220. exonware/xwnode/queries/strategies/graphql.py +0 -240
  221. exonware/xwnode/queries/strategies/gremlin.py +0 -181
  222. exonware/xwnode/queries/strategies/hiveql.py +0 -214
  223. exonware/xwnode/queries/strategies/hql.py +0 -70
  224. exonware/xwnode/queries/strategies/jmespath.py +0 -219
  225. exonware/xwnode/queries/strategies/jq.py +0 -66
  226. exonware/xwnode/queries/strategies/json_query.py +0 -66
  227. exonware/xwnode/queries/strategies/jsoniq.py +0 -248
  228. exonware/xwnode/queries/strategies/kql.py +0 -70
  229. exonware/xwnode/queries/strategies/linq.py +0 -238
  230. exonware/xwnode/queries/strategies/logql.py +0 -70
  231. exonware/xwnode/queries/strategies/mql.py +0 -68
  232. exonware/xwnode/queries/strategies/n1ql.py +0 -210
  233. exonware/xwnode/queries/strategies/partiql.py +0 -70
  234. exonware/xwnode/queries/strategies/pig.py +0 -215
  235. exonware/xwnode/queries/strategies/promql.py +0 -70
  236. exonware/xwnode/queries/strategies/sparql.py +0 -220
  237. exonware/xwnode/queries/strategies/sql.py +0 -275
  238. exonware/xwnode/queries/strategies/xml_query.py +0 -66
  239. exonware/xwnode/queries/strategies/xpath.py +0 -223
  240. exonware/xwnode/queries/strategies/xquery.py +0 -258
  241. exonware/xwnode/queries/strategies/xwnode_executor.py +0 -332
  242. exonware/xwnode/queries/strategies/xwquery.py +0 -456
  243. exonware_xwnode-0.0.1.21.dist-info/RECORD +0 -214
  244. /exonware/xwnode/nodes/strategies/{node_ordered_map.py → ordered_map.py} +0 -0
  245. /exonware/xwnode/nodes/strategies/{node_ordered_map_balanced.py → ordered_map_balanced.py} +0 -0
  246. /exonware/xwnode/nodes/strategies/{node_patricia.py → patricia.py} +0 -0
  247. /exonware/xwnode/nodes/strategies/{node_radix_trie.py → radix_trie.py} +0 -0
  248. /exonware/xwnode/nodes/strategies/{node_set_tree.py → set_tree.py} +0 -0
  249. {exonware_xwnode-0.0.1.21.dist-info → exonware_xwnode-0.0.1.23.dist-info}/WHEEL +0 -0
  250. {exonware_xwnode-0.0.1.21.dist-info → exonware_xwnode-0.0.1.23.dist-info}/licenses/LICENSE +0 -0
@@ -1,413 +0,0 @@
1
- """
2
- Linked List Node Strategy Implementation
3
-
4
- This module implements the LINKED_LIST strategy for efficient
5
- insertions and deletions with sequential access patterns.
6
- """
7
-
8
- from typing import Any, Iterator, List, Dict, Optional
9
- from ._base_node import aNodeStrategy
10
- from ...defs import NodeMode, NodeTrait
11
-
12
-
13
- class ListNode:
14
- """Node in the doubly linked list."""
15
-
16
- def __init__(self, key: str, value: Any):
17
- self.key = key
18
- self.value = value
19
- self.prev: Optional['ListNode'] = None
20
- self.next: Optional['ListNode'] = None
21
-
22
-
23
- class xLinkedListStrategy(aNodeStrategy):
24
- """
25
- Linked List node strategy for efficient insertions and deletions.
26
-
27
- Provides O(1) insertions/deletions at known positions with
28
- sequential access patterns optimized for iteration.
29
- """
30
-
31
- # Strategy type classification
32
- STRATEGY_TYPE = NodeType.LINEAR
33
-
34
-
35
- def __init__(self, traits: NodeTrait = NodeTrait.NONE, **options):
36
- """Initialize the Linked List strategy."""
37
- super().__init__(NodeMode.LINKED_LIST, traits, **options)
38
-
39
- self.doubly_linked = options.get('doubly_linked', True)
40
-
41
- # Doubly linked list with sentinel nodes
42
- self._head = ListNode("HEAD", None)
43
- self._tail = ListNode("TAIL", None)
44
- self._head.next = self._tail
45
- self._tail.prev = self._head
46
-
47
- # Quick access mapping
48
- self._key_to_node: Dict[str, ListNode] = {}
49
- self._size = 0
50
-
51
- def get_supported_traits(self) -> NodeTrait:
52
- """Get the traits supported by the linked list strategy."""
53
- return (NodeTrait.ORDERED | NodeTrait.INDEXED)
54
-
55
- def _insert_after(self, prev_node: ListNode, key: str, value: Any) -> ListNode:
56
- """Insert new node after given node."""
57
- new_node = ListNode(key, value)
58
- next_node = prev_node.next
59
-
60
- # Link new node
61
- prev_node.next = new_node
62
- new_node.prev = prev_node
63
- new_node.next = next_node
64
- next_node.prev = new_node
65
-
66
- return new_node
67
-
68
- def _remove_node(self, node: ListNode) -> None:
69
- """Remove node from list."""
70
- prev_node = node.prev
71
- next_node = node.next
72
-
73
- prev_node.next = next_node
74
- next_node.prev = prev_node
75
-
76
- # Clear references
77
- node.prev = None
78
- node.next = None
79
-
80
- def _get_node_at_index(self, index: int) -> Optional[ListNode]:
81
- """Get node at given index."""
82
- if index < 0 or index >= self._size:
83
- return None
84
-
85
- # Optimize direction based on index
86
- if index < self._size // 2:
87
- # Search from head
88
- current = self._head.next
89
- for _ in range(index):
90
- current = current.next
91
- else:
92
- # Search from tail
93
- current = self._tail.prev
94
- for _ in range(self._size - index - 1):
95
- current = current.prev
96
-
97
- return current if current != self._head and current != self._tail else None
98
-
99
- # ============================================================================
100
- # CORE OPERATIONS (Key-based interface for compatibility)
101
- # ============================================================================
102
-
103
- def put(self, key: Any, value: Any = None) -> None:
104
- """Add/update key-value pair."""
105
- key_str = str(key)
106
-
107
- if key_str in self._key_to_node:
108
- # Update existing
109
- self._key_to_node[key_str].value = value
110
- else:
111
- # Insert at end
112
- new_node = self._insert_after(self._tail.prev, key_str, value)
113
- self._key_to_node[key_str] = new_node
114
- self._size += 1
115
-
116
- def get(self, key: Any, default: Any = None) -> Any:
117
- """Get value by key."""
118
- key_str = str(key)
119
-
120
- if key_str == "list_info":
121
- return {
122
- 'size': self._size,
123
- 'doubly_linked': self.doubly_linked,
124
- 'first': self.first(),
125
- 'last': self.last()
126
- }
127
- elif key_str.isdigit():
128
- # Numeric access by index
129
- index = int(key_str)
130
- node = self._get_node_at_index(index)
131
- return node.value if node else default
132
-
133
- node = self._key_to_node.get(key_str)
134
- return node.value if node else default
135
-
136
- def has(self, key: Any) -> bool:
137
- """Check if key exists."""
138
- key_str = str(key)
139
-
140
- if key_str == "list_info":
141
- return True
142
- elif key_str.isdigit():
143
- index = int(key_str)
144
- return 0 <= index < self._size
145
-
146
- return key_str in self._key_to_node
147
-
148
- def remove(self, key: Any) -> bool:
149
- """Remove key from list."""
150
- key_str = str(key)
151
-
152
- if key_str.isdigit():
153
- # Remove by index
154
- index = int(key_str)
155
- node = self._get_node_at_index(index)
156
- if node:
157
- self._remove_node(node)
158
- del self._key_to_node[node.key]
159
- self._size -= 1
160
- return True
161
- return False
162
-
163
- node = self._key_to_node.get(key_str)
164
- if node:
165
- self._remove_node(node)
166
- del self._key_to_node[key_str]
167
- self._size -= 1
168
- return True
169
-
170
- return False
171
-
172
- def delete(self, key: Any) -> bool:
173
- """Remove key from list (alias for remove)."""
174
- return self.remove(key)
175
-
176
- def clear(self) -> None:
177
- """Clear all data."""
178
- self._head.next = self._tail
179
- self._tail.prev = self._head
180
- self._key_to_node.clear()
181
- self._size = 0
182
-
183
- def keys(self) -> Iterator[str]:
184
- """Get all keys in insertion order."""
185
- current = self._head.next
186
- while current != self._tail:
187
- yield current.key
188
- current = current.next
189
-
190
- def values(self) -> Iterator[Any]:
191
- """Get all values in insertion order."""
192
- current = self._head.next
193
- while current != self._tail:
194
- yield current.value
195
- current = current.next
196
-
197
- def items(self) -> Iterator[tuple[str, Any]]:
198
- """Get all key-value pairs in insertion order."""
199
- current = self._head.next
200
- while current != self._tail:
201
- yield (current.key, current.value)
202
- current = current.next
203
-
204
- def __len__(self) -> int:
205
- """Get number of elements."""
206
- return self._size
207
-
208
- def to_native(self) -> List[Any]:
209
- """Convert to native Python list."""
210
- return list(self.values())
211
-
212
- @property
213
- def is_list(self) -> bool:
214
- """This is a list strategy."""
215
- return True
216
-
217
- @property
218
- def is_dict(self) -> bool:
219
- """This also behaves like a dict."""
220
- return True
221
-
222
- # ============================================================================
223
- # LINKED LIST SPECIFIC OPERATIONS
224
- # ============================================================================
225
-
226
- def append(self, value: Any) -> str:
227
- """Append value to end of list."""
228
- key = str(self._size)
229
- self.put(key, value)
230
- return key
231
-
232
- def prepend(self, value: Any) -> str:
233
- """Prepend value to beginning of list."""
234
- key = f"prepend_{self._size}"
235
- new_node = self._insert_after(self._head, key, value)
236
- self._key_to_node[key] = new_node
237
- self._size += 1
238
- return key
239
-
240
- def insert_at(self, index: int, value: Any) -> str:
241
- """Insert value at specific index."""
242
- if index < 0 or index > self._size:
243
- raise IndexError(f"Index {index} out of range")
244
-
245
- if index == 0:
246
- return self.prepend(value)
247
- elif index == self._size:
248
- return self.append(value)
249
-
250
- # Find insertion point
251
- prev_node = self._get_node_at_index(index - 1)
252
- if not prev_node:
253
- raise IndexError(f"Cannot find insertion point at index {index}")
254
-
255
- key = f"insert_{index}_{self._size}"
256
- new_node = self._insert_after(prev_node, key, value)
257
- self._key_to_node[key] = new_node
258
- self._size += 1
259
- return key
260
-
261
- def pop(self) -> Any:
262
- """Remove and return last element."""
263
- if self._size == 0:
264
- raise IndexError("pop from empty list")
265
-
266
- last_node = self._tail.prev
267
- value = last_node.value
268
- self._remove_node(last_node)
269
- del self._key_to_node[last_node.key]
270
- self._size -= 1
271
- return value
272
-
273
- def popleft(self) -> Any:
274
- """Remove and return first element."""
275
- if self._size == 0:
276
- raise IndexError("popleft from empty list")
277
-
278
- first_node = self._head.next
279
- value = first_node.value
280
- self._remove_node(first_node)
281
- del self._key_to_node[first_node.key]
282
- self._size -= 1
283
- return value
284
-
285
- def first(self) -> Any:
286
- """Get first element without removing."""
287
- if self._size == 0:
288
- return None
289
- return self._head.next.value
290
-
291
- def last(self) -> Any:
292
- """Get last element without removing."""
293
- if self._size == 0:
294
- return None
295
- return self._tail.prev.value
296
-
297
- def reverse(self) -> None:
298
- """Reverse the list in place."""
299
- if self._size <= 1:
300
- return
301
-
302
- # Swap all next/prev pointers
303
- current = self._head
304
- while current:
305
- current.next, current.prev = current.prev, current.next
306
- current = current.prev # Note: we swapped, so prev is now next
307
-
308
- # Swap head and tail
309
- self._head, self._tail = self._tail, self._head
310
-
311
- def get_at_index(self, index: int) -> Any:
312
- """Get value at specific index."""
313
- node = self._get_node_at_index(index)
314
- if not node:
315
- raise IndexError(f"Index {index} out of range")
316
- return node.value
317
-
318
- def set_at_index(self, index: int, value: Any) -> None:
319
- """Set value at specific index."""
320
- node = self._get_node_at_index(index)
321
- if not node:
322
- raise IndexError(f"Index {index} out of range")
323
- node.value = value
324
-
325
- def find_index(self, value: Any) -> int:
326
- """Find index of first occurrence of value."""
327
- current = self._head.next
328
- index = 0
329
-
330
- while current != self._tail:
331
- if current.value == value:
332
- return index
333
- current = current.next
334
- index += 1
335
-
336
- return -1
337
-
338
- def remove_value(self, value: Any) -> bool:
339
- """Remove first occurrence of value."""
340
- current = self._head.next
341
-
342
- while current != self._tail:
343
- if current.value == value:
344
- self._remove_node(current)
345
- del self._key_to_node[current.key]
346
- self._size -= 1
347
- return True
348
- current = current.next
349
-
350
- return False
351
-
352
- def count_value(self, value: Any) -> int:
353
- """Count occurrences of value."""
354
- count = 0
355
- current = self._head.next
356
-
357
- while current != self._tail:
358
- if current.value == value:
359
- count += 1
360
- current = current.next
361
-
362
- return count
363
-
364
- def to_array(self) -> List[Any]:
365
- """Convert to array representation."""
366
- return list(self.values())
367
-
368
- def get_statistics(self) -> Dict[str, Any]:
369
- """Get comprehensive linked list statistics."""
370
- return {
371
- 'size': self._size,
372
- 'doubly_linked': self.doubly_linked,
373
- 'first_value': self.first(),
374
- 'last_value': self.last(),
375
- 'memory_overhead': self._size * (64 if self.doubly_linked else 32), # Pointer overhead
376
- 'access_pattern': 'sequential'
377
- }
378
-
379
- # ============================================================================
380
- # PERFORMANCE CHARACTERISTICS
381
- # ============================================================================
382
-
383
- @property
384
- def backend_info(self) -> Dict[str, Any]:
385
- """Get backend implementation info."""
386
- return {
387
- 'strategy': 'LINKED_LIST',
388
- 'backend': f'{"Doubly" if self.doubly_linked else "Singly"} linked list with sentinel nodes',
389
- 'doubly_linked': self.doubly_linked,
390
- 'complexity': {
391
- 'append': 'O(1)',
392
- 'prepend': 'O(1)',
393
- 'insert_at': 'O(n)',
394
- 'remove_at': 'O(n)',
395
- 'access_by_index': 'O(n)',
396
- 'search': 'O(n)',
397
- 'space': 'O(n)'
398
- }
399
- }
400
-
401
- @property
402
- def metrics(self) -> Dict[str, Any]:
403
- """Get performance metrics."""
404
- stats = self.get_statistics()
405
-
406
- return {
407
- 'size': stats['size'],
408
- 'first_value': str(stats['first_value']) if stats['first_value'] is not None else 'None',
409
- 'last_value': str(stats['last_value']) if stats['last_value'] is not None else 'None',
410
- 'doubly_linked': stats['doubly_linked'],
411
- 'memory_overhead': f"{stats['memory_overhead']} bytes",
412
- 'access_pattern': stats['access_pattern']
413
- }
@@ -1,257 +0,0 @@
1
- """
2
- Trie Node Strategy Implementation
3
-
4
- This module implements the TRIE strategy for efficient string prefix operations.
5
- """
6
-
7
- from typing import Any, Iterator, Dict, List, Optional
8
- from .base import ANodeTreeStrategy
9
- from .contracts import NodeType
10
- from ...defs import NodeMode, NodeTrait
11
- from ..utils import (
12
- TrieNode,
13
- safe_to_native_conversion,
14
- create_basic_metrics,
15
- create_basic_backend_info,
16
- create_size_tracker,
17
- create_access_tracker,
18
- update_size_tracker,
19
- record_access,
20
- get_access_metrics
21
- )
22
-
23
-
24
- class TrieStrategy(ANodeTreeStrategy):
25
- """
26
- Trie node strategy for efficient string prefix operations.
27
-
28
- Optimized for prefix matching, autocomplet
29
-
30
- # Strategy type classification
31
- STRATEGY_TYPE = NodeType.TREE
32
- e, and string searching.
33
- """
34
-
35
- def __init__(self, traits: NodeTrait = NodeTrait.NONE, **options):
36
- """Initialize the trie strategy."""
37
- super().__init__(NodeMode.TRIE, traits, **options)
38
- self._root = TrieNode()
39
- self._size_tracker = create_size_tracker()
40
- self._access_tracker = create_access_tracker()
41
-
42
- def get_supported_traits(self) -> NodeTrait:
43
- """Get the traits supported by the trie strategy."""
44
- return (NodeTrait.ORDERED | NodeTrait.HIERARCHICAL | NodeTrait.INDEXED)
45
-
46
- # ============================================================================
47
- # CORE OPERATIONS
48
- # ============================================================================
49
-
50
- def put(self, key: Any, value: Any = None) -> None:
51
- """Store a key-value pair (key should be string-like)."""
52
- word = str(key)
53
- node = self._root
54
-
55
- # Traverse/create path
56
- for char in word:
57
- if char not in node.children:
58
- node.children[char] = TrieNode()
59
- node = node.children[char]
60
-
61
- # Mark end and store value
62
- if not node.is_end_word:
63
- update_size_tracker(self._size_tracker, 1)
64
- node.is_end_word = True
65
- node.value = value
66
- record_access(self._access_tracker, 'put_count')
67
-
68
- def get(self, key: Any, default: Any = None) -> Any:
69
- """Retrieve a value by key."""
70
- word = str(key)
71
- node = self._find_node(word)
72
- record_access(self._access_tracker, 'get_count')
73
- if node and node.is_end_word:
74
- return node.value
75
- return default
76
-
77
- def has(self, key: Any) -> bool:
78
- """Check if key exists."""
79
- word = str(key)
80
- node = self._find_node(word)
81
- return node is not None and node.is_end_word
82
-
83
- def remove(self, key: Any) -> bool:
84
- """Remove a key-value pair."""
85
- word = str(key)
86
- result = self._remove_recursive(self._root, word, 0)
87
- if result:
88
- update_size_tracker(self._size_tracker, -1)
89
- record_access(self._access_tracker, 'delete_count')
90
- return result
91
-
92
- def delete(self, key: Any) -> bool:
93
- """Remove a key-value pair (alias for remove)."""
94
- return self.remove(key)
95
-
96
- def clear(self) -> None:
97
- """Clear all data."""
98
- self._root = TrieNode()
99
- self._size_tracker['size'] = 0
100
-
101
- def keys(self) -> Iterator[str]:
102
- """Get all keys."""
103
- return iter(self._collect_words())
104
-
105
- def values(self) -> Iterator[Any]:
106
- """Get all values."""
107
- words = self._collect_words()
108
- for word in words:
109
- node = self._find_node(word)
110
- if node:
111
- yield node.value
112
-
113
- def items(self) -> Iterator[tuple[str, Any]]:
114
- """Get all key-value pairs."""
115
- words = self._collect_words()
116
- for word in words:
117
- node = self._find_node(word)
118
- if node:
119
- yield (word, node.value)
120
-
121
- def __len__(self) -> int:
122
- """Get the number of items."""
123
- return self._size_tracker['size']
124
-
125
- def to_native(self) -> Dict[str, Any]:
126
- """Convert to native Python dictionary."""
127
- result = {}
128
- for word in self._collect_words():
129
- node = self._find_node(word)
130
- if node:
131
- result[word] = safe_to_native_conversion(node.value)
132
- return result
133
-
134
- @property
135
- def is_list(self) -> bool:
136
- """This is not a list strategy."""
137
- return False
138
-
139
- @property
140
- def is_dict(self) -> bool:
141
- """This behaves like a dict with string keys."""
142
- return True
143
-
144
- # ============================================================================
145
- # TRIE-SPECIFIC OPERATIONS
146
- # ============================================================================
147
-
148
- def starts_with(self, prefix: str) -> List[str]:
149
- """Get all keys that start with the given prefix."""
150
- node = self._find_node(prefix)
151
- if not node:
152
- return []
153
-
154
- words = []
155
- self._collect_words_from_node(node, prefix, words)
156
- return words
157
-
158
- def longest_common_prefix(self) -> str:
159
- """Find the longest common prefix of all stored keys."""
160
- if not self._root.children:
161
- return ""
162
-
163
- prefix = ""
164
- node = self._root
165
-
166
- while len(node.children) == 1 and not node.is_end_word:
167
- char = next(iter(node.children.keys()))
168
- prefix += char
169
- node = node.children[char]
170
-
171
- return prefix
172
-
173
- def get_all_prefixes(self, word: str) -> List[str]:
174
- """Get all prefixes of the given word that exist in the trie."""
175
- prefixes = []
176
- node = self._root
177
-
178
- for i, char in enumerate(word):
179
- if char not in node.children:
180
- break
181
- node = node.children[char]
182
- if node.is_end_word:
183
- prefixes.append(word[:i+1])
184
-
185
- return prefixes
186
-
187
- # ============================================================================
188
- # HELPER METHODS
189
- # ============================================================================
190
-
191
- def _find_node(self, word: str) -> Optional[TrieNode]:
192
- """Find the node corresponding to the given word."""
193
- node = self._root
194
- for char in word:
195
- if char not in node.children:
196
- return None
197
- node = node.children[char]
198
- return node
199
-
200
- def _remove_recursive(self, node: TrieNode, word: str, index: int) -> bool:
201
- """Recursively remove a word from the trie."""
202
- if index == len(word):
203
- if node.is_end_word:
204
- node.is_end_word = False
205
- node.value = None
206
- return True
207
- return False
208
-
209
- char = word[index]
210
- if char not in node.children:
211
- return False
212
-
213
- child = node.children[char]
214
- should_delete_child = self._remove_recursive(child, word, index + 1)
215
-
216
- if should_delete_child and not child.is_end_word and not child.children:
217
- del node.children[char]
218
-
219
- return should_delete_child
220
-
221
- def _collect_words(self) -> List[str]:
222
- """Collect all words stored in the trie."""
223
- words = []
224
- self._collect_words_from_node(self._root, "", words)
225
- return words
226
-
227
- def _collect_words_from_node(self, node: TrieNode, prefix: str, words: List[str]) -> None:
228
- """Collect all words from a given node."""
229
- if node.is_end_word:
230
- words.append(prefix)
231
-
232
- for char, child in node.children.items():
233
- self._collect_words_from_node(child, prefix + char, words)
234
-
235
- # ============================================================================
236
- # PERFORMANCE CHARACTERISTICS
237
- # ============================================================================
238
-
239
- def backend_info(self) -> Dict[str, Any]:
240
- """Get backend implementation info."""
241
- return create_basic_backend_info(
242
- 'TRIE',
243
- 'TrieNode tree',
244
- complexity={
245
- 'get': 'O(m) where m is key length',
246
- 'put': 'O(m) where m is key length',
247
- 'has': 'O(m) where m is key length',
248
- 'starts_with': 'O(m + k) where m is prefix length, k is number of matches'
249
- }
250
- )
251
-
252
- def metrics(self) -> Dict[str, Any]:
253
- """Get performance metrics."""
254
- base_metrics = create_basic_metrics('TRIE', self._size_tracker['size'])
255
- access_metrics = get_access_metrics(self._access_tracker)
256
- base_metrics.update(access_metrics)
257
- return base_metrics