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.
- exonware/__init__.py +8 -1
- exonware/xwnode/__init__.py +18 -5
- exonware/xwnode/add_strategy_types.py +165 -0
- exonware/xwnode/base.py +7 -5
- 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 +9 -9
- exonware/xwnode/common/management/migration.py +6 -6
- exonware/xwnode/common/monitoring/__init__.py +3 -5
- exonware/xwnode/common/monitoring/metrics.py +7 -3
- exonware/xwnode/common/monitoring/pattern_detector.py +2 -2
- exonware/xwnode/common/monitoring/performance_monitor.py +6 -2
- exonware/xwnode/common/patterns/__init__.py +3 -5
- exonware/xwnode/common/patterns/advisor.py +1 -1
- exonware/xwnode/common/patterns/flyweight.py +6 -2
- exonware/xwnode/common/patterns/registry.py +203 -184
- 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.21.dist-info → exonware_xwnode-0.0.1.23.dist-info}/METADATA +23 -3
- exonware_xwnode-0.0.1.23.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.21.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.21.dist-info → exonware_xwnode-0.0.1.23.dist-info}/WHEEL +0 -0
- {exonware_xwnode-0.0.1.21.dist-info → exonware_xwnode-0.0.1.23.dist-info}/licenses/LICENSE +0 -0
exonware/__init__.py
CHANGED
@@ -4,10 +4,17 @@ exonware package - Enterprise-grade Python framework ecosystem
|
|
4
4
|
Company: eXonware.com
|
5
5
|
Author: Eng. Muhammad AlShehri
|
6
6
|
Email: connect@exonware.com
|
7
|
-
Version: 0.0.1.
|
7
|
+
Version: 0.0.1.23
|
8
8
|
Generation Date: 2025-01-03
|
9
|
+
|
10
|
+
This is a namespace package allowing multiple exonware subpackages
|
11
|
+
to coexist (xwsystem, xwnode, xwdata, etc.)
|
9
12
|
"""
|
10
13
|
|
14
|
+
# Make this a namespace package - DO NOT set __path__
|
15
|
+
# This allows both exonware.xwsystem and exonware.xwnode to coexist
|
16
|
+
__path__ = __import__('pkgutil').extend_path(__path__, __name__)
|
17
|
+
|
11
18
|
__version__ = '0.0.1'
|
12
19
|
__author__ = 'Eng. Muhammad AlShehri'
|
13
20
|
__email__ = 'connect@exonware.com'
|
exonware/xwnode/__init__.py
CHANGED
@@ -10,12 +10,11 @@ data handling libraries like xdata.
|
|
10
10
|
Company: eXonware.com
|
11
11
|
Author: Eng. Muhammad AlShehri
|
12
12
|
Email: connect@exonware.com
|
13
|
-
Version: 0.0.1.
|
13
|
+
Version: 0.0.1.23
|
14
14
|
Generation Date: 07-Sep-2025
|
15
15
|
|
16
16
|
Main Classes:
|
17
17
|
XWNode: The primary interface for working with hierarchical data
|
18
|
-
XWQuery: Query interface for searching and filtering nodes
|
19
18
|
XWFactory: Factory for creating XWNode instances
|
20
19
|
|
21
20
|
Exceptions:
|
@@ -57,7 +56,7 @@ Example:
|
|
57
56
|
# IMPORTS - Standard Python Imports (No Defensive Code!)
|
58
57
|
# =============================================================================
|
59
58
|
from .facade import (
|
60
|
-
XWNode, XWEdge,
|
59
|
+
XWNode, XWEdge, XWFactory,
|
61
60
|
# A+ Usability Presets
|
62
61
|
create_with_preset, list_available_presets,
|
63
62
|
# Performance Modes
|
@@ -68,9 +67,12 @@ from .errors import (
|
|
68
67
|
XWNodeSecurityError, XWNodeLimitError, XWNodePathSecurityError
|
69
68
|
)
|
70
69
|
from .config import XWNodeConfig, get_config, set_config
|
70
|
+
from .defs import NodeMode, EdgeMode, NodeTrait, EdgeTrait, GraphOptimization
|
71
|
+
# Note: QueryMode and QueryTrait are in xwquery.defs module
|
72
|
+
from .common.graph import XWGraphManager
|
71
73
|
|
72
74
|
# xwsystem lazy install functionality
|
73
|
-
from exonware.xwsystem.utils.
|
75
|
+
from exonware.xwsystem.utils.lazy_package import xwimport
|
74
76
|
from exonware.xwsystem.monitoring import get_metrics as get_xwsystem_metrics, reset_metrics as reset_xwsystem_metrics
|
75
77
|
|
76
78
|
# Version info
|
@@ -84,7 +86,6 @@ __all__ = [
|
|
84
86
|
# Main classes
|
85
87
|
'XWNode',
|
86
88
|
'XWEdge',
|
87
|
-
'XWQuery',
|
88
89
|
'XWFactory',
|
89
90
|
|
90
91
|
# A+ Usability Presets
|
@@ -102,6 +103,18 @@ __all__ = [
|
|
102
103
|
'get_config',
|
103
104
|
'set_config',
|
104
105
|
|
106
|
+
# Enums and Types
|
107
|
+
'NodeMode',
|
108
|
+
'EdgeMode',
|
109
|
+
'QueryMode',
|
110
|
+
'NodeTrait',
|
111
|
+
'EdgeTrait',
|
112
|
+
'QueryTrait',
|
113
|
+
'GraphOptimization',
|
114
|
+
|
115
|
+
# Graph Optimization
|
116
|
+
'XWGraphManager',
|
117
|
+
|
105
118
|
# Lazy Install
|
106
119
|
'xwimport',
|
107
120
|
|
@@ -0,0 +1,165 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
Add STRATEGY_TYPE to All Node Strategies
|
4
|
+
|
5
|
+
This script automatically adds STRATEGY_TYPE declarations to all node strategy files
|
6
|
+
based on the inheritance audit.
|
7
|
+
|
8
|
+
Company: eXonware.com
|
9
|
+
Author: Eng. Muhammad AlShehri
|
10
|
+
Email: connect@exonware.com
|
11
|
+
Version: 0.0.1.23
|
12
|
+
Generation Date: 08-Oct-2025
|
13
|
+
"""
|
14
|
+
|
15
|
+
import re
|
16
|
+
from pathlib import Path
|
17
|
+
from typing import Dict
|
18
|
+
|
19
|
+
# Map strategy files to their NodeType
|
20
|
+
STRATEGY_TYPE_MAP = {
|
21
|
+
# LINEAR
|
22
|
+
'array_list.py': 'LINEAR',
|
23
|
+
'linked_list.py': 'LINEAR',
|
24
|
+
'stack.py': 'LINEAR',
|
25
|
+
'queue.py': 'LINEAR',
|
26
|
+
'deque.py': 'LINEAR',
|
27
|
+
'priority_queue.py': 'LINEAR',
|
28
|
+
|
29
|
+
# TREE
|
30
|
+
'hash_map.py': 'TREE',
|
31
|
+
'heap.py': 'TREE',
|
32
|
+
'trie.py': 'TREE',
|
33
|
+
'aho_corasick.py': 'TREE',
|
34
|
+
'avl_tree.py': 'TREE',
|
35
|
+
'b_plus_tree.py': 'TREE',
|
36
|
+
'btree.py': 'TREE',
|
37
|
+
'cow_tree.py': 'TREE',
|
38
|
+
'fenwick_tree.py': 'TREE',
|
39
|
+
'lsm_tree.py': 'TREE',
|
40
|
+
'ordered_map.py': 'TREE',
|
41
|
+
'ordered_map_balanced.py': 'TREE',
|
42
|
+
'patricia.py': 'TREE',
|
43
|
+
'persistent_tree.py': 'TREE',
|
44
|
+
'radix_trie.py': 'TREE',
|
45
|
+
'red_black_tree.py': 'TREE',
|
46
|
+
'segment_tree.py': 'TREE',
|
47
|
+
'skip_list.py': 'TREE',
|
48
|
+
'splay_tree.py': 'TREE',
|
49
|
+
'suffix_array.py': 'TREE',
|
50
|
+
'treap.py': 'TREE',
|
51
|
+
'art.py': 'TREE',
|
52
|
+
'bw_tree.py': 'TREE',
|
53
|
+
'hamt.py': 'TREE',
|
54
|
+
'masstree.py': 'TREE',
|
55
|
+
'extendible_hash.py': 'TREE',
|
56
|
+
'linear_hash.py': 'TREE',
|
57
|
+
't_tree.py': 'TREE',
|
58
|
+
'learned_index.py': 'TREE',
|
59
|
+
|
60
|
+
# GRAPH
|
61
|
+
'union_find.py': 'GRAPH',
|
62
|
+
'adjacency_list.py': 'GRAPH',
|
63
|
+
|
64
|
+
# MATRIX
|
65
|
+
'sparse_matrix.py': 'MATRIX',
|
66
|
+
'bitmap.py': 'MATRIX',
|
67
|
+
'bitset_dynamic.py': 'MATRIX',
|
68
|
+
'roaring_bitmap.py': 'MATRIX',
|
69
|
+
'bloom_filter.py': 'MATRIX',
|
70
|
+
'count_min_sketch.py': 'MATRIX',
|
71
|
+
'hyperloglog.py': 'MATRIX',
|
72
|
+
'set_hash.py': 'MATRIX',
|
73
|
+
'set_tree.py': 'TREE',
|
74
|
+
'cuckoo_hash.py': 'TREE',
|
75
|
+
|
76
|
+
# HYBRID
|
77
|
+
'tree_graph_hybrid.py': 'HYBRID',
|
78
|
+
'xdata_optimized.py': 'HYBRID',
|
79
|
+
}
|
80
|
+
|
81
|
+
|
82
|
+
def add_strategy_type_to_file(file_path: Path, node_type: str) -> bool:
|
83
|
+
"""Add STRATEGY_TYPE to a strategy file."""
|
84
|
+
try:
|
85
|
+
with open(file_path, 'r', encoding='utf-8') as f:
|
86
|
+
content = f.read()
|
87
|
+
|
88
|
+
# Check if STRATEGY_TYPE already exists
|
89
|
+
if 'STRATEGY_TYPE' in content:
|
90
|
+
print(f" ⏭️ Already has STRATEGY_TYPE: {file_path.name}")
|
91
|
+
return False
|
92
|
+
|
93
|
+
# Find class definition
|
94
|
+
class_match = re.search(r'(class \w+Strategy\([^)]+\):\s*\n\s*"""[^"]*""")', content, re.MULTILINE)
|
95
|
+
if not class_match:
|
96
|
+
print(f" ⚠️ Could not find class definition: {file_path.name}")
|
97
|
+
return False
|
98
|
+
|
99
|
+
# Add import if not present
|
100
|
+
if 'from .contracts import NodeType' not in content:
|
101
|
+
# Find where to add import (after other local imports)
|
102
|
+
if 'from .base import' in content:
|
103
|
+
content = content.replace(
|
104
|
+
'from .base import',
|
105
|
+
'from .base import'
|
106
|
+
)
|
107
|
+
# Add after base import
|
108
|
+
import_pos = content.find('from .base import')
|
109
|
+
line_end = content.find('\n', import_pos)
|
110
|
+
content = content[:line_end+1] + 'from .contracts import NodeType\n' + content[line_end+1:]
|
111
|
+
|
112
|
+
# Add STRATEGY_TYPE after class docstring
|
113
|
+
class_end = class_match.end()
|
114
|
+
|
115
|
+
# Add STRATEGY_TYPE declaration
|
116
|
+
strategy_type_line = f'\n \n # Strategy type classification\n STRATEGY_TYPE = NodeType.{node_type}\n'
|
117
|
+
content = content[:class_end] + strategy_type_line + content[class_end:]
|
118
|
+
|
119
|
+
# Write back
|
120
|
+
with open(file_path, 'w', encoding='utf-8') as f:
|
121
|
+
f.write(content)
|
122
|
+
|
123
|
+
print(f" ✅ Added STRATEGY_TYPE.{node_type}: {file_path.name}")
|
124
|
+
return True
|
125
|
+
|
126
|
+
except Exception as e:
|
127
|
+
print(f" ❌ Error processing {file_path.name}: {e}")
|
128
|
+
return False
|
129
|
+
|
130
|
+
|
131
|
+
def main():
|
132
|
+
"""Main function."""
|
133
|
+
print("="*70)
|
134
|
+
print("Adding STRATEGY_TYPE to All Node Strategies")
|
135
|
+
print("="*70)
|
136
|
+
|
137
|
+
base_path = Path(__file__).parent / 'src' / 'exonware' / 'xwnode' / 'nodes' / 'strategies'
|
138
|
+
|
139
|
+
count_added = 0
|
140
|
+
count_skipped = 0
|
141
|
+
count_errors = 0
|
142
|
+
|
143
|
+
for filename, node_type in STRATEGY_TYPE_MAP.items():
|
144
|
+
file_path = base_path / filename
|
145
|
+
|
146
|
+
if not file_path.exists():
|
147
|
+
print(f" ⚠️ File not found: {filename}")
|
148
|
+
count_errors += 1
|
149
|
+
continue
|
150
|
+
|
151
|
+
result = add_strategy_type_to_file(file_path, node_type)
|
152
|
+
if result:
|
153
|
+
count_added += 1
|
154
|
+
elif 'Already has' in str(result):
|
155
|
+
count_skipped += 1
|
156
|
+
else:
|
157
|
+
count_errors += 1
|
158
|
+
|
159
|
+
print("\n" + "="*70)
|
160
|
+
print(f"Summary: {count_added} added, {count_skipped} skipped, {count_errors} errors")
|
161
|
+
print("="*70)
|
162
|
+
|
163
|
+
|
164
|
+
if __name__ == '__main__':
|
165
|
+
main()
|
exonware/xwnode/base.py
CHANGED
@@ -24,9 +24,8 @@ from .contracts import iNodeFacade, iNodeStrategy, iEdge, iEdgeStrategy, iQuery,
|
|
24
24
|
# System-level imports - standard imports (no defensive code!)
|
25
25
|
from exonware.xwsystem.security import get_resource_limits
|
26
26
|
from exonware.xwsystem.validation import validate_untrusted_data
|
27
|
-
from exonware.xwsystem.monitoring import create_component_metrics
|
27
|
+
from exonware.xwsystem.monitoring import create_component_metrics, CircuitBreaker, CircuitBreakerConfig
|
28
28
|
from exonware.xwsystem.threading import ThreadSafeFactory, create_thread_safe_cache
|
29
|
-
from exonware.xwsystem.patterns import CircuitBreaker
|
30
29
|
from exonware.xwsystem import get_logger
|
31
30
|
|
32
31
|
logger = get_logger('xwnode.base')
|
@@ -42,9 +41,12 @@ _path_cache = create_thread_safe_cache(max_size=1024)
|
|
42
41
|
|
43
42
|
# Circuit breaker for strategy operations
|
44
43
|
_strategy_circuit_breaker = CircuitBreaker(
|
45
|
-
|
46
|
-
|
47
|
-
|
44
|
+
name='xwnode_strategy',
|
45
|
+
config=CircuitBreakerConfig(
|
46
|
+
failure_threshold=5,
|
47
|
+
recovery_timeout=30,
|
48
|
+
expected_exception=Exception
|
49
|
+
)
|
48
50
|
)
|
49
51
|
|
50
52
|
|
@@ -0,0 +1,30 @@
|
|
1
|
+
"""
|
2
|
+
#exonware/xwnode/src/exonware/xwnode/common/graph/__init__.py
|
3
|
+
|
4
|
+
Graph optimization module for XWNode.
|
5
|
+
|
6
|
+
Provides O(1) relationship queries with multi-tenant security isolation.
|
7
|
+
|
8
|
+
Company: eXonware.com
|
9
|
+
Author: Eng. Muhammad AlShehri
|
10
|
+
Email: connect@exonware.com
|
11
|
+
Version: 0.0.1.23
|
12
|
+
Generation Date: 11-Oct-2025
|
13
|
+
"""
|
14
|
+
|
15
|
+
from .manager import XWGraphManager
|
16
|
+
from .errors import (
|
17
|
+
XWGraphError,
|
18
|
+
XWGraphSecurityError,
|
19
|
+
XWGraphEntityNotFoundError,
|
20
|
+
XWGraphRelationshipNotFoundError
|
21
|
+
)
|
22
|
+
|
23
|
+
__all__ = [
|
24
|
+
'XWGraphManager',
|
25
|
+
'XWGraphError',
|
26
|
+
'XWGraphSecurityError',
|
27
|
+
'XWGraphEntityNotFoundError',
|
28
|
+
'XWGraphRelationshipNotFoundError'
|
29
|
+
]
|
30
|
+
|
@@ -0,0 +1,131 @@
|
|
1
|
+
"""
|
2
|
+
#exonware/xwnode/src/exonware/xwnode/common/graph/caching.py
|
3
|
+
|
4
|
+
LRU cache manager for frequent relationship queries.
|
5
|
+
|
6
|
+
Company: eXonware.com
|
7
|
+
Author: Eng. Muhammad AlShehri
|
8
|
+
Email: connect@exonware.com
|
9
|
+
Version: 0.0.1.23
|
10
|
+
Generation Date: 11-Oct-2025
|
11
|
+
"""
|
12
|
+
|
13
|
+
import threading
|
14
|
+
from typing import Any, Optional, List
|
15
|
+
from collections import OrderedDict
|
16
|
+
|
17
|
+
|
18
|
+
class CacheManager:
|
19
|
+
"""
|
20
|
+
Thread-safe LRU cache for query results.
|
21
|
+
|
22
|
+
Provides O(1) cache operations with automatic eviction
|
23
|
+
of least recently used entries.
|
24
|
+
"""
|
25
|
+
|
26
|
+
def __init__(self, max_size: int = 1000):
|
27
|
+
"""
|
28
|
+
Initialize cache manager.
|
29
|
+
|
30
|
+
Args:
|
31
|
+
max_size: Maximum number of cached entries
|
32
|
+
"""
|
33
|
+
self._cache: OrderedDict[str, Any] = OrderedDict()
|
34
|
+
self._max_size = max_size
|
35
|
+
self._hits = 0
|
36
|
+
self._misses = 0
|
37
|
+
self._lock = threading.RLock()
|
38
|
+
|
39
|
+
def get(self, key: str) -> Optional[Any]:
|
40
|
+
"""
|
41
|
+
Get cached result.
|
42
|
+
|
43
|
+
Args:
|
44
|
+
key: Cache key
|
45
|
+
|
46
|
+
Returns:
|
47
|
+
Cached value or None if not found
|
48
|
+
|
49
|
+
Time Complexity: O(1)
|
50
|
+
"""
|
51
|
+
with self._lock:
|
52
|
+
if key in self._cache:
|
53
|
+
self._hits += 1
|
54
|
+
# Move to end (most recently used)
|
55
|
+
self._cache.move_to_end(key)
|
56
|
+
return self._cache[key]
|
57
|
+
|
58
|
+
self._misses += 1
|
59
|
+
return None
|
60
|
+
|
61
|
+
def put(self, key: str, value: Any) -> None:
|
62
|
+
"""
|
63
|
+
Cache a query result.
|
64
|
+
|
65
|
+
Args:
|
66
|
+
key: Cache key
|
67
|
+
value: Value to cache
|
68
|
+
|
69
|
+
Time Complexity: O(1)
|
70
|
+
"""
|
71
|
+
with self._lock:
|
72
|
+
if key in self._cache:
|
73
|
+
# Update existing entry
|
74
|
+
self._cache.move_to_end(key)
|
75
|
+
self._cache[key] = value
|
76
|
+
else:
|
77
|
+
# Add new entry
|
78
|
+
if len(self._cache) >= self._max_size:
|
79
|
+
# Remove least recently used (first item)
|
80
|
+
self._cache.popitem(last=False)
|
81
|
+
self._cache[key] = value
|
82
|
+
|
83
|
+
def invalidate(self, entity_id: str) -> None:
|
84
|
+
"""
|
85
|
+
Invalidate cache entries for entity.
|
86
|
+
|
87
|
+
Removes all cached queries that involve the specified entity.
|
88
|
+
|
89
|
+
Args:
|
90
|
+
entity_id: Entity whose cache entries should be invalidated
|
91
|
+
"""
|
92
|
+
with self._lock:
|
93
|
+
# Find all cache keys containing this entity
|
94
|
+
keys_to_remove = [k for k in self._cache.keys() if entity_id in k]
|
95
|
+
|
96
|
+
# Remove them
|
97
|
+
for key in keys_to_remove:
|
98
|
+
del self._cache[key]
|
99
|
+
|
100
|
+
def clear(self) -> None:
|
101
|
+
"""Clear all cached entries."""
|
102
|
+
with self._lock:
|
103
|
+
self._cache.clear()
|
104
|
+
|
105
|
+
def get_hit_rate(self) -> float:
|
106
|
+
"""
|
107
|
+
Get cache hit rate.
|
108
|
+
|
109
|
+
Returns:
|
110
|
+
Hit rate as float between 0.0 and 1.0
|
111
|
+
"""
|
112
|
+
with self._lock:
|
113
|
+
total = self._hits + self._misses
|
114
|
+
return self._hits / total if total > 0 else 0.0
|
115
|
+
|
116
|
+
def get_stats(self) -> dict:
|
117
|
+
"""
|
118
|
+
Get cache statistics.
|
119
|
+
|
120
|
+
Returns:
|
121
|
+
Dictionary with cache metrics
|
122
|
+
"""
|
123
|
+
with self._lock:
|
124
|
+
return {
|
125
|
+
'size': len(self._cache),
|
126
|
+
'max_size': self._max_size,
|
127
|
+
'hits': self._hits,
|
128
|
+
'misses': self._misses,
|
129
|
+
'hit_rate': self.get_hit_rate()
|
130
|
+
}
|
131
|
+
|
@@ -0,0 +1,100 @@
|
|
1
|
+
"""
|
2
|
+
#exonware/xwnode/src/exonware/xwnode/common/graph/contracts.py
|
3
|
+
|
4
|
+
Graph manager contracts and enums.
|
5
|
+
|
6
|
+
Company: eXonware.com
|
7
|
+
Author: Eng. Muhammad AlShehri
|
8
|
+
Email: connect@exonware.com
|
9
|
+
Version: 0.0.1.23
|
10
|
+
Generation Date: 11-Oct-2025
|
11
|
+
"""
|
12
|
+
|
13
|
+
from enum import Enum
|
14
|
+
from abc import ABC, abstractmethod
|
15
|
+
from typing import Dict, List, Optional, Any
|
16
|
+
|
17
|
+
|
18
|
+
class GraphOptimization(Enum):
|
19
|
+
"""
|
20
|
+
Graph optimization levels for XWGraphManager.
|
21
|
+
|
22
|
+
Controls indexing and caching behavior for performance tuning.
|
23
|
+
"""
|
24
|
+
|
25
|
+
OFF = 0 # No optimization - fallback to O(n) iteration
|
26
|
+
INDEX_ONLY = 1 # Only indexing - O(1) lookups, no caching
|
27
|
+
CACHE_ONLY = 2 # Only caching - benefits from repeated queries
|
28
|
+
FULL = 3 # Both indexing + caching - maximum performance
|
29
|
+
|
30
|
+
# Aliases for clarity
|
31
|
+
DISABLED = 0
|
32
|
+
MINIMAL = 1
|
33
|
+
MODERATE = 2
|
34
|
+
MAXIMUM = 3
|
35
|
+
|
36
|
+
|
37
|
+
class IGraphManager(ABC):
|
38
|
+
"""Interface for graph manager implementations."""
|
39
|
+
|
40
|
+
@abstractmethod
|
41
|
+
def add_relationship(
|
42
|
+
self,
|
43
|
+
source: str,
|
44
|
+
target: str,
|
45
|
+
relationship_type: str,
|
46
|
+
**properties
|
47
|
+
) -> str:
|
48
|
+
"""Add a relationship between entities."""
|
49
|
+
pass
|
50
|
+
|
51
|
+
@abstractmethod
|
52
|
+
def remove_relationship(
|
53
|
+
self,
|
54
|
+
source: str,
|
55
|
+
target: str,
|
56
|
+
relationship_type: Optional[str] = None
|
57
|
+
) -> bool:
|
58
|
+
"""Remove relationship(s) between entities."""
|
59
|
+
pass
|
60
|
+
|
61
|
+
@abstractmethod
|
62
|
+
def get_outgoing(
|
63
|
+
self,
|
64
|
+
entity_id: str,
|
65
|
+
relationship_type: Optional[str] = None,
|
66
|
+
limit: Optional[int] = None
|
67
|
+
) -> List[Dict[str, Any]]:
|
68
|
+
"""Get outgoing relationships for entity."""
|
69
|
+
pass
|
70
|
+
|
71
|
+
@abstractmethod
|
72
|
+
def get_incoming(
|
73
|
+
self,
|
74
|
+
entity_id: str,
|
75
|
+
relationship_type: Optional[str] = None,
|
76
|
+
limit: Optional[int] = None
|
77
|
+
) -> List[Dict[str, Any]]:
|
78
|
+
"""Get incoming relationships for entity."""
|
79
|
+
pass
|
80
|
+
|
81
|
+
@abstractmethod
|
82
|
+
def has_relationship(
|
83
|
+
self,
|
84
|
+
source: str,
|
85
|
+
target: str,
|
86
|
+
relationship_type: Optional[str] = None
|
87
|
+
) -> bool:
|
88
|
+
"""Check if relationship exists."""
|
89
|
+
pass
|
90
|
+
|
91
|
+
@abstractmethod
|
92
|
+
def get_stats(self) -> Dict[str, Any]:
|
93
|
+
"""Get graph statistics."""
|
94
|
+
pass
|
95
|
+
|
96
|
+
@abstractmethod
|
97
|
+
def clear_cache(self) -> None:
|
98
|
+
"""Clear query cache."""
|
99
|
+
pass
|
100
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
"""
|
2
|
+
#exonware/xwnode/src/exonware/xwnode/common/graph/errors.py
|
3
|
+
|
4
|
+
Graph-specific error classes.
|
5
|
+
|
6
|
+
Company: eXonware.com
|
7
|
+
Author: Eng. Muhammad AlShehri
|
8
|
+
Email: connect@exonware.com
|
9
|
+
Version: 0.0.1.23
|
10
|
+
Generation Date: 11-Oct-2025
|
11
|
+
"""
|
12
|
+
|
13
|
+
from ...errors import XWNodeError
|
14
|
+
|
15
|
+
|
16
|
+
class XWGraphError(XWNodeError):
|
17
|
+
"""Base error for graph operations."""
|
18
|
+
pass
|
19
|
+
|
20
|
+
|
21
|
+
class XWGraphSecurityError(XWGraphError):
|
22
|
+
"""Security violation in graph operations."""
|
23
|
+
pass
|
24
|
+
|
25
|
+
|
26
|
+
class XWGraphEntityNotFoundError(XWGraphError):
|
27
|
+
"""Entity not found in graph."""
|
28
|
+
pass
|
29
|
+
|
30
|
+
|
31
|
+
class XWGraphRelationshipNotFoundError(XWGraphError):
|
32
|
+
"""Relationship not found in graph."""
|
33
|
+
pass
|
34
|
+
|
35
|
+
|
36
|
+
class XWGraphCycleDetectedError(XWGraphError):
|
37
|
+
"""Cycle detected in graph traversal."""
|
38
|
+
pass
|
39
|
+
|
40
|
+
|
41
|
+
class XWGraphInvalidOperationError(XWGraphError):
|
42
|
+
"""Invalid graph operation."""
|
43
|
+
pass
|
44
|
+
|