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.
Files changed (132) hide show
  1. exonware/__init__.py +14 -0
  2. exonware/xwnode/__init__.py +127 -0
  3. exonware/xwnode/base.py +676 -0
  4. exonware/xwnode/config.py +178 -0
  5. exonware/xwnode/contracts.py +730 -0
  6. exonware/xwnode/errors.py +503 -0
  7. exonware/xwnode/facade.py +460 -0
  8. exonware/xwnode/strategies/__init__.py +158 -0
  9. exonware/xwnode/strategies/advisor.py +463 -0
  10. exonware/xwnode/strategies/edges/__init__.py +32 -0
  11. exonware/xwnode/strategies/edges/adj_list.py +227 -0
  12. exonware/xwnode/strategies/edges/adj_matrix.py +391 -0
  13. exonware/xwnode/strategies/edges/base.py +169 -0
  14. exonware/xwnode/strategies/flyweight.py +328 -0
  15. exonware/xwnode/strategies/impls/__init__.py +13 -0
  16. exonware/xwnode/strategies/impls/_base_edge.py +403 -0
  17. exonware/xwnode/strategies/impls/_base_node.py +307 -0
  18. exonware/xwnode/strategies/impls/edge_adj_list.py +353 -0
  19. exonware/xwnode/strategies/impls/edge_adj_matrix.py +445 -0
  20. exonware/xwnode/strategies/impls/edge_bidir_wrapper.py +455 -0
  21. exonware/xwnode/strategies/impls/edge_block_adj_matrix.py +539 -0
  22. exonware/xwnode/strategies/impls/edge_coo.py +533 -0
  23. exonware/xwnode/strategies/impls/edge_csc.py +447 -0
  24. exonware/xwnode/strategies/impls/edge_csr.py +492 -0
  25. exonware/xwnode/strategies/impls/edge_dynamic_adj_list.py +503 -0
  26. exonware/xwnode/strategies/impls/edge_flow_network.py +555 -0
  27. exonware/xwnode/strategies/impls/edge_hyperedge_set.py +516 -0
  28. exonware/xwnode/strategies/impls/edge_neural_graph.py +650 -0
  29. exonware/xwnode/strategies/impls/edge_octree.py +574 -0
  30. exonware/xwnode/strategies/impls/edge_property_store.py +655 -0
  31. exonware/xwnode/strategies/impls/edge_quadtree.py +519 -0
  32. exonware/xwnode/strategies/impls/edge_rtree.py +820 -0
  33. exonware/xwnode/strategies/impls/edge_temporal_edgeset.py +558 -0
  34. exonware/xwnode/strategies/impls/edge_tree_graph_basic.py +271 -0
  35. exonware/xwnode/strategies/impls/edge_weighted_graph.py +411 -0
  36. exonware/xwnode/strategies/manager.py +775 -0
  37. exonware/xwnode/strategies/metrics.py +538 -0
  38. exonware/xwnode/strategies/migration.py +432 -0
  39. exonware/xwnode/strategies/nodes/__init__.py +50 -0
  40. exonware/xwnode/strategies/nodes/_base_node.py +307 -0
  41. exonware/xwnode/strategies/nodes/adjacency_list.py +267 -0
  42. exonware/xwnode/strategies/nodes/aho_corasick.py +345 -0
  43. exonware/xwnode/strategies/nodes/array_list.py +209 -0
  44. exonware/xwnode/strategies/nodes/base.py +247 -0
  45. exonware/xwnode/strategies/nodes/deque.py +200 -0
  46. exonware/xwnode/strategies/nodes/hash_map.py +135 -0
  47. exonware/xwnode/strategies/nodes/heap.py +307 -0
  48. exonware/xwnode/strategies/nodes/linked_list.py +232 -0
  49. exonware/xwnode/strategies/nodes/node_aho_corasick.py +520 -0
  50. exonware/xwnode/strategies/nodes/node_array_list.py +175 -0
  51. exonware/xwnode/strategies/nodes/node_avl_tree.py +371 -0
  52. exonware/xwnode/strategies/nodes/node_b_plus_tree.py +542 -0
  53. exonware/xwnode/strategies/nodes/node_bitmap.py +420 -0
  54. exonware/xwnode/strategies/nodes/node_bitset_dynamic.py +513 -0
  55. exonware/xwnode/strategies/nodes/node_bloom_filter.py +347 -0
  56. exonware/xwnode/strategies/nodes/node_btree.py +357 -0
  57. exonware/xwnode/strategies/nodes/node_count_min_sketch.py +470 -0
  58. exonware/xwnode/strategies/nodes/node_cow_tree.py +473 -0
  59. exonware/xwnode/strategies/nodes/node_cuckoo_hash.py +392 -0
  60. exonware/xwnode/strategies/nodes/node_fenwick_tree.py +301 -0
  61. exonware/xwnode/strategies/nodes/node_hash_map.py +269 -0
  62. exonware/xwnode/strategies/nodes/node_heap.py +191 -0
  63. exonware/xwnode/strategies/nodes/node_hyperloglog.py +407 -0
  64. exonware/xwnode/strategies/nodes/node_linked_list.py +409 -0
  65. exonware/xwnode/strategies/nodes/node_lsm_tree.py +400 -0
  66. exonware/xwnode/strategies/nodes/node_ordered_map.py +390 -0
  67. exonware/xwnode/strategies/nodes/node_ordered_map_balanced.py +565 -0
  68. exonware/xwnode/strategies/nodes/node_patricia.py +512 -0
  69. exonware/xwnode/strategies/nodes/node_persistent_tree.py +378 -0
  70. exonware/xwnode/strategies/nodes/node_radix_trie.py +452 -0
  71. exonware/xwnode/strategies/nodes/node_red_black_tree.py +497 -0
  72. exonware/xwnode/strategies/nodes/node_roaring_bitmap.py +570 -0
  73. exonware/xwnode/strategies/nodes/node_segment_tree.py +289 -0
  74. exonware/xwnode/strategies/nodes/node_set_hash.py +354 -0
  75. exonware/xwnode/strategies/nodes/node_set_tree.py +480 -0
  76. exonware/xwnode/strategies/nodes/node_skip_list.py +316 -0
  77. exonware/xwnode/strategies/nodes/node_splay_tree.py +393 -0
  78. exonware/xwnode/strategies/nodes/node_suffix_array.py +487 -0
  79. exonware/xwnode/strategies/nodes/node_treap.py +387 -0
  80. exonware/xwnode/strategies/nodes/node_tree_graph_hybrid.py +1434 -0
  81. exonware/xwnode/strategies/nodes/node_trie.py +252 -0
  82. exonware/xwnode/strategies/nodes/node_union_find.py +187 -0
  83. exonware/xwnode/strategies/nodes/node_xdata_optimized.py +369 -0
  84. exonware/xwnode/strategies/nodes/priority_queue.py +209 -0
  85. exonware/xwnode/strategies/nodes/queue.py +161 -0
  86. exonware/xwnode/strategies/nodes/sparse_matrix.py +206 -0
  87. exonware/xwnode/strategies/nodes/stack.py +152 -0
  88. exonware/xwnode/strategies/nodes/trie.py +274 -0
  89. exonware/xwnode/strategies/nodes/union_find.py +283 -0
  90. exonware/xwnode/strategies/pattern_detector.py +603 -0
  91. exonware/xwnode/strategies/performance_monitor.py +487 -0
  92. exonware/xwnode/strategies/queries/__init__.py +24 -0
  93. exonware/xwnode/strategies/queries/base.py +236 -0
  94. exonware/xwnode/strategies/queries/cql.py +201 -0
  95. exonware/xwnode/strategies/queries/cypher.py +181 -0
  96. exonware/xwnode/strategies/queries/datalog.py +70 -0
  97. exonware/xwnode/strategies/queries/elastic_dsl.py +70 -0
  98. exonware/xwnode/strategies/queries/eql.py +70 -0
  99. exonware/xwnode/strategies/queries/flux.py +70 -0
  100. exonware/xwnode/strategies/queries/gql.py +70 -0
  101. exonware/xwnode/strategies/queries/graphql.py +240 -0
  102. exonware/xwnode/strategies/queries/gremlin.py +181 -0
  103. exonware/xwnode/strategies/queries/hiveql.py +214 -0
  104. exonware/xwnode/strategies/queries/hql.py +70 -0
  105. exonware/xwnode/strategies/queries/jmespath.py +219 -0
  106. exonware/xwnode/strategies/queries/jq.py +66 -0
  107. exonware/xwnode/strategies/queries/json_query.py +66 -0
  108. exonware/xwnode/strategies/queries/jsoniq.py +248 -0
  109. exonware/xwnode/strategies/queries/kql.py +70 -0
  110. exonware/xwnode/strategies/queries/linq.py +238 -0
  111. exonware/xwnode/strategies/queries/logql.py +70 -0
  112. exonware/xwnode/strategies/queries/mql.py +68 -0
  113. exonware/xwnode/strategies/queries/n1ql.py +210 -0
  114. exonware/xwnode/strategies/queries/partiql.py +70 -0
  115. exonware/xwnode/strategies/queries/pig.py +215 -0
  116. exonware/xwnode/strategies/queries/promql.py +70 -0
  117. exonware/xwnode/strategies/queries/sparql.py +220 -0
  118. exonware/xwnode/strategies/queries/sql.py +275 -0
  119. exonware/xwnode/strategies/queries/xml_query.py +66 -0
  120. exonware/xwnode/strategies/queries/xpath.py +223 -0
  121. exonware/xwnode/strategies/queries/xquery.py +258 -0
  122. exonware/xwnode/strategies/queries/xwnode_executor.py +332 -0
  123. exonware/xwnode/strategies/queries/xwquery_strategy.py +424 -0
  124. exonware/xwnode/strategies/registry.py +604 -0
  125. exonware/xwnode/strategies/simple.py +273 -0
  126. exonware/xwnode/strategies/utils.py +532 -0
  127. exonware/xwnode/types.py +912 -0
  128. exonware/xwnode/version.py +78 -0
  129. exonware_xwnode-0.0.1.12.dist-info/METADATA +169 -0
  130. exonware_xwnode-0.0.1.12.dist-info/RECORD +132 -0
  131. exonware_xwnode-0.0.1.12.dist-info/WHEEL +4 -0
  132. exonware_xwnode-0.0.1.12.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,289 @@
