2
2
partial ,
3
3
)
4
4
import itertools
5
- from numbers import (
6
- Integral ,
7
- )
8
5
from typing import (
9
6
Any ,
10
7
Callable ,
14
11
Tuple ,
15
12
Union ,
16
13
cast ,
14
+ overload ,
17
15
)
18
16
19
17
# `transform` comes from a non-public API which is considered stable, but future changes
40
38
from pyrsistent .typing import (
41
39
PMap ,
42
40
PVector ,
41
+ PVectorEvolver ,
43
42
)
44
43
45
44
from ssz .constants import (
@@ -163,7 +162,9 @@ def extend(self, value: Iterable[Hash32]) -> "HashTree":
163
162
def __add__ (self , other : Iterable [Hash32 ]) -> "HashTree" :
164
163
return self .extend (other )
165
164
166
- def __mul__ (self , times : int ) -> "HashTree" :
165
+ # we override __mul__ to allow for a more natural syntax
166
+ # when using the evolver
167
+ def __mul__ (self , times : int ) -> "HashTree" : # type: ignore[override]
167
168
if times <= 0 :
168
169
raise ValueError (f"Multiplier must be greater or equal to 1, got { times } " )
169
170
@@ -202,7 +203,7 @@ def remove(self, value: Hash32) -> "HashTree":
202
203
return self .__class__ .compute (chunks , self .chunk_count )
203
204
204
205
205
- class HashTreeEvolver :
206
+ class HashTreeEvolver ( PVectorEvolver [ Hash32 ]) :
206
207
def __init__ (self , hash_tree : "HashTree" ) -> None :
207
208
self .original_hash_tree = hash_tree
208
209
self .updated_chunks : PMap [int , Hash32 ] = pmap ()
@@ -211,7 +212,18 @@ def __init__(self, hash_tree: "HashTree") -> None:
211
212
#
212
213
# Getters
213
214
#
215
+ @overload
214
216
def __getitem__ (self , index : int ) -> Hash32 :
217
+ ...
218
+
219
+ @overload
220
+ def __getitem__ (self , index : slice ) -> "HashTreeEvolver" :
221
+ ...
222
+
223
+ def __getitem__ (self , index : Union [int , slice ]) -> Union [Hash32 , "HashTreeEvolver" ]:
224
+ if isinstance (index , slice ):
225
+ raise NotImplementedError ("Slicing not implemented." )
226
+
215
227
if index < 0 :
216
228
index += len (self )
217
229
@@ -235,33 +247,34 @@ def is_dirty(self) -> bool:
235
247
#
236
248
# Setters
237
249
#
238
- def set (self , index : Integral , value : Hash32 ) -> None :
250
+ def set (self , index : int , value : Hash32 ) -> "HashTreeEvolver" :
239
251
self [index ] = value
252
+ return self
240
253
241
- def __setitem__ (self , index : Integral , value : Hash32 ) -> None :
242
- idx = int (index )
243
-
244
- if idx < 0 :
245
- idx += len (self )
254
+ def __setitem__ (self , index : int , value : Hash32 ) -> None :
255
+ if index < 0 :
256
+ index += len (self )
246
257
247
- if 0 <= idx < len (self .original_hash_tree ):
248
- self .updated_chunks = self .updated_chunks .set (idx , value )
249
- elif idx < len (self ):
250
- index_in_appendix = idx - len (self .original_hash_tree )
258
+ if 0 <= index < len (self .original_hash_tree ):
259
+ self .updated_chunks = self .updated_chunks .set (index , value )
260
+ elif index < len (self ):
261
+ index_in_appendix = index - len (self .original_hash_tree )
251
262
self .appended_chunks = self .appended_chunks .set (index_in_appendix , value )
252
263
else :
253
- raise IndexError (f"Index out of bounds: { idx } " )
264
+ raise IndexError (f"Index out of bounds: { index } " )
254
265
255
266
#
256
267
# Length changing modifiers
257
268
#
258
- def append (self , value : Hash32 ) -> None :
269
+ def append (self , value : Hash32 ) -> "HashTreeEvolver" :
259
270
self .appended_chunks = self .appended_chunks .append (value )
260
271
self ._check_chunk_count ()
272
+ return self
261
273
262
- def extend (self , values : Iterable [Hash32 ]) -> None :
274
+ def extend (self , values : Iterable [Hash32 ]) -> "HashTreeEvolver" :
263
275
self .appended_chunks = self .appended_chunks .extend (values )
264
276
self ._check_chunk_count ()
277
+ return self
265
278
266
279
def _check_chunk_count (self ) -> None :
267
280
chunk_count = self .original_hash_tree .chunk_count
@@ -271,10 +284,10 @@ def _check_chunk_count(self) -> None:
271
284
#
272
285
# Not implemented
273
286
#
274
- def delete (self , index : int , stop : Optional [int ] = None ) -> None :
287
+ def delete (self , index : int , stop : Optional [int ] = None ) -> None : # type: ignore[override] # noqa: E501
275
288
raise NotImplementedError ()
276
289
277
- def __delitem__ (self , index : int ) -> None :
290
+ def __delitem__ (self , index : Union [ int , slice ] ) -> None :
278
291
raise NotImplementedError ()
279
292
280
293
def remove (self , value : Hash32 ) -> None :
@@ -432,7 +445,7 @@ def set_chunk_in_tree(hash_tree: RawHashTree, index: int, chunk: Hash32) -> RawH
432
445
for layer_index , hash_index in zip (parent_layer_indices , parent_hash_indices )
433
446
)
434
447
435
- hash_tree_with_updated_branch = pipe (
448
+ hash_tree_with_updated_branch : PVector [ PVector [ Any ]] = pipe (
436
449
hash_tree_with_updated_chunk , * update_functions
437
450
)
438
451
0 commit comments