exonware-xwnode 0.0.1.22__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 +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.22.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.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.23.dist-info}/WHEEL +0 -0
- {exonware_xwnode-0.0.1.22.dist-info → exonware_xwnode-0.0.1.23.dist-info}/licenses/LICENSE +0 -0
@@ -1,68 +1,173 @@
|
|
1
1
|
#!/usr/bin/env python3
|
2
2
|
"""
|
3
|
-
|
3
|
+
#exonware/xwnode/src/exonware/xwnode/nodes/strategies/base.py
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
-
|
9
|
-
-
|
10
|
-
- ANodeMatrixStrategy: Matrix
|
5
|
+
Node Strategy Base Classes - Production-Grade Implementation
|
6
|
+
|
7
|
+
This module defines the complete abstract base class hierarchy for all node strategies:
|
8
|
+
- ANodeStrategy: Universal base with full iNodeStrategy implementation
|
9
|
+
- ANodeLinearStrategy: Linear data structures (Stack, Queue, Deque, PriorityQueue)
|
10
|
+
- ANodeMatrixStrategy: Matrix data structures (SparseMatrix, Bitmap, etc.)
|
11
|
+
- ANodeGraphStrategy: Graph data structures (AdjacencyList, UnionFind)
|
12
|
+
- ANodeTreeStrategy: Tree data structures (BTree, Trie, Heap, etc.)
|
11
13
|
|
12
14
|
Company: eXonware.com
|
13
15
|
Author: Eng. Muhammad AlShehri
|
14
16
|
Email: connect@exonware.com
|
15
|
-
Version: 0.0.1.
|
16
|
-
Generation Date:
|
17
|
+
Version: 0.0.1.23
|
18
|
+
Generation Date: October 12, 2025
|
17
19
|
"""
|
18
20
|
|
19
21
|
from abc import ABC, abstractmethod
|
20
|
-
from typing import Any, Optional, List, Dict, Iterator
|
22
|
+
from typing import Any, Optional, List, Dict, Iterator, Union
|
21
23
|
|
22
24
|
from ...contracts import iNodeStrategy
|
23
|
-
from ...
|
25
|
+
from ...defs import NodeMode, NodeTrait
|
26
|
+
from ...errors import XWNodeUnsupportedCapabilityError
|
24
27
|
from .contracts import NodeType
|
25
28
|
|
26
29
|
|
27
30
|
class ANodeStrategy(iNodeStrategy):
|
28
|
-
"""
|
31
|
+
"""
|
32
|
+
Production-grade base strategy for ALL node implementations.
|
33
|
+
|
34
|
+
This class provides:
|
35
|
+
- Complete iNodeStrategy interface implementation
|
36
|
+
- Default implementations for common operations
|
37
|
+
- Trait validation and capability checking
|
38
|
+
- Performance metadata and metrics
|
39
|
+
- Factory methods for strategy creation
|
40
|
+
|
41
|
+
Follows eXonware Priorities:
|
42
|
+
1. Security: Trait validation, safe operations
|
43
|
+
2. Usability: Clear interface, helpful errors
|
44
|
+
3. Maintainability: Clean base implementation
|
45
|
+
4. Performance: Efficient default methods
|
46
|
+
5. Extensibility: Easy to override and extend
|
47
|
+
"""
|
29
48
|
|
30
49
|
# Strategy type classification (must be overridden by subclasses)
|
31
50
|
STRATEGY_TYPE: NodeType = NodeType.TREE # Default for backward compatibility
|
32
51
|
|
33
|
-
#
|
34
|
-
|
52
|
+
# Make NodeType available to all subclasses
|
53
|
+
NodeType = NodeType
|
54
|
+
|
55
|
+
def __init__(self, mode: NodeMode, traits: NodeTrait = NodeTrait.NONE, **options):
|
56
|
+
"""
|
57
|
+
Initialize the node strategy.
|
58
|
+
|
59
|
+
Args:
|
60
|
+
mode: The NodeMode for this strategy
|
61
|
+
traits: NodeTrait flags for this strategy
|
62
|
+
**options: Additional strategy-specific options
|
63
|
+
"""
|
64
|
+
self.mode = mode
|
65
|
+
self.traits = traits
|
66
|
+
self.options = options
|
67
|
+
self._data: Dict[str, Any] = {}
|
68
|
+
self._size = 0
|
69
|
+
|
70
|
+
# Validate traits compatibility with mode
|
71
|
+
self._validate_traits()
|
72
|
+
|
73
|
+
def _validate_traits(self) -> None:
|
74
|
+
"""Validate that the requested traits are compatible with this strategy."""
|
75
|
+
supported_traits = self.get_supported_traits()
|
76
|
+
unsupported = self.traits & ~supported_traits
|
77
|
+
if unsupported != NodeTrait.NONE:
|
78
|
+
unsupported_names = [trait.name for trait in NodeTrait if trait in unsupported]
|
79
|
+
raise ValueError(f"Strategy {self.mode.name} does not support traits: {unsupported_names}")
|
80
|
+
|
81
|
+
def get_supported_traits(self) -> NodeTrait:
|
82
|
+
"""Get the traits supported by this strategy implementation (override in subclasses)."""
|
83
|
+
return NodeTrait.NONE
|
84
|
+
|
85
|
+
def has_trait(self, trait: NodeTrait) -> bool:
|
86
|
+
"""Check if this strategy has a specific trait."""
|
87
|
+
return bool(self.traits & trait)
|
88
|
+
|
89
|
+
def require_trait(self, trait: NodeTrait, operation: str = "operation") -> None:
|
90
|
+
"""Require a specific trait for an operation."""
|
91
|
+
if not self.has_trait(trait):
|
92
|
+
raise XWNodeUnsupportedCapabilityError(
|
93
|
+
operation,
|
94
|
+
self.mode.name,
|
95
|
+
[t.name for t in NodeTrait if t in self.traits]
|
96
|
+
)
|
97
|
+
|
98
|
+
# ============================================================================
|
99
|
+
# CORE OPERATIONS (Must be implemented by concrete strategies)
|
100
|
+
# ============================================================================
|
35
101
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
102
|
+
@abstractmethod
|
103
|
+
def put(self, key: Any, value: Any = None) -> None:
|
104
|
+
"""
|
105
|
+
Store a key-value pair.
|
106
|
+
|
107
|
+
Args:
|
108
|
+
key: The key to store
|
109
|
+
value: The value to associate with the key
|
110
|
+
"""
|
111
|
+
pass
|
42
112
|
|
43
113
|
@abstractmethod
|
44
|
-
def
|
45
|
-
"""
|
114
|
+
def get(self, key: Any, default: Any = None) -> Any:
|
115
|
+
"""
|
116
|
+
Retrieve a value by key.
|
117
|
+
|
118
|
+
Args:
|
119
|
+
key: The key to look up
|
120
|
+
default: Default value if key not found
|
121
|
+
|
122
|
+
Returns:
|
123
|
+
The value associated with the key, or default if not found
|
124
|
+
"""
|
46
125
|
pass
|
47
126
|
|
48
127
|
@abstractmethod
|
49
|
-
def
|
50
|
-
"""
|
128
|
+
def has(self, key: Any) -> bool:
|
129
|
+
"""
|
130
|
+
Check if a key exists.
|
131
|
+
|
132
|
+
Args:
|
133
|
+
key: The key to check
|
134
|
+
|
135
|
+
Returns:
|
136
|
+
True if key exists, False otherwise
|
137
|
+
"""
|
51
138
|
pass
|
52
139
|
|
53
140
|
@abstractmethod
|
54
141
|
def delete(self, key: Any) -> bool:
|
55
|
-
"""
|
142
|
+
"""
|
143
|
+
Remove a key-value pair.
|
144
|
+
|
145
|
+
Args:
|
146
|
+
key: The key to remove
|
147
|
+
|
148
|
+
Returns:
|
149
|
+
True if key was found and removed, False otherwise
|
150
|
+
"""
|
56
151
|
pass
|
57
152
|
|
58
153
|
@abstractmethod
|
59
|
-
def
|
60
|
-
"""Get
|
154
|
+
def keys(self) -> Iterator[Any]:
|
155
|
+
"""Get an iterator over all keys."""
|
61
156
|
pass
|
62
157
|
|
63
158
|
@abstractmethod
|
64
|
-
def
|
65
|
-
"""
|
159
|
+
def values(self) -> Iterator[Any]:
|
160
|
+
"""Get an iterator over all values."""
|
161
|
+
pass
|
162
|
+
|
163
|
+
@abstractmethod
|
164
|
+
def items(self) -> Iterator[tuple[Any, Any]]:
|
165
|
+
"""Get an iterator over all key-value pairs."""
|
166
|
+
pass
|
167
|
+
|
168
|
+
@abstractmethod
|
169
|
+
def __len__(self) -> int:
|
170
|
+
"""Get the number of key-value pairs."""
|
66
171
|
pass
|
67
172
|
|
68
173
|
@abstractmethod
|
@@ -70,21 +175,258 @@ class ANodeStrategy(iNodeStrategy):
|
|
70
175
|
"""Convert to native Python object."""
|
71
176
|
pass
|
72
177
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
def
|
78
|
-
"""
|
79
|
-
return self.
|
178
|
+
# ============================================================================
|
179
|
+
# DEFAULT IMPLEMENTATIONS (iNodeStrategy interface)
|
180
|
+
# ============================================================================
|
181
|
+
|
182
|
+
def exists(self, path: str) -> bool:
|
183
|
+
"""Check if path exists (default implementation)."""
|
184
|
+
return self.get(path) is not None
|
185
|
+
|
186
|
+
@classmethod
|
187
|
+
def create_from_data(cls, data: Any) -> 'ANodeStrategy':
|
188
|
+
"""
|
189
|
+
Create a new strategy instance from data.
|
190
|
+
|
191
|
+
Args:
|
192
|
+
data: The data to create the strategy from
|
193
|
+
|
194
|
+
Returns:
|
195
|
+
A new strategy instance containing the data
|
196
|
+
"""
|
197
|
+
instance = cls()
|
198
|
+
if isinstance(data, dict):
|
199
|
+
for key, value in data.items():
|
200
|
+
instance.put(key, value)
|
201
|
+
elif isinstance(data, (list, tuple)):
|
202
|
+
for i, value in enumerate(data):
|
203
|
+
instance.put(i, value)
|
204
|
+
else:
|
205
|
+
# For primitive values, store as root value
|
206
|
+
instance.put('_value', data)
|
207
|
+
return instance
|
208
|
+
|
209
|
+
def clear(self) -> None:
|
210
|
+
"""Clear all data (default implementation)."""
|
211
|
+
self._data.clear()
|
212
|
+
self._size = 0
|
213
|
+
|
214
|
+
def __contains__(self, key: Any) -> bool:
|
215
|
+
"""Check if key exists (default implementation)."""
|
216
|
+
return self.has(key)
|
217
|
+
|
218
|
+
def __getitem__(self, key: Any) -> Any:
|
219
|
+
"""Get value by key (default implementation)."""
|
220
|
+
return self.get(key)
|
221
|
+
|
222
|
+
def __setitem__(self, key: Any, value: Any) -> None:
|
223
|
+
"""Set value by key (default implementation)."""
|
224
|
+
self.put(key, value)
|
225
|
+
|
226
|
+
def __delitem__(self, key: Any) -> None:
|
227
|
+
"""Delete key (default implementation)."""
|
228
|
+
if not self.delete(key):
|
229
|
+
raise KeyError(key)
|
230
|
+
|
231
|
+
def __iter__(self) -> Iterator[Any]:
|
232
|
+
"""Iterate over keys (default implementation)."""
|
233
|
+
return self.keys()
|
234
|
+
|
235
|
+
def __str__(self) -> str:
|
236
|
+
"""String representation (default implementation)."""
|
237
|
+
return f"{self.__class__.__name__}(mode={self.mode.name}, size={len(self)})"
|
238
|
+
|
239
|
+
def __repr__(self) -> str:
|
240
|
+
"""Detailed string representation (default implementation)."""
|
241
|
+
return f"{self.__class__.__name__}(mode={self.mode.name}, traits={self.traits}, size={len(self)})"
|
242
|
+
|
243
|
+
# ============================================================================
|
244
|
+
# TYPE CHECKING PROPERTIES (Default implementations for iNodeStrategy)
|
245
|
+
# ============================================================================
|
246
|
+
|
247
|
+
@property
|
248
|
+
def is_leaf(self) -> bool:
|
249
|
+
"""Check if this is a leaf node (default: false)."""
|
250
|
+
return len(self) == 0
|
251
|
+
|
252
|
+
@property
|
253
|
+
def is_list(self) -> bool:
|
254
|
+
"""Check if this is a list node (default: false, override in list strategies)."""
|
255
|
+
return False
|
256
|
+
|
257
|
+
@property
|
258
|
+
def is_dict(self) -> bool:
|
259
|
+
"""Check if this is a dict node (default: true for most strategies)."""
|
260
|
+
return True
|
261
|
+
|
262
|
+
@property
|
263
|
+
def is_reference(self) -> bool:
|
264
|
+
"""Check if this is a reference node (default: false)."""
|
265
|
+
return False
|
266
|
+
|
267
|
+
@property
|
268
|
+
def is_object(self) -> bool:
|
269
|
+
"""Check if this is an object node (default: false)."""
|
270
|
+
return False
|
271
|
+
|
272
|
+
@property
|
273
|
+
def type(self) -> str:
|
274
|
+
"""Get the type of this node (default: 'dict')."""
|
275
|
+
return "dict"
|
276
|
+
|
277
|
+
@property
|
278
|
+
def value(self) -> Any:
|
279
|
+
"""Get the value of this node (default: native representation)."""
|
280
|
+
return self.to_native()
|
281
|
+
|
282
|
+
# Optional properties with default implementations
|
283
|
+
@property
|
284
|
+
def uri(self) -> Optional[str]:
|
285
|
+
"""Get URI (for reference/object nodes)."""
|
286
|
+
return None
|
287
|
+
|
288
|
+
@property
|
289
|
+
def reference_type(self) -> Optional[str]:
|
290
|
+
"""Get reference type (for reference nodes)."""
|
291
|
+
return None
|
292
|
+
|
293
|
+
@property
|
294
|
+
def object_type(self) -> Optional[str]:
|
295
|
+
"""Get object type (for object nodes)."""
|
296
|
+
return None
|
297
|
+
|
298
|
+
@property
|
299
|
+
def mime_type(self) -> Optional[str]:
|
300
|
+
"""Get MIME type (for object nodes)."""
|
301
|
+
return None
|
302
|
+
|
303
|
+
@property
|
304
|
+
def metadata(self) -> Optional[Dict[str, Any]]:
|
305
|
+
"""Get metadata (for reference/object nodes)."""
|
306
|
+
return None
|
307
|
+
|
308
|
+
# Strategy information
|
309
|
+
@property
|
310
|
+
def strategy_name(self) -> str:
|
311
|
+
"""Get the name of this strategy."""
|
312
|
+
return self.mode.name
|
313
|
+
|
314
|
+
@property
|
315
|
+
def supported_traits(self) -> List[NodeTrait]:
|
316
|
+
"""Get supported traits for this strategy."""
|
317
|
+
supported = self.get_supported_traits()
|
318
|
+
return [trait for trait in NodeTrait if trait in supported]
|
319
|
+
|
320
|
+
# ============================================================================
|
321
|
+
# CAPABILITY-BASED OPERATIONS (Default implementations with trait checking)
|
322
|
+
# ============================================================================
|
323
|
+
|
324
|
+
def get_ordered(self, start: Any = None, end: Any = None) -> List[tuple[Any, Any]]:
|
325
|
+
"""
|
326
|
+
Get items in order (requires ORDERED trait).
|
327
|
+
|
328
|
+
Raises:
|
329
|
+
XWNodeUnsupportedCapabilityError: If ORDERED trait not supported
|
330
|
+
"""
|
331
|
+
if NodeTrait.ORDERED not in self.traits:
|
332
|
+
raise XWNodeUnsupportedCapabilityError("ORDERED", self.mode.name, [str(t) for t in self.traits])
|
333
|
+
|
334
|
+
# Default implementation for ordered strategies
|
335
|
+
items = list(self.items())
|
336
|
+
if start is not None:
|
337
|
+
items = [(k, v) for k, v in items if k >= start]
|
338
|
+
if end is not None:
|
339
|
+
items = [(k, v) for k, v in items if k < end]
|
340
|
+
return items
|
341
|
+
|
342
|
+
def get_with_prefix(self, prefix: str) -> List[tuple[Any, Any]]:
|
343
|
+
"""
|
344
|
+
Get items with given prefix (requires HIERARCHICAL trait).
|
345
|
+
|
346
|
+
Raises:
|
347
|
+
XWNodeUnsupportedCapabilityError: If HIERARCHICAL trait not supported
|
348
|
+
"""
|
349
|
+
if NodeTrait.HIERARCHICAL not in self.traits:
|
350
|
+
raise XWNodeUnsupportedCapabilityError("HIERARCHICAL", self.mode.name, [str(t) for t in self.traits])
|
351
|
+
|
352
|
+
# Default implementation for hierarchical strategies
|
353
|
+
return [(k, v) for k, v in self.items() if str(k).startswith(prefix)]
|
354
|
+
|
355
|
+
def get_priority(self) -> Optional[tuple[Any, Any]]:
|
356
|
+
"""
|
357
|
+
Get highest priority item (requires PRIORITY trait).
|
358
|
+
|
359
|
+
Raises:
|
360
|
+
XWNodeUnsupportedCapabilityError: If PRIORITY trait not supported
|
361
|
+
"""
|
362
|
+
if NodeTrait.PRIORITY not in self.traits:
|
363
|
+
raise XWNodeUnsupportedCapabilityError("PRIORITY", self.mode.name, [str(t) for t in self.traits])
|
364
|
+
|
365
|
+
# Default implementation for priority strategies
|
366
|
+
if len(self) == 0:
|
367
|
+
return None
|
368
|
+
return min(self.items(), key=lambda x: x[0])
|
369
|
+
|
370
|
+
def get_weighted(self, key: Any) -> float:
|
371
|
+
"""
|
372
|
+
Get weight for a key (requires WEIGHTED trait).
|
373
|
+
|
374
|
+
Raises:
|
375
|
+
XWNodeUnsupportedCapabilityError: If WEIGHTED trait not supported
|
376
|
+
"""
|
377
|
+
if NodeTrait.WEIGHTED not in self.traits:
|
378
|
+
raise XWNodeUnsupportedCapabilityError("WEIGHTED", self.mode.name, [str(t) for t in self.traits])
|
379
|
+
|
380
|
+
# Default implementation for weighted strategies
|
381
|
+
return 1.0
|
382
|
+
|
383
|
+
# ============================================================================
|
384
|
+
# STRATEGY METADATA (Default implementations)
|
385
|
+
# ============================================================================
|
386
|
+
|
387
|
+
def capabilities(self) -> NodeTrait:
|
388
|
+
"""Get the capabilities supported by this strategy."""
|
389
|
+
return self.traits
|
390
|
+
|
391
|
+
def backend_info(self) -> Dict[str, Any]:
|
392
|
+
"""Get information about the backend implementation."""
|
393
|
+
return {
|
394
|
+
"mode": self.mode.name,
|
395
|
+
"traits": str(self.traits),
|
396
|
+
"size": len(self),
|
397
|
+
"options": self.options.copy() if self.options else {}
|
398
|
+
}
|
399
|
+
|
400
|
+
def metrics(self) -> Dict[str, Any]:
|
401
|
+
"""Get performance metrics for this strategy."""
|
402
|
+
return {
|
403
|
+
"size": len(self),
|
404
|
+
"mode": self.mode.name,
|
405
|
+
"traits": str(self.traits)
|
406
|
+
}
|
80
407
|
|
81
408
|
|
409
|
+
# ==============================================================================
|
410
|
+
# LINEAR DATA STRUCTURE BASE CLASS
|
411
|
+
# ==============================================================================
|
412
|
+
|
82
413
|
class ANodeLinearStrategy(ANodeStrategy):
|
83
|
-
"""
|
414
|
+
"""
|
415
|
+
Abstract base for linear data structures.
|
416
|
+
|
417
|
+
Linear structures include:
|
418
|
+
- Stack (LIFO)
|
419
|
+
- Queue (FIFO)
|
420
|
+
- Deque (Double-ended)
|
421
|
+
- Priority Queue (Heap-based)
|
422
|
+
- Linked List
|
423
|
+
- Array List
|
424
|
+
"""
|
84
425
|
|
85
426
|
# Linear node type
|
86
427
|
STRATEGY_TYPE: NodeType = NodeType.LINEAR
|
87
428
|
|
429
|
+
# Linear-specific operations (optional - implement if supported)
|
88
430
|
def push_front(self, value: Any) -> None:
|
89
431
|
"""Add element to front."""
|
90
432
|
raise NotImplementedError("Subclasses must implement push_front")
|
@@ -109,7 +451,7 @@ class ANodeLinearStrategy(ANodeStrategy):
|
|
109
451
|
"""Set element at index."""
|
110
452
|
raise NotImplementedError("Subclasses must implement set_at_index")
|
111
453
|
|
112
|
-
#
|
454
|
+
# Behavioral views (optional)
|
113
455
|
def as_linked_list(self):
|
114
456
|
"""Provide LinkedList behavioral view."""
|
115
457
|
raise NotImplementedError("Subclasses must implement as_linked_list")
|
@@ -127,56 +469,25 @@ class ANodeLinearStrategy(ANodeStrategy):
|
|
127
469
|
raise NotImplementedError("Subclasses must implement as_deque")
|
128
470
|
|
129
471
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
# Graph node type
|
134
|
-
STRATEGY_TYPE: NodeType = NodeType.GRAPH
|
135
|
-
|
136
|
-
def add_edge(self, from_node: Any, to_node: Any, weight: float = 1.0) -> None:
|
137
|
-
"""Add edge between nodes."""
|
138
|
-
raise NotImplementedError("Subclasses must implement add_edge")
|
139
|
-
|
140
|
-
def remove_edge(self, from_node: Any, to_node: Any) -> bool:
|
141
|
-
"""Remove edge between nodes."""
|
142
|
-
raise NotImplementedError("Subclasses must implement remove_edge")
|
143
|
-
|
144
|
-
def has_edge(self, from_node: Any, to_node: Any) -> bool:
|
145
|
-
"""Check if edge exists."""
|
146
|
-
raise NotImplementedError("Subclasses must implement has_edge")
|
147
|
-
|
148
|
-
def find_path(self, start: Any, end: Any) -> List[Any]:
|
149
|
-
"""Find path between nodes."""
|
150
|
-
raise NotImplementedError("Subclasses must implement find_path")
|
151
|
-
|
152
|
-
def get_neighbors(self, node: Any) -> List[Any]:
|
153
|
-
"""Get neighboring nodes."""
|
154
|
-
raise NotImplementedError("Subclasses must implement get_neighbors")
|
155
|
-
|
156
|
-
def get_edge_weight(self, from_node: Any, to_node: Any) -> float:
|
157
|
-
"""Get edge weight."""
|
158
|
-
raise NotImplementedError("Subclasses must implement get_edge_weight")
|
159
|
-
|
160
|
-
# AUTO-3 Phase 3&4 methods
|
161
|
-
def as_union_find(self):
|
162
|
-
"""Provide Union-Find behavioral view."""
|
163
|
-
raise NotImplementedError("Subclasses must implement as_union_find")
|
164
|
-
|
165
|
-
def as_neural_graph(self):
|
166
|
-
"""Provide Neural Graph behavioral view."""
|
167
|
-
raise NotImplementedError("Subclasses must implement as_neural_graph")
|
168
|
-
|
169
|
-
def as_flow_network(self):
|
170
|
-
"""Provide Flow Network behavioral view."""
|
171
|
-
raise NotImplementedError("Subclasses must implement as_flow_network")
|
172
|
-
|
472
|
+
# ==============================================================================
|
473
|
+
# MATRIX DATA STRUCTURE BASE CLASS
|
474
|
+
# ==============================================================================
|
173
475
|
|
174
476
|
class ANodeMatrixStrategy(ANodeStrategy):
|
175
|
-
"""
|
477
|
+
"""
|
478
|
+
Abstract base for matrix data structures.
|
479
|
+
|
480
|
+
Matrix structures include:
|
481
|
+
- Sparse Matrix (COO, CSR, CSC)
|
482
|
+
- Bitmap
|
483
|
+
- Roaring Bitmap
|
484
|
+
- Dynamic Bitset
|
485
|
+
"""
|
176
486
|
|
177
487
|
# Matrix node type
|
178
488
|
STRATEGY_TYPE: NodeType = NodeType.MATRIX
|
179
489
|
|
490
|
+
# Matrix-specific operations (must be implemented)
|
180
491
|
def get_dimensions(self) -> tuple:
|
181
492
|
"""Get matrix dimensions (rows, cols)."""
|
182
493
|
raise NotImplementedError("Subclasses must implement get_dimensions")
|
@@ -209,7 +520,7 @@ class ANodeMatrixStrategy(ANodeStrategy):
|
|
209
520
|
"""Matrix addition."""
|
210
521
|
raise NotImplementedError("Subclasses must implement add")
|
211
522
|
|
212
|
-
# Matrix
|
523
|
+
# Matrix behavioral views (optional)
|
213
524
|
def as_adjacency_matrix(self):
|
214
525
|
"""Provide Adjacency Matrix behavioral view."""
|
215
526
|
raise NotImplementedError("Subclasses must implement as_adjacency_matrix")
|
@@ -223,26 +534,86 @@ class ANodeMatrixStrategy(ANodeStrategy):
|
|
223
534
|
raise NotImplementedError("Subclasses must implement as_sparse_matrix")
|
224
535
|
|
225
536
|
|
226
|
-
|
227
|
-
|
537
|
+
# ==============================================================================
|
538
|
+
# GRAPH DATA STRUCTURE BASE CLASS
|
539
|
+
# ==============================================================================
|
540
|
+
|
541
|
+
class ANodeGraphStrategy(ANodeStrategy):
|
542
|
+
"""
|
543
|
+
Abstract base for graph data structures.
|
228
544
|
|
229
|
-
|
230
|
-
|
545
|
+
Graph structures include:
|
546
|
+
- Adjacency List
|
547
|
+
- Union Find
|
548
|
+
"""
|
231
549
|
|
232
|
-
|
233
|
-
|
234
|
-
raise NotImplementedError("Subclasses must implement insert")
|
550
|
+
# Graph node type
|
551
|
+
STRATEGY_TYPE: NodeType = NodeType.GRAPH
|
235
552
|
|
236
|
-
|
237
|
-
|
238
|
-
|
553
|
+
# Graph-specific operations (must be implemented)
|
554
|
+
def add_edge(self, from_node: Any, to_node: Any, weight: float = 1.0) -> None:
|
555
|
+
"""Add edge between nodes."""
|
556
|
+
raise NotImplementedError("Subclasses must implement add_edge")
|
239
557
|
|
240
|
-
def
|
241
|
-
"""
|
242
|
-
raise NotImplementedError("Subclasses must implement
|
558
|
+
def remove_edge(self, from_node: Any, to_node: Any) -> bool:
|
559
|
+
"""Remove edge between nodes."""
|
560
|
+
raise NotImplementedError("Subclasses must implement remove_edge")
|
561
|
+
|
562
|
+
def has_edge(self, from_node: Any, to_node: Any) -> bool:
|
563
|
+
"""Check if edge exists."""
|
564
|
+
raise NotImplementedError("Subclasses must implement has_edge")
|
565
|
+
|
566
|
+
def find_path(self, start: Any, end: Any) -> List[Any]:
|
567
|
+
"""Find path between nodes."""
|
568
|
+
raise NotImplementedError("Subclasses must implement find_path")
|
569
|
+
|
570
|
+
def get_neighbors(self, node: Any) -> List[Any]:
|
571
|
+
"""Get neighboring nodes."""
|
572
|
+
raise NotImplementedError("Subclasses must implement get_neighbors")
|
573
|
+
|
574
|
+
def get_edge_weight(self, from_node: Any, to_node: Any) -> float:
|
575
|
+
"""Get edge weight."""
|
576
|
+
raise NotImplementedError("Subclasses must implement get_edge_weight")
|
577
|
+
|
578
|
+
# Graph behavioral views (optional)
|
579
|
+
def as_union_find(self):
|
580
|
+
"""Provide Union-Find behavioral view."""
|
581
|
+
raise NotImplementedError("Subclasses must implement as_union_find")
|
582
|
+
|
583
|
+
def as_neural_graph(self):
|
584
|
+
"""Provide Neural Graph behavioral view."""
|
585
|
+
raise NotImplementedError("Subclasses must implement as_neural_graph")
|
586
|
+
|
587
|
+
def as_flow_network(self):
|
588
|
+
"""Provide Flow Network behavioral view."""
|
589
|
+
raise NotImplementedError("Subclasses must implement as_flow_network")
|
590
|
+
|
591
|
+
|
592
|
+
# ==============================================================================
|
593
|
+
# TREE DATA STRUCTURE BASE CLASS
|
594
|
+
# ==============================================================================
|
595
|
+
|
596
|
+
class ANodeTreeStrategy(ANodeGraphStrategy):
|
597
|
+
"""
|
598
|
+
Abstract base for tree data structures.
|
599
|
+
|
600
|
+
Tree structures include:
|
601
|
+
- BTree, B+ Tree
|
602
|
+
- Trie, Radix Trie, Patricia Trie
|
603
|
+
- Heap
|
604
|
+
- AVL Tree, Red-Black Tree
|
605
|
+
- Skip List, Splay Tree, Treap
|
606
|
+
- And many more...
|
607
|
+
|
608
|
+
Note: Trees extend Graph because trees ARE graphs (connected acyclic graphs)
|
609
|
+
"""
|
610
|
+
|
611
|
+
# Tree node type
|
612
|
+
STRATEGY_TYPE: NodeType = NodeType.TREE
|
243
613
|
|
614
|
+
# Tree-specific operations (optional)
|
244
615
|
def traverse(self, order: str = 'inorder') -> List[Any]:
|
245
|
-
"""Traverse tree in specified order."""
|
616
|
+
"""Traverse tree in specified order (inorder, preorder, postorder)."""
|
246
617
|
raise NotImplementedError("Subclasses must implement traverse")
|
247
618
|
|
248
619
|
def get_min(self) -> Any:
|
@@ -253,7 +624,7 @@ class ANodeTreeStrategy(ANodeGraphStrategy):
|
|
253
624
|
"""Get maximum key."""
|
254
625
|
raise NotImplementedError("Subclasses must implement get_max")
|
255
626
|
|
256
|
-
#
|
627
|
+
# Tree behavioral views (optional)
|
257
628
|
def as_trie(self):
|
258
629
|
"""Provide Trie behavioral view."""
|
259
630
|
raise NotImplementedError("Subclasses must implement as_trie")
|