exonware-xwnode 0.0.1.22__py3-none-any.whl → 0.0.1.24__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 (249) hide show
  1. exonware/__init__.py +1 -1
  2. exonware/xwnode/__init__.py +18 -5
  3. exonware/xwnode/add_strategy_types.py +165 -0
  4. exonware/xwnode/common/__init__.py +1 -1
  5. exonware/xwnode/common/graph/__init__.py +30 -0
  6. exonware/xwnode/common/graph/caching.py +131 -0
  7. exonware/xwnode/common/graph/contracts.py +100 -0
  8. exonware/xwnode/common/graph/errors.py +44 -0
  9. exonware/xwnode/common/graph/indexing.py +260 -0
  10. exonware/xwnode/common/graph/manager.py +568 -0
  11. exonware/xwnode/common/management/__init__.py +3 -5
  12. exonware/xwnode/common/management/manager.py +2 -2
  13. exonware/xwnode/common/management/migration.py +3 -3
  14. exonware/xwnode/common/monitoring/__init__.py +3 -5
  15. exonware/xwnode/common/monitoring/metrics.py +6 -2
  16. exonware/xwnode/common/monitoring/pattern_detector.py +1 -1
  17. exonware/xwnode/common/monitoring/performance_monitor.py +5 -1
  18. exonware/xwnode/common/patterns/__init__.py +3 -5
  19. exonware/xwnode/common/patterns/flyweight.py +5 -1
  20. exonware/xwnode/common/patterns/registry.py +202 -183
  21. exonware/xwnode/common/utils/__init__.py +25 -11
  22. exonware/xwnode/common/utils/simple.py +1 -1
  23. exonware/xwnode/config.py +3 -8
  24. exonware/xwnode/contracts.py +4 -105
  25. exonware/xwnode/defs.py +413 -159
  26. exonware/xwnode/edges/strategies/__init__.py +86 -4
  27. exonware/xwnode/edges/strategies/_base_edge.py +2 -2
  28. exonware/xwnode/edges/strategies/adj_list.py +287 -121
  29. exonware/xwnode/edges/strategies/adj_matrix.py +316 -222
  30. exonware/xwnode/edges/strategies/base.py +1 -1
  31. exonware/xwnode/edges/strategies/{edge_bidir_wrapper.py → bidir_wrapper.py} +45 -4
  32. exonware/xwnode/edges/strategies/bitemporal.py +520 -0
  33. exonware/xwnode/edges/strategies/{edge_block_adj_matrix.py → block_adj_matrix.py} +77 -6
  34. exonware/xwnode/edges/strategies/bv_graph.py +664 -0
  35. exonware/xwnode/edges/strategies/compressed_graph.py +217 -0
  36. exonware/xwnode/edges/strategies/{edge_coo.py → coo.py} +46 -4
  37. exonware/xwnode/edges/strategies/{edge_csc.py → csc.py} +45 -4
  38. exonware/xwnode/edges/strategies/{edge_csr.py → csr.py} +94 -12
  39. exonware/xwnode/edges/strategies/{edge_dynamic_adj_list.py → dynamic_adj_list.py} +46 -4
  40. exonware/xwnode/edges/strategies/edge_list.py +168 -0
  41. exonware/xwnode/edges/strategies/edge_property_store.py +2 -2
  42. exonware/xwnode/edges/strategies/euler_tour.py +560 -0
  43. exonware/xwnode/edges/strategies/{edge_flow_network.py → flow_network.py} +2 -2
  44. exonware/xwnode/edges/strategies/graphblas.py +449 -0
  45. exonware/xwnode/edges/strategies/hnsw.py +637 -0
  46. exonware/xwnode/edges/strategies/hop2_labels.py +467 -0
  47. exonware/xwnode/edges/strategies/{edge_hyperedge_set.py → hyperedge_set.py} +2 -2
  48. exonware/xwnode/edges/strategies/incidence_matrix.py +250 -0
  49. exonware/xwnode/edges/strategies/k2_tree.py +613 -0
  50. exonware/xwnode/edges/strategies/link_cut.py +626 -0
  51. exonware/xwnode/edges/strategies/multiplex.py +532 -0
  52. exonware/xwnode/edges/strategies/{edge_neural_graph.py → neural_graph.py} +2 -2
  53. exonware/xwnode/edges/strategies/{edge_octree.py → octree.py} +69 -11
  54. exonware/xwnode/edges/strategies/{edge_quadtree.py → quadtree.py} +66 -10
  55. exonware/xwnode/edges/strategies/roaring_adj.py +438 -0
  56. exonware/xwnode/edges/strategies/{edge_rtree.py → rtree.py} +43 -5
  57. exonware/xwnode/edges/strategies/{edge_temporal_edgeset.py → temporal_edgeset.py} +24 -5
  58. exonware/xwnode/edges/strategies/{edge_tree_graph_basic.py → tree_graph_basic.py} +78 -7
  59. exonware/xwnode/edges/strategies/{edge_weighted_graph.py → weighted_graph.py} +188 -10
  60. exonware/xwnode/errors.py +3 -6
  61. exonware/xwnode/facade.py +20 -20
  62. exonware/xwnode/nodes/strategies/__init__.py +29 -9
  63. exonware/xwnode/nodes/strategies/adjacency_list.py +650 -177
  64. exonware/xwnode/nodes/strategies/aho_corasick.py +358 -183
  65. exonware/xwnode/nodes/strategies/array_list.py +36 -3
  66. exonware/xwnode/nodes/strategies/art.py +581 -0
  67. exonware/xwnode/nodes/strategies/{node_avl_tree.py → avl_tree.py} +77 -6
  68. exonware/xwnode/nodes/strategies/{node_b_plus_tree.py → b_plus_tree.py} +81 -40
  69. exonware/xwnode/nodes/strategies/{node_btree.py → b_tree.py} +79 -9
  70. exonware/xwnode/nodes/strategies/base.py +469 -98
  71. exonware/xwnode/nodes/strategies/{node_bitmap.py → bitmap.py} +12 -12
  72. exonware/xwnode/nodes/strategies/{node_bitset_dynamic.py → bitset_dynamic.py} +11 -11
  73. exonware/xwnode/nodes/strategies/{node_bloom_filter.py → bloom_filter.py} +15 -2
  74. exonware/xwnode/nodes/strategies/bloomier_filter.py +519 -0
  75. exonware/xwnode/nodes/strategies/bw_tree.py +531 -0
  76. exonware/xwnode/nodes/strategies/contracts.py +1 -1
  77. exonware/xwnode/nodes/strategies/{node_count_min_sketch.py → count_min_sketch.py} +3 -2
  78. exonware/xwnode/nodes/strategies/{node_cow_tree.py → cow_tree.py} +135 -13
  79. exonware/xwnode/nodes/strategies/crdt_map.py +629 -0
  80. exonware/xwnode/nodes/strategies/{node_cuckoo_hash.py → cuckoo_hash.py} +2 -2
  81. exonware/xwnode/nodes/strategies/{node_xdata_optimized.py → data_interchange_optimized.py} +21 -4
  82. exonware/xwnode/nodes/strategies/dawg.py +876 -0
  83. exonware/xwnode/nodes/strategies/deque.py +321 -153
  84. exonware/xwnode/nodes/strategies/extendible_hash.py +93 -0
  85. exonware/xwnode/nodes/strategies/{node_fenwick_tree.py → fenwick_tree.py} +111 -19
  86. exonware/xwnode/nodes/strategies/hamt.py +403 -0
  87. exonware/xwnode/nodes/strategies/hash_map.py +354 -67
  88. exonware/xwnode/nodes/strategies/heap.py +105 -5
  89. exonware/xwnode/nodes/strategies/hopscotch_hash.py +525 -0
  90. exonware/xwnode/nodes/strategies/{node_hyperloglog.py → hyperloglog.py} +6 -5
  91. exonware/xwnode/nodes/strategies/interval_tree.py +742 -0
  92. exonware/xwnode/nodes/strategies/kd_tree.py +703 -0
  93. exonware/xwnode/nodes/strategies/learned_index.py +533 -0
  94. exonware/xwnode/nodes/strategies/linear_hash.py +93 -0
  95. exonware/xwnode/nodes/strategies/linked_list.py +316 -119
  96. exonware/xwnode/nodes/strategies/{node_lsm_tree.py → lsm_tree.py} +219 -15
  97. exonware/xwnode/nodes/strategies/masstree.py +130 -0
  98. exonware/xwnode/nodes/strategies/{node_persistent_tree.py → persistent_tree.py} +149 -9
  99. exonware/xwnode/nodes/strategies/priority_queue.py +544 -132
  100. exonware/xwnode/nodes/strategies/queue.py +249 -120
  101. exonware/xwnode/nodes/strategies/{node_red_black_tree.py → red_black_tree.py} +183 -72
  102. exonware/xwnode/nodes/strategies/{node_roaring_bitmap.py → roaring_bitmap.py} +19 -6
  103. exonware/xwnode/nodes/strategies/rope.py +717 -0
  104. exonware/xwnode/nodes/strategies/{node_segment_tree.py → segment_tree.py} +106 -106
  105. exonware/xwnode/nodes/strategies/{node_set_hash.py → set_hash.py} +30 -29
  106. exonware/xwnode/nodes/strategies/{node_skip_list.py → skip_list.py} +74 -6
  107. exonware/xwnode/nodes/strategies/sparse_matrix.py +427 -131
  108. exonware/xwnode/nodes/strategies/{node_splay_tree.py → splay_tree.py} +55 -6
  109. exonware/xwnode/nodes/strategies/stack.py +244 -112
  110. exonware/xwnode/nodes/strategies/{node_suffix_array.py → suffix_array.py} +5 -1
  111. exonware/xwnode/nodes/strategies/t_tree.py +94 -0
  112. exonware/xwnode/nodes/strategies/{node_treap.py → treap.py} +75 -6
  113. exonware/xwnode/nodes/strategies/{node_tree_graph_hybrid.py → tree_graph_hybrid.py} +46 -5
  114. exonware/xwnode/nodes/strategies/trie.py +153 -9
  115. exonware/xwnode/nodes/strategies/union_find.py +111 -5
  116. exonware/xwnode/nodes/strategies/veb_tree.py +856 -0
  117. exonware/xwnode/strategies/__init__.py +5 -51
  118. exonware/xwnode/version.py +3 -3
  119. exonware_xwnode-0.0.1.24.dist-info/METADATA +900 -0
  120. exonware_xwnode-0.0.1.24.dist-info/RECORD +130 -0
  121. exonware/xwnode/edges/strategies/edge_adj_list.py +0 -353
  122. exonware/xwnode/edges/strategies/edge_adj_matrix.py +0 -445
  123. exonware/xwnode/nodes/strategies/_base_node.py +0 -307
  124. exonware/xwnode/nodes/strategies/node_aho_corasick.py +0 -525
  125. exonware/xwnode/nodes/strategies/node_array_list.py +0 -179
  126. exonware/xwnode/nodes/strategies/node_hash_map.py +0 -273
  127. exonware/xwnode/nodes/strategies/node_heap.py +0 -196
  128. exonware/xwnode/nodes/strategies/node_linked_list.py +0 -413
  129. exonware/xwnode/nodes/strategies/node_trie.py +0 -257
  130. exonware/xwnode/nodes/strategies/node_union_find.py +0 -192
  131. exonware/xwnode/queries/executors/__init__.py +0 -47
  132. exonware/xwnode/queries/executors/advanced/__init__.py +0 -37
  133. exonware/xwnode/queries/executors/advanced/aggregate_executor.py +0 -50
  134. exonware/xwnode/queries/executors/advanced/ask_executor.py +0 -50
  135. exonware/xwnode/queries/executors/advanced/construct_executor.py +0 -50
  136. exonware/xwnode/queries/executors/advanced/describe_executor.py +0 -50
  137. exonware/xwnode/queries/executors/advanced/for_loop_executor.py +0 -50
  138. exonware/xwnode/queries/executors/advanced/foreach_executor.py +0 -50
  139. exonware/xwnode/queries/executors/advanced/join_executor.py +0 -50
  140. exonware/xwnode/queries/executors/advanced/let_executor.py +0 -50
  141. exonware/xwnode/queries/executors/advanced/mutation_executor.py +0 -50
  142. exonware/xwnode/queries/executors/advanced/options_executor.py +0 -50
  143. exonware/xwnode/queries/executors/advanced/pipe_executor.py +0 -50
  144. exonware/xwnode/queries/executors/advanced/subscribe_executor.py +0 -50
  145. exonware/xwnode/queries/executors/advanced/subscription_executor.py +0 -50
  146. exonware/xwnode/queries/executors/advanced/union_executor.py +0 -50
  147. exonware/xwnode/queries/executors/advanced/window_executor.py +0 -51
  148. exonware/xwnode/queries/executors/advanced/with_cte_executor.py +0 -50
  149. exonware/xwnode/queries/executors/aggregation/__init__.py +0 -21
  150. exonware/xwnode/queries/executors/aggregation/avg_executor.py +0 -50
  151. exonware/xwnode/queries/executors/aggregation/count_executor.py +0 -38
  152. exonware/xwnode/queries/executors/aggregation/distinct_executor.py +0 -50
  153. exonware/xwnode/queries/executors/aggregation/group_executor.py +0 -50
  154. exonware/xwnode/queries/executors/aggregation/having_executor.py +0 -50
  155. exonware/xwnode/queries/executors/aggregation/max_executor.py +0 -50
  156. exonware/xwnode/queries/executors/aggregation/min_executor.py +0 -50
  157. exonware/xwnode/queries/executors/aggregation/sum_executor.py +0 -50
  158. exonware/xwnode/queries/executors/aggregation/summarize_executor.py +0 -50
  159. exonware/xwnode/queries/executors/array/__init__.py +0 -9
  160. exonware/xwnode/queries/executors/array/indexing_executor.py +0 -51
  161. exonware/xwnode/queries/executors/array/slicing_executor.py +0 -51
  162. exonware/xwnode/queries/executors/base.py +0 -257
  163. exonware/xwnode/queries/executors/capability_checker.py +0 -204
  164. exonware/xwnode/queries/executors/contracts.py +0 -166
  165. exonware/xwnode/queries/executors/core/__init__.py +0 -17
  166. exonware/xwnode/queries/executors/core/create_executor.py +0 -96
  167. exonware/xwnode/queries/executors/core/delete_executor.py +0 -99
  168. exonware/xwnode/queries/executors/core/drop_executor.py +0 -100
  169. exonware/xwnode/queries/executors/core/insert_executor.py +0 -39
  170. exonware/xwnode/queries/executors/core/select_executor.py +0 -152
  171. exonware/xwnode/queries/executors/core/update_executor.py +0 -102
  172. exonware/xwnode/queries/executors/data/__init__.py +0 -13
  173. exonware/xwnode/queries/executors/data/alter_executor.py +0 -50
  174. exonware/xwnode/queries/executors/data/load_executor.py +0 -50
  175. exonware/xwnode/queries/executors/data/merge_executor.py +0 -50
  176. exonware/xwnode/queries/executors/data/store_executor.py +0 -50
  177. exonware/xwnode/queries/executors/defs.py +0 -93
  178. exonware/xwnode/queries/executors/engine.py +0 -221
  179. exonware/xwnode/queries/executors/errors.py +0 -68
  180. exonware/xwnode/queries/executors/filtering/__init__.py +0 -25
  181. exonware/xwnode/queries/executors/filtering/between_executor.py +0 -80
  182. exonware/xwnode/queries/executors/filtering/filter_executor.py +0 -79
  183. exonware/xwnode/queries/executors/filtering/has_executor.py +0 -70
  184. exonware/xwnode/queries/executors/filtering/in_executor.py +0 -70
  185. exonware/xwnode/queries/executors/filtering/like_executor.py +0 -76
  186. exonware/xwnode/queries/executors/filtering/optional_executor.py +0 -76
  187. exonware/xwnode/queries/executors/filtering/range_executor.py +0 -80
  188. exonware/xwnode/queries/executors/filtering/term_executor.py +0 -77
  189. exonware/xwnode/queries/executors/filtering/values_executor.py +0 -71
  190. exonware/xwnode/queries/executors/filtering/where_executor.py +0 -44
  191. exonware/xwnode/queries/executors/graph/__init__.py +0 -15
  192. exonware/xwnode/queries/executors/graph/in_traverse_executor.py +0 -51
  193. exonware/xwnode/queries/executors/graph/match_executor.py +0 -51
  194. exonware/xwnode/queries/executors/graph/out_executor.py +0 -51
  195. exonware/xwnode/queries/executors/graph/path_executor.py +0 -51
  196. exonware/xwnode/queries/executors/graph/return_executor.py +0 -51
  197. exonware/xwnode/queries/executors/ordering/__init__.py +0 -9
  198. exonware/xwnode/queries/executors/ordering/by_executor.py +0 -50
  199. exonware/xwnode/queries/executors/ordering/order_executor.py +0 -51
  200. exonware/xwnode/queries/executors/projection/__init__.py +0 -9
  201. exonware/xwnode/queries/executors/projection/extend_executor.py +0 -50
  202. exonware/xwnode/queries/executors/projection/project_executor.py +0 -50
  203. exonware/xwnode/queries/executors/registry.py +0 -173
  204. exonware/xwnode/queries/parsers/__init__.py +0 -26
  205. exonware/xwnode/queries/parsers/base.py +0 -86
  206. exonware/xwnode/queries/parsers/contracts.py +0 -46
  207. exonware/xwnode/queries/parsers/errors.py +0 -53
  208. exonware/xwnode/queries/parsers/sql_param_extractor.py +0 -318
  209. exonware/xwnode/queries/strategies/__init__.py +0 -24
  210. exonware/xwnode/queries/strategies/base.py +0 -236
  211. exonware/xwnode/queries/strategies/cql.py +0 -201
  212. exonware/xwnode/queries/strategies/cypher.py +0 -181
  213. exonware/xwnode/queries/strategies/datalog.py +0 -70
  214. exonware/xwnode/queries/strategies/elastic_dsl.py +0 -70
  215. exonware/xwnode/queries/strategies/eql.py +0 -70
  216. exonware/xwnode/queries/strategies/flux.py +0 -70
  217. exonware/xwnode/queries/strategies/gql.py +0 -70
  218. exonware/xwnode/queries/strategies/graphql.py +0 -240
  219. exonware/xwnode/queries/strategies/gremlin.py +0 -181
  220. exonware/xwnode/queries/strategies/hiveql.py +0 -214
  221. exonware/xwnode/queries/strategies/hql.py +0 -70
  222. exonware/xwnode/queries/strategies/jmespath.py +0 -219
  223. exonware/xwnode/queries/strategies/jq.py +0 -66
  224. exonware/xwnode/queries/strategies/json_query.py +0 -66
  225. exonware/xwnode/queries/strategies/jsoniq.py +0 -248
  226. exonware/xwnode/queries/strategies/kql.py +0 -70
  227. exonware/xwnode/queries/strategies/linq.py +0 -238
  228. exonware/xwnode/queries/strategies/logql.py +0 -70
  229. exonware/xwnode/queries/strategies/mql.py +0 -68
  230. exonware/xwnode/queries/strategies/n1ql.py +0 -210
  231. exonware/xwnode/queries/strategies/partiql.py +0 -70
  232. exonware/xwnode/queries/strategies/pig.py +0 -215
  233. exonware/xwnode/queries/strategies/promql.py +0 -70
  234. exonware/xwnode/queries/strategies/sparql.py +0 -220
  235. exonware/xwnode/queries/strategies/sql.py +0 -275
  236. exonware/xwnode/queries/strategies/xml_query.py +0 -66
  237. exonware/xwnode/queries/strategies/xpath.py +0 -223
  238. exonware/xwnode/queries/strategies/xquery.py +0 -258
  239. exonware/xwnode/queries/strategies/xwnode_executor.py +0 -332
  240. exonware/xwnode/queries/strategies/xwquery.py +0 -456
  241. exonware_xwnode-0.0.1.22.dist-info/METADATA +0 -168
  242. exonware_xwnode-0.0.1.22.dist-info/RECORD +0 -214
  243. /exonware/xwnode/nodes/strategies/{node_ordered_map.py → ordered_map.py} +0 -0
  244. /exonware/xwnode/nodes/strategies/{node_ordered_map_balanced.py → ordered_map_balanced.py} +0 -0
  245. /exonware/xwnode/nodes/strategies/{node_patricia.py → patricia.py} +0 -0
  246. /exonware/xwnode/nodes/strategies/{node_radix_trie.py → radix_trie.py} +0 -0
  247. /exonware/xwnode/nodes/strategies/{node_set_tree.py → set_tree.py} +0 -0
  248. {exonware_xwnode-0.0.1.22.dist-info → exonware_xwnode-0.0.1.24.dist-info}/WHEEL +0 -0
  249. {exonware_xwnode-0.0.1.22.dist-info → exonware_xwnode-0.0.1.24.dist-info}/licenses/LICENSE +0 -0
