def ast_value(val, scope, return_name=False):
    '''Recursively parse out an AST value.  This makes no attempt to load
    modules or reconstruct functions on purpose.  We do not want to
    inadvertently call destructive code.
    '''
    # :TODO: refactor the hell out of this
    try:
        if isinstance(val, (ast.Assign, ast.Delete)):
            if hasattr(val, 'value'):
                value = ast_value(val.value, scope)
            else:
                value = None
            for t in val.targets:
                name = ast_value(t, scope, return_name=True)
                if isinstance(t.ctx, ast.Del):
                    if name in scope:
                        scope.pop(name)
                elif isinstance(t.ctx, ast.Store):
                    scope[name] = value
            return
        elif isinstance(val, ast.Expr) and isinstance(val.value, ast.Name):
            return ast_value(val.value)

        if isinstance(val, ast.Name):
            if isinstance(val.ctx, ast.Load):
                if val.id == 'None':
                    return None
                elif val.id == 'True':
                    return True
                elif val.id == 'False':
                    return False

                if val.id in scope:
                    return scope[val.id]

                if return_name:
                    return val.id
            elif isinstance(val.ctx, ast.Store):
                if return_name:
                    return val.id
            return None

        if isinstance(val, ast.Subscript):
            toslice = ast_value(val.value, scope)
            theslice = ast_value(val.slice, scope)
            return toslice[theslice]
        elif isinstance(val, ast.Index):
            return ast_value(val.value, scope)
        elif isinstance(val, ast.Slice):
            lower = ast_value(val.lower)
            upper = ast_value(val.upper)
            step = ast_value(val.step)
            return slice(lower, upper, step)

        if isinstance(val, list):
            return [ast_value(x, scope) for x in val]
        elif isinstance(val, tuple):
            return tuple(ast_value(x, scope) for x in val)

        if isinstance(val, ast.Attribute):
            name = ast_value(val.value, scope, return_name=True)
            if isinstance(val.ctx, ast.Load):
                return '.'.join((name, val.attr))
            if return_name:
                return name
        elif isinstance(val, ast.keyword):
            return {val.arg: ast_value(val.value, scope)}
        elif isinstance(val, ast.List):
            return [ast_value(x, scope) for x in val.elts]
        elif isinstance(val, ast.Tuple):
            return tuple(ast_value(x, scope) for x in val.elts)
        elif isinstance(val, ast.Dict):
            return dict(zip([ast_value(x, scope) for x in val.keys],
                            [ast_value(x, scope) for x in val.values]))
        elif isinstance(val, ast.Num):
            return val.n
        elif isinstance(val, ast.Str):
            return val.s
        elif hasattr(ast, 'Bytes') and isinstance(val, ast.Bytes):
            return bytes(val.s)
    except Exception:
        # Don't care, just return None
        pass

    return None
def ast_value ( val , scope , return_name = False ) : try : if isinstance ( val , ( ast . Assign , ast . Delete ) ) : if hasattr ( val , 'value' ) : value = ast_value ( val . value , scope ) else : value = None for t in val . targets : name = ast_value ( t , scope , return_name = True ) if isinstance ( t . ctx , ast . Del ) : if name in scope : scope . pop ( name ) elif isinstance ( t . ctx , ast . Store ) : scope [ name ] = value return elif isinstance ( val , ast . Expr ) and isinstance ( val . value , ast . Name ) : return ast_value ( val . value ) if isinstance ( val , ast . Name ) : if isinstance ( val . ctx , ast . Load ) : if val . id == 'None' : return None elif val . id == 'True' : return True elif val . id == 'False' : return False if val . id in scope : return scope [ val . id ] if return_name : return val . id elif isinstance ( val . ctx , ast . Store ) : if return_name : return val . id return None if isinstance ( val , ast . Subscript ) : toslice = ast_value ( val . value , scope ) theslice = ast_value ( val . slice , scope ) return toslice [ theslice ] elif isinstance ( val , ast . Index ) : return ast_value ( val . value , scope ) elif isinstance ( val , ast . Slice ) : lower = ast_value ( val . lower ) upper = ast_value ( val . upper ) step = ast_value ( val . step ) return slice ( lower , upper , step ) if isinstance ( val , list ) : return [ ast_value ( x , scope ) for x in val ] elif isinstance ( val , tuple ) : return tuple ( ast_value ( x , scope ) for x in val ) if isinstance ( val , ast . Attribute ) : name = ast_value ( val . value , scope , return_name = True ) if isinstance ( val . ctx , ast . Load ) : return '.' . join ( ( name , val . attr ) ) if return_name : return name elif isinstance ( val , ast . keyword ) : return { val . arg : ast_value ( val . value , scope ) } elif isinstance ( val , ast . List ) : return [ ast_value ( x , scope ) for x in val . elts ] elif isinstance ( val , ast . Tuple ) : return tuple ( ast_value ( x , scope ) for x in val . elts ) elif isinstance ( val , ast . Dict ) : return dict ( zip ( [ ast_value ( x , scope ) for x in val . keys ] , [ ast_value ( x , scope ) for x in val . values ] ) ) elif isinstance ( val , ast . Num ) : return val . n elif isinstance ( val , ast . Str ) : return val . s elif hasattr ( ast , 'Bytes' ) and isinstance ( val , ast . Bytes ) : return bytes ( val . s ) except Exception : pass return None
Recursively parse out an AST value.  This makes no attempt to load
    modules or reconstruct functions on purpose.  We do not want to
    inadvertently call destructive code.