def get_attr_usage( func, attrpath ): ''' attrpath = [a, b, c] -> a.b.c attrpath = [1, b.c] -> func_args[1].b.c ''' if not isinstance( func, Code): code = Code.from_code( getattr( func, 'im_func', func).func_code) else: code = func #print code.code root_var = attrpath[0] subattrs = attrpath[1:] if isinstance( root_var, int): #argix root_var = code.args[ root_var] return get_var_attr_usage( code, root_var, subattrs)
def execode( func, noargs =True, get_all_data =False): '''expose func code as plain executable block without own namespace usage: pass all args/vars in locals/globals: cf = execode( func1) #no return value: exec cf in mylocalz( x=7, y=6, max= mymax ) #with return value: r = eval( cf, mylocalz( x=9, y=0, max= mymax ) ) ref: http://wiki.python.org/moin/ByteplayDoc http://www.voidspace.org.uk/python/articles/code_blocks.shtml http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/498242 ''' fc = getattr( func, 'im_func', func).func_code code = Code.from_code( fc) #XXX TODO: # LOAD_DEREF -> LOAD_NAME: needs same to be done in all nested funcs!! #if opmap['LOAD_DEREF'] in [ c for c,a in code.code ]: # print code.code #print code.code #print code.__dict__ assert not code.varargs, func assert not code.varkwargs, func code.code = [ (replacer.get( opcode,opcode),arg) for opcode,arg in code.code] global_names = [ arg for opcode,arg in code.code if opcode == opload_glob ] code.newlocals = False #no local namespace assert not code.freevars code.freevars = () #kill (to-be-bound) vars org_args = code.args if noargs: code.args = () #kill (to-be-bound) args c = code.to_code() #assert not fc.co_cellvars, fc.co_cellvars if not get_all_data: return c return c, org_args, global_names return dict( code=c, org_args=org_args, global_names=global_names)