def test_report(self): source = """\ import example_printing __live_coding_context__ = globals()['report_builder'] # variable name is important! example_printing.custom_print('42', 'xyz') """ expected_report_python2 = """\ print '42xyz' """ expected_report_python3 = """\ print('42xyz') """ expected_report = (expected_report_python3 if version_info.major >= 3 else expected_report_python2) report_builder = ReportBuilder() environment = dict(report_builder=report_builder) swallower = FileSwallower(sys.stdout) with patch('sys.stdout', swallower): exec(source, environment, environment) report = report_builder.report() self.assertReportEqual(expected_report, report)
def test_assign_function(self): # SETUP expected_report = '' f = lambda n: n + 1 # EXEC builder = ReportBuilder() builder.assign(name='f', value=f, line_number=2) report = builder.report() # VERIFY self.assertEqual(expected_report.splitlines(), report.splitlines())
def test_multiple_messages(self): # SETUP expected_report = """\ x = 1 y = 2 """ # EXEC builder = ReportBuilder() builder.assign(name='x', value=1, line_number=1) builder.assign(name='y', value=2, line_number=1) report = builder.report() # VERIFY self.assertEqual(expected_report.splitlines(), report.splitlines())
def test_assign_object_without_repr(self): # SETUP expected_report = '' class class_without_repr(object): pass # EXEC builder = ReportBuilder() builder.assign(name='x', value=class_without_repr(), line_number=2) report = builder.report() # VERIFY self.assertEqual(expected_report.splitlines(), report.splitlines())
def test_assign_function(self): # SETUP expected_report = '' def f(n): return n+1 # EXEC builder = ReportBuilder() builder.assign(name='f', value=f, line_number=2) report = builder.report() # VERIFY self.assertReportEqual(expected_report, report)
def test_delete_item(self): # SETUP expected_report = "d = {'a': 1}" d = {'a': 1, 'b': 2} expected_d = {'a': 1} # EXEC builder = ReportBuilder() del builder.record_delete(name='d', target=d, line_number=1)['b'] report = builder.report() # VERIFY self.assertReportEqual(expected_report, report) self.assertEqual(expected_d, d)
def test_assign_object_with_repr_exception(self): # SETUP expected_report = '' class BadReprClass(object): def __repr__(self): raise NotImplementedError() # EXEC builder = ReportBuilder() builder.assign(name='m', value=BadReprClass(), line_number=1) report = builder.report() # VERIFY self.assertReportEqual(expected_report, report)
def test_assign(self): # SETUP expected_value = 5 expected_report = """\ x = 5 """ # EXEC builder = ReportBuilder() value = builder.assign(name='x', value=expected_value, line_number=2) report = builder.report() # VERIFY self.assertEqual(expected_report.splitlines(), report.splitlines()) self.assertEqual(expected_value, value)
def test_return(self): # SETUP expected_value = 'bob' expected_report = """\ return 'bob' """ # EXEC builder = ReportBuilder() value = builder.return_value(value=expected_value, line_number=2) report = builder.report() # VERIFY self.assertEqual(expected_report.splitlines(), report.splitlines()) self.assertEqual(expected_value, value)
def test_call_no_change(self): # SETUP expected_report = "" expected_result = 23 # EXEC builder = ReportBuilder() result = builder.record_call(names=['a'], displays_before=['[1, 2]'], result=expected_result, displays_after=['[1, 2]'], line_number=2) report = builder.report() # VERIFY self.assertReportEqual(expected_report, report) self.assertEqual(expected_result, result)
def trace_code(self, source): builder = ReportBuilder(self.message_limit) try: tree = parse(source) visitor = TraceAssignments() new_tree = visitor.visit(tree) fix_missing_locations(new_tree) code = compile(new_tree, PSEUDO_FILENAME, 'exec') self.environment[CONTEXT_NAME] = builder exec code in self.environment except SyntaxError, ex: messages = traceback.format_exception_only(type(ex), ex) builder.add_message(messages[-1].strip() + ' ', ex.lineno)
def test_frames(self): # SETUP expected_report = """\ i = 1 | i = 2 n = 2 | """ # EXEC builder = ReportBuilder() frame1 = builder.start_frame(1, 2) frame1.assign(name='i', value=1, line_number=1) frame2 = builder.start_frame(1, 2) frame2.assign(name='i', value=2, line_number=1) frame1.assign(name='n', value=2, line_number=2) report = builder.report() # VERIFY self.assertEqual(expected_report.splitlines(), report.splitlines())
def test_assign_object_with_multiline_repr(self): # SETUP expected_report = 'm = multiline_class(1, 2) ' class multiline_class(object): def __init__(self, x, y): self.x = x self.y = y def __repr__(self): return "multiline_class(%r,\n%r)" % (self.x, self.y) # EXEC builder = ReportBuilder() builder.assign(name='m', value=multiline_class(1, 2), line_number=1) report = builder.report() # VERIFY self.assertEqual(expected_report.splitlines(), report.splitlines())
def test_call_no_change(self): # SETUP expected_report = "" expected_result = 23 # EXEC builder = ReportBuilder() result = builder.record_call(name='a', display_before='[1, 2]', result=expected_result, display_after='[1, 2]', line_number=2) report = builder.report() # VERIFY self.assertEqual(expected_report.splitlines(), report.splitlines()) self.assertEqual(expected_result, result)
def test_return_multiline(self): # SETUP class Multiline(object): def __repr__(self): return 'Multiline(\n)' expected_value = Multiline() expected_report = """\ return Multiline( ) """ # EXEC builder = ReportBuilder() value = builder.return_value(value=expected_value, line_number=2) report = builder.report() # VERIFY self.assertReportEqual(expected_report, report) self.assertEqual(expected_value, value)
def test_call_multiple_changes(self): # SETUP expected_report = """\ a = [1, 2] b = 6 """ expected_result = 23 # EXEC builder = ReportBuilder() result = builder.record_call(names=['a', 'b'], displays_before=['[2, 1]', '5'], result=expected_result, displays_after=['[1, 2]', '6'], line_number=2) report = builder.report() # VERIFY self.assertReportEqual(expected_report, report) self.assertEqual(expected_result, result)
def test_exception_multiline_message(self): # SETUP source = """\ try: raise RuntimeError('a\\nb') except: builder.exception()""" expected_report = """\ RuntimeError: a b """ # EXEC builder = ReportBuilder() environment = dict(builder=builder) exec(source, environment, environment) report = builder.report() # VERIFY self.assertReportEqual(expected_report, report)
def test_exception(self): # SETUP source = """\ try: raise RuntimeError('foo') except: builder.exception()""" expected_report = """\ RuntimeError: foo """ # EXEC builder = ReportBuilder() environment = dict(builder=builder) exec_code(source, environment, environment) report = builder.report() # VERIFY self.assertEqual(expected_report.splitlines(), report.splitlines())
def test_multiple_lines(self): # SETUP expected_report = """\ a = 3 b = 'xyz' """ # EXEC builder = ReportBuilder() builder.assign(name='a', value=3, line_number=1) builder.assign(name='b', value="xyz", line_number=3) report = builder.report() # VERIFY self.assertEqual(expected_report.splitlines(), report.splitlines())
def test_frames_with_extra_message(self): # SETUP expected_report = """\ i = 1 | i = 2 | extra message""" # EXEC builder = ReportBuilder() frame1 = builder.start_frame(1, 2) frame1.assign(name='i', value=1, line_number=1) frame2 = builder.start_frame(1, 2) frame2.assign(name='i', value=2, line_number=1) builder.add_extra_message('extra message', 2) report = builder.report() # VERIFY self.assertEqual(expected_report.splitlines(), report.splitlines())
def trace_code(self, source, load_as=SCOPE_NAME, is_module=False, dump=False, driver=None, filename=None, bad_driver=None, is_zoomed=False): """ 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 :param bool is_zoomed: True if matplotlib is zoomed """ 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, is_zoomed) 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 test_assign_value_after_indexes(self): # SETUP expected_report = "a[0][23] = 99 " # EXEC builder = ReportBuilder() builder.start_assignment() builder.add_assignment_index(0) builder.add_assignment_index(23) builder.set_assignment_value(99) builder.report_assignment('a[{!r}][{!r}] = {!r}', line_number=1) builder.end_assignment() report = builder.report() # VERIFY self.assertReportEqual(expected_report, report)
def test_multiple_visits(self): # SETUP expected_report = """\ x = 'first' | x = 'second' y = 'continue' | """ # EXEC builder = ReportBuilder() builder.start_block(1, 2) builder.assign(name='x', value='first', line_number=1) builder.assign(name='y', value='continue', line_number=2) builder.start_block(1, 2) builder.assign(name='x', value='second', line_number=1) report = builder.report() # VERIFY self.assertReportEqual(expected_report, report)
def test_separate_scopes(self): # SETUP expected_report = """\ x = 'child' | x = 'child again' y = 'main' """ # EXEC builder = ReportBuilder() builder.assign(name='y', value='main', line_number=3) builder.start_block(1, 1) builder.assign(name='x', value='child', line_number=1) builder.start_block(1, 1) builder.assign(name='x', value='child again', line_number=1) report = builder.report() # VERIFY self.assertEqual(expected_report.splitlines(), report.splitlines())
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 test_multiple_visits(self): # SETUP expected_report = """\ x = 'first' | x = 'second' y = 'continue' | """ # EXEC builder = ReportBuilder() builder.start_block(1, 2) builder.assign(name='x', value='first', line_number=1) builder.assign(name='y', value='continue', line_number=2) builder.start_block(1, 2) builder.assign(name='x', value='second', line_number=1) report = builder.report() # VERIFY self.assertEqual(expected_report.splitlines(), report.splitlines())
def test_nested_blocks(self): # SETUP expected_report = """\ x = 'first' | x = 'second' | y = 1 | y = 2 """ # EXEC builder = ReportBuilder() builder.start_block(1, 2) builder.assign(name='x', value='first', line_number=1) builder.start_block(1, 2) builder.assign(name='x', value='second', line_number=1) builder.start_block(2, 2) builder.assign(name='y', value=1, line_number=2) builder.start_block(2, 2) builder.assign(name='y', value=2, line_number=2) report = builder.report() # VERIFY self.assertReportEqual(expected_report, report)
def test_separate_scopes(self): # SETUP expected_report = """\ x = 'child' | x = 'child again' y = 'main' """ # EXEC builder = ReportBuilder() builder.assign(name='y', value='main', line_number=3) builder.start_block(1, 1) builder.assign(name='x', value='child', line_number=1) builder.start_block(1, 1) builder.assign(name='x', value='child again', line_number=1) report = builder.report() # VERIFY self.assertReportEqual(expected_report, 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 test_assign_with_indexes(self): # SETUP expected_report = "a[0][23] = b['x'] = 99 " # EXEC builder = ReportBuilder() builder.start_assignment() builder.set_assignment_value(99) builder.add_assignment_index(0) builder.add_assignment_index(23) builder.add_assignment_index('x') builder.report_assignment('a[{!r}][{!r}] = b[{!r}] = {!r}', line_number=1) builder.end_assignment() report = builder.report() # VERIFY self.assertReportEqual(expected_report, report)
import pandas as pd from report_builder import ReportBuilder import os import sys sys.path.append( os.path.dirname(os.path.dirname(os.path.abspath( os.path.abspath(__file__))))) from utils import bytes_to_pb_string, bytes_to_pib_string, bytes_to_readable import argparse TIME_DATA_FILE = 'spark_exec_time_leftovers.txt' report_builder = ReportBuilder() def get_script_dir(): return os.path.dirname(os.path.abspath(__file__)) def get_report_dir(): return '%s/../../../bash/CERNTasks.wiki' % get_script_dir() def get_destination_dir(): return '%s/../../../bash/report_leftovers' % get_script_dir() def append_report(lines): report_builder.append(lines) report_builder.append('\n')
def test_nested_blocks(self): # SETUP expected_report = """\ x = 'first' | x = 'second' | y = 1 | y = 2 """ # EXEC builder = ReportBuilder() builder.start_block(1, 2) builder.assign(name='x', value='first', line_number=1) builder.start_block(1, 2) builder.assign(name='x', value='second', line_number=1) builder.start_block(2, 2) builder.assign(name='y', value=1, line_number=2) builder.start_block(2, 2) builder.assign(name='y', value=2, line_number=2) report = builder.report() # VERIFY self.assertEqual(expected_report.splitlines(), report.splitlines())
def __init__(self, arguments): self.args = arguments self.data_manager = DataManager(arguments, arguments["galloper_url"], arguments["token"], arguments["project_id"]) self.report_builder = ReportBuilder()
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 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 ex.code: if module_name != 'unittest': raise self.return_code = ex.code result = (sys.stderr.last_line or 'FAIL ') 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: 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() 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