def clean_traceback(tb): tb_lines = split_and_strip_tb_lines(tb) first_line_should_be = 'Traceback (most recent call last):' if first_line_should_be not in tb_lines: raise ValueError("Malformed traceback: first line must be " "exactly equal to '{}' " "(no spaces around)".format(first_line_should_be)) first_line_index = len(tb_lines) - tb_lines[::-1].index( first_line_should_be) - 1 tb_lines = tb_lines[first_line_index:] last_line = tb_lines[-1] = tb_lines[-1].lstrip() exception_re_match = _exception_re.match(last_line) if not exception_re_match: raise ValueError("Malformed traceback: last line must be " "exception type and message") file_lines = tb_lines[1:-1:2] for i, line in enumerate(file_lines): if not _file_line_re.match(line.strip()): raise ValueError("Malformed traceback: line {} (1-indexed) " "doesn't matches regex {}".format( i * 2 + 2, _file_line_re_text)) if not is_django_exception(tb_lines): raise ValueError("Invalid traceback: exception not thrown by Django") # try to parse tb = '\n'.join(tb_lines) ParsedException.from_string(tb) return tb
def test_parsed_exc_nosrcline(): """just making sure that everything can be parsed even if there is a line without source and also if the exception has no message""" _tb_str = u"""\ Traceback (most recent call last): File "/home/mahmoud/virtualenvs/chert/bin/chert", line 9, in <module> load_entry_point('chert==0.2.1.dev0', 'console_scripts', 'chert')() File "/home/mahmoud/projects/chert/chert/core.py", line 1281, in main ch.process() File "/home/mahmoud/projects/chert/chert/core.py", line 741, in process self.load() File "<boltons.FunctionBuilder-0>", line 2, in load File "/home/mahmoud/projects/lithoxyl/lithoxyl/logger.py", line 291, in logged_func return func_to_log(*a, **kw) File "/home/mahmoud/projects/chert/chert/core.py", line 775, in load raise RuntimeError RuntimeError""" parsed_tb = ParsedException.from_string(_tb_str) assert parsed_tb.exc_type == 'RuntimeError' assert parsed_tb.exc_msg == '' assert len(parsed_tb.frames) == 6 assert parsed_tb.frames[3] == {'source_line': u'', 'filepath': u'<boltons.FunctionBuilder-0>', 'lineno': u'2', 'funcname': u'load'} assert parsed_tb.to_string() == _tb_str
def test_normal_tb(): tb = '''\ Traceback (most recent call last): File "<string>", line 2, in _some_function return some_other_function(1) File "myfile.py", line 3, in some_other_function return foo(bar, baz) MyException: ExceptionValue ''' parsed = ParsedException.from_string(tb) assert parsed.exc_type == 'MyException' assert parsed.exc_msg == ' ExceptionValue' assert parsed.frames == [ { 'source_line': 'return some_other_function(1)', 'filepath': '<string>', 'lineno': '2', 'funcname': '_some_function' }, { 'source_line': 'return foo(bar, baz)', 'filepath': 'myfile.py', 'lineno': '3', 'funcname': 'some_other_function', } ]
def test_extract_traceback_info(): tb_info = extract_traceback_info(django_tb) tb_info_expected = { 'parsed_traceback': ParsedException.from_string(django_tb).to_dict(), 'raised_by': 'django/template/loader.py', 'raised_by_line': 186 } assert tb_info == tb_info_expected
def test_last_line_is_eval_like(): tb = '''\ Traceback (most recent call last): File "<string>", line 2, in _some_function MyException: ExceptionValue ''' parsed = ParsedException.from_string(tb) assert parsed.exc_type == 'MyException'
def save(self, *args, **kwargs): self.traceback = clean_traceback(self.traceback) self.sanitized_traceback = sanitize_traceback(self.traceback) self.parsed_traceback = ParsedException.from_string( self.sanitized_traceback ).to_dict() self.raised_by = self._get_raised_by() self.raised_by_line = self._get_raised_by_line() super(ErrorPost, self).save(*args, **kwargs)
def test_eval_tb(): tb = '''\ Traceback (most recent call last): File "<string>", line 2, in _some_function File "myfile.py", line 3, in some_other_function return foo(bar, baz) MyException: ExceptionValue ''' parsed = ParsedException.from_string(tb) assert parsed.exc_type == 'MyException'
def extract_traceback_info(tb): parsed_traceback = ParsedException.from_string(tb).to_dict() last_frame = parsed_traceback['frames'][-1] last_frame_filepath = last_frame['filepath'] return { 'parsed_traceback': parsed_traceback, 'raised_by': last_frame_filepath[last_frame_filepath.index('django/'):], 'raised_by_line': int(last_frame['lineno']) }
def test_multiline_exception_message(): tb = '''\ Traceback (most recent call last): File "<string>", line 2, in _some_function return some_other_function(1) File "myfile.py", line 3, in some_other_function return foo(bar, baz) MyException: ExceptionValue that spans two lines ''' parsed = ParsedException.from_string(tb) assert parsed.exc_msg == 'ExceptionValue that\nspans two lines'
def clean_traceback(tb): tb_lines = split_and_strip_tb_lines(tb) first_line_should_be = 'Traceback (most recent call last):' if first_line_should_be not in tb_lines: raise ValueError( "Malformed traceback: first line must be " "exactly equal to '{}' " "(no spaces around)".format(first_line_should_be)) first_line_index = len(tb_lines) - tb_lines[::-1].index(first_line_should_be) - 1 tb_lines = tb_lines[first_line_index:] last_line = tb_lines[-1] = tb_lines[-1].lstrip() exception_re_match = _exception_re.match(last_line) if not exception_re_match: raise ValueError( "Malformed traceback: last line must be " "exception type and message") file_lines = tb_lines[1:-1:2] for i, line in enumerate(file_lines): if not _file_line_re.match(line.strip()): raise ValueError( "Malformed traceback: line {} (1-indexed) " "doesn't matches regex {}".format(i * 2 + 2, _file_line_re_text)) if not is_django_exception(tb_lines): raise ValueError( "Invalid traceback: exception not thrown by Django") # try to parse tb = '\n'.join(tb_lines) ParsedException.from_string(tb) return tb
def test_parsed_exc(): FAKE_TB_STR = u""" Traceback (most recent call last): File "example.py", line 2, in <module> plarp NameError: name 'plarp' is not defined """ parsed_tb = ParsedException.from_string(FAKE_TB_STR) print(parsed_tb) assert parsed_tb.exc_type == 'NameError' assert parsed_tb.exc_msg == "name 'plarp' is not defined" assert parsed_tb.frames == [{'source_line': u'plarp', 'filepath': u'example.py', 'lineno': u'2', 'funcname': u'<module>'}]
def group_errors(id_, output=None): """ Return dict with errors grouped by type of error """ errors = OAIRecordExc.query.filter_by(oai_sync_id=id_).all() result = defaultdict(list) for error in errors: print(error.oai_identifier) tb = error.traceback tb_formated = ParsedException.from_string(tb) key = tb_formated.exc_msg assert isinstance(key, str) result[key].append(error.oai_identifier) result = dict(result) if output: f = open(output + '/errors.json', 'w+') json.dump(result, f, ensure_ascii=False) else: print(result.keys())
def test_normal_tb(): tb = '''\ Traceback (most recent call last): File "<string>", line 2, in _some_function return some_other_function(1) File "myfile.py", line 3, in some_other_function return foo(bar, baz) MyException: ExceptionValue ''' parsed = ParsedException.from_string(tb) assert parsed.exc_type == 'MyException' assert parsed.exc_msg == ' ExceptionValue' assert parsed.frames == [{ 'source_line': 'return some_other_function(1)', 'filepath': '<string>', 'lineno': '2', 'funcname': '_some_function' }, { 'source_line': 'return foo(bar, baz)', 'filepath': 'myfile.py', 'lineno': '3', 'funcname': 'some_other_function', }]