in runtool/runtool/transformations.py [0:0]
def apply_each(node: dict) -> Versions:
"""
If `$each` is in the node, it means that the node can become
several different values.
NOTE::
nodes which can take multiple values are represented as
`runtool.datatypes.Versions` objects. Refer to their documentation
for further information.
Example, a node which can take the values `1` or `2` or `3` can be generated
as follows:
>>> apply_each({"$each":[1,2,3]})
Versions([1, 2, 3])
If dictionaries are passed to $each, these will be updated with the
value of the passed `node` before a Versions object is generated.
>>> apply_each({"a": 1, "$each": [{"b": 2}, {"b": 3}]})
Versions([{'b': 2, 'a': 1}, {'b': 3, 'a': 1}])
It is possible to have an unaltered version of the parent node by
inserting $None into the values of $each. In the example below,
apply_each generates two versions of the node, one which is unaltered
and one which is merged with another dict.
>>> apply_each({"a": 1, "$each": ["$None", {"b": 2}]})
Versions([{'a': 1}, {'b': 2, 'a': 1}])
Below is a more complicated example combining the two examples above:
>>> apply_each(
... {
... "a": 1,
... "$each": ["$None", {"b": 2, "c": 3}]
... }
... )
Versions([{'a': 1}, {'b': 2, 'c': 3, 'a': 1}])
Parameters
----------
node
The node which should have `$each` applied to it.
Returns
-------
runtool.datatypes.Versions
The versions object representing the different values of the node.
"""
if not (isinstance(node, dict) and "$each" in node):
return node
each = node.pop("$each")
if not isinstance(each, list):
raise TypeError(
f"$each requires a list, not an object of type {type(each)}"
)
# Generate versions of the current node
versions = []
for item in each:
if item == "$None":
# return unaltered node
# node = {"a": 1, "$each": ["$None"]}
# ==>
# {"a": 1}
versions.append(node)
elif isinstance(item, dict):
# merge node with value in $each
# node = {"a": 1, "$each": [{"b: 2"}]}
# ==>
# {"a": 1, "b": 2}
item.update(node)
versions.append(item)
else:
# any other value overwrites the node if node is
# otherwise empty.
# node = {"$each": [2]}
# ==>
# 2
if node:
node["$each"] = each
raise TypeError(
"Using $each in a non-empty node is only supported"
" when using dictionaries or with the $None operator."
f" The error occured in:\n{node}"
)
versions.append(item)
return Versions(versions)