in runtool/runtool/transformations.py [0:0]
def recurse_eval(path: str, data: dict, fn: Callable) -> Tuple[str, Any]:
"""
Given a `path` such as `a.b.0.split(' ')` this function traverses
the `data` dictionary using the path, stopping whenever a key cannot be
found in the `data`. `fn` is then applied to the extracted data and the
result is returned along with the part of the path which was traversed.
In the following example, `a.b.0` is identified as the path to return
since `.split()` is not an item in `data`.
>>> recurse_eval(
... path="a.b.0.split(' ')",
... data={"a": {"b": [{"$eval": "'hey ' * 2"}]}},
... fn=lambda node, _ : eval(node["$eval"]) if "$eval" in node else node
... )
('a.b.0', 'hey hey ')
Parameters
----------
path
The path to fetch from in the data
data
Dictionary which should be traversed using the path
fn
function to call with the fetched data as parameter
Returns
-------
Tuple[str, Any]
The path and the value after applying the `fn`
"""
tmp = data
current_path = []
path = path.replace("[", ".[")
for key in path.split("."):
original_key = key
if "[" in key:
key = key.replace("[", "").replace("]", "").replace('"', "")
try:
tmp = tmp[key]
current_path.append(original_key)
except TypeError:
try:
tmp = tmp[int(key)]
current_path.append(original_key)
except ValueError:
break
except:
break
return ".".join(current_path).replace(".[", "["), fn(tmp, data)