def Call(func, args=(), kwargs=(), star=None, dstar=None, fold=True, code=None): if code is None: data = (func, tuple(args), tuple(kwargs), star or (), dstar or (), fold) if fold and (args or kwargs or star or dstar): return fold_args(Call, *data) else: return data code(func, *args) for k, v in kwargs: code(k, v) argc = len(args) kwargc = len(kwargs) if star: if dstar: code(star, dstar) return code.CALL_FUNCTION_VAR_KW(argc, kwargc) else: code(star) return code.CALL_FUNCTION_VAR(argc, kwargc) else: if dstar: code(dstar) return code.CALL_FUNCTION_KW(argc, kwargc) else: return code.CALL_FUNCTION(argc, kwargc)
def gen_map(code, ob): code.BUILD_MAP(0) for k, v in ob.items(): code.DUP_TOP() code(k, v) code.ROT_THREE() code.STORE_SUBSCR()
def Getattr(ob, name, code=None): try: name = const_value(name) except NotAConstant: return Call(Const(getattr), [ob, name]) if code is None: return fold_args(Getattr, ob, name) code(ob) code.LOAD_ATTR(name)
def If(cond, then, else_=Pass, code=None): if code is None: return cond, then, else_ else_clause = Label() end_if = Label() code(cond, else_clause.JUMP_IF_FALSE_OR_POP, then) if code.stack_size is not None: end_if.JUMP_FORWARD(code) code(else_clause, Code.POP_TOP, else_, end_if)
def Or(values, code=None): if code is None: return fold_args(Or, tuple(values)) end = Label() for value in values[:-1]: try: if not const_value(value): continue # false constants can be skipped except NotAConstant: # but non-constants require code code(value, end.JUMP_IF_TRUE_OR_POP) else: # and true constants end the chain right away return code(value, end) code(values[-1], end)
def _pop_funclist(f): """_pop_funclist(f) -> list or None Evaluates and returns a list constant defined at the beginning of a function. If the function doesn't begin with a list, or the list refers to parameters or other locals, a None is returned. The returned list is removed from the function code. """ op = dis.opmap.__getitem__ i = 0 co = f.func_code s = co.co_code stopcodes = [op('LOAD_FAST'), op('STORE_FAST'), op('STORE_NAME'), op('POP_TOP'), op('JUMP_FORWARD')] while i < len(s): code = ord(s[i]) i += 1 if code >= dis.HAVE_ARGUMENT: i += 2 if code in stopcodes: return if code == op('BUILD_LIST') and ord(s[i]) == op('POP_TOP'): i += 1 break else: return varname = '__func_list__' names = co.co_names + (varname,) dict_code = co.co_code[:i-1] + ''.join(map(chr, [ op('STORE_NAME'), list(names).index(varname), 0, op('LOAD_CONST'), list(co.co_consts).index(None), 0, op('RETURN_VALUE'), ])) func_code = chr(op('JUMP_FORWARD')) \ + chr(i-3) + chr(0) \ + co.co_code[3:] list_co = new.code(0, 0, co.co_stacksize, 64, dict_code, co.co_consts, names, co.co_varnames, co.co_filename, co.co_name, co.co_firstlineno, co.co_lnotab) func_co = new.code(co.co_argcount, co.co_nlocals, co.co_stacksize, co.co_flags, func_code, co.co_consts, co.co_names, co.co_varnames, co.co_filename, co.co_name, co.co_firstlineno, co.co_lnotab) f.func_code = func_co globals = f.func_globals.copy() exec list_co in globals result = globals[varname] return result
def function(self): def fn(): pass t = self.fn_tuple fn.func_code = new.code(t[0],t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8],t[9],t[10],t[11],t[12],t[13]) fn.__doc__ = self.doc_string return fn
def compile(self, expr): if type(expr) is unicode: code = compile(expr.encode('utf-8'), '', 'eval') # XXX This stupid compiler encoded all strings to utf-8, so we # need to convert them to unicode. consts = [] for const in code.co_consts: if type(const) is str: # We have to leave ascii strings just str not unicode # because they can be python function keywords or # something else try: const.decode('ascii') except UnicodeError: # UnicodeDecodeError consts.append(const.decode('utf-8')) else: consts.append(const) else: consts.append(const) import new code = new.code(code.co_argcount, code.co_nlocals, code.co_stacksize, code.co_flags, code.co_code, tuple(consts), code.co_names, code.co_varnames, code.co_filename, code.co_name, code.co_firstlineno, code.co_lnotab) else: code = compile(expr, '', 'eval') return code
def _to_code(self): """For debugging only.""" consts = [None] * len(self.co_consts_w) num = 0 for w in self.co_consts_w: if isinstance(w, PyCode): consts[num] = w._to_code() else: consts[num] = self.space.unwrap(w) num += 1 assert ( self.co_kwonlyargcount == 0 ), "kwonlyargcount is py3k only, cannot turn this code object into a Python2 one" return new.code( self.co_argcount, # self.co_kwonlyargcount, # this does not exists in python2 self.co_nlocals, self.co_stacksize, self.co_flags, self.co_code, tuple(consts), tuple(self.co_names), tuple(self.co_varnames), self.co_filename, self.co_name, self.co_firstlineno, self.co_lnotab, tuple(self.co_freevars), tuple(self.co_cellvars), )
def code_all_variables_dynamic(fun): co = fun.func_code len_co_names = len(co.co_names) new_co_names = co.co_names + co.co_varnames new_co_flags = co.co_flags & ~0x02 new_code = '' for end, op, arg in bytecode(fun): if dis.opname[op] == 'STORE_FAST': new_arg = arg + len_co_names new_code += chr(dis.opmap['STORE_NAME']) + \ chr(new_arg % 256) + \ chr(new_arg // 256) elif dis.opname[op] == 'LOAD_FAST': new_arg = arg + len_co_names new_code += chr(dis.opmap['LOAD_NAME']) + \ chr(new_arg % 256) + \ chr(new_arg // 256) else: if arg is None: new_code += chr(op) else: new_code += chr(op) + chr(arg % 256) + chr(arg // 256) func_co = new.code(co.co_argcount, co.co_nlocals, co.co_stacksize, new_co_flags, new_code, co.co_consts, new_co_names, co.co_varnames, co.co_filename, co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars, co.co_cellvars) return func_co
def get_code(self, start=None): ''' Produce a new code object based on the graph ''' self.refactor() # generate a new co_lineno new_co_lineno = self.calc_lnotab() # generate new bytecode stream new_co_code = "" for x in self.nodes(start): new_co_code += x.bin() # create a new code object with modified bytecode and updated line numbers # a new code object is necessary because co_code is readonly rvalue = new.code(self.code.co_argcount, self.code.co_nlocals, self.code.co_stacksize, self.code.co_flags, new_co_code, self.code.co_consts, self.code.co_names, self.code.co_varnames, self.code.co_filename, self.code.co_name, self.code.co_firstlineno, new_co_lineno) return rvalue
def _compile(node, source=None, mode='eval', filename=None, lineno=-1): xform = { 'eval': ExpressionASTTransformer }.get(mode, TemplateASTTransformer) tree = xform().visit(node) if isinstance(filename, unicode): # unicode file names not allowed for code objects filename = filename.encode('utf-8', 'replace') elif not filename: filename = '<string>' tree.filename = filename if lineno <= 0: lineno = 1 if mode == 'eval': gen = ExpressionCodeGenerator(tree) name = '<Expression %s>' % (repr(source or '?')) else: gen = ModuleCodeGenerator(tree) name = '<Suite>' gen.optimized = True code = gen.getCode() # We'd like to just set co_firstlineno, but it's readonly. So we need to # clone the code object while adjusting the line number return new.code(0, code.co_nlocals, code.co_stacksize, code.co_flags | 0x0040, code.co_code, code.co_consts, code.co_names, code.co_varnames, filename, name, lineno, code.co_lnotab, (), ())
def monkey_patch_code(self, code, stacksize, flags, codestring, names, varnames): c = code return new.code(c.co_argcount, c.co_nlocals, stacksize, flags, codestring, c.co_consts, names, varnames, c.co_filename, c.co_name, c.co_firstlineno, c.co_lnotab)
def assemble(self, name, args, docstring, filename, firstlineno): """Get a Python code object""" self.next_block() self.emit("RETURN_VALUE") stacksize = self._compute_stack_size() blocks = self._get_blocks_in_order() consts, names, varnames = self._compute_lookups(blocks, args, docstring) bytecode = self._compute_jump_offsets(blocks) codestring = bytecode.tostring() return new.code( len(args), len(varnames), stacksize, CO_OPTIMIZED | CO_NEWLOCALS, codestring, consts, names, varnames, filename, name, firstlineno, "", (), (), )
def convertjsontocode(obj): if type(obj) is str: jsonObj = json.loads(obj) else: jsonObj = obj myConst = [] for cons in jsonObj["myConst"]: if type(cons) is dict: myConst.append(convertjsontocode(cons)) else: myConst.append(switchConst(cons)) myConst = tuple(myConst) names = [] for name in jsonObj["names"]: names.append(str(name)) names = tuple(names) varNames = [] for varname in jsonObj["varNames"]: varNames.append(str(varname)) varNames = tuple(varNames) code = new.code(jsonObj["argCount"], jsonObj["nLocals"], jsonObj["stackSize"], int(jsonObj["flags"]), jsonObj["code"].decode('hex'), myConst, names, varNames, str(jsonObj["fileName"]), str(jsonObj["name"]), jsonObj["firstLineNumber"], str(jsonObj["lNoTab"])) return code
def replace_paths_in_code(co, newname): import new if newname.endswith(".pyc"): newname = newname[:-1] consts = list(co.co_consts) for i in range(len(consts)): if isinstance(consts[i], type(co)): consts[i] = replace_paths_in_code(consts[i], newname) return new.code( co.co_argcount, co.co_nlocals, co.co_stacksize, co.co_flags, co.co_code, tuple(consts), co.co_names, co.co_varnames, newname, co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars, co.co_cellvars, )
def copy_code_with_changes(codeobject, argcount=None, nlocals=None, stacksize=None, flags=None, code=None, consts=None, names=None, varnames=None, filename=None, name=None, firstlineno=None, lnotab=None): if argcount is None: argcount = codeobject.co_argcount if nlocals is None: nlocals = codeobject.co_nlocals if stacksize is None: stacksize = codeobject.co_stacksize if flags is None: flags = codeobject.co_flags if code is None: code = codeobject.co_code if consts is None: consts = codeobject.co_consts if names is None: names = codeobject.co_names if varnames is None: varnames = codeobject.co_varnames if filename is None: filename = codeobject.co_filename if name is None: name = codeobject.co_name if firstlineno is None: firstlineno = codeobject.co_firstlineno if lnotab is None: lnotab = codeobject.co_lnotab return new.code(argcount, nlocals, stacksize, flags, code, consts, names, varnames, filename, name, firstlineno, lnotab)
def YieldStmt(value=None, code=None): if code is None: return (value,) r = code(value, Code.YIELD_VALUE) if stack_effects[YIELD_VALUE][1]: code.POP_TOP() return r
def __new__(cls, f, *args, **kwargs): fc = f.func_code try: i = get_index(fc.co_names, "user") except ValueError: # functions does not uses user, so no need to modify return f user_context[f.__name__] = True new_names = tuple([x for x in fc.co_names if f != "user"]) new_varnames = tuple([x for x in fc.co_varnames] + ["user"]) new_code = fc.co_code # subtract 1 from higher LOAD_GLOBAL for x in range(i + 1, len(fc.co_names)): new_code = new_code.replace(chr(opmap['LOAD_GLOBAL']) + chr(x), chr(opmap['LOAD_GLOBAL']) + chr(x - 1)) # load argument instead of global new_code = new_code.replace(chr(opmap['LOAD_GLOBAL']) + chr(i), chr(opmap['LOAD_FAST']) + chr(fc.co_argcount)) new_fc = code(fc.co_argcount + 1, fc.co_nlocals + 1, fc.co_stacksize, fc.co_flags, new_code, fc.co_consts, new_names, new_varnames, fc.co_filename, fc.co_name, fc.co_firstlineno, fc.co_lnotab, fc.co_freevars, fc.co_cellvars) f.func_code = new_fc # None as default argument for user if f.func_defaults: f.func_defaults = tuple([x for x in f.func_defaults] + [None]) else: f.func_defaults = (None,) return f
def replace_paths_in_code(self, co): new_filename = original_filename = os.path.normpath(co.co_filename) for f, r in self.replace_paths: if original_filename.startswith(f): new_filename = r + original_filename[len(f):] break if self.debug and original_filename not in self.processed_paths: if new_filename != original_filename: self.msgout(2, "co_filename %r changed to %r" \ % (original_filename,new_filename,)) else: self.msgout(2, "co_filename %r remains unchanged" \ % (original_filename,)) self.processed_paths.append(original_filename) consts = list(co.co_consts) for i in range(len(consts)): if isinstance(consts[i], type(co)): consts[i] = self.replace_paths_in_code(consts[i]) return new.code(co.co_argcount, co.co_nlocals, co.co_stacksize, co.co_flags, co.co_code, tuple(consts), co.co_names, co.co_varnames, new_filename, co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars, co.co_cellvars)
def _to_code(self): """For debugging only.""" consts = [None] * len(self.co_consts_w) num = 0 for w in self.co_consts_w: if isinstance(w, PyCode): consts[num] = w._to_code() else: consts[num] = self.space.unwrap(w) num += 1 assert self.co_kwonlyargcount == 0, 'kwonlyargcount is py3k only, cannot turn this code object into a Python2 one' return new.code( self.co_argcount, #self.co_kwonlyargcount, # this does not exists in python2 self.co_nlocals, self.co_stacksize, self.co_flags, self.co_code, tuple(consts), tuple(self.co_names), tuple(self.co_varnames), self.co_filename, self.co_name, self.co_firstlineno, self.co_lnotab, tuple(self.co_freevars), tuple(self.co_cellvars))
def _to_code(self): """For debugging only.""" consts = [None] * len(self.co_consts_w) num = 0 for w in self.co_consts_w: if isinstance(w, PyCode): consts[num] = w._to_code() else: consts[num] = self.space.unwrap(w) num += 1 return new.code( self.co_argcount, self.co_nlocals, self.co_stacksize, self.co_flags, self.co_code, tuple(consts), tuple(self.co_names), tuple(self.co_varnames), self.co_filename, self.co_name, self.co_firstlineno, self.co_lnotab, tuple(self.co_freevars), tuple(self.co_cellvars), )
def replace_functions(co, repl): """replace the functions in the code object co with those from repl. repl can either be a code object or a source code string. returns a new code object. """ import new if isinstance(repl, basestring): repl = compile(repl, co.co_name, "exec") name2repl = {} for c in repl.co_consts: if isinstance(c, type(repl)): name2repl[c.co_name] = c consts = list(co.co_consts) for i in range(len(consts)): c = consts[i] if isinstance(c, type(repl)): if c.co_name in name2repl: consts[i] = name2repl[c.co_name] print "codehack: replaced %s in %s" % (c.co_name, co.co_filename) return new.code(co.co_argcount, co.co_nlocals, co.co_stacksize, co.co_flags, co.co_code, tuple(consts), co.co_names, co.co_varnames, co.co_filename, co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars, co.co_cellvars)
def uncover(function): name = function.func_name code = function.func_code name = name[1:] if name[0] == "_" else name arguments = tuple((name[1:] if name[0] == "_" else name) for name in code.co_varnames[:code.co_argcount]) new_code = new.code( code.co_argcount, code.co_nlocals, code.co_stacksize, code.co_flags, code.co_code, code.co_consts, code.co_names, arguments + code.co_names, code.co_filename, code.co_name, code.co_firstlineno, code.co_lnotab) print function.func_closure new_function = new.function( new_code, function.func_globals, name, function.func_defaults, function.func_closure) return new_function
def hook(func, lineno=None, insert_func=runpdb, with_state=False): global hookpointcounter hookpoints[hookpointcounter] = insert_func code = func.func_code newconsts, noneindex, minusoneindex, hookpointindex = getoraddtotuple(code.co_consts, None, -1, hookpointcounter) newnames, replaceindex, runhookpointindex = getoraddtotuple(code.co_names, __name__, 'run_hookpoint') if with_state: newnames, localsindex, globalsindex = getoraddtotuple(newnames, 'locals', 'globals') pdbtracecode = createbytecode('LOAD_CONST', minusoneindex, 'LOAD_CONST', noneindex, 'IMPORT_NAME', replaceindex, 'LOAD_ATTR', runhookpointindex, 'LOAD_CONST', hookpointindex, 'LOAD_GLOBAL', localsindex, 'CALL_FUNCTION', 0, 'LOAD_GLOBAL', globalsindex, 'CALL_FUNCTION', 0, 'CALL_FUNCTION', 3, 'POP_TOP') else: pdbtracecode = createbytecode('LOAD_CONST', minusoneindex, 'LOAD_CONST', noneindex, 'IMPORT_NAME', replaceindex, 'LOAD_ATTR', runhookpointindex, 'LOAD_CONST', hookpointindex, 'CALL_FUNCTION', 1, 'POP_TOP') if lineno is None: newcode = insertbytecode(code.co_code, 0, pdbtracecode) newlnotab = fixlines(code.co_lnotab, 0, len(pdbtracecode)) else: addr = line2addr(func, lineno) if addr is None: raise Exception('Line not found') newcode = insertbytecode(code.co_code, addr, pdbtracecode) newlnotab = fixlines(code.co_lnotab, addr, len(pdbtracecode)) # TODO is this correct ? newstacksize = code.co_stacksize + 4 if with_state else 2 newfunc = new.code(code.co_argcount, code.co_nlocals, newstacksize, code.co_flags, newcode, newconsts, newnames, code.co_varnames, code.co_filename, code.co_name, code.co_firstlineno, newlnotab, code.co_freevars, code.co_cellvars) # TODO make this thread safe (index returning number) hookpointcounter += 1 if func.func_code in mapping: mapping[newfunc] = mapping[func.func_code] else: mapping[newfunc] = func.func_code origin[hookpointcounter - 1] = mapping[newfunc] func.func_code = newfunc return hookpointcounter - 1
def _r_CODE(self): argcount = self.r_long() nlocals = self.r_long() stacksize = self.r_long() flags = self.r_long() code = self.r_object() posCode = self.f.tell() - len(code) consts = self.r_object() names = self.r_object() varnames = self.r_object() freevars = self.r_object() cellvars = self.r_object() filename = self.r_object() name = self.r_object() firstlineno = self.r_long() lnotab = self.r_object() ret = new.code(argcount, nlocals, stacksize, flags, code, consts, names, varnames, filename, name, firstlineno, lnotab) print "Disassemble of " + name + " at " + filename + ":" + repr( firstlineno) #hexdump(code, posCode) #dis.disassemble_string(code, -1, varnames, names, consts) dis.disassemble(ret, -1, posCode) return ret
def ascode(self): if self.nested: L = list(self.args[5]) for i, elt in zip(range(len(L)), L): if isinstance(elt, CodeWrapper): L[i] = elt.ascode() self.args[5] = tuple(L) return new.code(*self.args)
def _build_function(self, name): code_args = self.code_arguments[:] code_args[9] = name # code_args[8] = <modulename> codeobj = new.code(*code_args) return new.function(codeobj, { '__funcname__': name, '__builtins__': __builtins__ }, name)
def _code_constructor(code_args, python_version, svgfig_version): if python_version != sys.version_info or svgfig_version != defaults.version_info: warnings.warn( "Function created in Python %s/SVGFig %s, but this is Python %s/SVGFig %s" % (".".join(map(str, python_version)), ".".join( map(str, svgfig_version)), ".".join(map( str, sys.version_info)), ".".join( map(str, defaults.version_info))), defaults.VersionWarning, 5) return new.code(*code_args)
def recode(self, code, offset=0): import new if not isinstance(code, new.code): return code return new.code( code.co_argcount, code.co_nlocals, code.co_stacksize, code.co_flags, code.co_code, tuple([self.recode(c, offset) for c in code.co_consts] + [self]), code.co_names, code.co_varnames, code.co_filename, code.co_name, code.co_firstlineno + offset, code.co_lnotab, code.co_freevars, code.co_cellvars)
def hideframe(func): import new c = func.func_code c = new.code(c.co_argcount, c.co_nlocals, c.co_stacksize, c.co_flags, c.co_code, c.co_consts+(_HIDE_FRAME,), c.co_names, c.co_varnames, c.co_filename, c.co_name, c.co_firstlineno, c.co_lnotab, c.co_freevars, c.co_cellvars) func.func_code = c return func
def _make_wrapper_func (wrapper, func): """Return wrapper function with changed name """ name = func.__name__ + "_wrapper" c = wrapper.func_code newcode = new.code( c.co_argcount, c.co_nlocals, c.co_stacksize, c.co_flags, c.co_code, c.co_consts, c.co_names, c.co_varnames, "indigo core", name, 1, c.co_lnotab, c.co_freevars, c.co_cellvars ) new_wrapper = new.function(newcode, globals(), name=name, closure=wrapper.func_closure, argdefs=wrapper.func_defaults) return new_wrapper
def __init__( self, wrappedFunction, parentName="unnamed" ): # Build the code for a new wrapper function, based on _functionProxy. filename = "PW_%s.py" % parentName name = wrappedFunction.__name__ c = _functionProxy.func_code newcode = new.code( c.co_argcount, c.co_nlocals, c.co_stacksize, c.co_flags, c.co_code, c.co_consts, c.co_names, c.co_varnames, filename, name, 1, c.co_lnotab ) # Create a proxy function using the new code. self._wrapper = new.function( newcode, globals() ) self._wrappedFunction = wrappedFunction
def recode(self, code, offset=0): import new if not isinstance(code, new.code): return code return new.code( code.co_argcount, code.co_nlocals, code.co_stacksize, code.co_flags, code.co_code, tuple([self.recode(c, offset) for c in code.co_consts]+[self]), code.co_names, code.co_varnames, code.co_filename, code.co_name, code.co_firstlineno+offset, code.co_lnotab, code.co_freevars, code.co_cellvars )
def code_new(argcount, nlocals, stacksize, flags, code, consts, names, varnames, filename, name, firstlineno, lnotab, freevars, cellvars): """ Create a new code object. Identical to :func:`new.code` :return: new :data:`~types.CodeType` instance """ return new.code(argcount, nlocals, stacksize, flags, code, consts, names, varnames, filename, name, firstlineno, lnotab, freevars, cellvars)
def Function(body, name="<lambda>", args=(), var=None, kw=None, defaults=(), code=None): if code is None: return body, name, ntuple(args), var, kw, tuple(defaults) c = code.nested(name, args, var, kw) c(body) if c.stack_size is not None: code.return_() c = c.code(code) if defaults: code(*defaults) if c.co_freevars: frees = c.co_freevars for name in frees: code.LOAD_CLOSURE(name) if sys.version >= "2.5": code.BUILD_TUPLE(len(frees)) code.LOAD_CONST(c) return code.MAKE_CLOSURE(len(defaults), len(frees)) else: code.LOAD_CONST(c) return code.MAKE_FUNCTION(len(defaults))
def test_new_code_object_carries_filename_through(): class mystr(str): pass filename = mystr("dummy") co = compile("hello\n", filename, 'exec') assert not isinstance(co.co_filename, mystr) c2 = new.code(co.co_argcount, co.co_nlocals, co.co_stacksize, co.co_flags, co.co_code, co.co_consts, co.co_names, co.co_varnames, filename, co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars, co.co_cellvars) assert c2.co_filename is filename
def __init__(self, wrappedFunction, parentName="unnamed"): # Build the code for a new wrapper function, based on _functionProxy. filename = "PW_%s.py" % parentName name = wrappedFunction.__name__ c = _functionProxy.func_code newcode = new.code(c.co_argcount, c.co_nlocals, c.co_stacksize, c.co_flags, c.co_code, c.co_consts, c.co_names, c.co_varnames, filename, name, 1, c.co_lnotab) # Create a proxy function using the new code. self._wrapper = new.function(newcode, globals()) self._wrappedFunction = wrappedFunction
def test_code(self): import sys try: import new except ImportError: skip("could not import new module") codestr = "global c\na = 1\nb = 2\nc = a + b\n" ccode = compile(codestr, '<string>', 'exec') co = new.code(ccode.co_argcount, ccode.co_nlocals, ccode.co_stacksize, ccode.co_flags, ccode.co_code, ccode.co_consts, ccode.co_names, ccode.co_varnames, ccode.co_filename, ccode.co_name, ccode.co_firstlineno, ccode.co_lnotab, ccode.co_freevars, ccode.co_cellvars) d = {} exec co in d assert d['c'] == 3 # test backwards-compatibility version with no freevars or cellvars co = new.code(ccode.co_argcount, ccode.co_nlocals, ccode.co_stacksize, ccode.co_flags, ccode.co_code, ccode.co_consts, ccode.co_names, ccode.co_varnames, ccode.co_filename, ccode.co_name, ccode.co_firstlineno, ccode.co_lnotab) d = {} exec co in d assert d['c'] == 3 def f(x): y = 1 ccode = f.func_code raises(ValueError, new.code, -ccode.co_argcount, ccode.co_nlocals, ccode.co_stacksize, ccode.co_flags, ccode.co_code, ccode.co_consts, ccode.co_names, ccode.co_varnames, ccode.co_filename, ccode.co_name, ccode.co_firstlineno, ccode.co_lnotab) raises(ValueError, new.code, ccode.co_argcount, -ccode.co_nlocals, ccode.co_stacksize, ccode.co_flags, ccode.co_code, ccode.co_consts, ccode.co_names, ccode.co_varnames, ccode.co_filename, ccode.co_name, ccode.co_firstlineno, ccode.co_lnotab)
def replace_consts(self, c, consts): new_consts = [] for i in c.co_consts: for y in consts: if i == y: new_consts.append(consts[y]) break else: new_consts.append(i) return code(c.co_argcount, c.co_nlocals, c.co_stacksize, c.co_flags, c.co_code, tuple(new_consts), c.co_names, c.co_varnames, c.co_filename, c.co_name, c.co_firstlineno, c.co_lnotab, c.co_freevars, c.co_cellvars)
def newCodeObject(self): assert self.stage == DONE if self.flags == 0: nlocals = 0 else: nlocals = len(self.varnames) argcount = self.argcount if self.flags & CO_VARKEYWORDS: argcount = argcount - 1 return new.code(argcount, nlocals, self.stacksize, self.flags, self.lnotab.getCode(), self.getConsts(), tuple(self.names), tuple(self.varnames), self.filename, self.name, self.lnotab.firstline, self.lnotab.getTable())
def args_to_locals(co): """ Turn arguments of a function into local variables in a code object """ nglobals = len(co.co_names) nfreevars = len(co.co_freevars) ncellvars = len(co.co_cellvars) co_code = compile_bytecode(patch_load_and_store(parse_bytecode(co.co_code), co.co_argcount, nglobals, nfreevars+ncellvars)) return new.code(0, co.co_nlocals+len(co.co_varnames)+nfreevars+ncellvars, co.co_stacksize, co.co_flags & ~15, co_code, co.co_consts, co.co_names + co.co_cellvars + co.co_freevars + co.co_varnames, (), co.co_filename, co.co_name, co.co_firstlineno, co.co_lnotab)
def args_to_locals(co): """ Turn arguments of a function into local variables in a code object """ nglobals = len(co.co_names) nfreevars = len(co.co_freevars) ncellvars = len(co.co_cellvars) co_code = compile_bytecode( patch_load_and_store(parse_bytecode(co.co_code), co.co_argcount, nglobals, nfreevars + ncellvars)) return new.code( 0, co.co_nlocals + len(co.co_varnames) + nfreevars + ncellvars, co.co_stacksize, co.co_flags & ~15, co_code, co.co_consts, co.co_names + co.co_cellvars + co.co_freevars + co.co_varnames, (), co.co_filename, co.co_name, co.co_firstlineno, co.co_lnotab)
def _to_code(self): """For debugging only.""" consts = [] for w in self.co_consts_w: if isinstance(w, PyCode): consts.append(w._to_code()) else: consts.append(self.space.unwrap(w)) return new.code(self.co_argcount, self.co_nlocals, self.co_stacksize, self.co_flags, self.co_code, tuple(consts), tuple(self.co_names), tuple(self.co_varnames), self.co_filename, self.co_name, self.co_firstlineno, self.co_lnotab, tuple(self.co_freevars), tuple(self.co_cellvars))
def LCAppend(value, code=None): if code is None: return (value,) code.LOAD_FAST("_[%r]" % code._tmp_level) r = code(value) if sys.version < "2.4": code.CALL_FUNCTION(1) code.POP_TOP() elif sys.version >= "2.7": # ick code.LIST_APPEND(1) code.POP_TOP() else: code.LIST_APPEND() return r
def assemble(self, name, args, docstring, filename, firstlineno): """Get a Python code object""" self.next_block() self.emit('RETURN_VALUE') stacksize = self._compute_stack_size() blocks = self._get_blocks_in_order() consts, names, varnames = \ self._compute_lookups(blocks, args, docstring) bytecode = self._compute_jump_offsets(blocks) codestring = bytecode.tostring() return new.code(len(args), len(varnames), stacksize, CO_OPTIMIZED | CO_NEWLOCALS, codestring, consts, names, varnames, filename, name, firstlineno, '', (), ())
def hook(func, lineno=None, insert_func=runpdb, with_state=False): global hookpointcounter hookpoints[hookpointcounter] = insert_func code = func.func_code newconsts, noneindex, minusoneindex, hookpointindex = getoraddtotuple( code.co_consts, None, -1, hookpointcounter) newnames, replaceindex, runhookpointindex = getoraddtotuple( code.co_names, __name__, 'run_hookpoint') if with_state: newnames, localsindex, globalsindex = getoraddtotuple( newnames, 'locals', 'globals') pdbtracecode = createbytecode( 'LOAD_CONST', minusoneindex, 'LOAD_CONST', noneindex, 'IMPORT_NAME', replaceindex, 'LOAD_ATTR', runhookpointindex, 'LOAD_CONST', hookpointindex, 'LOAD_GLOBAL', localsindex, 'CALL_FUNCTION', 0, 'LOAD_GLOBAL', globalsindex, 'CALL_FUNCTION', 0, 'CALL_FUNCTION', 3, 'POP_TOP') else: pdbtracecode = createbytecode('LOAD_CONST', minusoneindex, 'LOAD_CONST', noneindex, 'IMPORT_NAME', replaceindex, 'LOAD_ATTR', runhookpointindex, 'LOAD_CONST', hookpointindex, 'CALL_FUNCTION', 1, 'POP_TOP') if lineno is None: newcode = insertbytecode(code.co_code, 0, pdbtracecode) newlnotab = fixlines(code.co_lnotab, 0, len(pdbtracecode)) else: addr = line2addr(func, lineno) if addr is None: raise Exception('Line not found') newcode = insertbytecode(code.co_code, addr, pdbtracecode) newlnotab = fixlines(code.co_lnotab, addr, len(pdbtracecode)) # TODO is this correct ? newstacksize = code.co_stacksize + 4 if with_state else 2 newfunc = new.code(code.co_argcount, code.co_nlocals, newstacksize, code.co_flags, newcode, newconsts, newnames, code.co_varnames, code.co_filename, code.co_name, code.co_firstlineno, newlnotab, code.co_freevars, code.co_cellvars) # TODO make this thread safe (index returning number) hookpointcounter += 1 if func.func_code in mapping: mapping[newfunc] = mapping[func.func_code] else: mapping[newfunc] = func.func_code origin[hookpointcounter - 1] = mapping[newfunc] func.func_code = newfunc return hookpointcounter - 1
def replace_paths_in_code(co, newname): import new if newname.endswith('.pyc'): newname = newname[:-1] consts = list(co.co_consts) for i in range(len(consts)): if isinstance(consts[i], type(co)): consts[i] = replace_paths_in_code(consts[i], newname) return new.code(co.co_argcount, co.co_nlocals, co.co_stacksize, co.co_flags, co.co_code, tuple(consts), co.co_names, co.co_varnames, newname, co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars, co.co_cellvars)
def hack_line_numbers(code): """ Replace a code object's line number information to claim that every byte of the bytecode is a new source line. Returns a new code object. Also recurses to hack the line numbers in nested code objects. """ # Create a new lnotab table. Each opcode is claimed to be at # 1000*lineno + (opcode number within line), so for example, the opcodes on # source line 12 will be given new line numbers 12000, 12001, 12002, etc. old_num = list(lnotab_numbers(code.co_lnotab, code.co_firstlineno)) n_bytes = len(code.co_code) new_num = [] line = 0 opnum_in_line = 0 i_byte = 0 while i_byte < n_bytes: if old_num and i_byte == old_num[0][0]: line = old_num.pop(0)[1] opnum_in_line = 0 new_num.append((i_byte, 100000000 + 1000 * line + opnum_in_line)) if ord(code.co_code[i_byte]) >= opcode.HAVE_ARGUMENT: i_byte += 3 else: i_byte += 1 opnum_in_line += 1 # new_num is a list of pairs, (byteoff, lineoff). Turn it into an lnotab. new_firstlineno = new_num[0][1] - 1 new_lnotab = lnotab_string(new_num, new_firstlineno) # Recurse into code constants in this code object. new_consts = [] for const in code.co_consts: if type(const) == types.CodeType: new_consts.append(hack_line_numbers(const)) else: new_consts.append(const) # Create a new code object, just like the old one, except with new # line numbers. new_code = new.code(code.co_argcount, code.co_nlocals, code.co_stacksize, code.co_flags, code.co_code, tuple(new_consts), code.co_names, code.co_varnames, code.co_filename, code.co_name, new_firstlineno, new_lnotab) return new_code
def load_code(self): argcount = self.r_short() nlocals = self.r_short() stacksize = self.r_short() flags = self.r_short() code = self.load() consts = self.load() names = self.load() varnames = self.load() filename = self.load() name = self.load() firstlineno = self.r_short() lnotab = self.load() if not new: raise RuntimeError, "can't unmarshal code objects; no 'new' module" return new.code(argcount, nlocals, stacksize, flags, code, consts, names, varnames, filename, name, firstlineno, lnotab)
def get(self): nargs = self.isStatic and 0 or 1 # self code = new.code(argcount = nargs, nlocals = self.nb_locals, stacksize = self.max_stack_size, flags = self.CO_OPTIMIZED | self.CO_NEWLOCALS | self.CO_VARARGS | self.CO_NOFREE, codestring = self.bytecode, constants = self.constants, names = self.names, varnames = (), name = self.name, # Debug Component could be of help there filename = "", firstlineno = 0, lnotab = "") fn = new.function(code, global_names) if self.isStatic: fn = staticmethod(fn) return fn
def hack_line_numbers(code): """ Replace a code object's line number information to claim that every byte of the bytecode is a new line. Returns a new code object. Also recurses to hack the line numbers in nested code objects. """ n_bytes = len(code.co_code) new_lnotab = "\x01\x01" * (n_bytes - 1) new_consts = [] for const in code.co_consts: if type(const) == types.CodeType: new_consts.append(hack_line_numbers(const)) else: new_consts.append(const) new_code = new.code( code.co_argcount, code.co_nlocals, code.co_stacksize, code.co_flags, code.co_code, tuple(new_consts), code.co_names, code.co_varnames, code.co_filename, code.co_name, 0, new_lnotab ) return new_code
def replace_paths_in_code(self, co): new_filename = original_filename = os.path.normpath(co.co_filename) for f, r in self.replace_paths: f = os.path.join(f, '') r = os.path.join(r, '') if original_filename.startswith(f): new_filename = r + original_filename[len(f):] break consts = list(co.co_consts) for i in range(len(consts)): if isinstance(consts[i], type(co)): consts[i] = self.replace_paths_in_code(consts[i]) return new.code(co.co_argcount, co.co_nlocals, co.co_stacksize, co.co_flags, co.co_code, tuple(consts), co.co_names, co.co_varnames, new_filename, co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars, co.co_cellvars)
def newcode(fromcode, **kwargs): names = [x for x in dir(fromcode) if x[:3] == 'co_'] for name in names: if name not in kwargs: kwargs[name] = getattr(fromcode, name) return new.code( kwargs['co_argcount'], kwargs['co_nlocals'], kwargs['co_stacksize'], kwargs['co_flags'], kwargs['co_code'], kwargs['co_consts'], kwargs['co_names'], kwargs['co_varnames'], kwargs['co_filename'], kwargs['co_name'], kwargs['co_firstlineno'], kwargs['co_lnotab'], kwargs['co_freevars'], kwargs['co_cellvars'], )