def rewrite(self, fn: FunctionType) -> Tuple[FunctionType, Set[Type[Exception]]]: # Normalize the source lines sourcelines, _ = inspect.getsourcelines(fn) sourcelines = normalize_source_lines(sourcelines) source = "".join(sourcelines) normalized_str = textwrap.dedent(source) # Rewrite the original AST source_ast = ast.parse(normalized_str) dest_ast = ast.fix_missing_locations(self.visit(source_ast)) # Pull out the compiled function from the newly-created Module code = compile(dest_ast, "", "exec") globals_dict = copy.copy(fn.__globals__) keys_before = set(globals_dict.keys()) exec(code, globals_dict) new_keys = list(set(globals_dict.keys()) - keys_before) assert len(new_keys) <= 1 fn_compiled = globals_dict[fn.__name__] # Return the correct FunctionType object and the Exceptions that were # rewritten during visit_If. return fn_compiled, self.exceptions_rewritten
def rewrite(self, fn: FunctionType): # Normalize the source lines sourcelines, _ = inspect.getsourcelines(fn) sourcelines = normalize_source_lines(sourcelines) source = ''.join(sourcelines) normalized_str = textwrap.dedent(source) # Rewrite the original AST source_ast = ast.parse(normalized_str) dest_ast = ast.fix_missing_locations(self.visit(source_ast)) # Pull out the compiled fucntion from the newly-created Module code = compile(dest_ast, "", "exec") globals_dict = copy.copy(fn.__globals__) keys_before = set(globals_dict.keys()) exec(code, globals_dict) new_keys = list(set(globals_dict.keys()) - keys_before) assert len(new_keys) == 1 fn_compiled = globals_dict[new_keys[0]] # return the compiled function with the original globals def change_func_globals(f, globals): """Based on https://stackoverflow.com/a/13503277/2988730 (@unutbu)""" # __globals__ is a private member of the function class # so we have to copy the function, f, all of its member, except f.__globals__ g = FunctionType( f.__code__, globals, name=f.__name__, argdefs=f.__defaults__, closure=f.__closure__, ) g = functools.update_wrapper(g, f) g.__kwdefaults__ = copy.copy(f.__kwdefaults__) return g # Return the correct FunctionType object return change_func_globals(fn_compiled, globals=fn.__globals__)
def rewrite(self, fn: FunctionType): # Normalize the source lines sourcelines, _ = inspect.getsourcelines(fn) sourcelines = normalize_source_lines(sourcelines) source = ''.join(sourcelines) normalized_str = textwrap.dedent(source) # Rewrite the original AST source_ast = ast.parse(normalized_str) dest_ast = ast.fix_missing_locations(self.visit(source_ast)) # Pull out the compiled fucntion from the newly-created Module code = compile(dest_ast, "", "exec") globals_dict = copy.copy(fn.__globals__) keys_before = set(globals_dict.keys()) exec(code, globals_dict) new_keys = list(set(globals_dict.keys()) - keys_before) assert len(new_keys) == 1 fn_compiled = globals_dict[new_keys[0]] # Return the correct FunctionType object return fn_compiled