11from copy import deepcopy
22from fnmatch import fnmatchcase
3- from typing import List , Sequence , Tuple
3+ from typing import List , Sequence , Tuple , Iterator , Any , Dict , Union
44
55from dpath import options
66from dpath .exceptions import InvalidGlob , InvalidKeyName , PathNotFound
77from dpath .util import PathSegment
88
99
10- def kvs (node ):
10+ def make_walkable (node ) -> Iterator [ Tuple [ PathSegment , Any ]] :
1111 """
12- Return a (key, value) iterator for the node.
12+ Returns an iterator which yields tuple pairs of (node index, node value), regardless of node type .
1313
14- kvs(node) -> (generator -> (key, value))
14+ * For dict nodes `node.items()` will be returned.
15+ * For sequence nodes (lists/tuples/etc.) a zip between index number and index value will be returned.
16+ * Edge cases will result in an empty iterator being returned.
17+
18+ make_walkable(node) -> (generator -> (key, value))
1519 """
1620 try :
1721 return iter (node .items ())
@@ -28,8 +32,6 @@ def kvs(node):
2832def leaf (thing ):
2933 """
3034 Return True if thing is a leaf, otherwise False.
31-
32- leaf(thing) -> bool
3335 """
3436 leaves = (bytes , str , int , float , bool , type (None ))
3537
@@ -40,8 +42,6 @@ def leafy(thing):
4042 """
4143 Same as leaf(thing), but also treats empty sequences and
4244 dictionaries as True.
43-
44- leafy(thing) -> bool
4545 """
4646
4747 try :
@@ -59,20 +59,21 @@ def walk(obj, location=()):
5959 walk(obj) -> (generator -> (segments, value))
6060 """
6161 if not leaf (obj ):
62- for k , v in kvs (obj ):
62+ for k , v in make_walkable (obj ):
6363 length = None
6464
6565 try :
6666 length = len (k )
67- except :
67+ except TypeError :
6868 pass
6969
7070 if length is not None and length == 0 and not options .ALLOW_EMPTY_STRING_KEYS :
7171 raise InvalidKeyName ("Empty string keys not allowed without "
7272 "dpath.options.ALLOW_EMPTY_STRING_KEYS=True: "
7373 "{}" .format (location + (k ,)))
74- yield ((location + (k ,)), v )
75- for k , v in kvs (obj ):
74+ yield (location + (k ,)), v
75+
76+ for k , v in make_walkable (obj ):
7677 for found in walk (v , location + (k ,)):
7778 yield found
7879
@@ -240,7 +241,7 @@ def match(segments, glob):
240241 return False
241242
242243
243- def extend (thing , index , value = None ):
244+ def extend (thing : List , index : int , value = None ):
244245 """
245246 Extend a sequence like thing such that it contains at least index +
246247 1 many elements. The extension values will be None (default).
@@ -265,7 +266,12 @@ def extend(thing, index, value=None):
265266 return thing
266267
267268
268- def __default_creator__ (current , segments : List [str ], i : int , hints : Sequence [Tuple [PathSegment , type ]] = ()):
269+ def __default_creator__ (
270+ current : Union [Dict , List ],
271+ segments : List [PathSegment ],
272+ i : int ,
273+ hints : Sequence [Tuple [PathSegment , type ]] = ()
274+ ):
269275 """
270276 Create missing path components. If the segment is an int, then it will
271277 create a list. Otherwise a dictionary is created.
0 commit comments