gnocchi-ajax / gnocchi / ajax /

def digattr(obj, attr, default=None):
    '''Perform template-style dotted lookup'''
    steps = attr.split('.')
    for step in steps:
        try:    # dict lookup
            obj = obj[step]
        except (TypeError, AttributeError, KeyError):
            try:    # attribute lookup
                obj = getattr(obj, step)
            except (TypeError, AttributeError):
                try:    # list index lookup
                    obj = obj[int(step)]
                except (IndexError, ValueError, KeyError, TypeError):
                    return default
        if callable(obj):
            obj = obj()
    return obj

def dehydrate(obj, fields):
    '''Turn an object into a flat dict according to the list of fields.

    If a field is a list/tuple, it will be taken to be (label, source)
    otherwise, label and source will be the same.

    If source is callable, the value will be source(obj, field, name)
    def gen(fields):
        for field in fields:
            if isinstance(field, (tuple, list)):
                name, source = field
                name = source = field
            if callable(source):
                yield name, source(obj, field, name)
                yield name, digattr(obj, source)

    return dict(gen(fields))