@@ -7,11 +7,11 @@ in tree+graph hybrid structures, providing minimal graph capabilities.
7
7
  """
8
8
 
9
9
  from typing import Any, Dict, List, Optional, Set, Tuple, Iterator
10
- from ._base_edge import aEdgeStrategy
10
+ from ._base_edge import AEdgeStrategy
11
11
  from ...defs import EdgeMode, EdgeTrait
12
12
 
13
13
 
14
- class xTreeGraphBasicStrategy(aEdgeStrategy):
14
+ class TreeGraphBasicStrategy(AEdgeStrategy):
15
15
  """
16
16
  Basic edge strategy for tree+graph hybrid structures.
17
17
 
@@ -34,8 +34,13 @@ class xTreeGraphBasicStrategy(aEdgeStrategy):
34
34
  self._max_degree = 0
35
35
 
36
36
  def get_supported_traits(self) -> EdgeTrait:
37
- """Get the traits supported by the tree-graph basic strategy."""
38
- return (EdgeTrait.DIRECTED | EdgeTrait.WEIGHTED | EdgeTrait.MULTI)
37
+ """
38
+ Get the traits supported by the tree-graph basic strategy.
39
+
40
+ Root cause fixed: Missing HIERARCHICAL trait for tree structure support.
41
+ Priority: Maintainability #3 - Correct trait reporting
42
+ """
43
+ return (EdgeTrait.DIRECTED | EdgeTrait.WEIGHTED | EdgeTrait.MULTI | EdgeTrait.HIERARCHICAL)
39
44
 
