def trace_code(self, source, module_name=None): builder = ReportBuilder(self.message_limit) builder.max_width = self.max_width try: tree = parse(source) new_tree = Tracer().visit(tree) fix_missing_locations(new_tree) LineNumberCleaner().visit(new_tree) # from ast import dump # print(dump(new_tree, include_attributes=False)) code = compile(new_tree, PSEUDO_FILENAME, 'exec') self.environment[CONTEXT_NAME] = builder if module_name is None: environment = self.environment else: mod = types.ModuleType(module_name) sys.modules[module_name] = mod # Any reason to set mod.__file__? mod.__dict__.update(self.environment) environment = mod.__dict__ exec(code, environment) for value in environment.values(): if isinstance(value, types.GeneratorType): value.close() except SyntaxError: ex = sys.exc_info()[1] messages = traceback.format_exception_only(type(ex), ex) builder.add_message(messages[-1].strip() + ' ', ex.lineno) except: etype, value, tb = sys.exc_info() is_reported = False builder.message_limit = None # make sure we don't hit limit builder.max_width = None # make sure we don't hit limit messages = traceback.format_exception_only(etype, value) message = messages[-1].strip() + ' ' entries = traceback.extract_tb(tb) for filename, line_number, _, _ in entries: if filename == PSEUDO_FILENAME: builder.add_extra_message(message, line_number) is_reported = True if not is_reported: builder.add_message(message, 1) # print('=== Unexpected Exception in tracing code ===') # traceback.print_exception(etype, value, tb) return builder.report()
def trace_code(self, source): builder = ReportBuilder(self.message_limit) builder.max_width = self.max_width try: tree = parse(source) visitor = TraceAssignments() new_tree = visitor.visit(tree) fix_missing_locations(new_tree) # from ast import dump # print(dump(new_tree, include_attributes=False)) code = compile(new_tree, PSEUDO_FILENAME, 'exec') self.environment[CONTEXT_NAME] = builder exec(code, self.environment, self.environment) except SyntaxError: ex = sys.exc_info()[1] messages = traceback.format_exception_only(type(ex), ex) builder.add_message(messages[-1].strip() + ' ', ex.lineno) except: etype, value, tb = sys.exc_info() is_reported = False builder.message_limit = None # make sure we don't hit limit builder.max_width = None # make sure we don't hit limit messages = traceback.format_exception_only(etype, value) message = messages[-1].strip() + ' ' entries = traceback.extract_tb(tb) for filename, line_number, _, _ in entries: if filename == PSEUDO_FILENAME: builder.add_extra_message(message, line_number) is_reported = True if not is_reported: builder.add_message(message, 1) # print('=== Unexpected Exception in tracing code ===') # traceback.print_exception(etype, value, tb) return builder.report()
def trace_code(self, source): builder = ReportBuilder(self.message_limit) builder.max_width = self.max_width try: tree = parse(source) visitor = TraceAssignments() new_tree = visitor.visit(tree) fix_missing_locations(new_tree) # from ast import dump # print(dump(new_tree, include_attributes=False)) code = compile(new_tree, PSEUDO_FILENAME, 'exec') self.environment[CONTEXT_NAME] = builder exec(code, self.environment, self.environment) except SyntaxError: ex = sys.exc_info()[1] messages = traceback.format_exception_only(type(ex), ex) builder.add_message(messages[-1].strip() + ' ', ex.lineno) except: etype, value, tb = sys.exc_info() is_reported = False builder.message_limit = None # make sure we don't hit limit builder.max_width = None # make sure we don't hit limit messages = traceback.format_exception_only(etype, value) message = messages[-1].strip() + ' ' entries = traceback.extract_tb(tb) for filename, line_number, _, _ in entries: if filename == PSEUDO_FILENAME: builder.add_extra_message(message, line_number) is_reported = True if not is_reported: builder.add_message(message, 1) # print('=== Unexpected Exception in tracing code ===') # traceback.print_exception(etype, value, tb) return builder.report()
def trace_code(self, source, load_as=SCOPE_NAME, is_module=False, dump=False, driver=None, filename=None, bad_driver=None): """ Trace a module of source code, possibly by running a driver script. :param str source: the source code to trace :param str load_as: the module name to load the source code as :param bool is_module: True if the driver is a module name instead of a file name :param bool dump: True if the source code should be included in the output :param list driver: the driver script's file name or module name and args :param str filename: the file name of the source code :param str bad_driver: a message to display if the driver doesn't call the module """ builder = ReportBuilder(self.message_limit) builder.max_width = self.max_width self.return_code = 0 try: tree = parse(source, PSEUDO_FILENAME) new_tree = Tracer().visit(tree) fix_missing_locations(new_tree) LineNumberCleaner().visit(new_tree) # from ast import dump # print(dump(new_tree, include_attributes=True)) code = compile(new_tree, PSEUDO_FILENAME, 'exec') # Set sys.argv properly. old_argv = sys.argv sys.argv = driver or [filename or load_as] try: self.run_code(code, builder, load_as, is_module, driver, filename, bad_driver) finally: # Restore the old argv and path sys.argv = old_argv # During testing, we import these modules for every test case, # so force a reload. This is only likely to happen during testing. for target in (load_as, SCOPE_NAME): if target in sys.modules: del sys.modules[target] for i in reversed(range(len(sys.meta_path))): if isinstance(sys.meta_path[i], TracedModuleImporter): sys.meta_path.pop(i) for value in self.environment.values(): if isinstance(value, types.GeneratorType): value.close() except SyntaxError: self.return_code = 1 ex = sys.exc_info()[1] messages = traceback.format_exception_only(type(ex), ex) message = messages[-1].strip() if ex.filename == PSEUDO_FILENAME: line_number = ex.lineno else: line_number = 1 message = '{} line {}: {}'.format(ex.filename, ex.lineno, message) builder.add_message(message, line_number) except BaseException as ex: self.return_code = getattr(ex, 'code', 1) etype, value, tb = sys.exc_info() is_reported = False entries = traceback.extract_tb(tb) for filename, _, _, _ in entries: if filename == PSEUDO_FILENAME: is_reported = True while not is_reported and tb is not None: frame = tb.tb_frame code = frame.f_code filename = code.co_filename if __file__ not in (filename, filename + 'c'): break tb = tb.tb_next if not is_reported: if tb: messages = traceback.format_exception(etype, value, tb) else: messages = traceback.format_exception_only(etype, value) self.report_driver_result(builder, messages) report = builder.report(source.count('\n')) if dump: source_lines = source.splitlines() report_lines = report.splitlines() dump_lines = [] source_width = max(map(len, source_lines)) indent = 4 for source_line, report_line in izip_longest(source_lines, report_lines, fillvalue=''): line = (indent * ' ' + source_line + (source_width - len(source_line)) * ' ' + ' | ' + report_line) dump_lines.append(line) report = '\n'.join(dump_lines) return report
def trace_code(self, source, load_as=None, module=None, dump=False, driver=None, filename=None): builder = ReportBuilder(self.message_limit) builder.max_width = self.max_width try: tree = parse(source) new_tree = Tracer().visit(tree) fix_missing_locations(new_tree) LineNumberCleaner().visit(new_tree) # from ast import dump # print(dump(new_tree, include_attributes=False)) code = compile(new_tree, PSEUDO_FILENAME, 'exec') self.environment[CONTEXT_NAME] = builder self.run_instrumented_module(code, load_as or SCOPE_NAME, filename) if driver: try: with self.swallow_output(): if module: self.run_python_module(driver[0], driver) else: self.run_python_file(driver[0], driver) except: if not (builder.message_count or builder.history): raise for value in self.environment.values(): if isinstance(value, types.GeneratorType): value.close() except SyntaxError: ex = sys.exc_info()[1] messages = traceback.format_exception_only(type(ex), ex) builder.add_message(messages[-1].strip() + ' ', ex.lineno) except: etype, value, tb = sys.exc_info() is_reported = False builder.message_limit = None # make sure we don't hit limit builder.max_width = None # make sure we don't hit limit messages = traceback.format_exception_only(etype, value) message = messages[-1].strip() + ' ' entries = traceback.extract_tb(tb) for filename, line_number, _, _ in entries: if filename == PSEUDO_FILENAME: builder.add_extra_message(message, line_number) is_reported = True if not is_reported: builder.add_message(message, 1) # print('=== Unexpected Exception in tracing code ===') # traceback.print_exception(etype, value, tb) report = builder.report() if dump: source_lines = source.splitlines() report_lines = report.splitlines() dump_lines = [] source_width = max(map(len, source_lines)) indent = 4 for source_line, report_line in izip_longest(source_lines, report_lines, fillvalue=''): line = (indent * ' ' + source_line + (source_width-len(source_line))*' ' + ' | ' + report_line) dump_lines.append(line) report = '\n'.join(dump_lines) return report
def trace_code(self, source, load_as=None, module=False, dump=False, driver=None, filename=None): """ Trace a module of source code, possibly by running a driver script. :param str source: the source code to trace :param str load_as: the module name to load the source code as :param bool module: True if the driver is a module name instead of a file name :param bool dump: True if the source code should be included in the output :param str driver: the driver script's file name or module name :param str filename: the file name of the source code """ builder = ReportBuilder(self.message_limit) builder.max_width = self.max_width self.return_code = 0 try: tree = parse(source) new_tree = Tracer().visit(tree) fix_missing_locations(new_tree) LineNumberCleaner().visit(new_tree) # from ast import dump # print(dump(new_tree, include_attributes=False)) code = compile(new_tree, PSEUDO_FILENAME, 'exec') self.environment[CONTEXT_NAME] = builder is_own_driver = module and driver and driver[0] == load_as seed(0) self.run_instrumented_module(code, load_as, filename, is_own_driver) if driver and not is_own_driver: with self.swallow_output(): if not module: self.run_python_file(driver[0], driver) else: module_name = driver[0] try: self.run_python_module(module_name, driver) except SystemExit as ex: if ex.code: if module_name not in ('unittest', 'pytest'): raise self.return_code = ex.code result = (sys.stderr.last_line or 'FAIL ') result = module_name + ': ' + result self.report_driver_result(builder, [result]) for value in self.environment.values(): if isinstance(value, types.GeneratorType): value.close() except SyntaxError: self.return_code = 1 ex = sys.exc_info()[1] messages = traceback.format_exception_only(type(ex), ex) builder.add_message(messages[-1].strip() + ' ', ex.lineno) except BaseException as ex: self.return_code = getattr(ex, 'code', 1) etype, value, tb = sys.exc_info() is_reported = False messages = traceback.format_exception_only(etype, value) entries = traceback.extract_tb(tb) for filename, _, _, _ in entries: if filename == PSEUDO_FILENAME: is_reported = True while not is_reported and tb is not None: frame = tb.tb_frame code = frame.f_code filename = code.co_filename if __file__ not in (filename, filename + 'c'): break tb = tb.tb_next if not is_reported: if tb: messages = traceback.format_exception(etype, value, tb) else: messages = traceback.format_exception_only(etype, value) self.report_driver_result(builder, messages) report = builder.report(source.count('\n')) if dump: source_lines = source.splitlines() report_lines = report.splitlines() dump_lines = [] source_width = max(map(len, source_lines)) indent = 4 for source_line, report_line in izip_longest(source_lines, report_lines, fillvalue=''): line = (indent * ' ' + source_line + (source_width - len(source_line)) * ' ' + ' | ' + report_line) dump_lines.append(line) report = '\n'.join(dump_lines) return report
def trace_code(self, source, load_as=None, module=None, dump=False, driver=None, filename=None): builder = ReportBuilder(self.message_limit) builder.max_width = self.max_width try: tree = parse(source) new_tree = Tracer().visit(tree) fix_missing_locations(new_tree) LineNumberCleaner().visit(new_tree) # from ast import dump # print(dump(new_tree, include_attributes=False)) code = compile(new_tree, PSEUDO_FILENAME, 'exec') self.environment[CONTEXT_NAME] = builder self.run_instrumented_module(code, load_as or SCOPE_NAME, filename) if driver: with self.swallow_output(): if module: module_name = driver[0] try: self.run_python_module(module_name, driver) except SystemExit as ex: if module_name != 'unittest': raise result = (sys.stderr.last_line or ex.code and 'FAIL ' or 'OK') result = 'unittest: ' + result self.report_driver_result(builder, [result]) else: self.run_python_file(driver[0], driver) for value in self.environment.values(): if isinstance(value, types.GeneratorType): value.close() except SyntaxError: ex = sys.exc_info()[1] messages = traceback.format_exception_only(type(ex), ex) builder.add_message(messages[-1].strip() + ' ', ex.lineno) except: etype, value, tb = sys.exc_info() is_reported = False builder.message_limit = None # make sure we don't hit limit builder.max_width = None # make sure we don't hit limit messages = traceback.format_exception_only(etype, value) entries = traceback.extract_tb(tb) for filename, _, _, _ in entries: if filename == PSEUDO_FILENAME: is_reported = True while not is_reported and tb is not None: frame = tb.tb_frame code = frame.f_code filename = code.co_filename if __file__ not in (filename, filename + 'c'): break tb = tb.tb_next if not is_reported: if tb: messages = traceback.format_exception(etype, value, tb) else: messages = traceback.format_exception_only(etype, value) self.report_driver_result(builder, messages) report = builder.report() if dump: source_lines = source.splitlines() report_lines = report.splitlines() dump_lines = [] source_width = max(map(len, source_lines)) indent = 4 for source_line, report_line in izip_longest(source_lines, report_lines, fillvalue=''): line = (indent * ' ' + source_line + (source_width-len(source_line))*' ' + ' | ' + report_line) dump_lines.append(line) report = '\n'.join(dump_lines) return report
def trace_code(self, source, global_context=dict(), local_context=dict(), dump=False): """ Trace a module of source code, possibly by running a driver script. :param str source: the source code to trace :param global_context: the context the code is executed in (globals) :param local_context: the local context the code is executed in (locals) :param bool dump: True if the source code should be included in the output """ builder = ReportBuilder(self.message_limit) builder.max_width = self.max_width self.report_builder = builder self.return_code = 0 try: # Parse the original AST tree = parse(source, PSEUDO_FILENAME) # Modify the tree to add the insert statements new_tree = Tracer().visit(tree) fix_missing_locations(new_tree) LineNumberCleaner().visit(new_tree) # from ast import dump # print(dump(new_tree, include_attributes=True)) code = compile(new_tree, PSEUDO_FILENAME, 'exec') # RUN CODE self.environment[CONTEXT_NAME] = builder # Make a copy of globals so as not to mutate global_context_copy = dict(global_context.items()) global_context_copy[CONTEXT_NAME] = builder seed(0) with swallow_output(): # ret_val = eval(code, context_copy) exec(code, global_context_copy, local_context) for value in self.environment.values(): if isinstance(value, types.GeneratorType): value.close() except SyntaxError: self.return_code = 1 ex = sys.exc_info()[1] messages = traceback.format_exception_only(type(ex), ex) message = messages[-1].strip() if ex.filename == PSEUDO_FILENAME: line_number = ex.lineno else: line_number = 1 message = '{} line {}: {}'.format(ex.filename, ex.lineno, message) builder.add_message(message, line_number) except BaseException as ex: self.return_code = getattr(ex, 'code', 1) etype, value, tb = sys.exc_info() is_reported = False entries = traceback.extract_tb(tb) for filename, _, _, _ in entries: if filename == PSEUDO_FILENAME: is_reported = True while not is_reported and tb is not None: frame = tb.tb_frame code = frame.f_code filename = code.co_filename if __file__ not in (filename, filename + 'c'): break tb = tb.tb_next if not is_reported: if tb: messages = traceback.format_exception(etype, value, tb) else: messages = traceback.format_exception_only(etype, value) self.report_driver_result(builder, messages) report = builder.report(source.count('\n')) if dump: source_lines = source.splitlines() report_lines = report.splitlines() dump_lines = [] source_width = max(map(len, source_lines)) indent = 4 for source_line, report_line in izip_longest(source_lines, report_lines, fillvalue=''): line = (indent * ' ' + source_line + (source_width - len(source_line)) * ' ' + ' | ' + report_line) dump_lines.append(line) report = '\n'.join(dump_lines) return report