Source code for aiida_vasp.utils.extended_dicts
"""
Extensions of dictionaries.
---------------------------
Extensions of Pythons standard dict as well as Aiida's AttributeDict.
"""
import collections.abc
from copy import deepcopy
from aiida.common.extendeddicts import AttributeDict
[docs]
class DictWithAttributes(AttributeDict):
"""
Extension of the AttributeDict from Aiida.common.
This class internally stores values in a dictionary, but exposes
the keys also as attributes, i.e. asking for attrdict.key
will return the value of attrdict['key'] and so on.
If the key is not in the dict a default value will be returned.
"""
def __getattr__(self, attr):
"""Read a key as an attribute. Return a Default value on missing key."""
return self.get(attr)
def __setattr__(self, attr, value):
"""Set a key as an attribute."""
self[attr] = value
[docs]
def delete_keys_from_dict(dictionary, keys):
"""
Delete a key from a nested dictionary.
Extended to support somekey.someotherkey in case we need some restrictions on the nesting.
"""
if not isinstance(keys, list):
keylist = [keys]
else:
keylist = keys
for key in keylist:
nested_keys = key.strip().split('.')
delete_nested_key(dictionary, nested_keys)
[docs]
def delete_nested_key(dictionary, keys):
"""Delete the dictionary entry corresponding to a nested hierarchy of keys."""
from collections.abc import MutableMapping # pylint: disable=import-outside-toplevel
from contextlib import suppress # pylint: disable=import-outside-toplevel
if keys and dictionary:
element = keys[0]
if element:
value = dictionary.get(element)
if len(keys) == 1:
with suppress(KeyError):
del dictionary[element]
else:
if isinstance(value, MutableMapping):
delete_nested_key(value, keys[1:])
[docs]
def update_nested_dict(dict1, dict2):
"""Updated a nested dictionary, where dict1 is updated with values in dict2."""
for key, value in dict2.items():
dict1_value = dict1.get(key)
if isinstance(value, collections.abc.Mapping) and isinstance(dict1_value, collections.abc.Mapping):
update_nested_dict(dict1_value, value)
else:
dict1[key] = deepcopy(value)
[docs]
def find_key_in_dicts(dictionary, supplied_key):
"""Find a key in a nested dictionary."""
for key, value in dictionary.items():
if key == supplied_key:
yield value
elif isinstance(value, dict):
for result in find_key_in_dicts(value, supplied_key):
yield result