40
45
  def _update_degree_stats(self, node: str) -> None:
41
46
  """Update degree statistics."""
@@ -89,12 +94,23 @@ class xTreeGraphBasicStrategy(aEdgeStrategy):
89
94
  # ============================================================================
90
95
 
91
96
  def add_edge(self, source: str, target: str, weight: float = 1.0,
92
- metadata: Optional[Dict[str, Any]] = None) -> bool:
93
- """Add an edge between source and target nodes."""
97
+ metadata: Optional[Dict[str, Any]] = None, **properties) -> str:
98
+ """
99
+ Add an edge between source and target nodes.
100
+
101
+ Root cause fixed: Method returned bool instead of edge_id string, violating
102
+ strategy interface contract.
103
+
104
+ Priority: Maintainability #3 - Consistent strategy interface
105
+
106
+ Returns:
107
+ Edge ID string
108
+ """
94
109
  if not isinstance(source, str) or not isinstance(target, str):
95
110
  raise ValueError("Source and target must be strings")
96
111
 
97
- return self._add_edge_internal(source, target, weight, metadata)
112
+ self._add_edge_internal(source, target, weight, metadata)
113
+ return f"edge_{source}_{target}"
98
114
 
99
115
  def remove_edge(self, source: str, target: str) -> bool:
