Skip to content

Instantly share code, notes, and snippets.

@inizovtsev
Last active August 29, 2015 14:25
Show Gist options
  • Save inizovtsev/3fb58a2fd611b7de9b72 to your computer and use it in GitHub Desktop.
Save inizovtsev/3fb58a2fd611b7de9b72 to your computer and use it in GitHub Desktop.
test = dict(
len=1,
objects=[
dict(foo='bar'),
dict(bar='baz'),
],
sub_object=dict(foo='bar')
)
COLLECTION_PROXY_METHODS = ('__getitem__', '__setitem__', '__len__', '__repr__')
LIST_PROXY_METHODS = COLLECTION_PROXY_METHODS + ('append',)
DICT_PROXY_METHODS = COLLECTION_PROXY_METHODS + ()
def assertion(condition, message):
if not condition:
raise AssertionError(message)
def proxy(name):
def wrapper(self, *args, **kwargs):
return getattr(self._obj, name)(*args, **kwargs)
return wrapper
def create_collections_wrapper(assertion_f=None, list_index_suffix='_', dict_keys_suffix='_'):
if assertion_f is None:
assertion_f = assertion
def get_data_from_dict(self, name):
alt_name = name
obj = self._obj
if name.startswith(dict_keys_suffix):
alt_name = name[len(dict_keys_suffix):]
assertion_f(name in obj or alt_name in obj, "key '{}' not found".format(name))
return obj.get(alt_name, obj.get(name))
def get_data_from_list(self, name):
obj = self._obj
assertion_f(
name.startswith(list_index_suffix),
"list index should start with '{}'".format(list_index_suffix)
)
index = name[len(list_index_suffix):]
assertion_f(
index.isdigit(),
"list index should be digit, not {}".format(index)
)
index = int(index)
assertion_f(
index < len(obj),
"index {} is out of range ({})".format(index, len(obj))
)
return obj[index]
class BaseCollectionWrapper(object):
def __init__(self, obj):
self._obj = obj
def __getattr__(self, name):
return wrap(self._get_data(name))
DictWrapper = type('DictWrapper', (BaseCollectionWrapper,), dict(
_get_data=get_data_from_dict,
**{method: proxy(method) for method in DICT_PROXY_METHODS}
))
ListWrapper = type('ListWrapper', (BaseCollectionWrapper,), dict(
_get_data=get_data_from_list,
**{method: proxy(method) for method in LIST_PROXY_METHODS}
))
def wrap(obj):
if isinstance(obj, dict):
return DictWrapper(obj)
elif isinstance(obj, list):
return ListWrapper(obj)
else:
return obj
return wrap
w = create_collections_wrapper()(test)
print w._objects._1.bar
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment