Skip to content

Commit 2a9a9c3

Browse files
committed
Speedup tuple based lookup and add map based lookup of childs
1 parent ce098f6 commit 2a9a9c3

File tree

2 files changed

+51
-19
lines changed

2 files changed

+51
-19
lines changed

yangson/instance.py

+50-18
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,10 @@ def __init__(self, key: InstanceKey, value: Value,
137137
self.value = value # type: Value
138138
"""Value of the receiver."""
139139

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
142144

143145
@property
144146
def name(self) -> InstanceName:
@@ -183,12 +185,19 @@ def __getitem__(self, key: InstanceKey) -> "InstanceNode":
183185
"""
184186
if isinstance(self.value, ArrayValue) and isinstance(key, tuple):
185187
return self._mapentry(key)
188+
if isinstance(self.value, ArrayValue) and isinstance(key, dict):
189+
return self._mapentry(self._map2tuple(key))
186190
if isinstance(self.value, ObjectValue):
187191
return self._member(key)
188192
if isinstance(self.value, ArrayValue):
189193
return self._entry(key)
190194
raise InstanceValueError(self.json_pointer(), "scalar instance")
191195

196+
def __contains__(self, key: InstanceKey) -> bool:
197+
"""Checks if key does exist
198+
"""
199+
return self.get(key) is not None
200+
192201
def __iter__(self):
193202
"""Return receiver's iterator.
194203
@@ -210,6 +219,14 @@ def ita():
210219
return iter(self._member_names())
211220
raise InstanceValueError(self.json_pointer(), "scalar instance")
212221

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+
213230
def is_internal(self) -> bool:
214231
"""Return ``True`` if the receiver is an instance of an internal node.
215232
"""
@@ -402,27 +419,42 @@ def _entry(self, index: int) -> "ArrayEntry":
402419
except (IndexError, TypeError):
403420
raise NonexistentInstance(self.json_pointer(), "entry " + str(index)) from None
404421

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+
405430
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
409434

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
413437

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]
417441

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)
420447

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
426458

427459
def _peek_schema_route(self, sroute: SchemaRoute) -> Value:
428460
irt = InstanceRoute()

yangson/instvalue.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
EntryValue = Union[ScalarValue, "ObjectValue"]
3636
"""Type of the value a list ot leaf-list entry."""
3737

38-
InstanceKey = Union[InstanceName, int, tuple]
38+
InstanceKey = Union[InstanceName, int, tuple, dict]
3939
"""Index of an array entry or name of an object member."""
4040

4141
MetadataObject = Dict[PrefName, ScalarValue]

0 commit comments

Comments
 (0)