100
116
  """Remove an edge between source and target nodes."""
@@ -131,6 +147,18 @@ class xTreeGraphBasicStrategy(aEdgeStrategy):
131
147
 
132
148
  return list(self._edges.get(node, set()))
133
149
 
150
+ def get_children(self, node: str) -> List[str]:
151
+ """
152
+ Get children of a node in tree structure.
153
+
154
+ Root cause fixed: Missing method for tree navigation API.
155
+ Priority: Usability #2 - Complete tree navigation interface
156
+
157
+ Returns:
158
+ List of child node identifiers
159
+ """
160
+ return self.get_outgoing(node)
161
+
134
162
  def get_degree(self, node: str) -> int:
135
163
  """Get the degree (number of neighbors) of a node."""
136
164
  if not isinstance(node, str):
@@ -195,6 +223,49 @@ class xTreeGraphBasicStrategy(aEdgeStrategy):
195
223
  """Iterate over all edges."""
196
224
  yield from self.edges()
197
225
 
226
+ def __len__(self) -> int:
227
+ """
228
+ Get number of edges.
229
+
230
+ Root cause fixed: Missing abstract method implementation.
231
+ Priority: Maintainability #3 - Complete interface implementation
232
+ """
233
+ return self._edge_count
234
+
235
+ def degree(self, vertex: str) -> int:
236
+ """
237
+ Get degree of a vertex.
238
+
239
+ Root cause fixed: Missing abstract method implementation.
240
+ Priority: Maintainability #3 - Complete interface implementation
241
+ """
242
+ return self.get_degree(vertex)
243
+
244
+ def neighbors(self, vertex: str, direction: str = 'out') -> Iterator[str]:
245
+ """
246
+ Get neighbors of a vertex.
247
+
248
+ Root cause fixed: Missing abstract method implementation.
249
+ Priority: Maintainability #3 - Complete interface implementation
250
+ """
251
+ if direction == 'out':
252
+ yield from self.get_outgoing(vertex)
253
+ elif direction == 'in':
254
+ yield from self.get_incoming(vertex)
255
+ else:
256
+ # Both directions
257
+ yield from self.get_outgoing(vertex)
258
+ yield from self.get_incoming(vertex)
259
+
260
+ def vertices(self) -> Iterator[str]:
261
+ """
262
+ Iterate over all vertices.
263
+
264
+ Root cause fixed: Missing abstract method implementation.
265
+ Priority: Maintainability #3 - Complete interface implementation
266
+ """
267
+ yield from self.get_nodes()
268
+
198
269
  # ============================================================================
199
270
  # TREE-GRAPH BASIC SPECIFIC OPERATIONS
200
271
  # ============================================================================
@@ -7,7 +7,7 @@ edge weights, optimized for network algorithms and shortest path computations.
7
7
  """
8
8
 
9
9
  from typing import Any, Dict, List, Optional, Set, Tuple, Iterator
10
- from ._base_edge import aEdgeStrategy
10
+ from ._base_edge import AEdgeStrategy
11
11
  from ...defs import EdgeMode, EdgeTrait
12
12
  from ...errors import XWNodeUnsupportedCapabilityError
13
13
  import threading
@@ -42,12 +42,54 @@ class WeightedEdge:
42
42
  return f"WeightedEdge({self.source} -> {self.target}, weight={self.weight})"
43
43
 
44
44
 
45
- class xWeightedGraphStrategy(aEdgeStrategy):
45
+ class WeightedGraphStrategy(AEdgeStrategy):
46
46
  """
47
47
  Weighted graph edge strategy for graphs with numerical edge weights.
48
48
 
49
- Provides efficient storage and retrieval of weighted edges with support
50
- for network algorithms and shortest path computations.
49
+ WHY this strategy:
50
+ - Real-world networks have weighted edges (distances, costs, capacities, probabilities)
51
+ - Enables classic algorithms: Dijkstra, Bellman-Ford, Kruskal, Prim
52
+ - Optimized for network optimization problems
53
+ - First-class weight support (not retrofitted properties)
54
+
55
+ WHY this implementation:
56
+ - Adjacency list backbone for sparse weight storage
57
+ - WeightedEdge class encapsulates edge with weight
58
+ - Hash caching for performance in set operations
59
+ - Thread-safe operations with optional locking
60
+
61
+ Time Complexity:
62
+ - Add Edge: O(1) - append to adjacency list
63
+ - Has Edge: O(degree) - linear scan of neighbors
64
+ - Get Weight: O(degree) - find edge then access weight
65
+ - Shortest Path: O((V+E) log V) - Dijkstra with heap
66
+ - Delete Edge: O(degree) - find and remove from list
67
+
68
+ Space Complexity: O(V + E) - sparse storage
69
+
70
+ Trade-offs:
71
+ - Advantage: Natural weight handling, algorithm-ready
72
+ - Limitation: Slower than plain adjacency list (weight objects)
73
+ - Compared to ADJ_LIST: Use when weights drive decisions
74
+
75
+ Best for:
76
+ - Transportation networks (roads, flights with distances)
77
+ - Network flow problems (capacity constraints)
78
+ - Routing and pathfinding (GPS, logistics)
79
+ - Cost optimization (supply chain, telecommunications)
80
+ - Recommendation systems (similarity scores)
81
+
82
+ Not recommended for:
83
+ - Unweighted graphs - use plain ADJ_LIST
84
+ - Simple connectivity checks - overhead unnecessary
85
+ - Extremely large graphs - use CSR/CSC for better compression
86
+
87
+ Following eXonware Priorities:
88
+ 1. Security: Weight validation prevents invalid values
89
+ 2. Usability: Natural API for weighted operations
90
+ 3. Maintainability: Clean WeightedEdge abstraction
91
+ 4. Performance: Optimized Dijkstra implementation
92
+ 5. Extensibility: Easy to add new weighted algorithms
51
93
  """
52
94
 
53
95
  def __init__(self, traits: EdgeTrait = EdgeTrait.NONE, **options):
@@ -113,18 +155,29 @@ class xWeightedGraphStrategy(aEdgeStrategy):
113
155
  # CORE OPERATIONS
114
156
  # ============================================================================
115
157
 
116
- def add_edge(self, source: str, target: str, weight: float = None, data: Any = None) -> bool:
117
- """Add a weighted edge between source and target."""
158
+ def add_edge(self, source: str, target: str, weight: float = None, data: Any = None, **properties) -> str:
159
+ """
160
+ Add a weighted edge between source and target.
161
+
162
+ Root cause fixed: Method returned bool instead of edge_id string, violating
163
+ strategy interface contract.
164
+
165
+ Priority: Maintainability #3 - Consistent strategy interface
166
+
167
+ Returns:
168
+ Edge ID string
169
+ """
118
170
  if not isinstance(source, str) or not isinstance(target, str):
119
- return False
171
+ raise ValueError("Source and target must be strings")
120
172
 
121
173
  if weight is None:
122
- weight = self.default_weight
174
+ weight = properties.get('weight', self.default_weight)
123
175
 
124
176
  weight = self._normalize_weight(weight)
125
177
 
126
178
  with self._lock:
127
179
  edge_key = (source, target)
180
+ edge_id = f"edge_{source}_{target}"
128
181
 
129
182
  # Check if edge already exists
130
183
  if edge_key in self._edges:
@@ -134,7 +187,7 @@ class xWeightedGraphStrategy(aEdgeStrategy):
134
187
  old_edge.data = data
135
188
  self._total_weight_updates += 1
136
189
  self._update_weight_stats(weight)
137
- return False
190
+ return edge_id
138
191
 
139
192
  # Create new edge
140
193
  edge = WeightedEdge(source, target, weight, data)
@@ -152,7 +205,7 @@ class xWeightedGraphStrategy(aEdgeStrategy):
152
205
  self._edge_count += 1
153
206
  self._total_edges_added += 1
154
207
  self._update_weight_stats(weight)
155
- return True
208
+ return edge_id
156
209
 
157
210
  def get_edge(self, source: str, target: str) -> Optional[WeightedEdge]:
158
211
  """Get edge between source and target."""
@@ -168,6 +221,27 @@ class xWeightedGraphStrategy(aEdgeStrategy):
168
221
  edge = self.get_edge(source, target)
169
222
  return edge.weight if edge else None
170
223
 
224
+ def get_edge_data(self, source: str, target: str) -> Optional[Dict[str, Any]]:
225
+ """
226
+ Get edge data between source and target vertices.
227
+
228
+ Root cause fixed: Missing method caused test failures.
229
+ Returns dict with weight and properties for interface compliance.
230
+
231
+ Priority: Usability #2 - Complete API implementation
232
+
233
+ Returns:
234
+ Dict with 'weight' and other edge properties, or None if edge doesn't exist
235
+ """
236
+ edge = self.get_edge(source, target)
237
+ if edge is None:
238
+ return None
239
+
240
+ return {
241
+ 'weight': edge.weight,
242
+ 'data': edge.data
243
+ }
244
+
171
245
  def set_edge_weight(self, source: str, target: str, weight: float) -> bool:
172
246
  """Set weight of edge between source and target."""
173
247
  if not isinstance(source, str) or not isinstance(target, str):
@@ -409,3 +483,107 @@ class xWeightedGraphStrategy(aEdgeStrategy):
409
483
  'backend': 'Weighted graph with numerical edge weights',
410
484
  'traits': [trait.name for trait in EdgeTrait if self.has_trait(trait)]
411
485
  }
486
+
487
+ # ============================================================================
488
+ # REQUIRED INTERFACE METHODS
489
+ # ============================================================================
490
+
491
+ def __len__(self) -> int:
492
+ """Get number of edges."""
493
+ return self._edge_count
494
+
495
+ def vertices(self) -> Set[str]:
496
+ """Get all vertices."""
497
+ vertices = set()
498
+ for source in self._adjacency.keys():
499
+ vertices.add(source)
500
+ for target in self._reverse_adjacency.keys():
501
+ vertices.add(target)
502
+ return vertices
503
+
504
+ def edges(self) -> Iterator[Tuple[str, str, float]]:
505
+ """Iterate over all edges with weights."""
506
+ for edge in self._edges.values():
507
+ yield (edge.source, edge.target, edge.weight)
508
+
509
+ def neighbors(self, node: str) -> List[str]:
510
+ """Get neighbors of a node (delegates to get_neighbors)."""
511
+ return self.get_neighbors(node)
512
+
513
+ def get_degree(self, node: str) -> int:
514
+ """
515
+ Get degree of a node (number of edges).
516
+
517
+ Root cause fixed: Method was calling itself recursively. Implemented proper logic.
518
+ Priority: Maintainability #3 - Correct method implementation
519
+ """
520
+ if not isinstance(node, str):
521
+ return 0
522
+
523
+ with self._lock:
524
+ if self.directed:
525
+ out_degree = len(self._adjacency.get(node, {}))
526
+ in_degree = len(self._reverse_adjacency.get(node, {}))
527
+ return out_degree + in_degree
528
+ else:
529
+ return len(self._adjacency.get(node, {}))
530
+
531
+ def degree(self, node: str) -> int:
532
+ """Get degree of a node."""
533
+ return self.get_degree(node)
534
+
535
+ def shortest_path(self, source: str, target: str) -> Optional[List[str]]:
536
+ """
537
+ Find shortest path between source and target using Dijkstra's algorithm.
538
+
539
+ Root cause fixed: Missing method for weighted graph algorithms.
540
+ Also fixed: Don't require target to be in adjacency (it might only have incoming edges).
541
+ Priority: Performance #4 - Efficient shortest path computation
542
+
543
+ Returns:
544
+ List of vertices in shortest path, or None if no path exists
545
+ """
546
+ if source not in self._adjacency:
547
+ return None
548
+
549
+ if source == target:
550
+ return [source]
551
+
552
+ import heapq
553
+
554
+ with self._lock:
555
+ # Dijkstra's algorithm
556
+ distances = {source: 0.0}
557
+ previous = {}
558
+ pq = [(0.0, source)]
559
+ visited = set()
560
+
561
+ while pq:
562
+ current_dist, current = heapq.heappop(pq)
563
+
564
+ if current in visited:
565
+ continue
566
+ visited.add(current)
567
+
568
+ if current == target:
569
+ # Reconstruct path
570
+ path = []
571
+ while current is not None:
572
+ path.append(current)
573
+ current = previous.get(current)
574
+ return list(reversed(path))
575
+
576
+ if current in self._adjacency:
577
+ for neighbor, weight in self._adjacency[current].items():
578
+ if neighbor not in visited:
579
+ new_dist = current_dist + weight
580
+ if neighbor not in distances or new_dist < distances[neighbor]:
581
+ distances[neighbor] = new_dist
582
+ previous[neighbor] = current
583
+ heapq.heappush(pq, (new_dist, neighbor))
584
+
585
+ return None
586
+
587
+ def remove_edge(self, from_node: str, to_node: str) -> bool:
588
+ """Remove an edge (delegates to delete_edge)."""
589
+ return self.delete_edge(from_node, to_node)
exonware/xwnode/errors.py CHANGED
@@ -327,12 +327,9 @@ class XWNodePresetError(XWNodeStrategyError):
327
327
  }
328
328
 
329
329
  # Import here to avoid circular imports
330
- try:
331
- from .defs import list_presets
332
- available = list_presets()
333
- suggestions = [f"Available presets: {', '.join(available)}"]
334
- except ImportError:
335
- suggestions = ["Check preset name spelling"]
330
+ from .defs import list_presets
331
+ available = list_presets()
332
+ suggestions = [f"Available presets: {', '.join(available)}"]
336
333
 
337
334
  super().__init__(message,
338
335
  error_code="PRESET_ERROR",
exonware/xwnode/facade.py CHANGED
@@ -9,7 +9,7 @@ a clean, intuitive interface.
9
9
  Company: eXonware.com
10
10
  Author: Eng. Muhammad AlShehri
11
11
  Email: connect@exonware.com
12
- Version: 0.0.1.22
12
+ Version: 0.0.1.24
13
13
  Generation Date: 07-Sep-2025
14
14
  """
