Skip to content

Instantly share code, notes, and snippets.

@theho
Forked from einnocent/dotdictify.py
Last active August 29, 2015 14:10
Show Gist options
  • Save theho/25cdc6dc5fe78b6c19f5 to your computer and use it in GitHub Desktop.
Save theho/25cdc6dc5fe78b6c19f5 to your computer and use it in GitHub Desktop.
# turn dict into an object that allows access to nested keys via dot notation
# from http://stackoverflow.com/questions/3797957/python-easily-access-deeply-nested-dict-get-and-set
# made three modifications:
# --added `get()` method
# --added `if not dict.__contains__...` to `__contains__()`
# --can now accept None as key
# JHO:
# --updated prints and Exceptions to be python3 friendly
# https://gist.github.com/einnocent/8854896
class dotdictify(dict):
def __init__(self, value=None):
if value is None:
pass
elif isinstance(value, dict):
for key in value:
print(key)
self.__setitem__(key, value[key])
else:
raise TypeError('expected dict')
def __setitem__(self, key, value):
if key is not None and '.' in key:
my_key, rest_of_key = key.split('.', 1)
target = self.setdefault(my_key, dotdictify())
if not isinstance(target, dotdictify):
raise KeyError('cannot set "{0}" in "{1}" ({2})'.format(rest_of_key, my_key, repr(target)))
target[rest_of_key] = value
else:
if isinstance(value, dict) and not isinstance(value, dotdictify):
value = dotdictify(value)
dict.__setitem__(self, key, value)
def __getitem__(self, key):
if key is None or '.' not in key:
return dict.__getitem__(self, key)
my_key, rest_of_key = key.split('.', 1)
target = dict.__getitem__(self, my_key)
if not isinstance(target, dotdictify):
raise KeyError('cannot get "{0}" in "{1}" ({2})'.format(rest_of_key, my_key, repr(target)))
return target[rest_of_key]
def __contains__(self, key):
if key is None or '.' not in key:
return dict.__contains__(self, key)
my_key, rest_of_key = key.split('.', 1)
if not dict.__contains__(self, my_key):
return False
target = dict.__getitem__(self, my_key)
if not isinstance(target, dotdictify):
return False
return rest_of_key in target
def setdefault(self, key, default=None):
if key not in self:
self[key] = default
return self[key]
def get(self, k, d=None):
if dotdictify.__contains__(self, k):
return dotdictify.__getitem__(self, k)
return d
__setattr__ = __setitem__
__getattr__ = __getitem__
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment