def walk_all_methods(pf, class_object): ''' ''' for func in dir(class_object): try: try: #we get each method from source, deindent it, and then parse it source_lines = inspect.getsourcelines( getattr(class_object, func))[0] indent = len(source_lines[0]) - len(source_lines[0].lstrip()) source_lines = [line[indent:] for line in source_lines] ast_tree = ast.parse(''.join(source_lines)) except IOError: print( 'Module source code not found: ({}, {}). Decompiling instead.' .format(class_object, func)) try: ast_tree = meta.decompile( getattr(class_object, func).__code__) except AssertionError: print 'meta failed to decompile function {} in class {}. Some parameters may be missing from the generated file.'.format( func, class_object.__name__) continue except NameError: print 'meta is not installed. Parameters may be missing from the generated file.' except TypeError: continue pf.visit(ast_tree) except AttributeError: continue
def decompile(code, version="2.7"): import meta from uncompyle2 import uncompyle try: source = StringIO.StringIO() uncompyle(version, code, source) source = source.getvalue() except: try: code_obj = meta.decompile(code) source = meta.dump_python_source(code_obj) except: return None return source.lstrip(' \n')
def instrument(fcn): def makeyield(x): out = ast.Expr(ast.Yield(ast.Num(x))) out.lineno, out.col_offset = 1, 0 out.value.lineno, out.value.col_offset = 1, 0 out.value.value.lineno, out.value.value.col_offset = 1, 0 return out text = [] def statement(node): if isinstance(node, list): out = [] for x in node: t = ("\n" + meta.dump_python_source(x).strip()).replace("\n", "\n ") out.append(makeyield(len(text))) text.append(t) out.append(statement(x)) node = out elif isinstance(node, ast.Module): node.body = statement(node.body) elif isinstance(node, (ast.ClassDef, ast.Exec, ast.FunctionDef, ast.Import, ast.Return)): raise SyntaxError("{0} statements are not allowed".format(node.__class__.__text__)) elif isinstance(node, ast.Expr): node.value = expression(node.value) elif isinstance(node, ast.Assert): node.test = expression(node.test) elif isinstance(node, ast.Assign): node.targets = [expression(x) for x in node.targets] node.value = expression(node.value) elif isinstance(node, ast.AugAssign): node.target = expression(node.target) node.value = expression(node.value) elif isinstance(node, ast.Delete): node.targets = [expression(x) for x in node.targets] elif isinstance(node, ast.ExceptHandler): node.body = statement(node.body) elif isinstance(node, ast.For): node.iter = expression(node.iter) node.body = statement(node.body) node.orelse = statement(node.orelse) elif isinstance(node, ast.If): node.test = expression(node.test) node.body = statement(node.body) node.orelse = statement(node.orelse) elif isinstance(node, ast.Print): node.values = expression(node.values) elif isinstance(node, ast.TryExcept): node.body = statement(node.body) node.orelse = statement(node.orelse) elif isinstance(node, ast.TryFinally): node.body = statement(node.body) node.finalbody = statement(node.finalbody) elif isinstance(node, ast.Try): node.body = statement(node.body) node.orelse = statement(node.orelse) node.finalbody = statement(node.finalbody) elif isinstance(node, ast.While): node.test = expression(node.test) node.body = statement(node.body) node.orelse = statement(node.orelse) elif isinstance(node, ast.With): node.body = statement(node.body) if hasattr(node, "items"): for x in node.items: x.context_expr = expression(x.context_expr) else: node.context_expr = expression(node.context_expr) return node def expression(node): if isinstance(node, list): node = [expression(x) for x in node] elif isinstance(node, (ast.DictComp, ast.GeneratorExp, ast.IfExp, ast.Lambda, ast.ListComp, ast.SetComp, ast.Yield)): raise SyntaxError("{0} expressions are not allowed".format(node.__class__.__text__)) elif isinstance(node, ast.AST): for n in node._fields: setattr(node, n, expression(getattr(node, n))) return node code = fcn.__code__ shellfcn = ast.parse("def fcn({0}): pass".format(", ".join(code.co_varnames[:code.co_argcount]))).body[0] shellfcn.body = statement(meta.decompile(code)).body shellfcn.body.append(makeyield(len(text))) instrumented = callexec(compile(ast.Module([shellfcn]), "<vectorized>", "exec"), "fcn").__code__ return len(text), text, types.FunctionType(instrumented, fcn.__globals__, fcn.__name__, fcn.__defaults__, fcn.__closure__)
def pyc_source(pyc_contents): code_section = pyc_contents[8:] code = marshal.load(code_section) return meta.dump_python_source(meta.decompile(code))