@@ -137,8 +137,10 @@ def __init__(self, key: InstanceKey, value: Value,
137
137
self .value = value # type: Value
138
138
"""Value of the receiver."""
139
139
140
- """" Mapping from key tuple to children """
141
- self ._childmap = None # type: dict
140
+ """Mapping from key tuple to children"""
141
+ self ._childmap = {} # type: dict
142
+ """Remember at which index we want to start parsing the childs"""
143
+ self ._parse_next = 0 # type: int
142
144
143
145
@property
144
146
def name (self ) -> InstanceName :
@@ -183,12 +185,19 @@ def __getitem__(self, key: InstanceKey) -> "InstanceNode":
183
185
"""
184
186
if isinstance (self .value , ArrayValue ) and isinstance (key , tuple ):
185
187
return self ._mapentry (key )
188
+ if isinstance (self .value , ArrayValue ) and isinstance (key , dict ):
189
+ return self ._mapentry (self ._map2tuple (key ))
186
190
if isinstance (self .value , ObjectValue ):
187
191
return self ._member (key )
188
192
if isinstance (self .value , ArrayValue ):
189
193
return self ._entry (key )
190
194
raise InstanceValueError (self .json_pointer (), "scalar instance" )
191
195
196
+ def __contains__ (self , key : InstanceKey ) -> bool :
197
+ """Checks if key does exist
198
+ """
199
+ return self .get (key ) is not None
200
+
192
201
def __iter__ (self ):
193
202
"""Return receiver's iterator.
194
203
@@ -210,6 +219,14 @@ def ita():
210
219
return iter (self ._member_names ())
211
220
raise InstanceValueError (self .json_pointer (), "scalar instance" )
212
221
222
+ def get (self , key : InstanceKey , d = None ):
223
+ """Return member or entry with given key, returns default if it does not exist
224
+ """
225
+ try :
226
+ return self [key ]
227
+ except (InstanceValueError , NonexistentInstance ):
228
+ return d
229
+
213
230
def is_internal (self ) -> bool :
214
231
"""Return ``True`` if the receiver is an instance of an internal node.
215
232
"""
@@ -402,27 +419,42 @@ def _entry(self, index: int) -> "ArrayEntry":
402
419
except (IndexError , TypeError ):
403
420
raise NonexistentInstance (self .json_pointer (), "entry " + str (index )) from None
404
421
422
+ def _map2tuple (self , key : dict ) -> tuple :
423
+ """generate tuple for key"""
424
+ keylist = []
425
+ for keyit in self .schema_node ._key_members :
426
+ keylist .append (key [keyit ])
427
+
428
+ return tuple (keylist )
429
+
405
430
def _mapentry (self , key : tuple ) -> "ArrayEntry" :
406
- if self ._childmap is None :
407
- self . _childmap = {}
408
- keys = self . schema_node . _key_members
431
+ child = self ._childmap . get ( key )
432
+ if child is not None :
433
+ return child
409
434
410
- # iterate over all childs
411
- for child in self :
412
- keylist = []
435
+ """lazy initialization of mapping from keys to childnodes"""
436
+ keys = self .schema_node ._key_members
413
437
414
- # collect key values into tuple
415
- for keyit in keys :
416
- keylist . append ( child [ keyit ]. value )
438
+ """iterate over all childs starting with last unparsed index"""
439
+ while self . _parse_next < len ( self . value ) :
440
+ child = self [ self . _parse_next ]
417
441
418
- # cache mapping
419
- self ._childmap [tuple (keylist )] = child
442
+ """generate tuple for key"""
443
+ keylist = []
444
+ for keyit in keys :
445
+ keylist .append (child [keyit ].value )
446
+ keytuple = tuple (keylist )
420
447
421
- try :
422
- return self ._childmap [key ]
423
- except (KeyError ):
424
- raise NonexistentInstance (self .json_pointer (),
425
- f"key '{ key } '" ) from None
448
+ """cache mapping for later use"""
449
+ self ._childmap [keytuple ] = child
450
+
451
+ """mark this child as done"""
452
+ self ._parse_next = self ._parse_next + 1 ;
453
+
454
+ if keytuple == key :
455
+ return child
456
+
457
+ raise NonexistentInstance (self .json_pointer (), f"key '{ key } '" ) from None
426
458
427
459
def _peek_schema_route (self , sroute : SchemaRoute ) -> Value :
428
460
irt = InstanceRoute ()
0 commit comments