Source code for prance.util.iterators
"""This submodule contains specialty iterators over specs."""
__author__ = "Jens Finkhaeuser"
__copyright__ = "Copyright (c) 2016-2018 Jens Finkhaeuser"
__license__ = "MIT"
__all__ = ()
[docs]def item_iterator(value, path=()):
"""
Return item iterator over the a nested dict- or list-like object.
Returns each item value as the second item to unpack, and a tuple path to the
item as the first value - in that, it behaves much like viewitems(). For list
like values, the path is made up of numeric indices.
Given a spec such as this::
spec = {
'foo': 42,
'bar': {
'some': 'dict',
},
'baz': [
{ 1: 2 },
{ 3: 4 },
]
}
Here, (parts of) the yielded values would be:
======== =============
item path
======== =============
[...] ('baz',)
{ 1: 2 } ('baz', 0)
2 ('baz', 0, 1)
======== =============
:param dict/list value: The specifications to iterate over.
:return: An iterator over all items in the value.
:rtype: iterator
"""
# Yield the top-level object, always
yield path, value
from collections.abc import Mapping, Sequence
# For dict and list like objects, we also need to yield each item
# recursively.
if isinstance(value, Mapping):
for key, item in value.items():
yield from item_iterator(item, path + (key,))
elif isinstance(value, Sequence) and not isinstance(value, str):
for idx, item in enumerate(value):
yield from item_iterator(item, path + (idx,))
[docs]def reference_iterator(specs, path=()):
"""
Iterate through the given specs, returning only references.
The iterator returns three values:
- The key, mimicking the behaviour of other iterators, although
it will always equal '$ref'
- The value
- The path to the item. This is a tuple of all the item's ancestors,
in sequence, so that you can reasonably easily find the containing
item. It does not include the final '$ref' key.
:param dict specs: The specifications to iterate over.
:return: An iterator over all references in the specs.
:rtype: iterator
"""
# We need to iterate through the nested specification dict, so let's
# start with an appropriate iterator. We can immediately optimize it by
# only returning '$ref' items.
for item_path, item in item_iterator(specs, path):
if len(item_path) <= 0:
continue
key = item_path[-1]
if key == "$ref":
yield key, item, item_path[:-1]