Last active
August 9, 2016 16:33
-
-
Save zzeleznick/a0bb0aa2dd461d0f9cf44755ba461442 to your computer and use it in GitHub Desktop.
Steals away keys from children
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from collections import OrderedDict | |
"""Q: How do we define a data structure that makes it easy | |
to determine which keys should be passed to children | |
and which should be passed to report summaries. | |
And which keys should be promoted? | |
## Thoughts: | |
- CAPS_AND_UNDERSCORE signify importance | |
- Optional updates | |
- All keys should be passed to children by default | |
""" | |
def issub_dict(obj): | |
return issubclass(type(obj), dict) | |
class GreedyDict(OrderedDict): | |
"""GreedyDict will absorb updates to children dictionaries | |
and place those key-value pairs top-level if the key has not | |
yet been added""" | |
def __init__(self, *args, **kwds): | |
super(GreedyDict, self).__init__() | |
# shallow_copy | |
for k in self.__dict__.keys(): | |
kk = k.replace('OrderedDict', 'GreedyDict') | |
self.__dict__[kk] = self.__dict__[k] | |
self.parent = None | |
self.root = None | |
self.update(*args, **kwds) | |
def __str__(self): | |
if not self: | |
return '%s()' % (self.__class__.__name__,) | |
return '%s(%r)' % (self.__class__.__name__, self.items()) | |
__repr__ = __str__ | |
def __getitem__(self, key): | |
try: | |
return super(GreedyDict, self).__getitem__(key) | |
except KeyError: | |
self[key] = {} | |
return self[key] | |
def __setitem__(self, key, value, PREV=0, NEXT=1, dict_setitem=dict.__setitem__): | |
""" Setting a new item creates a new link which goes at the end of the linked | |
list, and the inherited dictionary is updated with the new key/value pair. | |
""" | |
if self.parent: | |
pass # print 'I have a parent' | |
if key not in self: | |
root = self.__root | |
last = root[PREV] | |
last[NEXT] = root[PREV] = self.__map[key] = [last, root, key] | |
if issub_dict(value): | |
root = self.root if self.root else self | |
value = GreedyDict.make(value, parent=self, root=root) | |
if self.root: | |
if key not in self.root: | |
self.root[key] = value | |
elif issub_dict(self.root[key]) and len(self.root[key]) == 0: | |
self.root[key] = value | |
dict_setitem(self, key, value) | |
def __getattr__(self, name): | |
"""__getattr__ sets a default value by | |
determining how to handle attributes that are not found | |
""" | |
if name in self: | |
return self[name] | |
elif name.endswith('__root'): | |
# required to allow proper construction of object | |
raise AttributeError | |
else: | |
print '%s has no attribute %s' % (self.__class__.__name__, name) | |
return None | |
@classmethod | |
def make(cls, value, parent, root): | |
res = cls(value) | |
res.parent = parent | |
res.root = root | |
return res | |
def say_hi(self): | |
return 'HI' | |
def populate(): | |
pass | |
def main(): | |
x = GreedyDict() | |
x['PROTECTED'] = "I'm preserved" | |
x[0] = {3:0, 1:2} | |
x['args'] = {'junk': 2} # not saved to top-level | |
x['args'].update({'SAVEME': 10, 'ME_TOO': 40, 'PROTECTED': 'MUAHAHAH' }) | |
print x | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment