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
@@ -1,221 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- #exonware/xwnode/src/exonware/xwnode/queries/executors/engine.py
4
-
5
- Query Execution Engine
6
-
7
- This module provides the main execution engine that orchestrates operation execution
8
- with capability checking and routing.
9
-
10
- Company: eXonware.com
11
- Author: Eng. Muhammad AlShehri
12
- Email: connect@exonware.com
13
- Version: 0.0.1.22
14
- Generation Date: 08-Oct-2025
15
- """
16
-
17
- from typing import Any, List, Dict, Optional
18
- from .contracts import Action, ExecutionContext, ExecutionResult, NodeType
19
- from .registry import get_operation_registry, OperationRegistry
20
- from .capability_checker import check_operation_compatibility
21
- from .base import UnsupportedOperationError
22
- from ...base import XWNodeBase
23
-
24
-
25
- class ExecutionEngine:
26
- """
27
- Main query execution engine.
28
-
29
- Orchestrates execution of XWQuery operations on nodes with:
30
- - Capability-aware routing
31
- - Operation composition
32
- - Error handling
33
- - Performance monitoring
34
- """
35
-
36
- def __init__(self, registry: Optional[OperationRegistry] = None):
37
- """
38
- Initialize execution engine.
39
-
40
- Args:
41
- registry: Operation registry (uses global if not provided)
42
- """
43
- self._registry = registry or get_operation_registry()
44
- self._execution_history: List[Dict] = []
45
-
46
- def execute(self, query: str, node: Any, **kwargs) -> ExecutionResult:
47
- """
48
- Execute a query string on a node.
49
-
50
- Args:
51
- query: XWQuery script string
52
- node: Target node to execute on
53
- **kwargs: Additional execution options
54
-
55
- Returns:
56
- ExecutionResult with data
57
- """
58
- # Parse query to actions tree
59
- from ..strategies.xwquery import XWQueryScriptStrategy
60
-
61
- script_strategy = XWQueryScriptStrategy()
62
- parsed = script_strategy.parse_script(query)
63
- actions_tree = parsed.get_actions_tree()
64
-
65
- # Create execution context
66
- context = ExecutionContext(
67
- node=node,
68
- variables=kwargs.get('variables', {}),
69
- options=kwargs
70
- )
71
-
72
- # Execute actions tree
73
- return self.execute_actions_tree(actions_tree, context)
74
-
75
- def execute_actions_tree(self, actions_tree: XWNodeBase, context: ExecutionContext) -> ExecutionResult:
76
- """
77
- Execute an actions tree.
78
-
79
- Args:
80
- actions_tree: Parsed actions tree
81
- context: Execution context
82
-
83
- Returns:
84
- Combined execution result
85
- """
86
- tree_data = actions_tree.to_native()
87
- statements = tree_data.get('root', {}).get('statements', [])
88
-
89
- results = []
90
-
91
- for statement in statements:
92
- # Create action from statement
93
- action = Action(
94
- type=statement.get('type', 'UNKNOWN'),
95
- params=statement.get('params', {}),
96
- id=statement.get('id', ''),
97
- line_number=statement.get('line_number', 0)
98
- )
99
-
100
- # Execute action
101
- result = self.execute_action(action, context)
102
- results.append(result)
103
-
104
- # Store result for later actions
105
- if action.id:
106
- context.set_result(action.id, result.data)
107
-
108
- # Combine results
109
- return self._combine_results(results)
110
-
111
- def execute_action(self, action: Action, context: ExecutionContext) -> ExecutionResult:
112
- """
113
- Execute a single action.
114
-
115
- Args:
116
- action: Action to execute
117
- context: Execution context
118
-
119
- Returns:
120
- ExecutionResult
121
- """
122
- # Get executor for this operation
123
- executor = self._registry.get(action.type)
124
-
125
- if not executor:
126
- return ExecutionResult(
127
- data=None,
128
- success=False,
129
- error=f"No executor registered for operation: {action.type}"
130
- )
131
-
132
- # Check capability before execution
133
- try:
134
- node_type = self._get_node_type(context.node)
135
-
136
- if not executor.can_execute_on(node_type):
137
- return ExecutionResult(
138
- data=None,
139
- success=False,
140
- error=f"Operation {action.type} not supported on {node_type.name} nodes"
141
- )
142
-
143
- # Execute
144
- result = executor.execute(action, context)
145
-
146
- # Record execution
147
- self._record_execution(action, result)
148
-
149
- return result
150
-
151
- except UnsupportedOperationError as e:
152
- return ExecutionResult(
153
- data=None,
154
- success=False,
155
- error=str(e)
156
- )
157
- except Exception as e:
158
- return ExecutionResult(
159
- data=None,
160
- success=False,
161
- error=f"Execution error: {str(e)}"
162
- )
163
-
164
- def _get_node_type(self, node: Any) -> NodeType:
165
- """Get node's strategy type."""
166
- if hasattr(node, '_strategy') and hasattr(node._strategy, 'STRATEGY_TYPE'):
167
- return node._strategy.STRATEGY_TYPE
168
- elif hasattr(node, 'STRATEGY_TYPE'):
169
- return node.STRATEGY_TYPE
170
- return NodeType.TREE # Default
171
-
172
- def _combine_results(self, results: List[ExecutionResult]) -> ExecutionResult:
173
- """Combine multiple execution results."""
174
- if not results:
175
- return ExecutionResult(data=[])
176
-
177
- if len(results) == 1:
178
- return results[0]
179
-
180
- # Combine data from all results
181
- combined_data = []
182
- total_affected = 0
183
- total_time = 0.0
184
- all_success = True
185
-
186
- for result in results:
187
- if result.data:
188
- if isinstance(result.data, list):
189
- combined_data.extend(result.data)
190
- else:
191
- combined_data.append(result.data)
192
- total_affected += result.affected_count
193
- total_time += result.execution_time
194
- all_success = all_success and result.success
195
-
196
- return ExecutionResult(
197
- data=combined_data,
198
- affected_count=total_affected,
199
- execution_time=total_time,
200
- success=all_success
201
- )
202
-
203
- def _record_execution(self, action: Action, result: ExecutionResult) -> None:
204
- """Record execution in history."""
205
- self._execution_history.append({
206
- 'action': action.type,
207
- 'success': result.success,
208
- 'affected_count': result.affected_count,
209
- 'execution_time': result.execution_time
210
- })
211
-
212
- def get_execution_history(self) -> List[Dict]:
213
- """Get execution history."""
214
- return self._execution_history.copy()
215
-
216
- def clear_history(self) -> None:
217
- """Clear execution history."""
218
- self._execution_history.clear()
219
-
220
-
221
- __all__ = ['ExecutionEngine']
@@ -1,68 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- #exonware/xwnode/src/exonware/xwnode/queries/executors/errors.py
4
-
5
- Executor Error Classes
6
-
7
- Module-specific errors for query operation executors.
8
- Extends root error classes per DEV_GUIDELINES.md - no redundancy.
9
-
10
- Company: eXonware.com
11
- Author: Eng. Muhammad AlShehri
12
- Email: connect@exonware.com
13
- Version: 0.0.1.22
14
- Generation Date: 08-Oct-2025
15
- """
16
-
17
- # Import and REUSE root error classes per DEV_GUIDELINES
18
- from ...errors import (
19
- XWNodeError,
20
- XWNodeStrategyError,
21
- XWNodeUnsupportedCapabilityError,
22
- XWNodeValueError
23
- )
24
- from ...nodes.strategies.contracts import NodeType
25
-
26
-
27
- class ExecutorError(XWNodeStrategyError):
28
- """
29
- Base error for executor operations.
30
-
31
- Extends XWNodeStrategyError from root - follows DEV_GUIDELINES principle:
32
- "Never reinvent the wheel - reuse code from xwsystem library or xnode"
33
- """
34
- pass
35
-
36
-
37
- class OperationExecutionError(ExecutorError):
38
- """Raised when operation execution fails."""
39
-
40
- def __init__(self, operation: str, reason: str, context: dict = None):
41
- message = f"Operation '{operation}' execution failed: {reason}"
42
- super().__init__(message)
43
- self.operation = operation
44
- self.reason = reason
45
- self.add_context(**(context or {}))
46
-
47
-
48
- class ValidationError(ExecutorError):
49
- """Raised when action validation fails."""
50
-
51
- def __init__(self, action_type: str, reason: str):
52
- message = f"Action validation failed for '{action_type}': {reason}"
53
- super().__init__(message)
54
- self.action_type = action_type
55
- self.reason = reason
56
-
57
-
58
- # REUSE existing error from root, don't duplicate
59
- # Alias for convenience in this module
60
- UnsupportedOperationError = XWNodeUnsupportedCapabilityError
61
-
62
-
63
- __all__ = [
64
- 'ExecutorError',
65
- 'OperationExecutionError',
66
- 'ValidationError',
67
- 'UnsupportedOperationError', # Re-exported from root
68
- ]
@@ -1,25 +0,0 @@
1
- """Filtering operation executors."""
2
-
3
- from .where_executor import WhereExecutor
4
- from .filter_executor import FilterExecutor
5
- from .like_executor import LikeExecutor
6
- from .in_executor import InExecutor
7
- from .has_executor import HasExecutor
8
- from .between_executor import BetweenExecutor
9
- from .range_executor import RangeExecutor
10
- from .term_executor import TermExecutor
11
- from .optional_executor import OptionalExecutor
12
- from .values_executor import ValuesExecutor
13
-
14
- __all__ = [
15
- 'WhereExecutor',
16
- 'FilterExecutor',
17
- 'LikeExecutor',
18
- 'InExecutor',
19
- 'HasExecutor',
20
- 'BetweenExecutor',
21
- 'RangeExecutor',
22
- 'TermExecutor',
23
- 'OptionalExecutor',
24
- 'ValuesExecutor',
25
- ]
@@ -1,80 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- #exonware/xwnode/src/exonware/xwnode/queries/executors/filtering/between_executor.py
4
-
5
- BETWEEN Executor
6
-
7
- Company: eXonware.com
8
- Author: Eng. Muhammad AlShehri
9
- Email: connect@exonware.com
10
- Version: 0.0.1.22
11
- Generation Date: 08-Oct-2025
12
- """
13
-
14
- from typing import Any, Dict, List
15
- from ..base import AOperationExecutor
16
- from ..contracts import Action, ExecutionContext, ExecutionResult
17
- from ..defs import OperationType
18
- from ...nodes.strategies.contracts import NodeType
19
-
20
-
21
- class BetweenExecutor(AOperationExecutor):
22
- """
23
- BETWEEN operation executor - Tree/Matrix operation.
24
-
25
- Checks if values are within a range (inclusive).
26
- Optimized for TREE and MATRIX node types.
27
-
28
- Capability: Tree/Matrix only
29
- Operation Type: FILTERING
30
- """
31
-
32
- OPERATION_NAME = "BETWEEN"
33
- OPERATION_TYPE = OperationType.FILTERING
34
- SUPPORTED_NODE_TYPES = [NodeType.TREE, NodeType.MATRIX, NodeType.HYBRID]
35
-
36
- def _do_execute(self, action: Action, context: ExecutionContext) -> ExecutionResult:
37
- """Execute BETWEEN operation."""
38
- params = action.params
39
- field = params.get('field')
40
- min_value = params.get('min')
41
- max_value = params.get('max')
42
- path = params.get('path', None)
43
-
44
- node = context.node
45
- result_data = self._execute_between(node, field, min_value, max_value, path, context)
46
-
47
- return ExecutionResult(
48
- success=True,
49
- data=result_data,
50
- operation=self.OPERATION_NAME,
51
- metadata={'matched_count': len(result_data.get('items', []))}
52
- )
53
-
54
- def _execute_between(self, node: Any, field: str, min_val: Any, max_val: Any,
55
- path: str, context: ExecutionContext) -> Dict:
56
- """Execute BETWEEN range check."""
57
- matched_items = []
58
-
59
- # Get data
60
- if path:
61
- data = node.get(path, default=[])
62
- else:
63
- data = node.to_native()
64
-
65
- # Check range
66
- if isinstance(data, list):
67
- for item in data:
68
- value = item.get(field) if isinstance(item, dict) else item
69
- try:
70
- if min_val <= value <= max_val:
71
- matched_items.append(item)
72
- except (TypeError, ValueError):
73
- pass
74
-
75
- return {
76
- 'items': matched_items,
77
- 'count': len(matched_items),
78
- 'range': {'min': min_val, 'max': max_val}
79
- }
80
-
@@ -1,79 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- #exonware/xwnode/src/exonware/xwnode/queries/executors/filtering/filter_executor.py
4
-
5
- FILTER Executor
6
-
7
- Company: eXonware.com
8
- Author: Eng. Muhammad AlShehri
9
- Email: connect@exonware.com
10
- Version: 0.0.1.22
11
- Generation Date: 08-Oct-2025
12
- """
13
-
14
- from typing import Any, Dict, List, Callable
15
- from ..base import AUniversalOperationExecutor
16
- from ..contracts import Action, ExecutionContext, ExecutionResult
17
- from ..defs import OperationType
18
-
19
-
20
- class FilterExecutor(AUniversalOperationExecutor):
21
- """
22
- FILTER operation executor - Universal operation.
23
-
24
- Filters data based on specified conditions.
25
- General-purpose filtering that works on all node types.
26
-
27
- Capability: Universal
28
- Operation Type: FILTERING
29
- """
30
-
31
- OPERATION_NAME = "FILTER"
32
- OPERATION_TYPE = OperationType.FILTERING
33
- SUPPORTED_NODE_TYPES = [] # Universal
34
-
35
- def _do_execute(self, action: Action, context: ExecutionContext) -> ExecutionResult:
36
- """Execute FILTER operation."""
37
- params = action.params
38
- condition = params.get('condition', None)
39
- path = params.get('path', None)
40
-
41
- node = context.node
42
- result_data = self._execute_filter(node, condition, path, context)
43
-
44
- return ExecutionResult(
45
- success=True,
46
- data=result_data,
47
- operation=self.OPERATION_NAME,
48
- metadata={'filtered_count': len(result_data.get('items', []))}
49
- )
50
-
51
- def _execute_filter(self, node: Any, condition: Any, path: str, context: ExecutionContext) -> Dict:
52
- """Execute filter logic."""
53
- filtered_items = []
54
-
55
- # Get data to filter
56
- if path:
57
- data = node.get(path, default=[])
58
- else:
59
- data = node.to_native()
60
-
61
- # Apply filter (simplified)
62
- if isinstance(data, list):
63
- for item in data:
64
- if self._matches_filter(item, condition):
65
- filtered_items.append(item)
66
- elif isinstance(data, dict):
67
- for key, value in data.items():
68
- if self._matches_filter(value, condition):
69
- filtered_items.append({key: value})
70
-
71
- return {'items': filtered_items, 'count': len(filtered_items)}
72
-
73
- def _matches_filter(self, item: Any, condition: Any) -> bool:
74
- """Check if item matches filter condition."""
75
- if condition is None:
76
- return True
77
- # Simplified condition matching
78
- return True
79
-
@@ -1,70 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- #exonware/xwnode/src/exonware/xwnode/queries/executors/filtering/has_executor.py
4
-
5
- HAS Executor
6
-
7
- Company: eXonware.com
8
- Author: Eng. Muhammad AlShehri
9
- Email: connect@exonware.com
10
- Version: 0.0.1.22
11
- Generation Date: 08-Oct-2025
12
- """
13
-
14
- from typing import Any, Dict, List
15
- from ..base import AUniversalOperationExecutor
16
- from ..contracts import Action, ExecutionContext, ExecutionResult
17
- from ..defs import OperationType
18
-
19
-
20
- class HasExecutor(AUniversalOperationExecutor):
21
- """
22
- HAS operation executor - Universal operation.
23
-
24
- Checks if a property/field exists in data.
25
-
26
- Capability: Universal
27
- Operation Type: FILTERING
28
- """
29
-
30
- OPERATION_NAME = "HAS"
31
- OPERATION_TYPE = OperationType.FILTERING
32
- SUPPORTED_NODE_TYPES = [] # Universal
33
-
34
- def _do_execute(self, action: Action, context: ExecutionContext) -> ExecutionResult:
35
- """Execute HAS operation."""
36
- params = action.params
37
- property_name = params.get('property')
38
- path = params.get('path', None)
39
-
40
- node = context.node
41
- result_data = self._execute_has(node, property_name, path, context)
42
-
43
- return ExecutionResult(
44
- success=True,
45
- data=result_data,
46
- operation=self.OPERATION_NAME,
47
- metadata={'matched_count': len(result_data.get('items', []))}
48
- )
49
-
50
- def _execute_has(self, node: Any, property_name: str, path: str, context: ExecutionContext) -> Dict:
51
- """Execute HAS property check."""
52
- matched_items = []
53
-
54
- # Get data
55
- if path:
56
- data = node.get(path, default=[])
57
- else:
58
- data = node.to_native()
59
-
60
- # Check property existence
61
- if isinstance(data, list):
62
- for item in data:
63
- if isinstance(item, dict) and property_name in item:
64
- matched_items.append(item)
65
- elif isinstance(data, dict):
66
- if property_name in data:
67
- matched_items.append(data)
68
-
69
- return {'items': matched_items, 'count': len(matched_items), 'property': property_name}
70
-
@@ -1,70 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- #exonware/xwnode/src/exonware/xwnode/queries/executors/filtering/in_executor.py
4
-
5
- IN Executor
6
-
7
- Company: eXonware.com
8
- Author: Eng. Muhammad AlShehri
9
- Email: connect@exonware.com
10
- Version: 0.0.1.22
11
- Generation Date: 08-Oct-2025
12
- """
13
-
14
- from typing import Any, Dict, List
15
- from ..base import AUniversalOperationExecutor
16
- from ..contracts import Action, ExecutionContext, ExecutionResult
17
- from ..defs import OperationType
18
-
19
-
20
- class InExecutor(AUniversalOperationExecutor):
21
- """
22
- IN operation executor - Universal operation.
23
-
24
- Checks if a value is in a specified set.
25
-
26
- Capability: Universal
27
- Operation Type: FILTERING
28
- """
29
-
30
- OPERATION_NAME = "IN"
31
- OPERATION_TYPE = OperationType.FILTERING
32
- SUPPORTED_NODE_TYPES = [] # Universal
33
-
34
- def _do_execute(self, action: Action, context: ExecutionContext) -> ExecutionResult:
35
- """Execute IN operation."""
36
- params = action.params
37
- field = params.get('field')
38
- values = params.get('values', [])
39
- path = params.get('path', None)
40
-
41
- node = context.node
42
- result_data = self._execute_in(node, field, values, path, context)
43
-
44
- return ExecutionResult(
45
- success=True,
46
- data=result_data,
47
- operation=self.OPERATION_NAME,
48
- metadata={'matched_count': len(result_data.get('items', []))}
49
- )
50
-
51
- def _execute_in(self, node: Any, field: str, values: List, path: str, context: ExecutionContext) -> Dict:
52
- """Execute IN membership check."""
53
- matched_items = []
54
- values_set = set(values) if values else set()
55
-
56
- # Get data
57
- if path:
58
- data = node.get(path, default=[])
59
- else:
60
- data = node.to_native()
61
-
62
- # Check membership
63
- if isinstance(data, list):
64
- for item in data:
65
- value = item.get(field) if isinstance(item, dict) else item
66
- if value in values_set:
67
- matched_items.append(item)
68
-
69
- return {'items': matched_items, 'count': len(matched_items), 'values': values}
70
-
@@ -1,76 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- #exonware/xwnode/src/exonware/xwnode/queries/executors/filtering/like_executor.py
4
-
5
- LIKE Executor
6
-
7
- Company: eXonware.com
8
- Author: Eng. Muhammad AlShehri
9
- Email: connect@exonware.com
10
- Version: 0.0.1.22
11
- Generation Date: 08-Oct-2025
12
- """
13
-
14
- import re
15
- from typing import Any, Dict, List
16
- from ..base import AUniversalOperationExecutor
17
- from ..contracts import Action, ExecutionContext, ExecutionResult
18
- from ..defs import OperationType
19
-
20
-
21
- class LikeExecutor(AUniversalOperationExecutor):
22
- """
23
- LIKE operation executor - Universal operation.
24
-
25
- Pattern matching using SQL LIKE syntax (% and _ wildcards).
26
-
27
- Capability: Universal
28
- Operation Type: FILTERING
29
- """
30
-
31
- OPERATION_NAME = "LIKE"
32
- OPERATION_TYPE = OperationType.FILTERING
33
- SUPPORTED_NODE_TYPES = [] # Universal
34
-
35
- def _do_execute(self, action: Action, context: ExecutionContext) -> ExecutionResult:
36
- """Execute LIKE operation."""
37
- params = action.params
38
- field = params.get('field')
39
- pattern = params.get('pattern', '')
40
- path = params.get('path', None)
41
-
42
- node = context.node
43
- result_data = self._execute_like(node, field, pattern, path, context)
44
-
45
- return ExecutionResult(
46
- success=True,
47
- data=result_data,
48
- operation=self.OPERATION_NAME,
49
- metadata={'matched_count': len(result_data.get('items', []))}
50
- )
51
-
52
- def _execute_like(self, node: Any, field: str, pattern: str, path: str, context: ExecutionContext) -> Dict:
53
- """Execute LIKE pattern matching."""
54
- matched_items = []
55
-
56
- # Convert SQL LIKE pattern to regex
57
- # % = .* (any characters)
58
- # _ = . (single character)
59
- regex_pattern = pattern.replace('%', '.*').replace('_', '.')
60
- regex = re.compile(regex_pattern, re.IGNORECASE)
61
-
62
- # Get data
63
- if path:
64
- data = node.get(path, default=[])
65
- else:
66
- data = node.to_native()
67
-
68
- # Match pattern
69
- if isinstance(data, list):
70
- for item in data:
71
- value = item.get(field) if isinstance(item, dict) else str(item)
72
- if value and regex.match(str(value)):
73
- matched_items.append(item)
74
-
75
- return {'items': matched_items, 'count': len(matched_items), 'pattern': pattern}
76
-