1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
|
import pickle
import traceback
from tblib import Traceback
from tblib import pickling_support
pickling_support.install()
pytest_plugins = ('pytester',)
def test_get_locals():
def get_locals(frame):
print(frame, frame.f_locals)
if 'my_variable' in frame.f_locals:
return {'my_variable': int(frame.f_locals['my_variable'])}
else:
return {}
def func(my_arg='2'):
my_variable = '1'
raise ValueError(my_variable)
try:
func()
except Exception as e:
exc = e
else:
raise AssertionError
f_locals = exc.__traceback__.tb_next.tb_frame.f_locals
assert 'my_variable' in f_locals
assert f_locals['my_variable'] == '1'
value = Traceback(exc.__traceback__, get_locals=get_locals).as_dict()
lineno = exc.__traceback__.tb_lineno
assert value == {
'tb_frame': {
'f_globals': {'__name__': 'test_tblib', '__file__': __file__},
'f_locals': {},
'f_code': {'co_filename': __file__, 'co_name': 'test_get_locals'},
'f_lineno': lineno + 10,
},
'tb_lineno': lineno,
'tb_next': {
'tb_frame': {
'f_globals': {'__name__': 'test_tblib', '__file__': __file__},
'f_locals': {'my_variable': 1},
'f_code': {'co_filename': __file__, 'co_name': 'func'},
'f_lineno': lineno - 3,
},
'tb_lineno': lineno - 3,
'tb_next': None,
},
}
assert Traceback.from_dict(value).tb_next.tb_frame.f_locals == {'my_variable': 1}
def test_parse_traceback():
tb1 = Traceback.from_string(
"""
Traceback (most recent call last):
File "file1", line 123, in <module>
code1
File "file2", line 234, in ???
code2
File "file3", line 345, in function3
File "file4", line 456, in
code4
KeyboardInterrupt"""
)
pytb = tb1.as_traceback()
assert traceback.format_tb(pytb) == [
' File "file1", line 123, in <module>\n',
' File "file2", line 234, in ???\n',
' File "file3", line 345, in function3\n',
]
tb2 = Traceback(pytb)
expected_dict = {
'tb_frame': {
'f_code': {'co_filename': 'file1', 'co_name': '<module>'},
'f_globals': {'__file__': 'file1', '__name__': '?'},
'f_locals': {},
'f_lineno': 123,
},
'tb_lineno': 123,
'tb_next': {
'tb_frame': {
'f_code': {'co_filename': 'file2', 'co_name': '???'},
'f_globals': {'__file__': 'file2', '__name__': '?'},
'f_locals': {},
'f_lineno': 234,
},
'tb_lineno': 234,
'tb_next': {
'tb_frame': {
'f_code': {'co_filename': 'file3', 'co_name': 'function3'},
'f_globals': {'__file__': 'file3', '__name__': '?'},
'f_locals': {},
'f_lineno': 345,
},
'tb_lineno': 345,
'tb_next': None,
},
},
}
tb3 = Traceback.from_dict(expected_dict)
tb4 = pickle.loads(pickle.dumps(tb3)) # noqa: S301
assert tb4.as_dict() == tb3.as_dict() == tb2.as_dict() == tb1.as_dict() == expected_dict
def test_large_line_number():
line_number = 2**31 - 1
tb1 = Traceback.from_string(
f"""
Traceback (most recent call last):
File "file1", line {line_number}, in <module>
code1
"""
).as_traceback()
assert tb1.tb_lineno == line_number
def test_pytest_integration(testdir):
test = testdir.makepyfile(
"""
from tblib import Traceback
def test_raise():
tb1 = Traceback.from_string('''
Traceback (most recent call last):
File "file1", line 123, in <module>
code1
File "file2", line 234, in ???
code2
File "file3", line 345, in function3
File "file4", line 456, in ""
''')
pytb = tb1.as_traceback()
raise RuntimeError().with_traceback(pytb)
"""
)
# mode(auto / long / short / line / native / no).
result = testdir.runpytest_subprocess('--tb=long', '-vv', test)
result.stdout.fnmatch_lines(
[
'_ _ _ _ _ _ _ _ *',
'',
'> [?][?][?]',
'',
'file1:123:*',
'_ _ _ _ _ _ _ _ *',
'',
'> [?][?][?]',
'',
'file2:234:*',
'_ _ _ _ _ _ _ _ *',
'',
'> [?][?][?]',
'',
'file3:345:*',
'_ _ _ _ _ _ _ _ *',
'',
'> [?][?][?]',
'E RuntimeError',
'',
'file4:456: RuntimeError',
'===*=== 1 failed in * ===*===',
]
)
result = testdir.runpytest_subprocess('--tb=short', '-vv', test)
result.stdout.fnmatch_lines(
[
'test_pytest_integration.py:*: in test_raise',
' raise RuntimeError().with_traceback(pytb)',
'file1:123: in <module>',
' ???',
'file2:234: in ???',
' ???',
'file3:345: in function3',
' ???',
'file4:456: in ""',
' ???',
'E RuntimeError',
]
)
result = testdir.runpytest_subprocess('--tb=line', '-vv', test)
result.stdout.fnmatch_lines(
[
'===*=== FAILURES ===*===',
'file4:456: RuntimeError',
'===*=== 1 failed in * ===*===',
]
)
result = testdir.runpytest_subprocess('--tb=native', '-vv', test)
result.stdout.fnmatch_lines(
[
'Traceback (most recent call last):',
' File "*test_pytest_integration.py", line *, in test_raise',
' raise RuntimeError().with_traceback(pytb)',
' File "file1", line 123, in <module>',
' File "file2", line 234, in ???',
' File "file3", line 345, in function3',
' File "file4", line 456, in ""',
'RuntimeError',
]
)
|