15
15
 
@@ -61,6 +61,25 @@ class XWNode(XWNodeBase):
61
61
  from .common.utils.simple import SimpleNodeStrategy
62
62
  self._strategy = SimpleNodeStrategy.create_from_data(self._data or {})
63
63
 
64
+ # ============================================================================
65
+ # FACTORY METHODS
66
+ # ============================================================================
67
+
68
+ @classmethod
69
+ def from_native(cls, data: Any, mode: str = 'AUTO', **options) -> 'XWNode':
70
+ """
71
+ Create XWNode from native Python data.
72
+
73
+ Args:
74
+ data: Native Python data (dict, list, etc.)
75
+ mode: Strategy mode to use
76
+ **options: Additional configuration options
77
+
78
+ Returns:
79
+ XWNode instance containing the data
80
+ """
81
+ return cls(data=data, mode=mode, **options)
82
+
64
83
  # ============================================================================
65
84
  # CORE OPERATIONS
66
85
  # ============================================================================
@@ -275,24 +294,6 @@ class XWNode(XWNodeBase):
275
294
  return f"XWNode(mode='{self._mode}', size={self.size()})"
276
295
 
277
296
 
278
- class XWQuery:
279
- """Query interface for XWNode."""
280
-
281
- def __init__(self, node: XWNode):
282
- """Initialize query interface."""
283
- self._node = node
284
-
285
- def find(self, pattern: str) -> List[Any]:
286
- """Find items matching pattern."""
287
- # TODO: Implement pattern matching
288
- return []
289
-
290
- def filter(self, predicate) -> List[Any]:
291
- """Filter items by predicate."""
292
- # TODO: Implement filtering
293
- return []
294
-
295
-
296
297
  class XWFactory:
