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.
- exonware/__init__.py +1 -1
- exonware/xwnode/__init__.py +18 -5
- exonware/xwnode/add_strategy_types.py +165 -0
- exonware/xwnode/common/__init__.py +1 -1
- exonware/xwnode/common/graph/__init__.py +30 -0
- exonware/xwnode/common/graph/caching.py +131 -0
- exonware/xwnode/common/graph/contracts.py +100 -0
- exonware/xwnode/common/graph/errors.py +44 -0
- exonware/xwnode/common/graph/indexing.py +260 -0
- exonware/xwnode/common/graph/manager.py +568 -0
- exonware/xwnode/common/management/__init__.py +3 -5
- exonware/xwnode/common/management/manager.py +2 -2
- exonware/xwnode/common/management/migration.py +3 -3
- exonware/xwnode/common/monitoring/__init__.py +3 -5
- exonware/xwnode/common/monitoring/metrics.py +6 -2
- exonware/xwnode/common/monitoring/pattern_detector.py +1 -1
- exonware/xwnode/common/monitoring/performance_monitor.py +5 -1
- exonware/xwnode/common/patterns/__init__.py +3 -5
- exonware/xwnode/common/patterns/flyweight.py +5 -1
- exonware/xwnode/common/patterns/registry.py +202 -183
- exonware/xwnode/common/utils/__init__.py +25 -11
- exonware/xwnode/common/utils/simple.py +1 -1
- exonware/xwnode/config.py +3 -8
- exonware/xwnode/contracts.py +4 -105
- exonware/xwnode/defs.py +413 -159
- exonware/xwnode/edges/strategies/__init__.py +86 -4
- exonware/xwnode/edges/strategies/_base_edge.py +2 -2
- exonware/xwnode/edges/strategies/adj_list.py +287 -121
- exonware/xwnode/edges/strategies/adj_matrix.py +316 -222
- exonware/xwnode/edges/strategies/base.py +1 -1
- exonware/xwnode/edges/strategies/{edge_bidir_wrapper.py → bidir_wrapper.py} +45 -4
- exonware/xwnode/edges/strategies/bitemporal.py +520 -0
- exonware/xwnode/edges/strategies/{edge_block_adj_matrix.py → block_adj_matrix.py} +77 -6
- exonware/xwnode/edges/strategies/bv_graph.py +664 -0
- exonware/xwnode/edges/strategies/compressed_graph.py +217 -0
- exonware/xwnode/edges/strategies/{edge_coo.py → coo.py} +46 -4
- exonware/xwnode/edges/strategies/{edge_csc.py → csc.py} +45 -4
- exonware/xwnode/edges/strategies/{edge_csr.py → csr.py} +94 -12
- exonware/xwnode/edges/strategies/{edge_dynamic_adj_list.py → dynamic_adj_list.py} +46 -4
- exonware/xwnode/edges/strategies/edge_list.py +168 -0
- exonware/xwnode/edges/strategies/edge_property_store.py +2 -2
- exonware/xwnode/edges/strategies/euler_tour.py +560 -0
- exonware/xwnode/edges/strategies/{edge_flow_network.py → flow_network.py} +2 -2
- exonware/xwnode/edges/strategies/graphblas.py +449 -0
- exonware/xwnode/edges/strategies/hnsw.py +637 -0
- exonware/xwnode/edges/strategies/hop2_labels.py +467 -0
- exonware/xwnode/edges/strategies/{edge_hyperedge_set.py → hyperedge_set.py} +2 -2
- exonware/xwnode/edges/strategies/incidence_matrix.py +250 -0
- exonware/xwnode/edges/strategies/k2_tree.py +613 -0
- exonware/xwnode/edges/strategies/link_cut.py +626 -0
- exonware/xwnode/edges/strategies/multiplex.py +532 -0
- exonware/xwnode/edges/strategies/{edge_neural_graph.py → neural_graph.py} +2 -2
- exonware/xwnode/edges/strategies/{edge_octree.py → octree.py} +69 -11
- exonware/xwnode/edges/strategies/{edge_quadtree.py → quadtree.py} +66 -10
- exonware/xwnode/edges/strategies/roaring_adj.py +438 -0
- exonware/xwnode/edges/strategies/{edge_rtree.py → rtree.py} +43 -5
- exonware/xwnode/edges/strategies/{edge_temporal_edgeset.py → temporal_edgeset.py} +24 -5
- exonware/xwnode/edges/strategies/{edge_tree_graph_basic.py → tree_graph_basic.py} +78 -7
- exonware/xwnode/edges/strategies/{edge_weighted_graph.py → weighted_graph.py} +188 -10
- exonware/xwnode/errors.py +3 -6
- exonware/xwnode/facade.py +20 -20
- exonware/xwnode/nodes/strategies/__init__.py +29 -9
- exonware/xwnode/nodes/strategies/adjacency_list.py +650 -177
- exonware/xwnode/nodes/strategies/aho_corasick.py +358 -183
- exonware/xwnode/nodes/strategies/array_list.py +36 -3
- exonware/xwnode/nodes/strategies/art.py +581 -0
- exonware/xwnode/nodes/strategies/{node_avl_tree.py → avl_tree.py} +77 -6
- exonware/xwnode/nodes/strategies/{node_b_plus_tree.py → b_plus_tree.py} +81 -40
- exonware/xwnode/nodes/strategies/{node_btree.py → b_tree.py} +79 -9
- exonware/xwnode/nodes/strategies/base.py +469 -98
- exonware/xwnode/nodes/strategies/{node_bitmap.py → bitmap.py} +12 -12
- exonware/xwnode/nodes/strategies/{node_bitset_dynamic.py → bitset_dynamic.py} +11 -11
- exonware/xwnode/nodes/strategies/{node_bloom_filter.py → bloom_filter.py} +15 -2
- exonware/xwnode/nodes/strategies/bloomier_filter.py +519 -0
- exonware/xwnode/nodes/strategies/bw_tree.py +531 -0
- exonware/xwnode/nodes/strategies/contracts.py +1 -1
- exonware/xwnode/nodes/strategies/{node_count_min_sketch.py → count_min_sketch.py} +3 -2
- exonware/xwnode/nodes/strategies/{node_cow_tree.py → cow_tree.py} +135 -13
- exonware/xwnode/nodes/strategies/crdt_map.py +629 -0
- exonware/xwnode/nodes/strategies/{node_cuckoo_hash.py → cuckoo_hash.py} +2 -2
- exonware/xwnode/nodes/strategies/{node_xdata_optimized.py → data_interchange_optimized.py} +21 -4
- exonware/xwnode/nodes/strategies/dawg.py +876 -0
- exonware/xwnode/nodes/strategies/deque.py +321 -153
- exonware/xwnode/nodes/strategies/extendible_hash.py +93 -0
- exonware/xwnode/nodes/strategies/{node_fenwick_tree.py → fenwick_tree.py} +111 -19
- exonware/xwnode/nodes/strategies/hamt.py +403 -0
- exonware/xwnode/nodes/strategies/hash_map.py +354 -67
- exonware/xwnode/nodes/strategies/heap.py +105 -5
- exonware/xwnode/nodes/strategies/hopscotch_hash.py +525 -0
- exonware/xwnode/nodes/strategies/{node_hyperloglog.py → hyperloglog.py} +6 -5
- exonware/xwnode/nodes/strategies/interval_tree.py +742 -0
- exonware/xwnode/nodes/strategies/kd_tree.py +703 -0
- exonware/xwnode/nodes/strategies/learned_index.py +533 -0
- exonware/xwnode/nodes/strategies/linear_hash.py +93 -0
- exonware/xwnode/nodes/strategies/linked_list.py +316 -119
- exonware/xwnode/nodes/strategies/{node_lsm_tree.py → lsm_tree.py} +219 -15
- exonware/xwnode/nodes/strategies/masstree.py +130 -0
- exonware/xwnode/nodes/strategies/{node_persistent_tree.py → persistent_tree.py} +149 -9
- exonware/xwnode/nodes/strategies/priority_queue.py +544 -132
- exonware/xwnode/nodes/strategies/queue.py +249 -120
- exonware/xwnode/nodes/strategies/{node_red_black_tree.py → red_black_tree.py} +183 -72
- exonware/xwnode/nodes/strategies/{node_roaring_bitmap.py → roaring_bitmap.py} +19 -6
- exonware/xwnode/nodes/strategies/rope.py +717 -0
- exonware/xwnode/nodes/strategies/{node_segment_tree.py → segment_tree.py} +106 -106
- exonware/xwnode/nodes/strategies/{node_set_hash.py → set_hash.py} +30 -29
- exonware/xwnode/nodes/strategies/{node_skip_list.py → skip_list.py} +74 -6
- exonware/xwnode/nodes/strategies/sparse_matrix.py +427 -131
- exonware/xwnode/nodes/strategies/{node_splay_tree.py → splay_tree.py} +55 -6
- exonware/xwnode/nodes/strategies/stack.py +244 -112
- exonware/xwnode/nodes/strategies/{node_suffix_array.py → suffix_array.py} +5 -1
- exonware/xwnode/nodes/strategies/t_tree.py +94 -0
- exonware/xwnode/nodes/strategies/{node_treap.py → treap.py} +75 -6
- exonware/xwnode/nodes/strategies/{node_tree_graph_hybrid.py → tree_graph_hybrid.py} +46 -5
- exonware/xwnode/nodes/strategies/trie.py +153 -9
- exonware/xwnode/nodes/strategies/union_find.py +111 -5
- exonware/xwnode/nodes/strategies/veb_tree.py +856 -0
- exonware/xwnode/strategies/__init__.py +5 -51
- exonware/xwnode/version.py +3 -3
- exonware_xwnode-0.0.1.24.dist-info/METADATA +900 -0
- exonware_xwnode-0.0.1.24.dist-info/RECORD +130 -0
- exonware/xwnode/edges/strategies/edge_adj_list.py +0 -353
- exonware/xwnode/edges/strategies/edge_adj_matrix.py +0 -445
- exonware/xwnode/nodes/strategies/_base_node.py +0 -307
- exonware/xwnode/nodes/strategies/node_aho_corasick.py +0 -525
- exonware/xwnode/nodes/strategies/node_array_list.py +0 -179
- exonware/xwnode/nodes/strategies/node_hash_map.py +0 -273
- exonware/xwnode/nodes/strategies/node_heap.py +0 -196
- exonware/xwnode/nodes/strategies/node_linked_list.py +0 -413
- exonware/xwnode/nodes/strategies/node_trie.py +0 -257
- exonware/xwnode/nodes/strategies/node_union_find.py +0 -192
- exonware/xwnode/queries/executors/__init__.py +0 -47
- exonware/xwnode/queries/executors/advanced/__init__.py +0 -37
- exonware/xwnode/queries/executors/advanced/aggregate_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/ask_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/construct_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/describe_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/for_loop_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/foreach_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/join_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/let_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/mutation_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/options_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/pipe_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/subscribe_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/subscription_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/union_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/window_executor.py +0 -51
- exonware/xwnode/queries/executors/advanced/with_cte_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/__init__.py +0 -21
- exonware/xwnode/queries/executors/aggregation/avg_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/count_executor.py +0 -38
- exonware/xwnode/queries/executors/aggregation/distinct_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/group_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/having_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/max_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/min_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/sum_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/summarize_executor.py +0 -50
- exonware/xwnode/queries/executors/array/__init__.py +0 -9
- exonware/xwnode/queries/executors/array/indexing_executor.py +0 -51
- exonware/xwnode/queries/executors/array/slicing_executor.py +0 -51
- exonware/xwnode/queries/executors/base.py +0 -257
- exonware/xwnode/queries/executors/capability_checker.py +0 -204
- exonware/xwnode/queries/executors/contracts.py +0 -166
- exonware/xwnode/queries/executors/core/__init__.py +0 -17
- exonware/xwnode/queries/executors/core/create_executor.py +0 -96
- exonware/xwnode/queries/executors/core/delete_executor.py +0 -99
- exonware/xwnode/queries/executors/core/drop_executor.py +0 -100
- exonware/xwnode/queries/executors/core/insert_executor.py +0 -39
- exonware/xwnode/queries/executors/core/select_executor.py +0 -152
- exonware/xwnode/queries/executors/core/update_executor.py +0 -102
- exonware/xwnode/queries/executors/data/__init__.py +0 -13
- exonware/xwnode/queries/executors/data/alter_executor.py +0 -50
- exonware/xwnode/queries/executors/data/load_executor.py +0 -50
- exonware/xwnode/queries/executors/data/merge_executor.py +0 -50
- exonware/xwnode/queries/executors/data/store_executor.py +0 -50
- exonware/xwnode/queries/executors/defs.py +0 -93
- exonware/xwnode/queries/executors/engine.py +0 -221
- exonware/xwnode/queries/executors/errors.py +0 -68
- exonware/xwnode/queries/executors/filtering/__init__.py +0 -25
- exonware/xwnode/queries/executors/filtering/between_executor.py +0 -80
- exonware/xwnode/queries/executors/filtering/filter_executor.py +0 -79
- exonware/xwnode/queries/executors/filtering/has_executor.py +0 -70
- exonware/xwnode/queries/executors/filtering/in_executor.py +0 -70
- exonware/xwnode/queries/executors/filtering/like_executor.py +0 -76
- exonware/xwnode/queries/executors/filtering/optional_executor.py +0 -76
- exonware/xwnode/queries/executors/filtering/range_executor.py +0 -80
- exonware/xwnode/queries/executors/filtering/term_executor.py +0 -77
- exonware/xwnode/queries/executors/filtering/values_executor.py +0 -71
- exonware/xwnode/queries/executors/filtering/where_executor.py +0 -44
- exonware/xwnode/queries/executors/graph/__init__.py +0 -15
- exonware/xwnode/queries/executors/graph/in_traverse_executor.py +0 -51
- exonware/xwnode/queries/executors/graph/match_executor.py +0 -51
- exonware/xwnode/queries/executors/graph/out_executor.py +0 -51
- exonware/xwnode/queries/executors/graph/path_executor.py +0 -51
- exonware/xwnode/queries/executors/graph/return_executor.py +0 -51
- exonware/xwnode/queries/executors/ordering/__init__.py +0 -9
- exonware/xwnode/queries/executors/ordering/by_executor.py +0 -50
- exonware/xwnode/queries/executors/ordering/order_executor.py +0 -51
- exonware/xwnode/queries/executors/projection/__init__.py +0 -9
- exonware/xwnode/queries/executors/projection/extend_executor.py +0 -50
- exonware/xwnode/queries/executors/projection/project_executor.py +0 -50
- exonware/xwnode/queries/executors/registry.py +0 -173
- exonware/xwnode/queries/parsers/__init__.py +0 -26
- exonware/xwnode/queries/parsers/base.py +0 -86
- exonware/xwnode/queries/parsers/contracts.py +0 -46
- exonware/xwnode/queries/parsers/errors.py +0 -53
- exonware/xwnode/queries/parsers/sql_param_extractor.py +0 -318
- exonware/xwnode/queries/strategies/__init__.py +0 -24
- exonware/xwnode/queries/strategies/base.py +0 -236
- exonware/xwnode/queries/strategies/cql.py +0 -201
- exonware/xwnode/queries/strategies/cypher.py +0 -181
- exonware/xwnode/queries/strategies/datalog.py +0 -70
- exonware/xwnode/queries/strategies/elastic_dsl.py +0 -70
- exonware/xwnode/queries/strategies/eql.py +0 -70
- exonware/xwnode/queries/strategies/flux.py +0 -70
- exonware/xwnode/queries/strategies/gql.py +0 -70
- exonware/xwnode/queries/strategies/graphql.py +0 -240
- exonware/xwnode/queries/strategies/gremlin.py +0 -181
- exonware/xwnode/queries/strategies/hiveql.py +0 -214
- exonware/xwnode/queries/strategies/hql.py +0 -70
- exonware/xwnode/queries/strategies/jmespath.py +0 -219
- exonware/xwnode/queries/strategies/jq.py +0 -66
- exonware/xwnode/queries/strategies/json_query.py +0 -66
- exonware/xwnode/queries/strategies/jsoniq.py +0 -248
- exonware/xwnode/queries/strategies/kql.py +0 -70
- exonware/xwnode/queries/strategies/linq.py +0 -238
- exonware/xwnode/queries/strategies/logql.py +0 -70
- exonware/xwnode/queries/strategies/mql.py +0 -68
- exonware/xwnode/queries/strategies/n1ql.py +0 -210
- exonware/xwnode/queries/strategies/partiql.py +0 -70
- exonware/xwnode/queries/strategies/pig.py +0 -215
- exonware/xwnode/queries/strategies/promql.py +0 -70
- exonware/xwnode/queries/strategies/sparql.py +0 -220
- exonware/xwnode/queries/strategies/sql.py +0 -275
- exonware/xwnode/queries/strategies/xml_query.py +0 -66
- exonware/xwnode/queries/strategies/xpath.py +0 -223
- exonware/xwnode/queries/strategies/xquery.py +0 -258
- exonware/xwnode/queries/strategies/xwnode_executor.py +0 -332
- exonware/xwnode/queries/strategies/xwquery.py +0 -456
- exonware_xwnode-0.0.1.22.dist-info/METADATA +0 -168
- exonware_xwnode-0.0.1.22.dist-info/RECORD +0 -214
- /exonware/xwnode/nodes/strategies/{node_ordered_map.py → ordered_map.py} +0 -0
- /exonware/xwnode/nodes/strategies/{node_ordered_map_balanced.py → ordered_map_balanced.py} +0 -0
- /exonware/xwnode/nodes/strategies/{node_patricia.py → patricia.py} +0 -0
- /exonware/xwnode/nodes/strategies/{node_radix_trie.py → radix_trie.py} +0 -0
- /exonware/xwnode/nodes/strategies/{node_set_tree.py → set_tree.py} +0 -0
- {exonware_xwnode-0.0.1.22.dist-info → exonware_xwnode-0.0.1.24.dist-info}/WHEEL +0 -0
- {exonware_xwnode-0.0.1.22.dist-info → exonware_xwnode-0.0.1.24.dist-info}/licenses/LICENSE +0 -0
@@ -1,456 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
XWQuery Script Strategy
|
4
|
-
|
5
|
-
This module implements the central XWQuery Script strategy that handles all 50 action types
|
6
|
-
and provides conversion between different query formats using actions in tree format.
|
7
|
-
|
8
|
-
Company: eXonware.com
|
9
|
-
Author: Eng. Muhammad AlShehri
|
10
|
-
Email: connect@exonware.com
|
11
|
-
Version: 0.0.1.22
|
12
|
-
Generation Date: January 2, 2025
|
13
|
-
"""
|
14
|
-
|
15
|
-
import re
|
16
|
-
from abc import ABC, abstractmethod
|
17
|
-
from typing import Any, Dict, List, Optional, Union, Type
|
18
|
-
from datetime import datetime
|
19
|
-
|
20
|
-
from .base import AQueryStrategy
|
21
|
-
from ...base import XWNodeBase
|
22
|
-
from ...contracts import QueryMode, QueryTrait
|
23
|
-
from ...errors import XWNodeTypeError, XWNodeValueError
|
24
|
-
from ..parsers.sql_param_extractor import SQLParamExtractor
|
25
|
-
|
26
|
-
|
27
|
-
class XWQueryScriptStrategy(AQueryStrategy):
|
28
|
-
"""
|
29
|
-
Central script strategy using 50 action types in tree format.
|
30
|
-
|
31
|
-
This strategy serves as the universal converter between all query formats
|
32
|
-
by parsing them into a standardized action tree structure.
|
33
|
-
"""
|
34
|
-
|
35
|
-
# 50 Action Headers from XWQUERY_SCRIPT.md
|
36
|
-
ACTION_TYPES = [
|
37
|
-
# Core SQL Operations (1-45)
|
38
|
-
"SELECT", "INSERT", "UPDATE", "DELETE", "CREATE", "ALTER", "DROP",
|
39
|
-
"MERGE", "LOAD", "STORE", "WHERE", "FILTER", "OPTIONAL", "UNION",
|
40
|
-
"BETWEEN", "LIKE", "IN", "TERM", "RANGE", "HAS", "MATCH", "JOIN",
|
41
|
-
"WITH", "OUT", "IN_TRAVERSE", "PATH", "RETURN", "PROJECT", "EXTEND",
|
42
|
-
"FOREACH", "LET", "FOR", "DESCRIBE", "CONSTRUCT", "ORDER", "BY",
|
43
|
-
"GROUP", "HAVING", "SUMMARIZE", "AGGREGATE", "WINDOW", "SLICING",
|
44
|
-
"INDEXING", "ASK", "SUBSCRIBE", "SUBSCRIPTION", "MUTATION", "VALUES",
|
45
|
-
# Additional Operations (46-50)
|
46
|
-
"DISTINCT", "PIPE", "OPTIONS"
|
47
|
-
]
|
48
|
-
|
49
|
-
def __init__(self, actions_tree: Optional[XWNodeBase] = None, **options):
|
50
|
-
super().__init__(**options)
|
51
|
-
self._mode = QueryMode.AUTO
|
52
|
-
self._traits = QueryTrait.STRUCTURED | QueryTrait.ANALYTICAL | QueryTrait.BATCH
|
53
|
-
|
54
|
-
# Initialize parameter extractor for structured param extraction
|
55
|
-
self._param_extractor = SQLParamExtractor()
|
56
|
-
|
57
|
-
if actions_tree is None:
|
58
|
-
self._actions_tree = XWNodeBase.from_native({
|
59
|
-
"root": {
|
60
|
-
"type": "PROGRAM",
|
61
|
-
"statements": [],
|
62
|
-
"comments": [],
|
63
|
-
"metadata": {
|
64
|
-
"version": "1.0",
|
65
|
-
"created": datetime.now().isoformat(),
|
66
|
-
"source_format": "XWQUERY_SCRIPT"
|
67
|
-
}
|
68
|
-
}
|
69
|
-
})
|
70
|
-
else:
|
71
|
-
self._actions_tree = actions_tree
|
72
|
-
|
73
|
-
self._comments = []
|
74
|
-
self._metadata = {}
|
75
|
-
|
76
|
-
def execute(self, query: str, context: Dict[str, Any] = None, **kwargs) -> Any:
|
77
|
-
"""Execute XWQuery script."""
|
78
|
-
if not self.validate_query(query):
|
79
|
-
raise XWNodeValueError(f"Invalid XWQuery script: {query}")
|
80
|
-
|
81
|
-
# Parse and execute the script
|
82
|
-
script_strategy = self.parse_script(query)
|
83
|
-
return self._execute_actions_tree(script_strategy._actions_tree, **kwargs)
|
84
|
-
|
85
|
-
def validate_query(self, query: str) -> bool:
|
86
|
-
"""Validate XWQuery script syntax."""
|
87
|
-
if not query or not isinstance(query, str):
|
88
|
-
return False
|
89
|
-
|
90
|
-
# Basic validation - check for valid action types
|
91
|
-
query_upper = query.upper()
|
92
|
-
valid_actions = any(action in query_upper for action in self.ACTION_TYPES)
|
93
|
-
|
94
|
-
return valid_actions
|
95
|
-
|
96
|
-
def get_query_plan(self, query: str) -> Dict[str, Any]:
|
97
|
-
"""Get XWQuery script execution plan."""
|
98
|
-
return {
|
99
|
-
"query_type": "XWQUERY_SCRIPT",
|
100
|
-
"action_count": len(self._extract_actions(query)),
|
101
|
-
"complexity": self._estimate_complexity(query),
|
102
|
-
"estimated_cost": self._estimate_cost(query),
|
103
|
-
"optimization_hints": self._get_optimization_hints(query)
|
104
|
-
}
|
105
|
-
|
106
|
-
def can_handle(self, query_string: str) -> bool:
|
107
|
-
"""Check if this strategy can handle the given query string."""
|
108
|
-
return self.validate_query(query_string)
|
109
|
-
|
110
|
-
def get_supported_operations(self) -> List[str]:
|
111
|
-
"""Get list of supported query operations."""
|
112
|
-
return self.ACTION_TYPES.copy()
|
113
|
-
|
114
|
-
def estimate_complexity(self, query_string: str) -> Dict[str, Any]:
|
115
|
-
"""Estimate query complexity and resource requirements."""
|
116
|
-
actions = self._extract_actions(query_string)
|
117
|
-
complexity_level = self._estimate_complexity(query_string)
|
118
|
-
|
119
|
-
return {
|
120
|
-
"complexity": complexity_level,
|
121
|
-
"action_count": len(actions),
|
122
|
-
"estimated_cost": self._estimate_cost(query_string),
|
123
|
-
"memory_usage": "low" if complexity_level == "LOW" else "medium" if complexity_level == "MEDIUM" else "high",
|
124
|
-
"execution_time": f"{self._estimate_cost(query_string)}ms"
|
125
|
-
}
|
126
|
-
|
127
|
-
def parse_script(self, script_content: str) -> 'XWQueryScriptStrategy':
|
128
|
-
"""Parse XWQuery script content into actions tree."""
|
129
|
-
parsed_actions = self._parse_xwquery_script(script_content)
|
130
|
-
self._actions_tree = XWNodeBase.from_native(parsed_actions)
|
131
|
-
return self
|
132
|
-
|
133
|
-
def to_format(self, target_format: str) -> str:
|
134
|
-
"""Convert script to any supported format using available strategies."""
|
135
|
-
strategy_class = self._get_strategy_class(target_format)
|
136
|
-
if not strategy_class:
|
137
|
-
raise ValueError(f"No strategy available for format: {target_format}")
|
138
|
-
|
139
|
-
strategy = strategy_class()
|
140
|
-
return strategy.from_actions_tree(self._actions_tree)
|
141
|
-
|
142
|
-
def from_format(self, query_content: str, source_format: str) -> 'XWQueryScriptStrategy':
|
143
|
-
"""Create script strategy from any supported format."""
|
144
|
-
strategy_class = self._get_strategy_class(source_format)
|
145
|
-
if not strategy_class:
|
146
|
-
raise ValueError(f"No strategy available for format: {source_format}")
|
147
|
-
|
148
|
-
strategy = strategy_class()
|
149
|
-
actions_tree = strategy.to_actions_tree(query_content)
|
150
|
-
self._actions_tree = actions_tree
|
151
|
-
return self
|
152
|
-
|
153
|
-
def _parse_xwquery_script(self, script_content: str) -> Dict[str, Any]:
|
154
|
-
"""Parse XWQuery script into tree structure with nesting support."""
|
155
|
-
return {
|
156
|
-
"root": {
|
157
|
-
"type": "PROGRAM",
|
158
|
-
"statements": self._parse_statements(script_content),
|
159
|
-
"comments": self._extract_comments(script_content),
|
160
|
-
"metadata": {
|
161
|
-
"version": "1.0",
|
162
|
-
"created": datetime.now().isoformat(),
|
163
|
-
"source_format": "XWQUERY_SCRIPT"
|
164
|
-
}
|
165
|
-
}
|
166
|
-
}
|
167
|
-
|
168
|
-
def _parse_statements(self, script_content: str) -> List[Dict[str, Any]]:
|
169
|
-
"""Parse individual statements with nesting support."""
|
170
|
-
statements = []
|
171
|
-
lines = script_content.split('\n')
|
172
|
-
current_statement = None
|
173
|
-
|
174
|
-
for line_num, line in enumerate(lines, 1):
|
175
|
-
line = line.strip()
|
176
|
-
if not line or line.startswith('--'):
|
177
|
-
continue
|
178
|
-
|
179
|
-
# Parse statement based on action type
|
180
|
-
for action_type in self.ACTION_TYPES:
|
181
|
-
if line.upper().startswith(action_type):
|
182
|
-
statement = self._parse_statement_line(line, action_type, line_num)
|
183
|
-
if statement:
|
184
|
-
statements.append(statement)
|
185
|
-
break
|
186
|
-
|
187
|
-
return statements
|
188
|
-
|
189
|
-
def _parse_statement_line(self, line: str, action_type: str, line_num: int) -> Optional[Dict[str, Any]]:
|
190
|
-
"""
|
191
|
-
Parse a single statement line and extract structured parameters.
|
192
|
-
|
193
|
-
This now extracts structured params for executors instead of just storing raw text.
|
194
|
-
Follows DEV_GUIDELINES.md: proper parameter extraction for clean execution.
|
195
|
-
"""
|
196
|
-
# Extract structured parameters using the param extractor
|
197
|
-
params = self._param_extractor.extract_params(line, action_type)
|
198
|
-
|
199
|
-
return {
|
200
|
-
"type": action_type,
|
201
|
-
"id": f"action_{line_num}",
|
202
|
-
"params": params, # Now structured!
|
203
|
-
"content": line, # Keep raw for reference
|
204
|
-
"line_number": line_num,
|
205
|
-
"timestamp": datetime.now().isoformat(),
|
206
|
-
"children": [] # For nested actions
|
207
|
-
}
|
208
|
-
|
209
|
-
def _extract_comments(self, script_content: str) -> List[Dict[str, Any]]:
|
210
|
-
"""Extract comments from script content."""
|
211
|
-
comments = []
|
212
|
-
lines = script_content.split('\n')
|
213
|
-
|
214
|
-
for line_num, line in enumerate(lines, 1):
|
215
|
-
if line.strip().startswith('--'):
|
216
|
-
comments.append({
|
217
|
-
"text": line.strip(),
|
218
|
-
"line_number": line_num,
|
219
|
-
"timestamp": datetime.now().isoformat()
|
220
|
-
})
|
221
|
-
|
222
|
-
return comments
|
223
|
-
|
224
|
-
def _extract_actions(self, query: str) -> List[str]:
|
225
|
-
"""Extract action types from query."""
|
226
|
-
actions = []
|
227
|
-
query_upper = query.upper()
|
228
|
-
|
229
|
-
for action_type in self.ACTION_TYPES:
|
230
|
-
if action_type in query_upper:
|
231
|
-
actions.append(action_type)
|
232
|
-
|
233
|
-
return actions
|
234
|
-
|
235
|
-
def _estimate_complexity(self, query: str) -> str:
|
236
|
-
"""Estimate query complexity."""
|
237
|
-
actions = self._extract_actions(query)
|
238
|
-
|
239
|
-
if len(actions) > 10:
|
240
|
-
return "HIGH"
|
241
|
-
elif len(actions) > 5:
|
242
|
-
return "MEDIUM"
|
243
|
-
else:
|
244
|
-
return "LOW"
|
245
|
-
|
246
|
-
def _estimate_cost(self, query: str) -> int:
|
247
|
-
"""Estimate query cost."""
|
248
|
-
complexity = self._estimate_complexity(query)
|
249
|
-
if complexity == "HIGH":
|
250
|
-
return 100
|
251
|
-
elif complexity == "MEDIUM":
|
252
|
-
return 50
|
253
|
-
else:
|
254
|
-
return 10
|
255
|
-
|
256
|
-
def _get_optimization_hints(self, query: str) -> List[str]:
|
257
|
-
"""Get query optimization hints."""
|
258
|
-
hints = []
|
259
|
-
|
260
|
-
if "SELECT *" in query.upper():
|
261
|
-
hints.append("Consider specifying columns instead of using *")
|
262
|
-
if "WHERE" not in query.upper() and "SELECT" in query.upper():
|
263
|
-
hints.append("Consider adding WHERE clause to limit results")
|
264
|
-
|
265
|
-
return hints
|
266
|
-
|
267
|
-
def _get_strategy_class(self, format_name: str) -> Optional[Type[AQueryStrategy]]:
|
268
|
-
"""Get strategy class for format using XWNode's strategy registry."""
|
269
|
-
from ..registry import get_strategy_registry
|
270
|
-
registry = get_strategy_registry()
|
271
|
-
return registry.get_query_strategy(format_name.upper())
|
272
|
-
|
273
|
-
def _get_strategy_class_fallback(self, format_name: str) -> Optional[Type[AQueryStrategy]]:
|
274
|
-
"""Fallback strategy class lookup."""
|
275
|
-
strategy_map = {
|
276
|
-
"SQL": "sql",
|
277
|
-
"GRAPHQL": "graphql",
|
278
|
-
"CYPHER": "cypher",
|
279
|
-
"SPARQL": "sparql",
|
280
|
-
"JSON_QUERY": "json_query",
|
281
|
-
"XML_QUERY": "xml_query",
|
282
|
-
"XPATH": "xpath",
|
283
|
-
"XQUERY": "xquery",
|
284
|
-
"JQ": "jq",
|
285
|
-
"JMESPATH": "jmespath",
|
286
|
-
"JSONIQ": "jsoniq",
|
287
|
-
"GREMLIN": "gremlin",
|
288
|
-
"ELASTIC_DSL": "elastic_dsl",
|
289
|
-
"EQL": "eql",
|
290
|
-
"FLUX": "flux",
|
291
|
-
"PROMQL": "promql",
|
292
|
-
"LOGQL": "logql",
|
293
|
-
"SPL": "spl",
|
294
|
-
"KQL": "kql",
|
295
|
-
"CQL": "cql",
|
296
|
-
"N1QL": "n1ql",
|
297
|
-
"HIVEQL": "hiveql",
|
298
|
-
"PIG": "pig",
|
299
|
-
"MQL": "mql",
|
300
|
-
"PARTIQL": "partiql",
|
301
|
-
"LINQ": "linq",
|
302
|
-
"HQL": "hql",
|
303
|
-
"DATALOG": "datalog",
|
304
|
-
"KSQL": "ksql",
|
305
|
-
"GQL": "gql"
|
306
|
-
}
|
307
|
-
|
308
|
-
module_name = strategy_map.get(format_name.upper())
|
309
|
-
if module_name:
|
310
|
-
try:
|
311
|
-
module = __import__(f'.{module_name}', fromlist=['.'], package=__package__)
|
312
|
-
strategy_class_name = f"{format_name.title()}Strategy"
|
313
|
-
return getattr(module, strategy_class_name, None)
|
314
|
-
except (ImportError, AttributeError):
|
315
|
-
pass
|
316
|
-
|
317
|
-
return None
|
318
|
-
|
319
|
-
def _execute_actions_tree(self, actions_tree: XWNodeBase, **kwargs) -> Any:
|
320
|
-
"""
|
321
|
-
Execute actions tree - delegates to ExecutionEngine.
|
322
|
-
|
323
|
-
This method is kept for backward compatibility but should use ExecutionEngine.
|
324
|
-
Real execution happens in queries/executors/engine.py
|
325
|
-
"""
|
326
|
-
# Import here to avoid circular dependency
|
327
|
-
from ..executors.engine import ExecutionEngine
|
328
|
-
from ..executors.contracts import ExecutionContext
|
329
|
-
|
330
|
-
# Get or create node from kwargs
|
331
|
-
node = kwargs.get('node')
|
332
|
-
if node is None:
|
333
|
-
raise XWNodeValueError("Node is required for execution")
|
334
|
-
|
335
|
-
# Create execution context
|
336
|
-
context = ExecutionContext(
|
337
|
-
node=node,
|
338
|
-
variables=kwargs.get('variables', {}),
|
339
|
-
options=kwargs
|
340
|
-
)
|
341
|
-
|
342
|
-
# Use real ExecutionEngine
|
343
|
-
engine = ExecutionEngine()
|
344
|
-
result = engine.execute_actions_tree(actions_tree, context)
|
345
|
-
|
346
|
-
return result.data if result.success else {'error': result.error}
|
347
|
-
|
348
|
-
def add_action(self, action_type: str, **action_params) -> 'XWQueryScriptStrategy':
|
349
|
-
"""Add an action to the actions tree with proper nesting."""
|
350
|
-
if action_type not in self.ACTION_TYPES:
|
351
|
-
raise ValueError(f"Unknown action type: {action_type}")
|
352
|
-
|
353
|
-
action = {
|
354
|
-
"type": action_type,
|
355
|
-
"id": f"action_{len(self._get_all_actions())}",
|
356
|
-
"params": action_params,
|
357
|
-
"timestamp": datetime.now().isoformat(),
|
358
|
-
"children": []
|
359
|
-
}
|
360
|
-
|
361
|
-
# Get current statements and add new action
|
362
|
-
root_data = self._actions_tree.to_native()
|
363
|
-
if 'root' not in root_data:
|
364
|
-
root_data['root'] = {"statements": [], "comments": [], "metadata": {}}
|
365
|
-
|
366
|
-
if 'statements' not in root_data['root']:
|
367
|
-
root_data['root']['statements'] = []
|
368
|
-
|
369
|
-
root_data['root']['statements'].append(action)
|
370
|
-
|
371
|
-
# Update the actions tree
|
372
|
-
self._actions_tree = XWNodeBase.from_native(root_data)
|
373
|
-
|
374
|
-
return self
|
375
|
-
|
376
|
-
def add_nested_action(self, parent_action_id: str, action_type: str, **action_params) -> 'XWQueryScriptStrategy':
|
377
|
-
"""Add a nested action (e.g., subquery, JOIN condition)."""
|
378
|
-
parent = self._find_action_by_id(parent_action_id)
|
379
|
-
if parent:
|
380
|
-
child_action = {
|
381
|
-
"type": action_type,
|
382
|
-
"id": f"action_{len(self._get_all_actions())}",
|
383
|
-
"params": action_params,
|
384
|
-
"timestamp": datetime.now().isoformat(),
|
385
|
-
"children": []
|
386
|
-
}
|
387
|
-
parent.get('children', []).append(child_action)
|
388
|
-
|
389
|
-
return self
|
390
|
-
|
391
|
-
def _find_action_by_id(self, action_id: str) -> Optional[Dict[str, Any]]:
|
392
|
-
"""Find action by ID in the tree."""
|
393
|
-
return self._search_tree(self._actions_tree, action_id)
|
394
|
-
|
395
|
-
def _search_tree(self, node: XWNodeBase, action_id: str) -> Optional[Dict[str, Any]]:
|
396
|
-
"""Recursively search for action in tree."""
|
397
|
-
if isinstance(node, XWNodeBase):
|
398
|
-
node_data = node.to_native()
|
399
|
-
else:
|
400
|
-
node_data = node
|
401
|
-
|
402
|
-
if isinstance(node_data, dict):
|
403
|
-
if node_data.get('id') == action_id:
|
404
|
-
return node_data
|
405
|
-
|
406
|
-
for key, value in node_data.items():
|
407
|
-
if isinstance(value, (list, dict)):
|
408
|
-
result = self._search_tree(value, action_id)
|
409
|
-
if result:
|
410
|
-
return result
|
411
|
-
|
412
|
-
elif isinstance(node_data, list):
|
413
|
-
for item in node_data:
|
414
|
-
result = self._search_tree(item, action_id)
|
415
|
-
if result:
|
416
|
-
return result
|
417
|
-
|
418
|
-
return None
|
419
|
-
|
420
|
-
def _get_all_actions(self) -> List[Dict[str, Any]]:
|
421
|
-
"""Get all actions from the tree (flattened)."""
|
422
|
-
actions = []
|
423
|
-
self._flatten_tree(self._actions_tree, actions)
|
424
|
-
return actions
|
425
|
-
|
426
|
-
def _flatten_tree(self, node: XWNodeBase, actions: List[Dict[str, Any]]):
|
427
|
-
"""Flatten the tree to get all actions."""
|
428
|
-
if isinstance(node, XWNodeBase):
|
429
|
-
node_data = node.to_native()
|
430
|
-
else:
|
431
|
-
node_data = node
|
432
|
-
|
433
|
-
if isinstance(node_data, dict):
|
434
|
-
if 'type' in node_data and 'id' in node_data:
|
435
|
-
actions.append(node_data)
|
436
|
-
|
437
|
-
for value in node_data.values():
|
438
|
-
if isinstance(value, (list, dict)):
|
439
|
-
self._flatten_tree(value, actions)
|
440
|
-
|
441
|
-
elif isinstance(node_data, list):
|
442
|
-
for item in node_data:
|
443
|
-
self._flatten_tree(item, actions)
|
444
|
-
|
445
|
-
def get_actions_tree(self) -> XWNodeBase:
|
446
|
-
"""Get the actions tree as XWNodeBase."""
|
447
|
-
return self._actions_tree
|
448
|
-
|
449
|
-
def to_native(self) -> Dict[str, Any]:
|
450
|
-
"""Convert to native Python object."""
|
451
|
-
return {
|
452
|
-
"actions_tree": self._actions_tree.to_native(),
|
453
|
-
"comments": self._comments,
|
454
|
-
"metadata": self._metadata,
|
455
|
-
"action_types": self.ACTION_TYPES
|
456
|
-
}
|
@@ -1,168 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.4
|
2
|
-
Name: exonware-xwnode
|
3
|
-
Version: 0.0.1.22
|
4
|
-
Summary: Node-based data processing and graph computation library
|
5
|
-
Project-URL: Homepage, https://exonware.com
|
6
|
-
Project-URL: Repository, https://github.com/exonware/xwnode
|
7
|
-
Project-URL: Documentation, https://github.com/exonware/xwnode#readme
|
8
|
-
Author-email: "Eng. Muhammad AlShehri" <connect@exonware.com>
|
9
|
-
License: MIT
|
10
|
-
License-File: LICENSE
|
11
|
-
Keywords: computation,data-processing,exonware,graph,node,workflow
|
12
|
-
Classifier: Development Status :: 3 - Alpha
|
13
|
-
Classifier: Intended Audience :: Developers
|
14
|
-
Classifier: License :: OSI Approved :: MIT License
|
15
|
-
Classifier: Operating System :: OS Independent
|
16
|
-
Classifier: Programming Language :: Python :: 3
|
17
|
-
Classifier: Programming Language :: Python :: 3.8
|
18
|
-
Classifier: Programming Language :: Python :: 3.9
|
19
|
-
Classifier: Programming Language :: Python :: 3.10
|
20
|
-
Classifier: Programming Language :: Python :: 3.11
|
21
|
-
Classifier: Programming Language :: Python :: 3.12
|
22
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
23
|
-
Requires-Python: >=3.8
|
24
|
-
Requires-Dist: exonware-xwsystem
|
25
|
-
Provides-Extra: dev
|
26
|
-
Requires-Dist: black>=23.0.0; extra == 'dev'
|
27
|
-
Requires-Dist: isort>=5.12.0; extra == 'dev'
|
28
|
-
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
29
|
-
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
30
|
-
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
|
31
|
-
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
32
|
-
Provides-Extra: full
|
33
|
-
Requires-Dist: exonware-xwsystem[full]; extra == 'full'
|
34
|
-
Provides-Extra: lazy
|
35
|
-
Requires-Dist: exonware-xwsystem[lazy]; extra == 'lazy'
|
36
|
-
Description-Content-Type: text/markdown
|
37
|
-
|
38
|
-
# 🚀 **xwnode: Node-Based Data Processing Library**
|
39
|
-
|
40
|
-
**Company:** eXonware.com
|
41
|
-
**Author:** Eng. Muhammad AlShehri
|
42
|
-
**Email:** connect@exonware.com
|
43
|
-
**Version:** 0.0.1.22
|
44
|
-
|
45
|
-
## 🎯 **What is xwnode?**
|
46
|
-
|
47
|
-
xwnode is a powerful Python library for node-based data processing and graph computation. It provides a flexible framework for building data processing workflows using interconnected nodes, enabling complex data transformations and computations through an intuitive graph-based approach.
|
48
|
-
|
49
|
-
## ⚡ **Quick Start**
|
50
|
-
|
51
|
-
### **Installation**
|
52
|
-
|
53
|
-
xwnode offers three installation modes to match your needs:
|
54
|
-
|
55
|
-
#### **Default (Lite) - Minimal Installation**
|
56
|
-
```bash
|
57
|
-
pip install exonware-xwnode
|
58
|
-
# or
|
59
|
-
pip install xwnode
|
60
|
-
```
|
61
|
-
- ✅ Core node functionality
|
62
|
-
- ✅ Basic graph operations
|
63
|
-
- ✅ Essential data processing
|
64
|
-
- ✅ Zero external dependencies (beyond xwsystem)
|
65
|
-
|
66
|
-
#### **Lazy - Auto-Install on Demand**
|
67
|
-
```bash
|
68
|
-
pip install exonware-xwnode[lazy]
|
69
|
-
# or
|
70
|
-
pip install xwnode[lazy]
|
71
|
-
```
|
72
|
-
- ✅ Everything from default
|
73
|
-
- ✅ Automatic dependency installation
|
74
|
-
- ✅ Enterprise serialization on-demand
|
75
|
-
- ✅ Performance monitoring when needed
|
76
|
-
|
77
|
-
#### **Full - Complete Feature Set**
|
78
|
-
```bash
|
79
|
-
pip install exonware-xwnode[full]
|
80
|
-
# or
|
81
|
-
pip install xwnode[full]
|
82
|
-
```
|
83
|
-
- ✅ Everything from lazy
|
84
|
-
- ✅ All xwsystem serialization formats (50+)
|
85
|
-
- ✅ Advanced security features
|
86
|
-
- ✅ Performance monitoring
|
87
|
-
- ✅ Enterprise-grade capabilities
|
88
|
-
|
89
|
-
### **Basic Usage**
|
90
|
-
```python
|
91
|
-
from exonware.xwnode import XWNode, XWQuery, XWFactory
|
92
|
-
# Or use convenience import:
|
93
|
-
# import xwnode
|
94
|
-
|
95
|
-
# Your node-based processing code here
|
96
|
-
node = XWNode({'data': 'example'})
|
97
|
-
```
|
98
|
-
|
99
|
-
## 🎯 **Perfect For:**
|
100
|
-
|
101
|
-
- **🔄 Data Processing Pipelines** - Build complex data transformation workflows
|
102
|
-
- **📊 Graph Computation** - Process data through interconnected node networks
|
103
|
-
- **🔀 Workflow Management** - Create reusable processing components
|
104
|
-
- **🧠 Algorithm Development** - Implement graph-based algorithms and computations
|
105
|
-
- **🔗 System Integration** - Connect different data processing stages
|
106
|
-
|
107
|
-
## 🚀 **Key Features**
|
108
|
-
|
109
|
-
✅ **Node-based architecture** for modular data processing
|
110
|
-
✅ **Graph computation engine** for complex workflows
|
111
|
-
✅ **Flexible data flow** between processing nodes
|
112
|
-
✅ **Reusable components** for common operations
|
113
|
-
✅ **Performance optimized** for large-scale processing
|
114
|
-
✅ **Easy integration** with existing Python data tools
|
115
|
-
|
116
|
-
## 🚀 **Project Phases**
|
117
|
-
|
118
|
-
xWNode follows a structured 5-phase development approach designed to deliver enterprise-grade functionality while maintaining rapid iteration and continuous improvement.
|
119
|
-
|
120
|
-
### **Current Phase: 🧪 Version 0 - Experimental Stage**
|
121
|
-
- **Focus:** Fast applications & usage, refactoring to perfection of software patterns and design
|
122
|
-
- **Status:** 🟢 **ACTIVE** - Foundation complete with core node functionality, graph traversal algorithms, and comprehensive testing
|
123
|
-
|
124
|
-
### **Development Roadmap:**
|
125
|
-
- **Version 1 (Q1 2026):** Production Ready - Enterprise deployment and hardening
|
126
|
-
- **Version 2 (Q2 2026):** Mars Standard Draft Implementation - Cross-platform interoperability
|
127
|
-
- **Version 3 (Q3 2026):** RUST Core & Facades - High-performance multi-language support
|
128
|
-
- **Version 4 (Q4 2026):** Mars Standard Implementation - Full compliance and enterprise deployment
|
129
|
-
|
130
|
-
📖 **[View Complete Project Phases Documentation](docs/PROJECT_PHASES.md)**
|
131
|
-
|
132
|
-
## 📚 **Documentation**
|
133
|
-
|
134
|
-
- **[API Documentation](docs/)** - Complete reference and examples
|
135
|
-
- **[Examples](examples/)** - Practical usage examples
|
136
|
-
- **[Tests](tests/)** - Test suites and usage patterns
|
137
|
-
|
138
|
-
## 🔧 **Development**
|
139
|
-
|
140
|
-
```bash
|
141
|
-
# Install in development mode
|
142
|
-
pip install -e .
|
143
|
-
|
144
|
-
# Run tests
|
145
|
-
python tests/runner.py
|
146
|
-
|
147
|
-
# Run specific test types
|
148
|
-
python tests/runner.py --core
|
149
|
-
python tests/runner.py --unit
|
150
|
-
python tests/runner.py --integration
|
151
|
-
```
|
152
|
-
|
153
|
-
## 🤝 **Contributing**
|
154
|
-
|
155
|
-
1. Fork the repository
|
156
|
-
2. Create a feature branch
|
157
|
-
3. Make your changes
|
158
|
-
4. Add tests
|
159
|
-
5. Run the test suite
|
160
|
-
6. Submit a pull request
|
161
|
-
|
162
|
-
## 📄 **License**
|
163
|
-
|
164
|
-
MIT License - see LICENSE file for details.
|
165
|
-
|
166
|
-
---
|
167
|
-
|
168
|
-
*Built with ❤️ by eXonware.com - Making node-based data processing effortless*
|