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,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.21
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.21
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.21
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.21
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.21
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.21
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.21
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
-