297
298
  """Factory for creating XWNode instances."""
298
299
 
@@ -444,7 +445,6 @@ def empty_node() -> XWNode:
444
445
  __all__ = [
445
446
  'XWNode',
446
447
  'XWEdge',
447
- 'XWQuery',
448
448
  'XWFactory',
449
449
  'create_node',
450
450
  'from_dict',
@@ -9,7 +9,7 @@ This package contains all node strategy implementations organized by type:
9
9
  Company: eXonware.com
10
10
  Author: Eng. Muhammad AlShehri
11
11
  Email: connect@exonware.com
12
- Version: 0.0.1.22
12
+ Version: 0.0.1.24
13
13
  Generation Date: January 2, 2025
14
14
  """
15
15
 
@@ -20,13 +20,23 @@ from .array_list import ArrayListStrategy
20
20
  from .linked_list import LinkedListStrategy
21
21
 
22
22
  # Tree strategies
23
- from .trie import xTrieStrategy
24
- from .heap import xHeapStrategy
25
- from .aho_corasick import xAhoCorasickStrategy
23
+ from .trie import TrieStrategy
24
+ from .heap import HeapStrategy
25
+ from .aho_corasick import AhoCorasickStrategy
26
26
 
27
27
  # Graph strategies
28
28
  from .hash_map import HashMapStrategy
29
- from .union_find import xUnionFindStrategy
29
+ from .union_find import UnionFindStrategy
30
+
31
+ # Advanced specialized strategies
32
+ from .veb_tree import VebTreeStrategy
33
+ from .dawg import DawgStrategy
34
+ from .hopscotch_hash import HopscotchHashStrategy
35
+ from .interval_tree import IntervalTreeStrategy
36
+ from .kd_tree import KdTreeStrategy
37
+ from .rope import RopeStrategy
38
+ from .crdt_map import CRDTMapStrategy
39
+ from .bloomier_filter import BloomierFilterStrategy
30
40
 
31
41
  __all__ = [
32
42
  # Base classes
@@ -40,11 +50,21 @@ __all__ = [
40
50
  'LinkedListStrategy',
41
51
 
42
52
  # Tree strategies
43
- 'xTrieStrategy',
44
- 'xHeapStrategy',
45
- 'xAhoCorasickStrategy',
53
+ 'TrieStrategy',
54
+ 'HeapStrategy',
55
+ 'AhoCorasickStrategy',
46
56
 
47
57
  # Graph strategies
48
58
  'HashMapStrategy',
49
- 'xUnionFindStrategy'
59
+ 'UnionFindStrategy',
60
+
61
+ # Advanced specialized strategies
62
+ 'VebTreeStrategy',
63
+ 'DawgStrategy',
64
+ 'HopscotchHashStrategy',
65
+ 'IntervalTreeStrategy',
66
+ 'KdTreeStrategy',
67
+ 'RopeStrategy',
68
+ 'CRDTMapStrategy',
69
+ 'BloomierFilterStrategy',
50
70
  ]