1
+ """
2
+ Segment Tree Node Strategy Implementation
3
+
4
+ This module implements the SEGMENT_TREE strategy for range queries
5
+ and updates with O(log n) complexity.
6
+ """
7
+
8
+ from typing import Any, Iterator, List, Optional, Callable, Dict, Union
9
+ from .base import ANodeTreeStrategy
10
+ from ...types import NodeMode, NodeTrait
11
+
12
+
13
+ class SegmentTreeStrategy(ANodeTreeStrategy):
14
+ """
15
+ Segment Tree node strategy for efficient range queries and updates.
16
+
17
+ Provides O(log n) range queries and updates for associative operations
18
+ like sum, min, max, etc.
19
+ """
20
+
21
+ def __init__(self, traits: NodeTrait = NodeTrait.NONE, **options):
22
+ """Initialize the Segment Tree strategy."""
23
+ super().__init__(NodeMode.SEGMENT_TREE, traits, **options)
24
+
25
+ self._size = options.get('initial_size', 0)
26
+ self._operation = options.get('operation', 'sum') # sum, min, max, etc.
27
+ self._identity = self._get_identity(self._operation)
28
+ self._combiner = self._get_combiner(self._operation)
29
+
30
+ # Internal tree representation (0-indexed, 1-based tree)
31
+ self._tree: List[Any] = [self._identity] * (4 * max(1, self._size))
32
+ self._values: Dict[str, Any] = {} # Key-value storage for compatibility
33
+ self._indices: Dict[str, int] = {} # Map keys to tree indices
34
+ self._reverse_indices: Dict[int, str] = {} # Map indices to keys
35
+ self._next_index = 0
36
+
37
+ def get_supported_traits(self) -> NodeTrait:
38
+ """Get the traits supported by the segment tree strategy."""
39
+ return (NodeTrait.INDEXED | NodeTrait.HIERARCHICAL | NodeTrait.STREAMING)
40
+
41
+ def _get_identity(self, operation: str) -> Any:
42
+ """Get identity element for the operation."""
43
+ identities = {
44
+ 'sum': 0,
45
+ 'min': float('inf'),
46
+ 'max': float('-inf'),
47
+ 'product': 1,
48
+ 'gcd': 0,
49
+ 'lcm': 1,
50
+ 'xor': 0,
51
+ 'and': True,
52
+ 'or': False
53
+ }
54
+ return identities.get(operation, 0)
55
+
56
+ def _get_combiner(self, operation: str) -> Callable[[Any, Any], Any]:
57
+ """Get combiner function for the operation."""
58
+ import math
59
+
60
+ combiners = {
61
+ 'sum': lambda a, b: a + b,
62
+ 'min': lambda a, b: min(a, b),
63
+ 'max': lambda a, b: max(a, b),
64
+ 'product': lambda a, b: a * b,
65
+ 'gcd': lambda a, b: math.gcd(int(a), int(b)),
66
+ 'lcm': lambda a, b: abs(int(a) * int(b)) // math.gcd(int(a), int(b)),
67
+ 'xor': lambda a, b: a ^ b,
68
+ 'and': lambda a, b: a and b,
69
+ 'or': lambda a, b: a or b
70
+ }
71
+ return combiners.get(operation, lambda a, b: a + b)
72
+
73
+ # ============================================================================
74
+ # CORE OPERATIONS (Key-based interface for compatibility)
75
+ # ============================================================================
76
+
77
+ def put(self, key: Any, value: Any = None) -> None:
78
+ """Store a value at the given key."""
79
+ key_str = str(key)
80
+
81
+ # Convert value to numeric if possible
82
+ try:
83
+ numeric_value = float(value) if value is not None else 0.0
84
+ except (ValueError, TypeError):
85
+ numeric_value = 0.0
86
+
87
+ if key_str in self._indices:
88
+ # Update existing
89
+ idx = self._indices[key_str]
90
+ self._update_point(idx, numeric_value)
91
+ else:
92
+ # Add new
93
+ if self._next_index >= len(self._tree) // 4:
94
+ self._resize_tree()
95
+
96
+ idx = self._next_index
97
+ self._indices[key_str] = idx
98
+ self._reverse_indices[idx] = key_str
99
+ self._next_index += 1
100
+ self._update_point(idx, numeric_value)
101
+
102
+ self._values[key_str] = value
103
+
104
+ def get(self, key: Any, default: Any = None) -> Any:
105
+ """Retrieve a value by key."""
106
+ key_str = str(key)
107
+ return self._values.get(key_str, default)
108
+
109
+ def has(self, key: Any) -> bool:
110
+ """Check if key exists."""
111
+ return str(key) in self._values
112
+
113
+ def remove(self, key: Any) -> bool:
114
+ """Remove value by key."""
115
+ key_str = str(key)
116
+ if key_str not in self._indices:
117
+ return False
118
+
119
+ idx = self._indices[key_str]
120
+ self._update_point(idx, self._identity)
121
+
122
+ del self._indices[key_str]
123
+ del self._reverse_indices[idx]
124
+ del self._values[key_str]
125
+
126
+ return True
127
+
128
+ def delete(self, key: Any) -> bool:
129
+ """Remove value by key (alias for remove)."""
130
+ return self.remove(key)
131
+
132
+ def clear(self) -> None:
133
+ """Clear all data."""
134
+ self._tree = [self._identity] * (4 * max(1, self._size))
135
+ self._values.clear()
136
+ self._indices.clear()
137
+ self._reverse_indices.clear()
138
+ self._next_index = 0
139
+
140
+ def keys(self) -> Iterator[str]:
141
+ """Get all keys."""
142
+ return iter(self._values.keys())
143
+
144
+ def values(self) -> Iterator[Any]:
145
+ """Get all values."""
146
+ return iter(self._values.values())
147
+
148
+ def items(self) -> Iterator[tuple[str, Any]]:
149
+ """Get all key-value pairs."""
150
+ return iter(self._values.items())
151
+
152
+ def __len__(self) -> int:
153
+ """Get the number of items."""
154
+ return len(self._values)
155
+
156
+ def to_native(self) -> Dict[str, Any]:
157
+ """Convert to native Python dict."""
158
+ return dict(self._values)
159
+
160
+ @property
161
+ def is_list(self) -> bool:
162
+ """This can behave like a list."""
163
+ return True
164
+
165
+ @property
166
+ def is_dict(self) -> bool:
167
+ """This can behave like a dict."""
168
+ return True
169
+
170
+ # ============================================================================
171
+ # SEGMENT TREE SPECIFIC OPERATIONS
172
+ # ============================================================================
173
+
174
+ def _resize_tree(self) -> None:
175
+ """Resize the internal tree when needed."""
176
+ old_size = len(self._tree)
177
+ new_size = old_size * 2
178
+ self._tree.extend([self._identity] * (new_size - old_size))
179
+
180
+ def _update_point(self, idx: int, value: Any) -> None:
181
+ """Update a single point in the segment tree."""
182
+ # Convert to 1-based indexing for tree
183
+ tree_idx = idx + len(self._tree) // 4
184
+
185
+ # Ensure tree is large enough
186
+ while tree_idx >= len(self._tree):
187
+ self._resize_tree()
188
+ tree_idx = idx + len(self._tree) // 4
189
+
190
+ # Update leaf
191
+ self._tree[tree_idx] = value
192
+
193
+ # Update ancestors
194
+ while tree_idx > 1:
195
+ tree_idx //= 2
196
+ left_child = self._tree[tree_idx * 2] if tree_idx * 2 < len(self._tree) else self._identity
197
+ right_child = self._tree[tree_idx * 2 + 1] if tree_idx * 2 + 1 < len(self._tree) else self._identity
198
+ self._tree[tree_idx] = self._combiner(left_child, right_child)
199
+
200
+ def range_query(self, left: int, right: int) -> Any:
201
+ """Query range [left, right] inclusive."""
202
+ return self._range_query_recursive(1, 0, len(self._tree) // 4 - 1, left, right)
203
+
204
+ def _range_query_recursive(self, node: int, start: int, end: int,
205
+ query_left: int, query_right: int) -> Any:
206
+ """Recursive range query implementation."""
207
+ if query_right < start or query_left > end:
208
+ return self._identity
209
+
210
+ if query_left <= start and end <= query_right:
211
+ return self._tree[node] if node < len(self._tree) else self._identity
212
+
213
+ mid = (start + end) // 2
214
+ left_result = self._range_query_recursive(2 * node, start, mid, query_left, query_right)
215
+ right_result = self._range_query_recursive(2 * node + 1, mid + 1, end, query_left, query_right)
216
+
217
+ return self._combiner(left_result, right_result)
218
+
219
+ def range_update(self, left: int, right: int, value: Any) -> None:
220
+ """Update range [left, right] with value (point updates)."""
221
+ for i in range(left, right + 1):
222
+ if i in self._reverse_indices:
223
+ key = self._reverse_indices[i]
224
+ self.put(key, value)
225
+
226
+ def prefix_query(self, index: int) -> Any:
227
+ """Query prefix [0, index]."""
228
+ return self.range_query(0, index)
229
+
230
+ def suffix_query(self, index: int) -> Any:
231
+ """Query suffix [index, size-1]."""
232
+ return self.range_query(index, len(self._values) - 1)
233
+
234
+ def find_first_greater(self, value: Any) -> Optional[int]:
235
+ """Find first index where tree value > given value."""
236
+ for i in range(len(self._values)):
237
+ if i in self._reverse_indices:
238
+ key = self._reverse_indices[i]
239
+ if key in self._values:
240
+ try:
241
+ if float(self._values[key]) > float(value):
242
+ return i
243
+ except (ValueError, TypeError):
244
+ continue
245
+ return None
246
+
247
+ def get_operation_info(self) -> Dict[str, Any]:
248
+ """Get information about the current operation."""
249
+ return {
250
+ 'operation': self._operation,
251
+ 'identity': self._identity,
252
+ 'total_result': self.range_query(0, max(0, len(self._values) - 1))
253
+ }
254
+
255
+ # ============================================================================
256
+ # PERFORMANCE CHARACTERISTICS
257
+ # ============================================================================
258
+
259
+ @property
260
+ def backend_info(self) -> Dict[str, Any]:
261
+ """Get backend implementation info."""
262
+ return {
263
+ 'strategy': 'SEGMENT_TREE',
264
+ 'backend': 'Array-based segment tree',
265
+ 'operation': self._operation,
266
+ 'complexity': {
267
+ 'point_update': 'O(log n)',
268
+ 'range_query': 'O(log n)',
269
+ 'range_update': 'O(n log n)',
270
+ 'build': 'O(n)'
271
+ }
272
+ }
273
+
274
+ @property
275
+ def metrics(self) -> Dict[str, Any]:
276
+ """Get performance metrics."""
277
+ tree_height = 0
278
+ if len(self._values) > 0:
279
+ import math
280
+ tree_height = math.ceil(math.log2(len(self._values)))
281
+
282
+ return {
283
+ 'size': len(self._values),
284
+ 'tree_size': len(self._tree),
285
+ 'tree_height': tree_height,
286
+ 'operation': self._operation,
287
+ 'memory_usage': f"{len(self._tree) * 8 + len(self._values) * 24} bytes (estimated)",
288
+ 'utilization': f"{len(self._values) / max(1, len(self._tree) // 4) * 100:.1f}%"
289
+ }
@@ -0,0 +1,354 @@
1
+ """
2
+ Hash Set Node Strategy Implementation
3
+
4
+ This module implements the SET_HASH strategy for efficient set operations
5
+ with O(1) average-case membership testing and insertion.
6
+ """
7
+
8
+ from typing import Any, Iterator, Set, Dict, Union, List
9
+ import hashlib
10
+ from ._base_node import aNodeStrategy
11
+ from ...types import NodeMode, NodeTrait
12
+
13
+
14
+ class xSetHashStrategy(aNodeStrategy):
15
+ """
16
+ Hash Set node strategy for efficient set operations.
17
+
18
+ Provides O(1) average-case membership testing, insertion, and deletion
19
+ with automatic handling of duplicates and fast set operations.
20
+ """
21
+
22
+ def __init__(self, traits: NodeTrait = NodeTrait.NONE, **options):
23
+ """Initialize the Hash Set strategy."""
24
+ super().__init__(NodeMode.SET_HASH, traits, **options)
25
+
26
+ self.load_factor = options.get('load_factor', 0.75)
27
+ self.initial_capacity = options.get('initial_capacity', 16)
28
+
29
+ # Core storage: hash set for uniqueness
30
+ self._set: Set[str] = set()
31
+ self._values: Dict[str, Any] = {} # Value storage for compatibility
32
+ self._size = 0
33
+
34
+ # Set-specific options
35
+ self.case_sensitive = options.get('case_sensitive', True)
36
+ self.allow_none = options.get('allow_none', True)
37
+
38
+ def get_supported_traits(self) -> NodeTrait:
39
+ """Get the traits supported by the hash set strategy."""
40
+ return (NodeTrait.INDEXED | NodeTrait.STREAMING)
41
+
42
+ # ============================================================================
43
+ # CORE OPERATIONS (Key-based interface for compatibility)
44
+ # ============================================================================
45
+
46
+ def put(self, key: Any, value: Any = None) -> None:
47
+ """Add a value to the set (key becomes the set element)."""
48
+ if value is None and not self.allow_none:
49
+ return
50
+
51
+ # Use key as the set element
52
+ element = str(key) if not self.case_sensitive else str(key)
53
+ if not self.case_sensitive:
54
+ element = element.lower()
55
+
56
+ # Add to set (automatic deduplication)
57
+ was_new = element not in self._set
58
+ self._set.add(element)
59
+ self._values[element] = value if value is not None else key
60
+
61
+ if was_new:
62
+ self._size += 1
63
+
64
+ # Keep size in sync
65
+ self._size = len(self._set)
66
+
67
+ def get(self, key: Any, default: Any = None) -> Any:
68
+ """Retrieve a value by key (check if element exists in set)."""
69
+ element = str(key) if not self.case_sensitive else str(key)
70
+ if not self.case_sensitive:
71
+ element = element.lower()
72
+
73
+ return self._values.get(element, default)
74
+
75
+ def has(self, key: Any) -> bool:
76
+ """Check if key exists in set (O(1) membership test)."""
77
+ element = str(key) if not self.case_sensitive else str(key)
78
+ if not self.case_sensitive:
79
+ element = element.lower()
80
+
81
+ return element in self._set
82
+
83
+ def remove(self, key: Any) -> bool:
84
+ """Remove element from set."""
85
+ element = str(key) if not self.case_sensitive else str(key)
86
+ if not self.case_sensitive:
87
+ element = element.lower()
88
+
89
+ if element in self._set:
90
+ self._set.remove(element)
91
+ if element in self._values:
92
+ del self._values[element]
93
+ self._size -= 1
94
+ return True
95
+ return False
96
+
97
+ def delete(self, key: Any) -> bool:
98
+ """Remove element from set (alias for remove)."""
99
+ return self.remove(key)
100
+
101
+ def clear(self) -> None:
102
+ """Clear all elements from the set."""
103
+ self._set.clear()
104
+ self._values.clear()
105
+ self._size = 0
106
+
107
+ def keys(self) -> Iterator[str]:
108
+ """Get all elements in the set."""
109
+ return iter(self._set)
110
+
111
+ def values(self) -> Iterator[Any]:
112
+ """Get all values (for compatibility)."""
113
+ return iter(self._values.values())
114
+
115
+ def items(self) -> Iterator[tuple[str, Any]]:
116
+ """Get all element-value pairs."""
117
+ return iter(self._values.items())
118
+
119
+ def __len__(self) -> int:
120
+ """Get the number of elements in the set."""
121
+ return self._size
122
+
123
+ def to_native(self) -> Set[Any]:
124
+ """Convert to native Python set."""
125
+ return set(self._set)
126
+
127
+ @property
128
+ def is_list(self) -> bool:
129
+ """This is not a list strategy."""
130
+ return False
131
+
132
+ @property
133
+ def is_dict(self) -> bool:
134
+ """This behaves like a dict but represents a set."""
135
+ return True
136
+
137
+ # ============================================================================
138
+ # SET-SPECIFIC OPERATIONS
139
+ # ============================================================================
140
+
141
+ def add(self, element: Any) -> bool:
142
+ """Add an element to the set. Returns True if element was new."""
143
+ element_str = str(element) if not self.case_sensitive else str(element)
144
+ if not self.case_sensitive:
145
+ element_str = element_str.lower()
146
+
147
+ was_new = element_str not in self._set
148
+ self._set.add(element_str)
149
+ self._values[element_str] = element
150
+
151
+ if was_new:
152
+ self._size += 1
153
+
154
+ return was_new
155
+
156
+ def discard(self, element: Any) -> None:
157
+ """Remove element if present (no error if not found)."""
158
+ self.remove(element)
159
+
160
+ def pop(self) -> Any:
161
+ """Remove and return an arbitrary element."""
162
+ if not self._set:
163
+ raise KeyError("pop from empty set")
164
+
165
+ element = self._set.pop()
166
+ value = self._values.pop(element, element)
167
+ self._size -= 1
168
+ return value
169
+
170
+ def union(self, other: Union['xSetHashStrategy', Set, List]) -> 'xSetHashStrategy':
171
+ """Return union of this set with another."""
172
+ result = xSetHashStrategy(
173
+ traits=self._traits,
174
+ case_sensitive=self.case_sensitive,
175
+ allow_none=self.allow_none
176
+ )
177
+
178
+ # Add all elements from this set
179
+ for element in self._set:
180
+ result.add(self._values[element])
181
+
182
+ # Add elements from other
183
+ if isinstance(other, xSetHashStrategy):
184
+ for element in other._set:
185
+ result.add(other._values[element])
186
+ elif isinstance(other, (set, list)):
187
+ for element in other:
188
+ result.add(element)
189
+
190
+ return result
191
+
192
+ def intersection(self, other: Union['xSetHashStrategy', Set, List]) -> 'xSetHashStrategy':
193
+ """Return intersection of this set with another."""
194
+ result = xSetHashStrategy(
195
+ traits=self._traits,
196
+ case_sensitive=self.case_sensitive,
197
+ allow_none=self.allow_none
198
+ )
199
+
200
+ if isinstance(other, xSetHashStrategy):
201
+ common = self._set.intersection(other._set)
202
+ for element in common:
203
+ result.add(self._values[element])
204
+ elif isinstance(other, (set, list)):
205
+ other_set = {str(x).lower() if not self.case_sensitive else str(x) for x in other}
206
+ common = self._set.intersection(other_set)
207
+ for element in common:
208
+ result.add(self._values[element])
209
+
210
+ return result
211
+
212
+ def difference(self, other: Union['xSetHashStrategy', Set, List]) -> 'xSetHashStrategy':
213
+ """Return difference of this set with another."""
214
+ result = xSetHashStrategy(
215
+ traits=self._traits,
216
+ case_sensitive=self.case_sensitive,
217
+ allow_none=self.allow_none
218
+ )
219
+
220
+ if isinstance(other, xSetHashStrategy):
221
+ diff = self._set.difference(other._set)
222
+ elif isinstance(other, (set, list)):
223
+ other_set = {str(x).lower() if not self.case_sensitive else str(x) for x in other}
224
+ diff = self._set.difference(other_set)
225
+ else:
226
+ diff = self._set.copy()
227
+
228
+ for element in diff:
229
+ result.add(self._values[element])
230
+
231
+ return result
232
+
233
+ def symmetric_difference(self, other: Union['xSetHashStrategy', Set, List]) -> 'xSetHashStrategy':
234
+ """Return symmetric difference of this set with another."""
235
+ result = xSetHashStrategy(
236
+ traits=self._traits,
237
+ case_sensitive=self.case_sensitive,
238
+ allow_none=self.allow_none
239
+ )
240
+
241
+ if isinstance(other, xSetHashStrategy):
242
+ sym_diff = self._set.symmetric_difference(other._set)
243
+ for element in sym_diff:
244
+ if element in self._values:
245
+ result.add(self._values[element])
246
+ elif element in other._values:
247
+ result.add(other._values[element])
248
+ elif isinstance(other, (set, list)):
249
+ other_set = {str(x).lower() if not self.case_sensitive else str(x) for x in other}
250
+ sym_diff = self._set.symmetric_difference(other_set)
251
+ for element in sym_diff:
252
+ if element in self._values:
253
+ result.add(self._values[element])
254
+ else:
255
+ # Find original element in other
256
+ for orig in other:
257
+ if (str(orig).lower() if not self.case_sensitive else str(orig)) == element:
258
+ result.add(orig)
259
+ break
260
+
261
+ return result
262
+
263
+ def is_subset(self, other: Union['xSetHashStrategy', Set, List]) -> bool:
264
+ """Check if this set is a subset of another."""
265
+ if isinstance(other, xSetHashStrategy):
266
+ return self._set.issubset(other._set)
267
+ elif isinstance(other, (set, list)):
268
+ other_set = {str(x).lower() if not self.case_sensitive else str(x) for x in other}
269
+ return self._set.issubset(other_set)
270
+ return False
271
+
272
+ def is_superset(self, other: Union['xSetHashStrategy', Set, List]) -> bool:
273
+ """Check if this set is a superset of another."""
274
+ if isinstance(other, xSetHashStrategy):
275
+ return self._set.issuperset(other._set)
276
+ elif isinstance(other, (set, list)):
277
+ other_set = {str(x).lower() if not self.case_sensitive else str(x) for x in other}
278
+ return self._set.issuperset(other_set)
279
+ return False
280
+
281
+ def is_disjoint(self, other: Union['xSetHashStrategy', Set, List]) -> bool:
282
+ """Check if this set has no elements in common with another."""
283
+ if isinstance(other, xSetHashStrategy):
284
+ return self._set.isdisjoint(other._set)
285
+ elif isinstance(other, (set, list)):
286
+ other_set = {str(x).lower() if not self.case_sensitive else str(x) for x in other}
287
+ return self._set.isdisjoint(other_set)
288
+ return True
289
+
290
+ def copy(self) -> 'xSetHashStrategy':
291
+ """Create a shallow copy of the set."""
292
+ result = xSetHashStrategy(
293
+ traits=self._traits,
294
+ case_sensitive=self.case_sensitive,
295
+ allow_none=self.allow_none
296
+ )
297
+
298
+ for element in self._set:
299
+ result.add(self._values[element])
300
+
301
+ return result
302
+
303
+ def update(self, *others) -> None:
304
+ """Update the set with elements from other iterables."""
305
+ for other in others:
306
+ if isinstance(other, xSetHashStrategy):
307
+ for element in other._set:
308
+ self.add(other._values[element])
309
+ elif isinstance(other, (set, list, tuple)):
310
+ for element in other:
311
+ self.add(element)
312
+
313
+ def get_hash(self) -> str:
314
+ """Get a hash representation of the set."""
315
+ # Sort elements for consistent hashing
316
+ sorted_elements = sorted(self._set)
317
+ content = ''.join(sorted_elements)
318
+ return hashlib.md5(content.encode()).hexdigest()
319
+
320
+ # ============================================================================
321
+ # PERFORMANCE CHARACTERISTICS
322
+ # ============================================================================
323
+
324
+ @property
325
+ def backend_info(self) -> Dict[str, Any]:
326
+ """Get backend implementation info."""
327
+ return {
328
+ 'strategy': 'SET_HASH',
329
+ 'backend': 'Python set + dict',
330
+ 'case_sensitive': self.case_sensitive,
331
+ 'allow_none': self.allow_none,
332
+ 'complexity': {
333
+ 'add': 'O(1) average',
334
+ 'remove': 'O(1) average',
335
+ 'contains': 'O(1) average',
336
+ 'union': 'O(n + m)',
337
+ 'intersection': 'O(min(n, m))',
338
+ 'space': 'O(n)'
339
+ }
340
+ }
341
+
342
+ @property
343
+ def metrics(self) -> Dict[str, Any]:
344
+ """Get performance metrics."""
345
+ collision_estimate = max(0, len(self._values) - len(self._set))
346
+
347
+ return {
348
+ 'size': self._size,
349
+ 'unique_elements': len(self._set),
350
+ 'collisions_estimate': collision_estimate,
351
+ 'load_factor': self.load_factor,
352
+ 'memory_usage': f"{self._size * 32} bytes (estimated)",
353
+ 'hash': self.get_hash()[:8] + "..."
354
+ }