exonware-xwnode 0.0.1.12__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 +14 -0
- exonware/xwnode/__init__.py +127 -0
- exonware/xwnode/base.py +676 -0
- exonware/xwnode/config.py +178 -0
- exonware/xwnode/contracts.py +730 -0
- exonware/xwnode/errors.py +503 -0
- exonware/xwnode/facade.py +460 -0
- exonware/xwnode/strategies/__init__.py +158 -0
- exonware/xwnode/strategies/advisor.py +463 -0
- exonware/xwnode/strategies/edges/__init__.py +32 -0
- exonware/xwnode/strategies/edges/adj_list.py +227 -0
- exonware/xwnode/strategies/edges/adj_matrix.py +391 -0
- exonware/xwnode/strategies/edges/base.py +169 -0
- exonware/xwnode/strategies/flyweight.py +328 -0
- exonware/xwnode/strategies/impls/__init__.py +13 -0
- exonware/xwnode/strategies/impls/_base_edge.py +403 -0
- exonware/xwnode/strategies/impls/_base_node.py +307 -0
- exonware/xwnode/strategies/impls/edge_adj_list.py +353 -0
- exonware/xwnode/strategies/impls/edge_adj_matrix.py +445 -0
- exonware/xwnode/strategies/impls/edge_bidir_wrapper.py +455 -0
- exonware/xwnode/strategies/impls/edge_block_adj_matrix.py +539 -0
- exonware/xwnode/strategies/impls/edge_coo.py +533 -0
- exonware/xwnode/strategies/impls/edge_csc.py +447 -0
- exonware/xwnode/strategies/impls/edge_csr.py +492 -0
- exonware/xwnode/strategies/impls/edge_dynamic_adj_list.py +503 -0
- exonware/xwnode/strategies/impls/edge_flow_network.py +555 -0
- exonware/xwnode/strategies/impls/edge_hyperedge_set.py +516 -0
- exonware/xwnode/strategies/impls/edge_neural_graph.py +650 -0
- exonware/xwnode/strategies/impls/edge_octree.py +574 -0
- exonware/xwnode/strategies/impls/edge_property_store.py +655 -0
- exonware/xwnode/strategies/impls/edge_quadtree.py +519 -0
- exonware/xwnode/strategies/impls/edge_rtree.py +820 -0
- exonware/xwnode/strategies/impls/edge_temporal_edgeset.py +558 -0
- exonware/xwnode/strategies/impls/edge_tree_graph_basic.py +271 -0
- exonware/xwnode/strategies/impls/edge_weighted_graph.py +411 -0
- exonware/xwnode/strategies/manager.py +775 -0
- exonware/xwnode/strategies/metrics.py +538 -0
- exonware/xwnode/strategies/migration.py +432 -0
- exonware/xwnode/strategies/nodes/__init__.py +50 -0
- exonware/xwnode/strategies/nodes/_base_node.py +307 -0
- exonware/xwnode/strategies/nodes/adjacency_list.py +267 -0
- exonware/xwnode/strategies/nodes/aho_corasick.py +345 -0
- exonware/xwnode/strategies/nodes/array_list.py +209 -0
- exonware/xwnode/strategies/nodes/base.py +247 -0
- exonware/xwnode/strategies/nodes/deque.py +200 -0
- exonware/xwnode/strategies/nodes/hash_map.py +135 -0
- exonware/xwnode/strategies/nodes/heap.py +307 -0
- exonware/xwnode/strategies/nodes/linked_list.py +232 -0
- exonware/xwnode/strategies/nodes/node_aho_corasick.py +520 -0
- exonware/xwnode/strategies/nodes/node_array_list.py +175 -0
- exonware/xwnode/strategies/nodes/node_avl_tree.py +371 -0
- exonware/xwnode/strategies/nodes/node_b_plus_tree.py +542 -0
- exonware/xwnode/strategies/nodes/node_bitmap.py +420 -0
- exonware/xwnode/strategies/nodes/node_bitset_dynamic.py +513 -0
- exonware/xwnode/strategies/nodes/node_bloom_filter.py +347 -0
- exonware/xwnode/strategies/nodes/node_btree.py +357 -0
- exonware/xwnode/strategies/nodes/node_count_min_sketch.py +470 -0
- exonware/xwnode/strategies/nodes/node_cow_tree.py +473 -0
- exonware/xwnode/strategies/nodes/node_cuckoo_hash.py +392 -0
- exonware/xwnode/strategies/nodes/node_fenwick_tree.py +301 -0
- exonware/xwnode/strategies/nodes/node_hash_map.py +269 -0
- exonware/xwnode/strategies/nodes/node_heap.py +191 -0
- exonware/xwnode/strategies/nodes/node_hyperloglog.py +407 -0
- exonware/xwnode/strategies/nodes/node_linked_list.py +409 -0
- exonware/xwnode/strategies/nodes/node_lsm_tree.py +400 -0
- exonware/xwnode/strategies/nodes/node_ordered_map.py +390 -0
- exonware/xwnode/strategies/nodes/node_ordered_map_balanced.py +565 -0
- exonware/xwnode/strategies/nodes/node_patricia.py +512 -0
- exonware/xwnode/strategies/nodes/node_persistent_tree.py +378 -0
- exonware/xwnode/strategies/nodes/node_radix_trie.py +452 -0
- exonware/xwnode/strategies/nodes/node_red_black_tree.py +497 -0
- exonware/xwnode/strategies/nodes/node_roaring_bitmap.py +570 -0
- exonware/xwnode/strategies/nodes/node_segment_tree.py +289 -0
- exonware/xwnode/strategies/nodes/node_set_hash.py +354 -0
- exonware/xwnode/strategies/nodes/node_set_tree.py +480 -0
- exonware/xwnode/strategies/nodes/node_skip_list.py +316 -0
- exonware/xwnode/strategies/nodes/node_splay_tree.py +393 -0
- exonware/xwnode/strategies/nodes/node_suffix_array.py +487 -0
- exonware/xwnode/strategies/nodes/node_treap.py +387 -0
- exonware/xwnode/strategies/nodes/node_tree_graph_hybrid.py +1434 -0
- exonware/xwnode/strategies/nodes/node_trie.py +252 -0
- exonware/xwnode/strategies/nodes/node_union_find.py +187 -0
- exonware/xwnode/strategies/nodes/node_xdata_optimized.py +369 -0
- exonware/xwnode/strategies/nodes/priority_queue.py +209 -0
- exonware/xwnode/strategies/nodes/queue.py +161 -0
- exonware/xwnode/strategies/nodes/sparse_matrix.py +206 -0
- exonware/xwnode/strategies/nodes/stack.py +152 -0
- exonware/xwnode/strategies/nodes/trie.py +274 -0
- exonware/xwnode/strategies/nodes/union_find.py +283 -0
- exonware/xwnode/strategies/pattern_detector.py +603 -0
- exonware/xwnode/strategies/performance_monitor.py +487 -0
- exonware/xwnode/strategies/queries/__init__.py +24 -0
- exonware/xwnode/strategies/queries/base.py +236 -0
- exonware/xwnode/strategies/queries/cql.py +201 -0
- exonware/xwnode/strategies/queries/cypher.py +181 -0
- exonware/xwnode/strategies/queries/datalog.py +70 -0
- exonware/xwnode/strategies/queries/elastic_dsl.py +70 -0
- exonware/xwnode/strategies/queries/eql.py +70 -0
- exonware/xwnode/strategies/queries/flux.py +70 -0
- exonware/xwnode/strategies/queries/gql.py +70 -0
- exonware/xwnode/strategies/queries/graphql.py +240 -0
- exonware/xwnode/strategies/queries/gremlin.py +181 -0
- exonware/xwnode/strategies/queries/hiveql.py +214 -0
- exonware/xwnode/strategies/queries/hql.py +70 -0
- exonware/xwnode/strategies/queries/jmespath.py +219 -0
- exonware/xwnode/strategies/queries/jq.py +66 -0
- exonware/xwnode/strategies/queries/json_query.py +66 -0
- exonware/xwnode/strategies/queries/jsoniq.py +248 -0
- exonware/xwnode/strategies/queries/kql.py +70 -0
- exonware/xwnode/strategies/queries/linq.py +238 -0
- exonware/xwnode/strategies/queries/logql.py +70 -0
- exonware/xwnode/strategies/queries/mql.py +68 -0
- exonware/xwnode/strategies/queries/n1ql.py +210 -0
- exonware/xwnode/strategies/queries/partiql.py +70 -0
- exonware/xwnode/strategies/queries/pig.py +215 -0
- exonware/xwnode/strategies/queries/promql.py +70 -0
- exonware/xwnode/strategies/queries/sparql.py +220 -0
- exonware/xwnode/strategies/queries/sql.py +275 -0
- exonware/xwnode/strategies/queries/xml_query.py +66 -0
- exonware/xwnode/strategies/queries/xpath.py +223 -0
- exonware/xwnode/strategies/queries/xquery.py +258 -0
- exonware/xwnode/strategies/queries/xwnode_executor.py +332 -0
- exonware/xwnode/strategies/queries/xwquery_strategy.py +424 -0
- exonware/xwnode/strategies/registry.py +604 -0
- exonware/xwnode/strategies/simple.py +273 -0
- exonware/xwnode/strategies/utils.py +532 -0
- exonware/xwnode/types.py +912 -0
- exonware/xwnode/version.py +78 -0
- exonware_xwnode-0.0.1.12.dist-info/METADATA +169 -0
- exonware_xwnode-0.0.1.12.dist-info/RECORD +132 -0
- exonware_xwnode-0.0.1.12.dist-info/WHEEL +4 -0
- exonware_xwnode-0.0.1.12.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,369 @@
|
|
1
|
+
"""
|
2
|
+
DATA_INTERCHANGE_OPTIMIZED Node Strategy Implementation
|
3
|
+
|
4
|
+
Ultra-lightweight strategy specifically optimized for data interchange patterns:
|
5
|
+
- Copy-on-write semantics for data interchange
|
6
|
+
- Object pooling support for factory patterns
|
7
|
+
- Structural hash caching for fast equality checks
|
8
|
+
- Minimal metadata overhead
|
9
|
+
- Zero graph features for maximum performance
|
10
|
+
- __slots__ optimization for memory efficiency
|
11
|
+
"""
|
12
|
+
|
13
|
+
import weakref
|
14
|
+
from typing import Any, Iterator, Dict, List, Optional
|
15
|
+
from ._base_node import aNodeStrategy
|
16
|
+
from ...types import NodeMode, NodeTrait
|
17
|
+
from ...errors import XWNodeUnsupportedCapabilityError
|
18
|
+
|
19
|
+
# Import shared utilities
|
20
|
+
from ..utils import (
|
21
|
+
recursive_to_native, is_sequential_numeric_keys,
|
22
|
+
calculate_structural_hash, create_performance_tracker
|
23
|
+
)
|
24
|
+
|
25
|
+
|
26
|
+
class DataInterchangeOptimizedStrategy(aNodeStrategy):
|
27
|
+
"""
|
28
|
+
Ultra-lightweight node strategy optimized for data interchange patterns.
|
29
|
+
|
30
|
+
This strategy provides maximum performance for data interchange patterns:
|
31
|
+
- O(1) hash map operations using Python dict
|
32
|
+
- COW semantics with lazy copying
|
33
|
+
- Structural hash caching for fast equality
|
34
|
+
- Object pooling support
|
35
|
+
- Minimal memory overhead with __slots__
|
36
|
+
- Zero graph/edge overhead
|
37
|
+
"""
|
38
|
+
|
39
|
+
__slots__ = (
|
40
|
+
'_data', '_size', '_hash_cache', '_frozen', '_cow_enabled',
|
41
|
+
'_pool_ref', '_creation_time', '_access_count', 'mode', 'traits', 'options'
|
42
|
+
)
|
43
|
+
|
44
|
+
def __init__(self, traits: NodeTrait = NodeTrait.INDEXED, **options):
|
45
|
+
"""Initialize the xData-optimized strategy."""
|
46
|
+
# Initialize parent without calling super() to avoid dict overhead
|
47
|
+
self.mode = NodeMode.HASH_MAP # Using HASH_MAP as base mode
|
48
|
+
self.traits = traits
|
49
|
+
self.options = options
|
50
|
+
|
51
|
+
# Core data storage (ultra-efficient)
|
52
|
+
self._data: Dict[str, Any] = {}
|
53
|
+
self._size = 0
|
54
|
+
|
55
|
+
# COW optimization flags
|
56
|
+
self._hash_cache: Optional[int] = None
|
57
|
+
self._frozen = False # True after first copy
|
58
|
+
self._cow_enabled = options.get('enable_cow', True)
|
59
|
+
|
60
|
+
# Object pooling support
|
61
|
+
self._pool_ref: Optional[weakref.ref] = None
|
62
|
+
|
63
|
+
# Performance tracking (minimal overhead)
|
64
|
+
self._creation_time = options.get('creation_time', 0)
|
65
|
+
self._performance_tracker = create_performance_tracker()
|
66
|
+
|
67
|
+
self._validate_traits()
|
68
|
+
|
69
|
+
def get_supported_traits(self) -> NodeTrait:
|
70
|
+
"""Get the traits supported by the xData-optimized strategy."""
|
71
|
+
return NodeTrait.INDEXED # Only essential traits for maximum performance
|
72
|
+
|
73
|
+
# ============================================================================
|
74
|
+
# ULTRA-OPTIMIZED CORE OPERATIONS
|
75
|
+
# ============================================================================
|
76
|
+
|
77
|
+
def put(self, key: Any, value: Any = None) -> None:
|
78
|
+
"""Store a key-value pair with COW optimization."""
|
79
|
+
self._ensure_mutable()
|
80
|
+
|
81
|
+
str_key = str(key)
|
82
|
+
if str_key not in self._data:
|
83
|
+
self._size += 1
|
84
|
+
|
85
|
+
self._data[str_key] = value
|
86
|
+
self._invalidate_cache()
|
87
|
+
self._performance_tracker.record_access()
|
88
|
+
|
89
|
+
def get(self, key: Any, default: Any = None) -> Any:
|
90
|
+
"""Retrieve a value by key (zero-overhead success path)."""
|
91
|
+
self._performance_tracker.record_access()
|
92
|
+
return self._data.get(str(key), default)
|
93
|
+
|
94
|
+
def has(self, key: Any) -> bool:
|
95
|
+
"""Check if key exists (optimized)."""
|
96
|
+
return str(key) in self._data
|
97
|
+
|
98
|
+
def delete(self, key: Any) -> bool:
|
99
|
+
"""Remove a key-value pair with COW."""
|
100
|
+
self._ensure_mutable()
|
101
|
+
|
102
|
+
str_key = str(key)
|
103
|
+
if str_key in self._data:
|
104
|
+
del self._data[str_key]
|
105
|
+
self._size -= 1
|
106
|
+
self._invalidate_cache()
|
107
|
+
return True
|
108
|
+
return False
|
109
|
+
|
110
|
+
def remove(self, key: Any) -> bool:
|
111
|
+
"""Remove a key-value pair (alias for delete)."""
|
112
|
+
return self.delete(key)
|
113
|
+
|
114
|
+
def clear(self) -> None:
|
115
|
+
"""Clear all data with COW."""
|
116
|
+
self._ensure_mutable()
|
117
|
+
self._data.clear()
|
118
|
+
self._size = 0
|
119
|
+
self._invalidate_cache()
|
120
|
+
|
121
|
+
def keys(self) -> Iterator[str]:
|
122
|
+
"""Get all keys (zero-copy iterator)."""
|
123
|
+
return iter(self._data.keys())
|
124
|
+
|
125
|
+
def values(self) -> Iterator[Any]:
|
126
|
+
"""Get all values (zero-copy iterator)."""
|
127
|
+
return iter(self._data.values())
|
128
|
+
|
129
|
+
def items(self) -> Iterator[tuple[str, Any]]:
|
130
|
+
"""Get all key-value pairs (zero-copy iterator)."""
|
131
|
+
return iter(self._data.items())
|
132
|
+
|
133
|
+
def __len__(self) -> int:
|
134
|
+
"""Get the number of items (zero overhead)."""
|
135
|
+
return self._size
|
136
|
+
|
137
|
+
def to_native(self) -> Dict[str, Any]:
|
138
|
+
"""Convert to native Python dictionary (optimized for xData)."""
|
139
|
+
# Return a copy with all nested XWNode objects converted to native types
|
140
|
+
return {k: recursive_to_native(v) for k, v in self._data.items()}
|
141
|
+
|
142
|
+
# ============================================================================
|
143
|
+
# COPY-ON-WRITE OPTIMIZATIONS (xData Specific)
|
144
|
+
# ============================================================================
|
145
|
+
|
146
|
+
def _ensure_mutable(self) -> None:
|
147
|
+
"""Ensure this instance is mutable (COW implementation)."""
|
148
|
+
if not self._cow_enabled:
|
149
|
+
return
|
150
|
+
|
151
|
+
if self._frozen:
|
152
|
+
# Create a new data dict (copy-on-write)
|
153
|
+
self._data = dict(self._data)
|
154
|
+
self._frozen = False
|
155
|
+
self._invalidate_cache()
|
156
|
+
|
157
|
+
def freeze(self) -> None:
|
158
|
+
"""Freeze this instance for COW (called after first copy)."""
|
159
|
+
if self._cow_enabled:
|
160
|
+
self._frozen = True
|
161
|
+
|
162
|
+
def copy(self) -> 'DataInterchangeOptimizedStrategy':
|
163
|
+
"""Create a COW copy of this strategy."""
|
164
|
+
if self._cow_enabled:
|
165
|
+
self.freeze()
|
166
|
+
|
167
|
+
# Create new instance sharing data until mutation
|
168
|
+
new_instance = DataInterchangeOptimizedStrategy(self.traits, **self.options)
|
169
|
+
new_instance._data = self._data # Shared until mutation
|
170
|
+
new_instance._size = self._size
|
171
|
+
new_instance._hash_cache = self._hash_cache
|
172
|
+
new_instance._frozen = False # New instance can be mutated
|
173
|
+
|
174
|
+
return new_instance
|
175
|
+
|
176
|
+
# ============================================================================
|
177
|
+
# STRUCTURAL HASH CACHING (xData Performance)
|
178
|
+
# ============================================================================
|
179
|
+
|
180
|
+
def _invalidate_cache(self) -> None:
|
181
|
+
"""Invalidate cached hash (minimal overhead)."""
|
182
|
+
self._hash_cache = None
|
183
|
+
|
184
|
+
def structural_hash(self) -> int:
|
185
|
+
"""Get structural hash with caching (xData equality optimization)."""
|
186
|
+
if self._hash_cache is None:
|
187
|
+
# Compute hash based on structure, not values
|
188
|
+
# This is optimized for xData's equality checking
|
189
|
+
self._hash_cache = calculate_structural_hash(self._data)
|
190
|
+
|
191
|
+
return self._hash_cache
|
192
|
+
|
193
|
+
def fast_equals(self, other: 'DataInterchangeOptimizedStrategy') -> bool:
|
194
|
+
"""Fast equality check using structural hashes."""
|
195
|
+
if not isinstance(other, DataInterchangeOptimizedStrategy):
|
196
|
+
return False
|
197
|
+
|
198
|
+
# Quick size check
|
199
|
+
if self._size != other._size:
|
200
|
+
return False
|
201
|
+
|
202
|
+
# Structural hash comparison (much faster than deep comparison)
|
203
|
+
return self.structural_hash() == other.structural_hash()
|
204
|
+
|
205
|
+
# ============================================================================
|
206
|
+
# OBJECT POOLING SUPPORT (Factory Pattern)
|
207
|
+
# ============================================================================
|
208
|
+
|
209
|
+
def set_pool_reference(self, pool_ref: weakref.ref) -> None:
|
210
|
+
"""Set reference to object pool for cleanup."""
|
211
|
+
self._pool_ref = pool_ref
|
212
|
+
|
213
|
+
def return_to_pool(self) -> None:
|
214
|
+
"""Return this instance to object pool if available."""
|
215
|
+
if self._pool_ref is not None:
|
216
|
+
pool = self._pool_ref()
|
217
|
+
if pool is not None:
|
218
|
+
# Reset state for reuse
|
219
|
+
self._data.clear()
|
220
|
+
self._size = 0
|
221
|
+
self._invalidate_cache()
|
222
|
+
self._frozen = False
|
223
|
+
self._performance_tracker.reset()
|
224
|
+
pool.return_instance(self)
|
225
|
+
|
226
|
+
def __del__(self):
|
227
|
+
"""Destructor with object pool support."""
|
228
|
+
self.return_to_pool()
|
229
|
+
|
230
|
+
# ============================================================================
|
231
|
+
# XDATA-SPECIFIC OPTIMIZATIONS
|
232
|
+
# ============================================================================
|
233
|
+
|
234
|
+
@property
|
235
|
+
def is_list(self) -> bool:
|
236
|
+
"""Check if this represents a list (optimized for xData)."""
|
237
|
+
return is_sequential_numeric_keys(self._data)
|
238
|
+
|
239
|
+
@property
|
240
|
+
def is_dict(self) -> bool:
|
241
|
+
"""Check if this represents a dict (optimized for xData)."""
|
242
|
+
return not self.is_list
|
243
|
+
|
244
|
+
@property
|
245
|
+
def is_leaf(self) -> bool:
|
246
|
+
"""Check if this is a leaf node (xData pattern)."""
|
247
|
+
return len(self._data) == 1 and "value" in self._data
|
248
|
+
|
249
|
+
# ============================================================================
|
250
|
+
# PERFORMANCE MONITORING (Minimal Overhead)
|
251
|
+
# ============================================================================
|
252
|
+
|
253
|
+
@property
|
254
|
+
def backend_info(self) -> Dict[str, Any]:
|
255
|
+
"""Get backend implementation info."""
|
256
|
+
return {
|
257
|
+
'strategy': 'DATA_INTERCHANGE_OPTIMIZED',
|
258
|
+
'backend': 'Optimized Python dict with COW',
|
259
|
+
'complexity': {
|
260
|
+
'get': 'O(1)',
|
261
|
+
'put': 'O(1)',
|
262
|
+
'has': 'O(1)',
|
263
|
+
'delete': 'O(1)'
|
264
|
+
},
|
265
|
+
'features': [
|
266
|
+
'copy_on_write',
|
267
|
+
'structural_hashing',
|
268
|
+
'object_pooling',
|
269
|
+
'slots_optimization'
|
270
|
+
]
|
271
|
+
}
|
272
|
+
|
273
|
+
@property
|
274
|
+
def metrics(self) -> Dict[str, Any]:
|
275
|
+
"""Get performance metrics."""
|
276
|
+
metrics = self._performance_tracker.get_metrics()
|
277
|
+
metrics.update({
|
278
|
+
'size': self._size,
|
279
|
+
'memory_usage': f"{self._size * 32} bytes (estimated)",
|
280
|
+
'is_frozen': self._frozen,
|
281
|
+
'hash_cached': self._hash_cache is not None,
|
282
|
+
'cow_enabled': self._cow_enabled,
|
283
|
+
'creation_time': self._creation_time
|
284
|
+
})
|
285
|
+
return metrics
|
286
|
+
|
287
|
+
def get_xdata_stats(self) -> Dict[str, Any]:
|
288
|
+
"""Get xData-specific performance statistics."""
|
289
|
+
return {
|
290
|
+
'strategy': 'DATA_INTERCHANGE_OPTIMIZED',
|
291
|
+
'cow_active': self._cow_enabled,
|
292
|
+
'frozen_state': self._frozen,
|
293
|
+
'cache_efficiency': 'cached' if self._hash_cache else 'not_cached',
|
294
|
+
'memory_footprint': 'minimal',
|
295
|
+
'graph_overhead': 'zero',
|
296
|
+
'pooling_support': self._pool_ref is not None,
|
297
|
+
'access_pattern': f"{self._performance_tracker.get_metrics()['access_count']} operations"
|
298
|
+
}
|
299
|
+
|
300
|
+
# ============================================================================
|
301
|
+
# DISABLED FEATURES (Maximum Performance)
|
302
|
+
# ============================================================================
|
303
|
+
|
304
|
+
def get_ordered(self, start: Any = None, end: Any = None) -> List[tuple[Any, Any]]:
|
305
|
+
"""Ordered operations not supported in DATA_INTERCHANGE_OPTIMIZED."""
|
306
|
+
raise XWNodeUnsupportedCapabilityError(
|
307
|
+
'ordered_operations',
|
308
|
+
'DATA_INTERCHANGE_OPTIMIZED',
|
309
|
+
['fast_lookup', 'copy_on_write', 'structural_hashing']
|
310
|
+
).suggest("Use preset='ANALYTICS' for ordered operations")
|
311
|
+
|
312
|
+
def get_with_prefix(self, prefix: str) -> List[tuple[Any, Any]]:
|
313
|
+
"""Prefix operations not optimized in DATA_INTERCHANGE_OPTIMIZED."""
|
314
|
+
raise XWNodeUnsupportedCapabilityError(
|
315
|
+
'prefix_operations',
|
316
|
+
'DATA_INTERCHANGE_OPTIMIZED',
|
317
|
+
['fast_lookup', 'copy_on_write']
|
318
|
+
).suggest("Use preset='SEARCH_ENGINE' for prefix operations")
|
319
|
+
|
320
|
+
def get_priority(self) -> Optional[tuple[Any, Any]]:
|
321
|
+
"""Priority operations not supported in DATA_INTERCHANGE_OPTIMIZED."""
|
322
|
+
raise XWNodeUnsupportedCapabilityError(
|
323
|
+
'priority_operations',
|
324
|
+
'DATA_INTERCHANGE_OPTIMIZED',
|
325
|
+
['fast_lookup', 'copy_on_write']
|
326
|
+
).suggest("Use preset='ANALYTICS' with heap structure for priorities")
|
327
|
+
|
328
|
+
# ============================================================================
|
329
|
+
# STRING REPRESENTATION (Optimized)
|
330
|
+
# ============================================================================
|
331
|
+
|
332
|
+
def __str__(self) -> str:
|
333
|
+
"""Optimized string representation."""
|
334
|
+
return f"DataInterchangeOptimized(size={self._size}, cow={self._cow_enabled})"
|
335
|
+
|
336
|
+
def __repr__(self) -> str:
|
337
|
+
"""Detailed string representation."""
|
338
|
+
return (f"DataInterchangeOptimizedStrategy(size={self._size}, "
|
339
|
+
f"frozen={self._frozen}, cow={self._cow_enabled}, "
|
340
|
+
f"cached={self._hash_cache is not None})")
|
341
|
+
|
342
|
+
|
343
|
+
# ============================================================================
|
344
|
+
# FACTORY FUNCTION
|
345
|
+
# ============================================================================
|
346
|
+
|
347
|
+
def create_data_interchange_optimized_strategy(**options) -> DataInterchangeOptimizedStrategy:
|
348
|
+
"""
|
349
|
+
Factory function for creating data interchange optimized strategy instances.
|
350
|
+
|
351
|
+
This function provides the recommended way to create DATA_INTERCHANGE_OPTIMIZED
|
352
|
+
strategy instances with proper configuration for data interchange usage.
|
353
|
+
"""
|
354
|
+
# Set data interchange specific optimizations
|
355
|
+
data_interchange_options = {
|
356
|
+
'enable_cow': True,
|
357
|
+
'enable_pooling': True,
|
358
|
+
'enable_hash_caching': True,
|
359
|
+
'minimal_metadata': True,
|
360
|
+
'slots_optimization': True,
|
361
|
+
'fast_creation': True,
|
362
|
+
'lazy_loading': False, # Eager loading for predictability
|
363
|
+
'memory_profile': 'ultra_minimal'
|
364
|
+
}
|
365
|
+
|
366
|
+
# Merge with user options
|
367
|
+
data_interchange_options.update(options)
|
368
|
+
|
369
|
+
return DataInterchangeOptimizedStrategy(NodeTrait.INDEXED, **data_interchange_options)
|
@@ -0,0 +1,209 @@
|
|
1
|
+
"""
|
2
|
+
Priority Queue Strategy Implementation
|
3
|
+
|
4
|
+
Implements a priority queue using Python's heapq for efficient priority-based operations.
|
5
|
+
|
6
|
+
Company: eXonware.com
|
7
|
+
Author: Eng. Muhammad AlShehri
|
8
|
+
Email: connect@exonware.com
|
9
|
+
Version: 0.0.1.12
|
10
|
+
Generation Date: 07-Sep-2025
|
11
|
+
"""
|
12
|
+
|
13
|
+
from typing import Any, Iterator, Optional, Dict, Union, Tuple
|
14
|
+
import heapq
|
15
|
+
from .base import ANodeLinearStrategy
|
16
|
+
from ...types import NodeMode, NodeTrait
|
17
|
+
|
18
|
+
|
19
|
+
class PriorityQueueStrategy(ANodeLinearStrategy):
|
20
|
+
"""
|
21
|
+
Priority Queue node strategy for priority-based operations.
|
22
|
+
|
23
|
+
Uses a binary heap for efficient insertion and extraction of
|
24
|
+
highest priority elements, ideal for algorithms like Dijkstra's.
|
25
|
+
"""
|
26
|
+
|
27
|
+
def __init__(self):
|
28
|
+
"""Initialize an empty priority queue."""
|
29
|
+
super().__init__()
|
30
|
+
self._heap: List[Tuple[float, int, str, Any]] = [] # (priority, counter, key, value)
|
31
|
+
self._counter = 0 # For stable sorting
|
32
|
+
self._mode = NodeMode.PRIORITY_QUEUE
|
33
|
+
self._traits = {NodeTrait.PRIORITY, NodeTrait.FAST_INSERT, NodeTrait.FAST_DELETE}
|
34
|
+
|
35
|
+
def insert(self, key: str, value: Any) -> None:
|
36
|
+
"""Insert an item with default priority (0)."""
|
37
|
+
self.insert_with_priority(key, value, 0.0)
|
38
|
+
|
39
|
+
def find(self, key: str) -> Optional[Any]:
|
40
|
+
"""Find an item in the priority queue (O(n) operation)."""
|
41
|
+
for priority, counter, k, v in self._heap:
|
42
|
+
if k == key:
|
43
|
+
return v
|
44
|
+
return None
|
45
|
+
|
46
|
+
def delete(self, key: str) -> bool:
|
47
|
+
"""Remove an item from the priority queue."""
|
48
|
+
for i, (priority, counter, k, v) in enumerate(self._heap):
|
49
|
+
if k == key:
|
50
|
+
self._heap.pop(i)
|
51
|
+
heapq.heapify(self._heap) # Re-heapify after removal
|
52
|
+
return True
|
53
|
+
return False
|
54
|
+
|
55
|
+
def size(self) -> int:
|
56
|
+
"""Get the number of items in the priority queue."""
|
57
|
+
return len(self._heap)
|
58
|
+
|
59
|
+
def is_empty(self) -> bool:
|
60
|
+
"""Check if the priority queue is empty."""
|
61
|
+
return len(self._heap) == 0
|
62
|
+
|
63
|
+
def to_native(self) -> Dict[str, Any]:
|
64
|
+
"""Convert priority queue to native dictionary format."""
|
65
|
+
result = {}
|
66
|
+
for priority, counter, key, value in self._heap:
|
67
|
+
result[key] = value
|
68
|
+
return result
|
69
|
+
|
70
|
+
def from_native(self, data: Dict[str, Any]) -> None:
|
71
|
+
"""Load priority queue from native dictionary format."""
|
72
|
+
self._heap.clear()
|
73
|
+
for key, value in data.items():
|
74
|
+
self.insert(key, value)
|
75
|
+
|
76
|
+
def insert_with_priority(self, key: str, value: Any, priority: float) -> None:
|
77
|
+
"""Insert an item with specific priority."""
|
78
|
+
heapq.heappush(self._heap, (priority, self._counter, key, value))
|
79
|
+
self._counter += 1
|
80
|
+
|
81
|
+
def extract_min(self) -> Optional[Tuple[str, Any, float]]:
|
82
|
+
"""Extract item with minimum priority."""
|
83
|
+
if self.is_empty():
|
84
|
+
return None
|
85
|
+
|
86
|
+
priority, counter, key, value = heapq.heappop(self._heap)
|
87
|
+
return (key, value, priority)
|
88
|
+
|
89
|
+
def extract_max(self) -> Optional[Tuple[str, Any, float]]:
|
90
|
+
"""Extract item with maximum priority."""
|
91
|
+
if self.is_empty():
|
92
|
+
return None
|
93
|
+
|
94
|
+
# Convert to max-heap by negating priorities
|
95
|
+
max_heap = [(-priority, counter, key, value) for priority, counter, key, value in self._heap]
|
96
|
+
heapq.heapify(max_heap)
|
97
|
+
|
98
|
+
neg_priority, counter, key, value = heapq.heappop(max_heap)
|
99
|
+
priority = -neg_priority
|
100
|
+
|
101
|
+
# Remove from original heap
|
102
|
+
for i, (p, c, k, v) in enumerate(self._heap):
|
103
|
+
if k == key and c == counter:
|
104
|
+
self._heap.pop(i)
|
105
|
+
break
|
106
|
+
|
107
|
+
return (key, value, priority)
|
108
|
+
|
109
|
+
def peek_min(self) -> Optional[Tuple[str, Any, float]]:
|
110
|
+
"""Peek at item with minimum priority without removing it."""
|
111
|
+
if self.is_empty():
|
112
|
+
return None
|
113
|
+
|
114
|
+
priority, counter, key, value = self._heap[0]
|
115
|
+
return (key, value, priority)
|
116
|
+
|
117
|
+
def peek_max(self) -> Optional[Tuple[str, Any, float]]:
|
118
|
+
"""Peek at item with maximum priority without removing it."""
|
119
|
+
if self.is_empty():
|
120
|
+
return None
|
121
|
+
|
122
|
+
max_item = None
|
123
|
+
for priority, counter, key, value in self._heap:
|
124
|
+
if max_item is None or priority > max_item[2]:
|
125
|
+
max_item = (key, value, priority)
|
126
|
+
|
127
|
+
return max_item
|
128
|
+
|
129
|
+
def update_priority(self, key: str, new_priority: float) -> bool:
|
130
|
+
"""Update the priority of an existing item."""
|
131
|
+
for i, (priority, counter, k, v) in enumerate(self._heap):
|
132
|
+
if k == key:
|
133
|
+
self._heap[i] = (new_priority, counter, k, v)
|
134
|
+
heapq.heapify(self._heap) # Re-heapify after update
|
135
|
+
return True
|
136
|
+
return False
|
137
|
+
|
138
|
+
def get_priority(self, key: str) -> Optional[float]:
|
139
|
+
"""Get the priority of an item."""
|
140
|
+
for priority, counter, k, v in self._heap:
|
141
|
+
if k == key:
|
142
|
+
return priority
|
143
|
+
return None
|
144
|
+
|
145
|
+
def clear(self) -> None:
|
146
|
+
"""Clear all items from the priority queue."""
|
147
|
+
self._heap.clear()
|
148
|
+
self._counter = 0
|
149
|
+
|
150
|
+
def get_at_index(self, index: int) -> Optional[Any]:
|
151
|
+
"""Get item at specific index (not recommended for priority queue)."""
|
152
|
+
if 0 <= index < len(self._heap):
|
153
|
+
priority, counter, key, value = self._heap[index]
|
154
|
+
return value
|
155
|
+
return None
|
156
|
+
|
157
|
+
def push_front(self, value: Any) -> None:
|
158
|
+
"""Push to front with high priority."""
|
159
|
+
key = f"item_{len(self._heap)}"
|
160
|
+
self.insert_with_priority(key, value, float('inf'))
|
161
|
+
|
162
|
+
def push_back(self, value: Any) -> None:
|
163
|
+
"""Push to back with low priority."""
|
164
|
+
key = f"item_{len(self._heap)}"
|
165
|
+
self.insert_with_priority(key, value, float('-inf'))
|
166
|
+
|
167
|
+
def __iter__(self) -> Iterator[Any]:
|
168
|
+
"""Iterate through items (order not guaranteed)."""
|
169
|
+
for priority, counter, key, value in self._heap:
|
170
|
+
yield value
|
171
|
+
|
172
|
+
def __repr__(self) -> str:
|
173
|
+
"""String representation of the priority queue."""
|
174
|
+
min_item = self.peek_min()
|
175
|
+
max_item = self.peek_max()
|
176
|
+
return f"PriorityQueueStrategy(size={len(self._heap)}, min={min_item[2] if min_item else None}, max={max_item[2] if max_item else None})"
|
177
|
+
|
178
|
+
# Required abstract methods from base classes
|
179
|
+
def pop_front(self) -> Any:
|
180
|
+
"""Remove element from front (same as extract_min for priority queue)."""
|
181
|
+
result = self.extract_min()
|
182
|
+
return result[1] if result else None
|
183
|
+
|
184
|
+
def pop_back(self) -> Any:
|
185
|
+
"""Remove element from back (same as extract_max for priority queue)."""
|
186
|
+
result = self.extract_max()
|
187
|
+
return result[1] if result else None
|
188
|
+
|
189
|
+
def set_at_index(self, index: int, value: Any) -> None:
|
190
|
+
"""Set element at index (not recommended for priority queue)."""
|
191
|
+
if 0 <= index < len(self._heap):
|
192
|
+
priority, counter, key, old_value = self._heap[index]
|
193
|
+
self._heap[index] = (priority, counter, key, value)
|
194
|
+
|
195
|
+
def as_linked_list(self):
|
196
|
+
"""Provide LinkedList behavioral view."""
|
197
|
+
return self
|
198
|
+
|
199
|
+
def as_stack(self):
|
200
|
+
"""Provide Stack behavioral view (not recommended)."""
|
201
|
+
raise NotImplementedError("PriorityQueue cannot behave as Stack")
|
202
|
+
|
203
|
+
def as_queue(self):
|
204
|
+
"""Provide Queue behavioral view (not recommended)."""
|
205
|
+
raise NotImplementedError("PriorityQueue cannot behave as Queue")
|
206
|
+
|
207
|
+
def as_deque(self):
|
208
|
+
"""Provide Deque behavioral view (not recommended)."""
|
209
|
+
raise NotImplementedError("PriorityQueue cannot behave as Deque")
|