def METHOD_NAME(obj):
    if hasattr(obj, 'state'):
        return obj.METHOD_NAME()
    if hasattr(obj.__class__, 'StateKeys'):
        rv = {}
        for key in obj.__class__.StateKeys:
            attr = key
            if isinstance(key, tuple):
                (key, attr) = key
            rv[key] = METHOD_NAME(getattr(obj, attr))
        return rv
    if isinstance(obj, dict):
        return dict([(k, METHOD_NAME(v)) for k,v in list(obj.items())])
    if any([isinstance(obj, cls) for cls in [str, int, float]]):
        return obj
    try:
        obj = [METHOD_NAME(i) for i in obj]
        return obj
    except TypeError:
        pass
    return obj