##// END OF EJS Templates
Merge pull request #8882 from quantopian/fix-getargs...
Min RK -
r21722:873e9077 merge
parent child Browse files
Show More
@@ -1,197 +1,222 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for IPython.core.ultratb
2 """Tests for IPython.core.ultratb
3 """
3 """
4 import io
4 import io
5 import os.path
5 import os.path
6 from textwrap import dedent
6 import unittest
7 import unittest
7
8
9
8 from IPython.testing import tools as tt
10 from IPython.testing import tools as tt
9 from IPython.testing.decorators import onlyif_unicode_paths
11 from IPython.testing.decorators import onlyif_unicode_paths
10 from IPython.utils.syspathcontext import prepended_to_syspath
12 from IPython.utils.syspathcontext import prepended_to_syspath
11 from IPython.utils.tempdir import TemporaryDirectory
13 from IPython.utils.tempdir import TemporaryDirectory
12 from IPython.utils.py3compat import PY3
14 from IPython.utils.py3compat import PY3
13
15
14 ip = get_ipython()
16 ip = get_ipython()
15
17
16 file_1 = """1
18 file_1 = """1
17 2
19 2
18 3
20 3
19 def f():
21 def f():
20 1/0
22 1/0
21 """
23 """
22
24
23 file_2 = """def f():
25 file_2 = """def f():
24 1/0
26 1/0
25 """
27 """
26
28
27 class ChangedPyFileTest(unittest.TestCase):
29 class ChangedPyFileTest(unittest.TestCase):
28 def test_changing_py_file(self):
30 def test_changing_py_file(self):
29 """Traceback produced if the line where the error occurred is missing?
31 """Traceback produced if the line where the error occurred is missing?
30
32
31 https://github.com/ipython/ipython/issues/1456
33 https://github.com/ipython/ipython/issues/1456
32 """
34 """
33 with TemporaryDirectory() as td:
35 with TemporaryDirectory() as td:
34 fname = os.path.join(td, "foo.py")
36 fname = os.path.join(td, "foo.py")
35 with open(fname, "w") as f:
37 with open(fname, "w") as f:
36 f.write(file_1)
38 f.write(file_1)
37
39
38 with prepended_to_syspath(td):
40 with prepended_to_syspath(td):
39 ip.run_cell("import foo")
41 ip.run_cell("import foo")
40
42
41 with tt.AssertPrints("ZeroDivisionError"):
43 with tt.AssertPrints("ZeroDivisionError"):
42 ip.run_cell("foo.f()")
44 ip.run_cell("foo.f()")
43
45
44 # Make the file shorter, so the line of the error is missing.
46 # Make the file shorter, so the line of the error is missing.
45 with open(fname, "w") as f:
47 with open(fname, "w") as f:
46 f.write(file_2)
48 f.write(file_2)
47
49
48 # For some reason, this was failing on the *second* call after
50 # For some reason, this was failing on the *second* call after
49 # changing the file, so we call f() twice.
51 # changing the file, so we call f() twice.
50 with tt.AssertNotPrints("Internal Python error", channel='stderr'):
52 with tt.AssertNotPrints("Internal Python error", channel='stderr'):
51 with tt.AssertPrints("ZeroDivisionError"):
53 with tt.AssertPrints("ZeroDivisionError"):
52 ip.run_cell("foo.f()")
54 ip.run_cell("foo.f()")
53 with tt.AssertPrints("ZeroDivisionError"):
55 with tt.AssertPrints("ZeroDivisionError"):
54 ip.run_cell("foo.f()")
56 ip.run_cell("foo.f()")
55
57
56 iso_8859_5_file = u'''# coding: iso-8859-5
58 iso_8859_5_file = u'''# coding: iso-8859-5
57
59
58 def fail():
60 def fail():
59 """Π΄Π±Π˜Π–"""
61 """Π΄Π±Π˜Π–"""
60 1/0 # Π΄Π±Π˜Π–
62 1/0 # Π΄Π±Π˜Π–
61 '''
63 '''
62
64
63 class NonAsciiTest(unittest.TestCase):
65 class NonAsciiTest(unittest.TestCase):
64 @onlyif_unicode_paths
66 @onlyif_unicode_paths
65 def test_nonascii_path(self):
67 def test_nonascii_path(self):
66 # Non-ascii directory name as well.
68 # Non-ascii directory name as well.
67 with TemporaryDirectory(suffix=u'Γ©') as td:
69 with TemporaryDirectory(suffix=u'Γ©') as td:
68 fname = os.path.join(td, u"fooΓ©.py")
70 fname = os.path.join(td, u"fooΓ©.py")
69 with open(fname, "w") as f:
71 with open(fname, "w") as f:
70 f.write(file_1)
72 f.write(file_1)
71
73
72 with prepended_to_syspath(td):
74 with prepended_to_syspath(td):
73 ip.run_cell("import foo")
75 ip.run_cell("import foo")
74
76
75 with tt.AssertPrints("ZeroDivisionError"):
77 with tt.AssertPrints("ZeroDivisionError"):
76 ip.run_cell("foo.f()")
78 ip.run_cell("foo.f()")
77
79
78 def test_iso8859_5(self):
80 def test_iso8859_5(self):
79 with TemporaryDirectory() as td:
81 with TemporaryDirectory() as td:
80 fname = os.path.join(td, 'dfghjkl.py')
82 fname = os.path.join(td, 'dfghjkl.py')
81
83
82 with io.open(fname, 'w', encoding='iso-8859-5') as f:
84 with io.open(fname, 'w', encoding='iso-8859-5') as f:
83 f.write(iso_8859_5_file)
85 f.write(iso_8859_5_file)
84
86
85 with prepended_to_syspath(td):
87 with prepended_to_syspath(td):
86 ip.run_cell("from dfghjkl import fail")
88 ip.run_cell("from dfghjkl import fail")
87
89
88 with tt.AssertPrints("ZeroDivisionError"):
90 with tt.AssertPrints("ZeroDivisionError"):
89 with tt.AssertPrints(u'Π΄Π±Π˜Π–', suppress=False):
91 with tt.AssertPrints(u'Π΄Π±Π˜Π–', suppress=False):
90 ip.run_cell('fail()')
92 ip.run_cell('fail()')
91
93
94
95 class NestedGenExprTestCase(unittest.TestCase):
96 """
97 Regression test for the following issues:
98 https://github.com/ipython/ipython/issues/8293
99 https://github.com/ipython/ipython/issues/8205
100 """
101 def test_nested_genexpr(self):
102 code = dedent(
103 """\
104 class SpecificException(Exception):
105 pass
106
107 def foo(x):
108 raise SpecificException("Success!")
109
110 sum(sum(foo(x) for _ in [0]) for x in [0])
111 """
112 )
113 with tt.AssertPrints('SpecificException: Success!', suppress=False):
114 ip.run_cell(code)
115
116
92 indentationerror_file = """if True:
117 indentationerror_file = """if True:
93 zoon()
118 zoon()
94 """
119 """
95
120
96 class IndentationErrorTest(unittest.TestCase):
121 class IndentationErrorTest(unittest.TestCase):
97 def test_indentationerror_shows_line(self):
122 def test_indentationerror_shows_line(self):
98 # See issue gh-2398
123 # See issue gh-2398
99 with tt.AssertPrints("IndentationError"):
124 with tt.AssertPrints("IndentationError"):
100 with tt.AssertPrints("zoon()", suppress=False):
125 with tt.AssertPrints("zoon()", suppress=False):
101 ip.run_cell(indentationerror_file)
126 ip.run_cell(indentationerror_file)
102
127
103 with TemporaryDirectory() as td:
128 with TemporaryDirectory() as td:
104 fname = os.path.join(td, "foo.py")
129 fname = os.path.join(td, "foo.py")
105 with open(fname, "w") as f:
130 with open(fname, "w") as f:
106 f.write(indentationerror_file)
131 f.write(indentationerror_file)
107
132
108 with tt.AssertPrints("IndentationError"):
133 with tt.AssertPrints("IndentationError"):
109 with tt.AssertPrints("zoon()", suppress=False):
134 with tt.AssertPrints("zoon()", suppress=False):
110 ip.magic('run %s' % fname)
135 ip.magic('run %s' % fname)
111
136
112 se_file_1 = """1
137 se_file_1 = """1
113 2
138 2
114 7/
139 7/
115 """
140 """
116
141
117 se_file_2 = """7/
142 se_file_2 = """7/
118 """
143 """
119
144
120 class SyntaxErrorTest(unittest.TestCase):
145 class SyntaxErrorTest(unittest.TestCase):
121 def test_syntaxerror_without_lineno(self):
146 def test_syntaxerror_without_lineno(self):
122 with tt.AssertNotPrints("TypeError"):
147 with tt.AssertNotPrints("TypeError"):
123 with tt.AssertPrints("line unknown"):
148 with tt.AssertPrints("line unknown"):
124 ip.run_cell("raise SyntaxError()")
149 ip.run_cell("raise SyntaxError()")
125
150
126 def test_changing_py_file(self):
151 def test_changing_py_file(self):
127 with TemporaryDirectory() as td:
152 with TemporaryDirectory() as td:
128 fname = os.path.join(td, "foo.py")
153 fname = os.path.join(td, "foo.py")
129 with open(fname, 'w') as f:
154 with open(fname, 'w') as f:
130 f.write(se_file_1)
155 f.write(se_file_1)
131
156
132 with tt.AssertPrints(["7/", "SyntaxError"]):
157 with tt.AssertPrints(["7/", "SyntaxError"]):
133 ip.magic("run " + fname)
158 ip.magic("run " + fname)
134
159
135 # Modify the file
160 # Modify the file
136 with open(fname, 'w') as f:
161 with open(fname, 'w') as f:
137 f.write(se_file_2)
162 f.write(se_file_2)
138
163
139 # The SyntaxError should point to the correct line
164 # The SyntaxError should point to the correct line
140 with tt.AssertPrints(["7/", "SyntaxError"]):
165 with tt.AssertPrints(["7/", "SyntaxError"]):
141 ip.magic("run " + fname)
166 ip.magic("run " + fname)
142
167
143 def test_non_syntaxerror(self):
168 def test_non_syntaxerror(self):
144 # SyntaxTB may be called with an error other than a SyntaxError
169 # SyntaxTB may be called with an error other than a SyntaxError
145 # See e.g. gh-4361
170 # See e.g. gh-4361
146 try:
171 try:
147 raise ValueError('QWERTY')
172 raise ValueError('QWERTY')
148 except ValueError:
173 except ValueError:
149 with tt.AssertPrints('QWERTY'):
174 with tt.AssertPrints('QWERTY'):
150 ip.showsyntaxerror()
175 ip.showsyntaxerror()
151
176
152
177
153 class Python3ChainedExceptionsTest(unittest.TestCase):
178 class Python3ChainedExceptionsTest(unittest.TestCase):
154 DIRECT_CAUSE_ERROR_CODE = """
179 DIRECT_CAUSE_ERROR_CODE = """
155 try:
180 try:
156 x = 1 + 2
181 x = 1 + 2
157 print(not_defined_here)
182 print(not_defined_here)
158 except Exception as e:
183 except Exception as e:
159 x += 55
184 x += 55
160 x - 1
185 x - 1
161 y = {}
186 y = {}
162 raise KeyError('uh') from e
187 raise KeyError('uh') from e
163 """
188 """
164
189
165 EXCEPTION_DURING_HANDLING_CODE = """
190 EXCEPTION_DURING_HANDLING_CODE = """
166 try:
191 try:
167 x = 1 + 2
192 x = 1 + 2
168 print(not_defined_here)
193 print(not_defined_here)
169 except Exception as e:
194 except Exception as e:
170 x += 55
195 x += 55
171 x - 1
196 x - 1
172 y = {}
197 y = {}
173 raise KeyError('uh')
198 raise KeyError('uh')
174 """
199 """
175
200
176 SUPPRESS_CHAINING_CODE = """
201 SUPPRESS_CHAINING_CODE = """
177 try:
202 try:
178 1/0
203 1/0
179 except Exception:
204 except Exception:
180 raise ValueError("Yikes") from None
205 raise ValueError("Yikes") from None
181 """
206 """
182
207
183 def test_direct_cause_error(self):
208 def test_direct_cause_error(self):
184 if PY3:
209 if PY3:
185 with tt.AssertPrints(["KeyError", "NameError", "direct cause"]):
210 with tt.AssertPrints(["KeyError", "NameError", "direct cause"]):
186 ip.run_cell(self.DIRECT_CAUSE_ERROR_CODE)
211 ip.run_cell(self.DIRECT_CAUSE_ERROR_CODE)
187
212
188 def test_exception_during_handling_error(self):
213 def test_exception_during_handling_error(self):
189 if PY3:
214 if PY3:
190 with tt.AssertPrints(["KeyError", "NameError", "During handling"]):
215 with tt.AssertPrints(["KeyError", "NameError", "During handling"]):
191 ip.run_cell(self.EXCEPTION_DURING_HANDLING_CODE)
216 ip.run_cell(self.EXCEPTION_DURING_HANDLING_CODE)
192
217
193 def test_suppress_exception_chaining(self):
218 def test_suppress_exception_chaining(self):
194 if PY3:
219 if PY3:
195 with tt.AssertNotPrints("ZeroDivisionError"), \
220 with tt.AssertNotPrints("ZeroDivisionError"), \
196 tt.AssertPrints("ValueError", suppress=False):
221 tt.AssertPrints("ValueError", suppress=False):
197 ip.run_cell(self.SUPPRESS_CHAINING_CODE)
222 ip.run_cell(self.SUPPRESS_CHAINING_CODE)
@@ -1,1373 +1,1451 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Verbose and colourful traceback formatting.
3 Verbose and colourful traceback formatting.
4
4
5 **ColorTB**
5 **ColorTB**
6
6
7 I've always found it a bit hard to visually parse tracebacks in Python. The
7 I've always found it a bit hard to visually parse tracebacks in Python. The
8 ColorTB class is a solution to that problem. It colors the different parts of a
8 ColorTB class is a solution to that problem. It colors the different parts of a
9 traceback in a manner similar to what you would expect from a syntax-highlighting
9 traceback in a manner similar to what you would expect from a syntax-highlighting
10 text editor.
10 text editor.
11
11
12 Installation instructions for ColorTB::
12 Installation instructions for ColorTB::
13
13
14 import sys,ultratb
14 import sys,ultratb
15 sys.excepthook = ultratb.ColorTB()
15 sys.excepthook = ultratb.ColorTB()
16
16
17 **VerboseTB**
17 **VerboseTB**
18
18
19 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
19 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
20 of useful info when a traceback occurs. Ping originally had it spit out HTML
20 of useful info when a traceback occurs. Ping originally had it spit out HTML
21 and intended it for CGI programmers, but why should they have all the fun? I
21 and intended it for CGI programmers, but why should they have all the fun? I
22 altered it to spit out colored text to the terminal. It's a bit overwhelming,
22 altered it to spit out colored text to the terminal. It's a bit overwhelming,
23 but kind of neat, and maybe useful for long-running programs that you believe
23 but kind of neat, and maybe useful for long-running programs that you believe
24 are bug-free. If a crash *does* occur in that type of program you want details.
24 are bug-free. If a crash *does* occur in that type of program you want details.
25 Give it a shot--you'll love it or you'll hate it.
25 Give it a shot--you'll love it or you'll hate it.
26
26
27 .. note::
27 .. note::
28
28
29 The Verbose mode prints the variables currently visible where the exception
29 The Verbose mode prints the variables currently visible where the exception
30 happened (shortening their strings if too long). This can potentially be
30 happened (shortening their strings if too long). This can potentially be
31 very slow, if you happen to have a huge data structure whose string
31 very slow, if you happen to have a huge data structure whose string
32 representation is complex to compute. Your computer may appear to freeze for
32 representation is complex to compute. Your computer may appear to freeze for
33 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
33 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
34 with Ctrl-C (maybe hitting it more than once).
34 with Ctrl-C (maybe hitting it more than once).
35
35
36 If you encounter this kind of situation often, you may want to use the
36 If you encounter this kind of situation often, you may want to use the
37 Verbose_novars mode instead of the regular Verbose, which avoids formatting
37 Verbose_novars mode instead of the regular Verbose, which avoids formatting
38 variables (but otherwise includes the information and context given by
38 variables (but otherwise includes the information and context given by
39 Verbose).
39 Verbose).
40
40
41
41
42 Installation instructions for VerboseTB::
42 Installation instructions for VerboseTB::
43
43
44 import sys,ultratb
44 import sys,ultratb
45 sys.excepthook = ultratb.VerboseTB()
45 sys.excepthook = ultratb.VerboseTB()
46
46
47 Note: Much of the code in this module was lifted verbatim from the standard
47 Note: Much of the code in this module was lifted verbatim from the standard
48 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
48 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
49
49
50 Color schemes
50 Color schemes
51 -------------
51 -------------
52
52
53 The colors are defined in the class TBTools through the use of the
53 The colors are defined in the class TBTools through the use of the
54 ColorSchemeTable class. Currently the following exist:
54 ColorSchemeTable class. Currently the following exist:
55
55
56 - NoColor: allows all of this module to be used in any terminal (the color
56 - NoColor: allows all of this module to be used in any terminal (the color
57 escapes are just dummy blank strings).
57 escapes are just dummy blank strings).
58
58
59 - Linux: is meant to look good in a terminal like the Linux console (black
59 - Linux: is meant to look good in a terminal like the Linux console (black
60 or very dark background).
60 or very dark background).
61
61
62 - LightBG: similar to Linux but swaps dark/light colors to be more readable
62 - LightBG: similar to Linux but swaps dark/light colors to be more readable
63 in light background terminals.
63 in light background terminals.
64
64
65 You can implement other color schemes easily, the syntax is fairly
65 You can implement other color schemes easily, the syntax is fairly
66 self-explanatory. Please send back new schemes you develop to the author for
66 self-explanatory. Please send back new schemes you develop to the author for
67 possible inclusion in future releases.
67 possible inclusion in future releases.
68
68
69 Inheritance diagram:
69 Inheritance diagram:
70
70
71 .. inheritance-diagram:: IPython.core.ultratb
71 .. inheritance-diagram:: IPython.core.ultratb
72 :parts: 3
72 :parts: 3
73 """
73 """
74
74
75 #*****************************************************************************
75 #*****************************************************************************
76 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
76 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
77 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
77 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
78 #
78 #
79 # Distributed under the terms of the BSD License. The full license is in
79 # Distributed under the terms of the BSD License. The full license is in
80 # the file COPYING, distributed as part of this software.
80 # the file COPYING, distributed as part of this software.
81 #*****************************************************************************
81 #*****************************************************************************
82
82
83 from __future__ import unicode_literals
83 from __future__ import unicode_literals
84 from __future__ import print_function
84 from __future__ import print_function
85
85
86 import dis
86 import inspect
87 import inspect
87 import keyword
88 import keyword
88 import linecache
89 import linecache
89 import os
90 import os
90 import pydoc
91 import pydoc
91 import re
92 import re
92 import sys
93 import sys
93 import time
94 import time
94 import tokenize
95 import tokenize
95 import traceback
96 import traceback
96 import types
97 import types
97
98
98 try: # Python 2
99 try: # Python 2
99 generate_tokens = tokenize.generate_tokens
100 generate_tokens = tokenize.generate_tokens
100 except AttributeError: # Python 3
101 except AttributeError: # Python 3
101 generate_tokens = tokenize.tokenize
102 generate_tokens = tokenize.tokenize
102
103
103 # For purposes of monkeypatching inspect to fix a bug in it.
104 # For purposes of monkeypatching inspect to fix a bug in it.
104 from inspect import getsourcefile, getfile, getmodule, \
105 from inspect import getsourcefile, getfile, getmodule, \
105 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
106 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
106
107
107 # IPython's own modules
108 # IPython's own modules
108 # Modified pdb which doesn't damage IPython's readline handling
109 # Modified pdb which doesn't damage IPython's readline handling
109 from IPython import get_ipython
110 from IPython import get_ipython
110 from IPython.core import debugger
111 from IPython.core import debugger
111 from IPython.core.display_trap import DisplayTrap
112 from IPython.core.display_trap import DisplayTrap
112 from IPython.core.excolors import exception_colors
113 from IPython.core.excolors import exception_colors
113 from IPython.utils import PyColorize
114 from IPython.utils import PyColorize
114 from IPython.utils import io
115 from IPython.utils import io
115 from IPython.utils import openpy
116 from IPython.utils import openpy
116 from IPython.utils import path as util_path
117 from IPython.utils import path as util_path
117 from IPython.utils import py3compat
118 from IPython.utils import py3compat
118 from IPython.utils import ulinecache
119 from IPython.utils import ulinecache
119 from IPython.utils.data import uniq_stable
120 from IPython.utils.data import uniq_stable
120 from IPython.utils.warn import info, error
121 from IPython.utils.warn import info, error
121
122
122 # Globals
123 # Globals
123 # amount of space to put line numbers before verbose tracebacks
124 # amount of space to put line numbers before verbose tracebacks
124 INDENT_SIZE = 8
125 INDENT_SIZE = 8
125
126
126 # Default color scheme. This is used, for example, by the traceback
127 # Default color scheme. This is used, for example, by the traceback
127 # formatter. When running in an actual IPython instance, the user's rc.colors
128 # formatter. When running in an actual IPython instance, the user's rc.colors
128 # value is used, but having a module global makes this functionality available
129 # value is used, but having a module global makes this functionality available
129 # to users of ultratb who are NOT running inside ipython.
130 # to users of ultratb who are NOT running inside ipython.
130 DEFAULT_SCHEME = 'NoColor'
131 DEFAULT_SCHEME = 'NoColor'
131
132
132 # ---------------------------------------------------------------------------
133 # ---------------------------------------------------------------------------
133 # Code begins
134 # Code begins
134
135
135 # Utility functions
136 # Utility functions
136 def inspect_error():
137 def inspect_error():
137 """Print a message about internal inspect errors.
138 """Print a message about internal inspect errors.
138
139
139 These are unfortunately quite common."""
140 These are unfortunately quite common."""
140
141
141 error('Internal Python error in the inspect module.\n'
142 error('Internal Python error in the inspect module.\n'
142 'Below is the traceback from this internal error.\n')
143 'Below is the traceback from this internal error.\n')
143
144
144
145
145 # This function is a monkeypatch we apply to the Python inspect module. We have
146 # This function is a monkeypatch we apply to the Python inspect module. We have
146 # now found when it's needed (see discussion on issue gh-1456), and we have a
147 # now found when it's needed (see discussion on issue gh-1456), and we have a
147 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
148 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
148 # the monkeypatch is not applied. TK, Aug 2012.
149 # the monkeypatch is not applied. TK, Aug 2012.
149 def findsource(object):
150 def findsource(object):
150 """Return the entire source file and starting line number for an object.
151 """Return the entire source file and starting line number for an object.
151
152
152 The argument may be a module, class, method, function, traceback, frame,
153 The argument may be a module, class, method, function, traceback, frame,
153 or code object. The source code is returned as a list of all the lines
154 or code object. The source code is returned as a list of all the lines
154 in the file and the line number indexes a line in that list. An IOError
155 in the file and the line number indexes a line in that list. An IOError
155 is raised if the source code cannot be retrieved.
156 is raised if the source code cannot be retrieved.
156
157
157 FIXED version with which we monkeypatch the stdlib to work around a bug."""
158 FIXED version with which we monkeypatch the stdlib to work around a bug."""
158
159
159 file = getsourcefile(object) or getfile(object)
160 file = getsourcefile(object) or getfile(object)
160 # If the object is a frame, then trying to get the globals dict from its
161 # If the object is a frame, then trying to get the globals dict from its
161 # module won't work. Instead, the frame object itself has the globals
162 # module won't work. Instead, the frame object itself has the globals
162 # dictionary.
163 # dictionary.
163 globals_dict = None
164 globals_dict = None
164 if inspect.isframe(object):
165 if inspect.isframe(object):
165 # XXX: can this ever be false?
166 # XXX: can this ever be false?
166 globals_dict = object.f_globals
167 globals_dict = object.f_globals
167 else:
168 else:
168 module = getmodule(object, file)
169 module = getmodule(object, file)
169 if module:
170 if module:
170 globals_dict = module.__dict__
171 globals_dict = module.__dict__
171 lines = linecache.getlines(file, globals_dict)
172 lines = linecache.getlines(file, globals_dict)
172 if not lines:
173 if not lines:
173 raise IOError('could not get source code')
174 raise IOError('could not get source code')
174
175
175 if ismodule(object):
176 if ismodule(object):
176 return lines, 0
177 return lines, 0
177
178
178 if isclass(object):
179 if isclass(object):
179 name = object.__name__
180 name = object.__name__
180 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
181 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
181 # make some effort to find the best matching class definition:
182 # make some effort to find the best matching class definition:
182 # use the one with the least indentation, which is the one
183 # use the one with the least indentation, which is the one
183 # that's most probably not inside a function definition.
184 # that's most probably not inside a function definition.
184 candidates = []
185 candidates = []
185 for i in range(len(lines)):
186 for i in range(len(lines)):
186 match = pat.match(lines[i])
187 match = pat.match(lines[i])
187 if match:
188 if match:
188 # if it's at toplevel, it's already the best one
189 # if it's at toplevel, it's already the best one
189 if lines[i][0] == 'c':
190 if lines[i][0] == 'c':
190 return lines, i
191 return lines, i
191 # else add whitespace to candidate list
192 # else add whitespace to candidate list
192 candidates.append((match.group(1), i))
193 candidates.append((match.group(1), i))
193 if candidates:
194 if candidates:
194 # this will sort by whitespace, and by line number,
195 # this will sort by whitespace, and by line number,
195 # less whitespace first
196 # less whitespace first
196 candidates.sort()
197 candidates.sort()
197 return lines, candidates[0][1]
198 return lines, candidates[0][1]
198 else:
199 else:
199 raise IOError('could not find class definition')
200 raise IOError('could not find class definition')
200
201
201 if ismethod(object):
202 if ismethod(object):
202 object = object.__func__
203 object = object.__func__
203 if isfunction(object):
204 if isfunction(object):
204 object = object.__code__
205 object = object.__code__
205 if istraceback(object):
206 if istraceback(object):
206 object = object.tb_frame
207 object = object.tb_frame
207 if isframe(object):
208 if isframe(object):
208 object = object.f_code
209 object = object.f_code
209 if iscode(object):
210 if iscode(object):
210 if not hasattr(object, 'co_firstlineno'):
211 if not hasattr(object, 'co_firstlineno'):
211 raise IOError('could not find function definition')
212 raise IOError('could not find function definition')
212 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
213 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
213 pmatch = pat.match
214 pmatch = pat.match
214 # fperez - fix: sometimes, co_firstlineno can give a number larger than
215 # fperez - fix: sometimes, co_firstlineno can give a number larger than
215 # the length of lines, which causes an error. Safeguard against that.
216 # the length of lines, which causes an error. Safeguard against that.
216 lnum = min(object.co_firstlineno, len(lines)) - 1
217 lnum = min(object.co_firstlineno, len(lines)) - 1
217 while lnum > 0:
218 while lnum > 0:
218 if pmatch(lines[lnum]): break
219 if pmatch(lines[lnum]): break
219 lnum -= 1
220 lnum -= 1
220
221
221 return lines, lnum
222 return lines, lnum
222 raise IOError('could not find code object')
223 raise IOError('could not find code object')
223
224
224
225
226 # This is a patched version of inspect.getargs that applies the (unmerged)
227 # patch for http://bugs.python.org/issue14611 by Stefano Taschini. This fixes
228 # https://github.com/ipython/ipython/issues/8205 and
229 # https://github.com/ipython/ipython/issues/8293
230 def getargs(co):
231 """Get information about the arguments accepted by a code object.
232
233 Three things are returned: (args, varargs, varkw), where 'args' is
234 a list of argument names (possibly containing nested lists), and
235 'varargs' and 'varkw' are the names of the * and ** arguments or None."""
236 if not iscode(co):
237 raise TypeError('{!r} is not a code object'.format(co))
238
239 nargs = co.co_argcount
240 names = co.co_varnames
241 args = list(names[:nargs])
242 step = 0
243
244 # The following acrobatics are for anonymous (tuple) arguments.
245 for i in range(nargs):
246 if args[i][:1] in ('', '.'):
247 stack, remain, count = [], [], []
248 while step < len(co.co_code):
249 op = ord(co.co_code[step])
250 step = step + 1
251 if op >= dis.HAVE_ARGUMENT:
252 opname = dis.opname[op]
253 value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256
254 step = step + 2
255 if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'):
256 remain.append(value)
257 count.append(value)
258 elif opname in ('STORE_FAST', 'STORE_DEREF'):
259 if op in dis.haslocal:
260 stack.append(co.co_varnames[value])
261 elif op in dis.hasfree:
262 stack.append((co.co_cellvars + co.co_freevars)[value])
263 # Special case for sublists of length 1: def foo((bar))
264 # doesn't generate the UNPACK_TUPLE bytecode, so if
265 # `remain` is empty here, we have such a sublist.
266 if not remain:
267 stack[0] = [stack[0]]
268 break
269 else:
270 remain[-1] = remain[-1] - 1
271 while remain[-1] == 0:
272 remain.pop()
273 size = count.pop()
274 stack[-size:] = [stack[-size:]]
275 if not remain: break
276 remain[-1] = remain[-1] - 1
277 if not remain: break
278 args[i] = stack[0]
279
280 varargs = None
281 if co.co_flags & inspect.CO_VARARGS:
282 varargs = co.co_varnames[nargs]
283 nargs = nargs + 1
284 varkw = None
285 if co.co_flags & inspect.CO_VARKEYWORDS:
286 varkw = co.co_varnames[nargs]
287 return inspect.Arguments(args, varargs, varkw)
288
289
225 # Monkeypatch inspect to apply our bugfix.
290 # Monkeypatch inspect to apply our bugfix.
226 def with_patch_inspect(f):
291 def with_patch_inspect(f):
227 """decorator for monkeypatching inspect.findsource"""
292 """decorator for monkeypatching inspect.findsource"""
228
293
229 def wrapped(*args, **kwargs):
294 def wrapped(*args, **kwargs):
230 save_findsource = inspect.findsource
295 save_findsource = inspect.findsource
296 save_getargs = inspect.getargs
231 inspect.findsource = findsource
297 inspect.findsource = findsource
298 inspect.getargs = getargs
232 try:
299 try:
233 return f(*args, **kwargs)
300 return f(*args, **kwargs)
234 finally:
301 finally:
235 inspect.findsource = save_findsource
302 inspect.findsource = save_findsource
303 inspect.getargs = save_getargs
236
304
237 return wrapped
305 return wrapped
238
306
239
307
308 if py3compat.PY3:
309 fixed_getargvalues = inspect.getargvalues
310 else:
311 # Fixes for https://github.com/ipython/ipython/issues/8293
312 # and https://github.com/ipython/ipython/issues/8205.
313 # The relevant bug is caused by failure to correctly handle anonymous tuple
314 # unpacking, which only exists in Python 2.
315 fixed_getargvalues = with_patch_inspect(inspect.getargvalues)
316
317
240 def fix_frame_records_filenames(records):
318 def fix_frame_records_filenames(records):
241 """Try to fix the filenames in each record from inspect.getinnerframes().
319 """Try to fix the filenames in each record from inspect.getinnerframes().
242
320
243 Particularly, modules loaded from within zip files have useless filenames
321 Particularly, modules loaded from within zip files have useless filenames
244 attached to their code object, and inspect.getinnerframes() just uses it.
322 attached to their code object, and inspect.getinnerframes() just uses it.
245 """
323 """
246 fixed_records = []
324 fixed_records = []
247 for frame, filename, line_no, func_name, lines, index in records:
325 for frame, filename, line_no, func_name, lines, index in records:
248 # Look inside the frame's globals dictionary for __file__,
326 # Look inside the frame's globals dictionary for __file__,
249 # which should be better. However, keep Cython filenames since
327 # which should be better. However, keep Cython filenames since
250 # we prefer the source filenames over the compiled .so file.
328 # we prefer the source filenames over the compiled .so file.
251 filename = py3compat.cast_unicode_py2(filename, "utf-8")
329 filename = py3compat.cast_unicode_py2(filename, "utf-8")
252 if not filename.endswith(('.pyx', '.pxd', '.pxi')):
330 if not filename.endswith(('.pyx', '.pxd', '.pxi')):
253 better_fn = frame.f_globals.get('__file__', None)
331 better_fn = frame.f_globals.get('__file__', None)
254 if isinstance(better_fn, str):
332 if isinstance(better_fn, str):
255 # Check the type just in case someone did something weird with
333 # Check the type just in case someone did something weird with
256 # __file__. It might also be None if the error occurred during
334 # __file__. It might also be None if the error occurred during
257 # import.
335 # import.
258 filename = better_fn
336 filename = better_fn
259 fixed_records.append((frame, filename, line_no, func_name, lines, index))
337 fixed_records.append((frame, filename, line_no, func_name, lines, index))
260 return fixed_records
338 return fixed_records
261
339
262
340
263 @with_patch_inspect
341 @with_patch_inspect
264 def _fixed_getinnerframes(etb, context=1, tb_offset=0):
342 def _fixed_getinnerframes(etb, context=1, tb_offset=0):
265 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
343 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
266
344
267 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
345 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
268 # If the error is at the console, don't build any context, since it would
346 # If the error is at the console, don't build any context, since it would
269 # otherwise produce 5 blank lines printed out (there is no file at the
347 # otherwise produce 5 blank lines printed out (there is no file at the
270 # console)
348 # console)
271 rec_check = records[tb_offset:]
349 rec_check = records[tb_offset:]
272 try:
350 try:
273 rname = rec_check[0][1]
351 rname = rec_check[0][1]
274 if rname == '<ipython console>' or rname.endswith('<string>'):
352 if rname == '<ipython console>' or rname.endswith('<string>'):
275 return rec_check
353 return rec_check
276 except IndexError:
354 except IndexError:
277 pass
355 pass
278
356
279 aux = traceback.extract_tb(etb)
357 aux = traceback.extract_tb(etb)
280 assert len(records) == len(aux)
358 assert len(records) == len(aux)
281 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
359 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
282 maybeStart = lnum - 1 - context // 2
360 maybeStart = lnum - 1 - context // 2
283 start = max(maybeStart, 0)
361 start = max(maybeStart, 0)
284 end = start + context
362 end = start + context
285 lines = ulinecache.getlines(file)[start:end]
363 lines = ulinecache.getlines(file)[start:end]
286 buf = list(records[i])
364 buf = list(records[i])
287 buf[LNUM_POS] = lnum
365 buf[LNUM_POS] = lnum
288 buf[INDEX_POS] = lnum - 1 - start
366 buf[INDEX_POS] = lnum - 1 - start
289 buf[LINES_POS] = lines
367 buf[LINES_POS] = lines
290 records[i] = tuple(buf)
368 records[i] = tuple(buf)
291 return records[tb_offset:]
369 return records[tb_offset:]
292
370
293 # Helper function -- largely belongs to VerboseTB, but we need the same
371 # Helper function -- largely belongs to VerboseTB, but we need the same
294 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
372 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
295 # can be recognized properly by ipython.el's py-traceback-line-re
373 # can be recognized properly by ipython.el's py-traceback-line-re
296 # (SyntaxErrors have to be treated specially because they have no traceback)
374 # (SyntaxErrors have to be treated specially because they have no traceback)
297
375
298 _parser = PyColorize.Parser()
376 _parser = PyColorize.Parser()
299
377
300
378
301 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, scheme=None):
379 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, scheme=None):
302 numbers_width = INDENT_SIZE - 1
380 numbers_width = INDENT_SIZE - 1
303 res = []
381 res = []
304 i = lnum - index
382 i = lnum - index
305
383
306 # This lets us get fully syntax-highlighted tracebacks.
384 # This lets us get fully syntax-highlighted tracebacks.
307 if scheme is None:
385 if scheme is None:
308 ipinst = get_ipython()
386 ipinst = get_ipython()
309 if ipinst is not None:
387 if ipinst is not None:
310 scheme = ipinst.colors
388 scheme = ipinst.colors
311 else:
389 else:
312 scheme = DEFAULT_SCHEME
390 scheme = DEFAULT_SCHEME
313
391
314 _line_format = _parser.format2
392 _line_format = _parser.format2
315
393
316 for line in lines:
394 for line in lines:
317 line = py3compat.cast_unicode(line)
395 line = py3compat.cast_unicode(line)
318
396
319 new_line, err = _line_format(line, 'str', scheme)
397 new_line, err = _line_format(line, 'str', scheme)
320 if not err: line = new_line
398 if not err: line = new_line
321
399
322 if i == lnum:
400 if i == lnum:
323 # This is the line with the error
401 # This is the line with the error
324 pad = numbers_width - len(str(i))
402 pad = numbers_width - len(str(i))
325 if pad >= 3:
403 if pad >= 3:
326 marker = '-' * (pad - 3) + '-> '
404 marker = '-' * (pad - 3) + '-> '
327 elif pad == 2:
405 elif pad == 2:
328 marker = '> '
406 marker = '> '
329 elif pad == 1:
407 elif pad == 1:
330 marker = '>'
408 marker = '>'
331 else:
409 else:
332 marker = ''
410 marker = ''
333 num = marker + str(i)
411 num = marker + str(i)
334 line = '%s%s%s %s%s' % (Colors.linenoEm, num,
412 line = '%s%s%s %s%s' % (Colors.linenoEm, num,
335 Colors.line, line, Colors.Normal)
413 Colors.line, line, Colors.Normal)
336 else:
414 else:
337 num = '%*s' % (numbers_width, i)
415 num = '%*s' % (numbers_width, i)
338 line = '%s%s%s %s' % (Colors.lineno, num,
416 line = '%s%s%s %s' % (Colors.lineno, num,
339 Colors.Normal, line)
417 Colors.Normal, line)
340
418
341 res.append(line)
419 res.append(line)
342 if lvals and i == lnum:
420 if lvals and i == lnum:
343 res.append(lvals + '\n')
421 res.append(lvals + '\n')
344 i = i + 1
422 i = i + 1
345 return res
423 return res
346
424
347
425
348 #---------------------------------------------------------------------------
426 #---------------------------------------------------------------------------
349 # Module classes
427 # Module classes
350 class TBTools(object):
428 class TBTools(object):
351 """Basic tools used by all traceback printer classes."""
429 """Basic tools used by all traceback printer classes."""
352
430
353 # Number of frames to skip when reporting tracebacks
431 # Number of frames to skip when reporting tracebacks
354 tb_offset = 0
432 tb_offset = 0
355
433
356 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None):
434 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None):
357 # Whether to call the interactive pdb debugger after printing
435 # Whether to call the interactive pdb debugger after printing
358 # tracebacks or not
436 # tracebacks or not
359 self.call_pdb = call_pdb
437 self.call_pdb = call_pdb
360
438
361 # Output stream to write to. Note that we store the original value in
439 # Output stream to write to. Note that we store the original value in
362 # a private attribute and then make the public ostream a property, so
440 # a private attribute and then make the public ostream a property, so
363 # that we can delay accessing io.stdout until runtime. The way
441 # that we can delay accessing io.stdout until runtime. The way
364 # things are written now, the io.stdout object is dynamically managed
442 # things are written now, the io.stdout object is dynamically managed
365 # so a reference to it should NEVER be stored statically. This
443 # so a reference to it should NEVER be stored statically. This
366 # property approach confines this detail to a single location, and all
444 # property approach confines this detail to a single location, and all
367 # subclasses can simply access self.ostream for writing.
445 # subclasses can simply access self.ostream for writing.
368 self._ostream = ostream
446 self._ostream = ostream
369
447
370 # Create color table
448 # Create color table
371 self.color_scheme_table = exception_colors()
449 self.color_scheme_table = exception_colors()
372
450
373 self.set_colors(color_scheme)
451 self.set_colors(color_scheme)
374 self.old_scheme = color_scheme # save initial value for toggles
452 self.old_scheme = color_scheme # save initial value for toggles
375
453
376 if call_pdb:
454 if call_pdb:
377 self.pdb = debugger.Pdb(self.color_scheme_table.active_scheme_name)
455 self.pdb = debugger.Pdb(self.color_scheme_table.active_scheme_name)
378 else:
456 else:
379 self.pdb = None
457 self.pdb = None
380
458
381 def _get_ostream(self):
459 def _get_ostream(self):
382 """Output stream that exceptions are written to.
460 """Output stream that exceptions are written to.
383
461
384 Valid values are:
462 Valid values are:
385
463
386 - None: the default, which means that IPython will dynamically resolve
464 - None: the default, which means that IPython will dynamically resolve
387 to io.stdout. This ensures compatibility with most tools, including
465 to io.stdout. This ensures compatibility with most tools, including
388 Windows (where plain stdout doesn't recognize ANSI escapes).
466 Windows (where plain stdout doesn't recognize ANSI escapes).
389
467
390 - Any object with 'write' and 'flush' attributes.
468 - Any object with 'write' and 'flush' attributes.
391 """
469 """
392 return io.stdout if self._ostream is None else self._ostream
470 return io.stdout if self._ostream is None else self._ostream
393
471
394 def _set_ostream(self, val):
472 def _set_ostream(self, val):
395 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
473 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
396 self._ostream = val
474 self._ostream = val
397
475
398 ostream = property(_get_ostream, _set_ostream)
476 ostream = property(_get_ostream, _set_ostream)
399
477
400 def set_colors(self, *args, **kw):
478 def set_colors(self, *args, **kw):
401 """Shorthand access to the color table scheme selector method."""
479 """Shorthand access to the color table scheme selector method."""
402
480
403 # Set own color table
481 # Set own color table
404 self.color_scheme_table.set_active_scheme(*args, **kw)
482 self.color_scheme_table.set_active_scheme(*args, **kw)
405 # for convenience, set Colors to the active scheme
483 # for convenience, set Colors to the active scheme
406 self.Colors = self.color_scheme_table.active_colors
484 self.Colors = self.color_scheme_table.active_colors
407 # Also set colors of debugger
485 # Also set colors of debugger
408 if hasattr(self, 'pdb') and self.pdb is not None:
486 if hasattr(self, 'pdb') and self.pdb is not None:
409 self.pdb.set_colors(*args, **kw)
487 self.pdb.set_colors(*args, **kw)
410
488
411 def color_toggle(self):
489 def color_toggle(self):
412 """Toggle between the currently active color scheme and NoColor."""
490 """Toggle between the currently active color scheme and NoColor."""
413
491
414 if self.color_scheme_table.active_scheme_name == 'NoColor':
492 if self.color_scheme_table.active_scheme_name == 'NoColor':
415 self.color_scheme_table.set_active_scheme(self.old_scheme)
493 self.color_scheme_table.set_active_scheme(self.old_scheme)
416 self.Colors = self.color_scheme_table.active_colors
494 self.Colors = self.color_scheme_table.active_colors
417 else:
495 else:
418 self.old_scheme = self.color_scheme_table.active_scheme_name
496 self.old_scheme = self.color_scheme_table.active_scheme_name
419 self.color_scheme_table.set_active_scheme('NoColor')
497 self.color_scheme_table.set_active_scheme('NoColor')
420 self.Colors = self.color_scheme_table.active_colors
498 self.Colors = self.color_scheme_table.active_colors
421
499
422 def stb2text(self, stb):
500 def stb2text(self, stb):
423 """Convert a structured traceback (a list) to a string."""
501 """Convert a structured traceback (a list) to a string."""
424 return '\n'.join(stb)
502 return '\n'.join(stb)
425
503
426 def text(self, etype, value, tb, tb_offset=None, context=5):
504 def text(self, etype, value, tb, tb_offset=None, context=5):
427 """Return formatted traceback.
505 """Return formatted traceback.
428
506
429 Subclasses may override this if they add extra arguments.
507 Subclasses may override this if they add extra arguments.
430 """
508 """
431 tb_list = self.structured_traceback(etype, value, tb,
509 tb_list = self.structured_traceback(etype, value, tb,
432 tb_offset, context)
510 tb_offset, context)
433 return self.stb2text(tb_list)
511 return self.stb2text(tb_list)
434
512
435 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
513 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
436 context=5, mode=None):
514 context=5, mode=None):
437 """Return a list of traceback frames.
515 """Return a list of traceback frames.
438
516
439 Must be implemented by each class.
517 Must be implemented by each class.
440 """
518 """
441 raise NotImplementedError()
519 raise NotImplementedError()
442
520
443
521
444 #---------------------------------------------------------------------------
522 #---------------------------------------------------------------------------
445 class ListTB(TBTools):
523 class ListTB(TBTools):
446 """Print traceback information from a traceback list, with optional color.
524 """Print traceback information from a traceback list, with optional color.
447
525
448 Calling requires 3 arguments: (etype, evalue, elist)
526 Calling requires 3 arguments: (etype, evalue, elist)
449 as would be obtained by::
527 as would be obtained by::
450
528
451 etype, evalue, tb = sys.exc_info()
529 etype, evalue, tb = sys.exc_info()
452 if tb:
530 if tb:
453 elist = traceback.extract_tb(tb)
531 elist = traceback.extract_tb(tb)
454 else:
532 else:
455 elist = None
533 elist = None
456
534
457 It can thus be used by programs which need to process the traceback before
535 It can thus be used by programs which need to process the traceback before
458 printing (such as console replacements based on the code module from the
536 printing (such as console replacements based on the code module from the
459 standard library).
537 standard library).
460
538
461 Because they are meant to be called without a full traceback (only a
539 Because they are meant to be called without a full traceback (only a
462 list), instances of this class can't call the interactive pdb debugger."""
540 list), instances of this class can't call the interactive pdb debugger."""
463
541
464 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None):
542 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None):
465 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
543 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
466 ostream=ostream)
544 ostream=ostream)
467
545
468 def __call__(self, etype, value, elist):
546 def __call__(self, etype, value, elist):
469 self.ostream.flush()
547 self.ostream.flush()
470 self.ostream.write(self.text(etype, value, elist))
548 self.ostream.write(self.text(etype, value, elist))
471 self.ostream.write('\n')
549 self.ostream.write('\n')
472
550
473 def structured_traceback(self, etype, value, elist, tb_offset=None,
551 def structured_traceback(self, etype, value, elist, tb_offset=None,
474 context=5):
552 context=5):
475 """Return a color formatted string with the traceback info.
553 """Return a color formatted string with the traceback info.
476
554
477 Parameters
555 Parameters
478 ----------
556 ----------
479 etype : exception type
557 etype : exception type
480 Type of the exception raised.
558 Type of the exception raised.
481
559
482 value : object
560 value : object
483 Data stored in the exception
561 Data stored in the exception
484
562
485 elist : list
563 elist : list
486 List of frames, see class docstring for details.
564 List of frames, see class docstring for details.
487
565
488 tb_offset : int, optional
566 tb_offset : int, optional
489 Number of frames in the traceback to skip. If not given, the
567 Number of frames in the traceback to skip. If not given, the
490 instance value is used (set in constructor).
568 instance value is used (set in constructor).
491
569
492 context : int, optional
570 context : int, optional
493 Number of lines of context information to print.
571 Number of lines of context information to print.
494
572
495 Returns
573 Returns
496 -------
574 -------
497 String with formatted exception.
575 String with formatted exception.
498 """
576 """
499 tb_offset = self.tb_offset if tb_offset is None else tb_offset
577 tb_offset = self.tb_offset if tb_offset is None else tb_offset
500 Colors = self.Colors
578 Colors = self.Colors
501 out_list = []
579 out_list = []
502 if elist:
580 if elist:
503
581
504 if tb_offset and len(elist) > tb_offset:
582 if tb_offset and len(elist) > tb_offset:
505 elist = elist[tb_offset:]
583 elist = elist[tb_offset:]
506
584
507 out_list.append('Traceback %s(most recent call last)%s:' %
585 out_list.append('Traceback %s(most recent call last)%s:' %
508 (Colors.normalEm, Colors.Normal) + '\n')
586 (Colors.normalEm, Colors.Normal) + '\n')
509 out_list.extend(self._format_list(elist))
587 out_list.extend(self._format_list(elist))
510 # The exception info should be a single entry in the list.
588 # The exception info should be a single entry in the list.
511 lines = ''.join(self._format_exception_only(etype, value))
589 lines = ''.join(self._format_exception_only(etype, value))
512 out_list.append(lines)
590 out_list.append(lines)
513
591
514 # Note: this code originally read:
592 # Note: this code originally read:
515
593
516 ## for line in lines[:-1]:
594 ## for line in lines[:-1]:
517 ## out_list.append(" "+line)
595 ## out_list.append(" "+line)
518 ## out_list.append(lines[-1])
596 ## out_list.append(lines[-1])
519
597
520 # This means it was indenting everything but the last line by a little
598 # This means it was indenting everything but the last line by a little
521 # bit. I've disabled this for now, but if we see ugliness somewhere we
599 # bit. I've disabled this for now, but if we see ugliness somewhere we
522 # can restore it.
600 # can restore it.
523
601
524 return out_list
602 return out_list
525
603
526 def _format_list(self, extracted_list):
604 def _format_list(self, extracted_list):
527 """Format a list of traceback entry tuples for printing.
605 """Format a list of traceback entry tuples for printing.
528
606
529 Given a list of tuples as returned by extract_tb() or
607 Given a list of tuples as returned by extract_tb() or
530 extract_stack(), return a list of strings ready for printing.
608 extract_stack(), return a list of strings ready for printing.
531 Each string in the resulting list corresponds to the item with the
609 Each string in the resulting list corresponds to the item with the
532 same index in the argument list. Each string ends in a newline;
610 same index in the argument list. Each string ends in a newline;
533 the strings may contain internal newlines as well, for those items
611 the strings may contain internal newlines as well, for those items
534 whose source text line is not None.
612 whose source text line is not None.
535
613
536 Lifted almost verbatim from traceback.py
614 Lifted almost verbatim from traceback.py
537 """
615 """
538
616
539 Colors = self.Colors
617 Colors = self.Colors
540 list = []
618 list = []
541 for filename, lineno, name, line in extracted_list[:-1]:
619 for filename, lineno, name, line in extracted_list[:-1]:
542 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
620 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
543 (Colors.filename, py3compat.cast_unicode_py2(filename, "utf-8"), Colors.Normal,
621 (Colors.filename, py3compat.cast_unicode_py2(filename, "utf-8"), Colors.Normal,
544 Colors.lineno, lineno, Colors.Normal,
622 Colors.lineno, lineno, Colors.Normal,
545 Colors.name, py3compat.cast_unicode_py2(name, "utf-8"), Colors.Normal)
623 Colors.name, py3compat.cast_unicode_py2(name, "utf-8"), Colors.Normal)
546 if line:
624 if line:
547 item += ' %s\n' % line.strip()
625 item += ' %s\n' % line.strip()
548 list.append(item)
626 list.append(item)
549 # Emphasize the last entry
627 # Emphasize the last entry
550 filename, lineno, name, line = extracted_list[-1]
628 filename, lineno, name, line = extracted_list[-1]
551 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
629 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
552 (Colors.normalEm,
630 (Colors.normalEm,
553 Colors.filenameEm, py3compat.cast_unicode_py2(filename, "utf-8"), Colors.normalEm,
631 Colors.filenameEm, py3compat.cast_unicode_py2(filename, "utf-8"), Colors.normalEm,
554 Colors.linenoEm, lineno, Colors.normalEm,
632 Colors.linenoEm, lineno, Colors.normalEm,
555 Colors.nameEm, py3compat.cast_unicode_py2(name, "utf-8"), Colors.normalEm,
633 Colors.nameEm, py3compat.cast_unicode_py2(name, "utf-8"), Colors.normalEm,
556 Colors.Normal)
634 Colors.Normal)
557 if line:
635 if line:
558 item += '%s %s%s\n' % (Colors.line, line.strip(),
636 item += '%s %s%s\n' % (Colors.line, line.strip(),
559 Colors.Normal)
637 Colors.Normal)
560 list.append(item)
638 list.append(item)
561 return list
639 return list
562
640
563 def _format_exception_only(self, etype, value):
641 def _format_exception_only(self, etype, value):
564 """Format the exception part of a traceback.
642 """Format the exception part of a traceback.
565
643
566 The arguments are the exception type and value such as given by
644 The arguments are the exception type and value such as given by
567 sys.exc_info()[:2]. The return value is a list of strings, each ending
645 sys.exc_info()[:2]. The return value is a list of strings, each ending
568 in a newline. Normally, the list contains a single string; however,
646 in a newline. Normally, the list contains a single string; however,
569 for SyntaxError exceptions, it contains several lines that (when
647 for SyntaxError exceptions, it contains several lines that (when
570 printed) display detailed information about where the syntax error
648 printed) display detailed information about where the syntax error
571 occurred. The message indicating which exception occurred is the
649 occurred. The message indicating which exception occurred is the
572 always last string in the list.
650 always last string in the list.
573
651
574 Also lifted nearly verbatim from traceback.py
652 Also lifted nearly verbatim from traceback.py
575 """
653 """
576 have_filedata = False
654 have_filedata = False
577 Colors = self.Colors
655 Colors = self.Colors
578 list = []
656 list = []
579 stype = Colors.excName + etype.__name__ + Colors.Normal
657 stype = Colors.excName + etype.__name__ + Colors.Normal
580 if value is None:
658 if value is None:
581 # Not sure if this can still happen in Python 2.6 and above
659 # Not sure if this can still happen in Python 2.6 and above
582 list.append(py3compat.cast_unicode(stype) + '\n')
660 list.append(py3compat.cast_unicode(stype) + '\n')
583 else:
661 else:
584 if issubclass(etype, SyntaxError):
662 if issubclass(etype, SyntaxError):
585 have_filedata = True
663 have_filedata = True
586 if not value.filename: value.filename = "<string>"
664 if not value.filename: value.filename = "<string>"
587 if value.lineno:
665 if value.lineno:
588 lineno = value.lineno
666 lineno = value.lineno
589 textline = ulinecache.getline(value.filename, value.lineno)
667 textline = ulinecache.getline(value.filename, value.lineno)
590 else:
668 else:
591 lineno = 'unknown'
669 lineno = 'unknown'
592 textline = ''
670 textline = ''
593 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
671 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
594 (Colors.normalEm,
672 (Colors.normalEm,
595 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
673 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
596 Colors.linenoEm, lineno, Colors.Normal ))
674 Colors.linenoEm, lineno, Colors.Normal ))
597 if textline == '':
675 if textline == '':
598 textline = py3compat.cast_unicode(value.text, "utf-8")
676 textline = py3compat.cast_unicode(value.text, "utf-8")
599
677
600 if textline is not None:
678 if textline is not None:
601 i = 0
679 i = 0
602 while i < len(textline) and textline[i].isspace():
680 while i < len(textline) and textline[i].isspace():
603 i += 1
681 i += 1
604 list.append('%s %s%s\n' % (Colors.line,
682 list.append('%s %s%s\n' % (Colors.line,
605 textline.strip(),
683 textline.strip(),
606 Colors.Normal))
684 Colors.Normal))
607 if value.offset is not None:
685 if value.offset is not None:
608 s = ' '
686 s = ' '
609 for c in textline[i:value.offset - 1]:
687 for c in textline[i:value.offset - 1]:
610 if c.isspace():
688 if c.isspace():
611 s += c
689 s += c
612 else:
690 else:
613 s += ' '
691 s += ' '
614 list.append('%s%s^%s\n' % (Colors.caret, s,
692 list.append('%s%s^%s\n' % (Colors.caret, s,
615 Colors.Normal))
693 Colors.Normal))
616
694
617 try:
695 try:
618 s = value.msg
696 s = value.msg
619 except Exception:
697 except Exception:
620 s = self._some_str(value)
698 s = self._some_str(value)
621 if s:
699 if s:
622 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
700 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
623 Colors.Normal, s))
701 Colors.Normal, s))
624 else:
702 else:
625 list.append('%s\n' % str(stype))
703 list.append('%s\n' % str(stype))
626
704
627 # sync with user hooks
705 # sync with user hooks
628 if have_filedata:
706 if have_filedata:
629 ipinst = get_ipython()
707 ipinst = get_ipython()
630 if ipinst is not None:
708 if ipinst is not None:
631 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
709 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
632
710
633 return list
711 return list
634
712
635 def get_exception_only(self, etype, value):
713 def get_exception_only(self, etype, value):
636 """Only print the exception type and message, without a traceback.
714 """Only print the exception type and message, without a traceback.
637
715
638 Parameters
716 Parameters
639 ----------
717 ----------
640 etype : exception type
718 etype : exception type
641 value : exception value
719 value : exception value
642 """
720 """
643 return ListTB.structured_traceback(self, etype, value, [])
721 return ListTB.structured_traceback(self, etype, value, [])
644
722
645 def show_exception_only(self, etype, evalue):
723 def show_exception_only(self, etype, evalue):
646 """Only print the exception type and message, without a traceback.
724 """Only print the exception type and message, without a traceback.
647
725
648 Parameters
726 Parameters
649 ----------
727 ----------
650 etype : exception type
728 etype : exception type
651 value : exception value
729 value : exception value
652 """
730 """
653 # This method needs to use __call__ from *this* class, not the one from
731 # This method needs to use __call__ from *this* class, not the one from
654 # a subclass whose signature or behavior may be different
732 # a subclass whose signature or behavior may be different
655 ostream = self.ostream
733 ostream = self.ostream
656 ostream.flush()
734 ostream.flush()
657 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
735 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
658 ostream.flush()
736 ostream.flush()
659
737
660 def _some_str(self, value):
738 def _some_str(self, value):
661 # Lifted from traceback.py
739 # Lifted from traceback.py
662 try:
740 try:
663 return str(value)
741 return str(value)
664 except:
742 except:
665 return '<unprintable %s object>' % type(value).__name__
743 return '<unprintable %s object>' % type(value).__name__
666
744
667
745
668 #----------------------------------------------------------------------------
746 #----------------------------------------------------------------------------
669 class VerboseTB(TBTools):
747 class VerboseTB(TBTools):
670 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
748 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
671 of HTML. Requires inspect and pydoc. Crazy, man.
749 of HTML. Requires inspect and pydoc. Crazy, man.
672
750
673 Modified version which optionally strips the topmost entries from the
751 Modified version which optionally strips the topmost entries from the
674 traceback, to be used with alternate interpreters (because their own code
752 traceback, to be used with alternate interpreters (because their own code
675 would appear in the traceback)."""
753 would appear in the traceback)."""
676
754
677 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
755 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
678 tb_offset=0, long_header=False, include_vars=True,
756 tb_offset=0, long_header=False, include_vars=True,
679 check_cache=None):
757 check_cache=None):
680 """Specify traceback offset, headers and color scheme.
758 """Specify traceback offset, headers and color scheme.
681
759
682 Define how many frames to drop from the tracebacks. Calling it with
760 Define how many frames to drop from the tracebacks. Calling it with
683 tb_offset=1 allows use of this handler in interpreters which will have
761 tb_offset=1 allows use of this handler in interpreters which will have
684 their own code at the top of the traceback (VerboseTB will first
762 their own code at the top of the traceback (VerboseTB will first
685 remove that frame before printing the traceback info)."""
763 remove that frame before printing the traceback info)."""
686 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
764 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
687 ostream=ostream)
765 ostream=ostream)
688 self.tb_offset = tb_offset
766 self.tb_offset = tb_offset
689 self.long_header = long_header
767 self.long_header = long_header
690 self.include_vars = include_vars
768 self.include_vars = include_vars
691 # By default we use linecache.checkcache, but the user can provide a
769 # By default we use linecache.checkcache, but the user can provide a
692 # different check_cache implementation. This is used by the IPython
770 # different check_cache implementation. This is used by the IPython
693 # kernel to provide tracebacks for interactive code that is cached,
771 # kernel to provide tracebacks for interactive code that is cached,
694 # by a compiler instance that flushes the linecache but preserves its
772 # by a compiler instance that flushes the linecache but preserves its
695 # own code cache.
773 # own code cache.
696 if check_cache is None:
774 if check_cache is None:
697 check_cache = linecache.checkcache
775 check_cache = linecache.checkcache
698 self.check_cache = check_cache
776 self.check_cache = check_cache
699
777
700 def format_records(self, records):
778 def format_records(self, records):
701 Colors = self.Colors # just a shorthand + quicker name lookup
779 Colors = self.Colors # just a shorthand + quicker name lookup
702 ColorsNormal = Colors.Normal # used a lot
780 ColorsNormal = Colors.Normal # used a lot
703 col_scheme = self.color_scheme_table.active_scheme_name
781 col_scheme = self.color_scheme_table.active_scheme_name
704 indent = ' ' * INDENT_SIZE
782 indent = ' ' * INDENT_SIZE
705 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
783 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
706 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
784 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
707 frames = []
785 frames = []
708 # build some color string templates outside these nested loops
786 # build some color string templates outside these nested loops
709 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
787 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
710 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
788 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
711 ColorsNormal)
789 ColorsNormal)
712 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
790 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
713 (Colors.vName, Colors.valEm, ColorsNormal)
791 (Colors.vName, Colors.valEm, ColorsNormal)
714 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
792 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
715 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
793 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
716 Colors.vName, ColorsNormal)
794 Colors.vName, ColorsNormal)
717 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
795 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
718
796
719 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
797 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
720 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line,
798 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line,
721 ColorsNormal)
799 ColorsNormal)
722
800
723 abspath = os.path.abspath
801 abspath = os.path.abspath
724 for frame, file, lnum, func, lines, index in records:
802 for frame, file, lnum, func, lines, index in records:
725 #print '*** record:',file,lnum,func,lines,index # dbg
803 #print '*** record:',file,lnum,func,lines,index # dbg
726 if not file:
804 if not file:
727 file = '?'
805 file = '?'
728 elif file.startswith(str("<")) and file.endswith(str(">")):
806 elif file.startswith(str("<")) and file.endswith(str(">")):
729 # Not a real filename, no problem...
807 # Not a real filename, no problem...
730 pass
808 pass
731 elif not os.path.isabs(file):
809 elif not os.path.isabs(file):
732 # Try to make the filename absolute by trying all
810 # Try to make the filename absolute by trying all
733 # sys.path entries (which is also what linecache does)
811 # sys.path entries (which is also what linecache does)
734 for dirname in sys.path:
812 for dirname in sys.path:
735 try:
813 try:
736 fullname = os.path.join(dirname, file)
814 fullname = os.path.join(dirname, file)
737 if os.path.isfile(fullname):
815 if os.path.isfile(fullname):
738 file = os.path.abspath(fullname)
816 file = os.path.abspath(fullname)
739 break
817 break
740 except Exception:
818 except Exception:
741 # Just in case that sys.path contains very
819 # Just in case that sys.path contains very
742 # strange entries...
820 # strange entries...
743 pass
821 pass
744
822
745 file = py3compat.cast_unicode(file, util_path.fs_encoding)
823 file = py3compat.cast_unicode(file, util_path.fs_encoding)
746 link = tpl_link % file
824 link = tpl_link % file
747 args, varargs, varkw, locals = inspect.getargvalues(frame)
825 args, varargs, varkw, locals = fixed_getargvalues(frame)
748
826
749 if func == '?':
827 if func == '?':
750 call = ''
828 call = ''
751 else:
829 else:
752 # Decide whether to include variable details or not
830 # Decide whether to include variable details or not
753 var_repr = self.include_vars and eqrepr or nullrepr
831 var_repr = self.include_vars and eqrepr or nullrepr
754 try:
832 try:
755 call = tpl_call % (func, inspect.formatargvalues(args,
833 call = tpl_call % (func, inspect.formatargvalues(args,
756 varargs, varkw,
834 varargs, varkw,
757 locals, formatvalue=var_repr))
835 locals, formatvalue=var_repr))
758 except KeyError:
836 except KeyError:
759 # This happens in situations like errors inside generator
837 # This happens in situations like errors inside generator
760 # expressions, where local variables are listed in the
838 # expressions, where local variables are listed in the
761 # line, but can't be extracted from the frame. I'm not
839 # line, but can't be extracted from the frame. I'm not
762 # 100% sure this isn't actually a bug in inspect itself,
840 # 100% sure this isn't actually a bug in inspect itself,
763 # but since there's no info for us to compute with, the
841 # but since there's no info for us to compute with, the
764 # best we can do is report the failure and move on. Here
842 # best we can do is report the failure and move on. Here
765 # we must *not* call any traceback construction again,
843 # we must *not* call any traceback construction again,
766 # because that would mess up use of %debug later on. So we
844 # because that would mess up use of %debug later on. So we
767 # simply report the failure and move on. The only
845 # simply report the failure and move on. The only
768 # limitation will be that this frame won't have locals
846 # limitation will be that this frame won't have locals
769 # listed in the call signature. Quite subtle problem...
847 # listed in the call signature. Quite subtle problem...
770 # I can't think of a good way to validate this in a unit
848 # I can't think of a good way to validate this in a unit
771 # test, but running a script consisting of:
849 # test, but running a script consisting of:
772 # dict( (k,v.strip()) for (k,v) in range(10) )
850 # dict( (k,v.strip()) for (k,v) in range(10) )
773 # will illustrate the error, if this exception catch is
851 # will illustrate the error, if this exception catch is
774 # disabled.
852 # disabled.
775 call = tpl_call_fail % func
853 call = tpl_call_fail % func
776
854
777 # Don't attempt to tokenize binary files.
855 # Don't attempt to tokenize binary files.
778 if file.endswith(('.so', '.pyd', '.dll')):
856 if file.endswith(('.so', '.pyd', '.dll')):
779 frames.append('%s %s\n' % (link, call))
857 frames.append('%s %s\n' % (link, call))
780 continue
858 continue
781 elif file.endswith(('.pyc', '.pyo')):
859 elif file.endswith(('.pyc', '.pyo')):
782 # Look up the corresponding source file.
860 # Look up the corresponding source file.
783 file = openpy.source_from_cache(file)
861 file = openpy.source_from_cache(file)
784
862
785 def linereader(file=file, lnum=[lnum], getline=ulinecache.getline):
863 def linereader(file=file, lnum=[lnum], getline=ulinecache.getline):
786 line = getline(file, lnum[0])
864 line = getline(file, lnum[0])
787 lnum[0] += 1
865 lnum[0] += 1
788 return line
866 return line
789
867
790 # Build the list of names on this line of code where the exception
868 # Build the list of names on this line of code where the exception
791 # occurred.
869 # occurred.
792 try:
870 try:
793 names = []
871 names = []
794 name_cont = False
872 name_cont = False
795
873
796 for token_type, token, start, end, line in generate_tokens(linereader):
874 for token_type, token, start, end, line in generate_tokens(linereader):
797 # build composite names
875 # build composite names
798 if token_type == tokenize.NAME and token not in keyword.kwlist:
876 if token_type == tokenize.NAME and token not in keyword.kwlist:
799 if name_cont:
877 if name_cont:
800 # Continuation of a dotted name
878 # Continuation of a dotted name
801 try:
879 try:
802 names[-1].append(token)
880 names[-1].append(token)
803 except IndexError:
881 except IndexError:
804 names.append([token])
882 names.append([token])
805 name_cont = False
883 name_cont = False
806 else:
884 else:
807 # Regular new names. We append everything, the caller
885 # Regular new names. We append everything, the caller
808 # will be responsible for pruning the list later. It's
886 # will be responsible for pruning the list later. It's
809 # very tricky to try to prune as we go, b/c composite
887 # very tricky to try to prune as we go, b/c composite
810 # names can fool us. The pruning at the end is easy
888 # names can fool us. The pruning at the end is easy
811 # to do (or the caller can print a list with repeated
889 # to do (or the caller can print a list with repeated
812 # names if so desired.
890 # names if so desired.
813 names.append([token])
891 names.append([token])
814 elif token == '.':
892 elif token == '.':
815 name_cont = True
893 name_cont = True
816 elif token_type == tokenize.NEWLINE:
894 elif token_type == tokenize.NEWLINE:
817 break
895 break
818
896
819 except (IndexError, UnicodeDecodeError, SyntaxError):
897 except (IndexError, UnicodeDecodeError, SyntaxError):
820 # signals exit of tokenizer
898 # signals exit of tokenizer
821 # SyntaxError can occur if the file is not actually Python
899 # SyntaxError can occur if the file is not actually Python
822 # - see gh-6300
900 # - see gh-6300
823 pass
901 pass
824 except tokenize.TokenError as msg:
902 except tokenize.TokenError as msg:
825 _m = ("An unexpected error occurred while tokenizing input\n"
903 _m = ("An unexpected error occurred while tokenizing input\n"
826 "The following traceback may be corrupted or invalid\n"
904 "The following traceback may be corrupted or invalid\n"
827 "The error message is: %s\n" % msg)
905 "The error message is: %s\n" % msg)
828 error(_m)
906 error(_m)
829
907
830 # Join composite names (e.g. "dict.fromkeys")
908 # Join composite names (e.g. "dict.fromkeys")
831 names = ['.'.join(n) for n in names]
909 names = ['.'.join(n) for n in names]
832 # prune names list of duplicates, but keep the right order
910 # prune names list of duplicates, but keep the right order
833 unique_names = uniq_stable(names)
911 unique_names = uniq_stable(names)
834
912
835 # Start loop over vars
913 # Start loop over vars
836 lvals = []
914 lvals = []
837 if self.include_vars:
915 if self.include_vars:
838 for name_full in unique_names:
916 for name_full in unique_names:
839 name_base = name_full.split('.', 1)[0]
917 name_base = name_full.split('.', 1)[0]
840 if name_base in frame.f_code.co_varnames:
918 if name_base in frame.f_code.co_varnames:
841 if name_base in locals:
919 if name_base in locals:
842 try:
920 try:
843 value = repr(eval(name_full, locals))
921 value = repr(eval(name_full, locals))
844 except:
922 except:
845 value = undefined
923 value = undefined
846 else:
924 else:
847 value = undefined
925 value = undefined
848 name = tpl_local_var % name_full
926 name = tpl_local_var % name_full
849 else:
927 else:
850 if name_base in frame.f_globals:
928 if name_base in frame.f_globals:
851 try:
929 try:
852 value = repr(eval(name_full, frame.f_globals))
930 value = repr(eval(name_full, frame.f_globals))
853 except:
931 except:
854 value = undefined
932 value = undefined
855 else:
933 else:
856 value = undefined
934 value = undefined
857 name = tpl_global_var % name_full
935 name = tpl_global_var % name_full
858 lvals.append(tpl_name_val % (name, value))
936 lvals.append(tpl_name_val % (name, value))
859 if lvals:
937 if lvals:
860 lvals = '%s%s' % (indent, em_normal.join(lvals))
938 lvals = '%s%s' % (indent, em_normal.join(lvals))
861 else:
939 else:
862 lvals = ''
940 lvals = ''
863
941
864 level = '%s %s\n' % (link, call)
942 level = '%s %s\n' % (link, call)
865
943
866 if index is None:
944 if index is None:
867 frames.append(level)
945 frames.append(level)
868 else:
946 else:
869 frames.append('%s%s' % (level, ''.join(
947 frames.append('%s%s' % (level, ''.join(
870 _format_traceback_lines(lnum, index, lines, Colors, lvals,
948 _format_traceback_lines(lnum, index, lines, Colors, lvals,
871 col_scheme))))
949 col_scheme))))
872
950
873 return frames
951 return frames
874
952
875 def prepare_chained_exception_message(self, cause):
953 def prepare_chained_exception_message(self, cause):
876 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
954 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
877 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
955 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
878
956
879 if cause:
957 if cause:
880 message = [[direct_cause]]
958 message = [[direct_cause]]
881 else:
959 else:
882 message = [[exception_during_handling]]
960 message = [[exception_during_handling]]
883 return message
961 return message
884
962
885 def prepare_header(self, etype, long_version=False):
963 def prepare_header(self, etype, long_version=False):
886 colors = self.Colors # just a shorthand + quicker name lookup
964 colors = self.Colors # just a shorthand + quicker name lookup
887 colorsnormal = colors.Normal # used a lot
965 colorsnormal = colors.Normal # used a lot
888 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
966 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
889 if long_version:
967 if long_version:
890 # Header with the exception type, python version, and date
968 # Header with the exception type, python version, and date
891 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
969 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
892 date = time.ctime(time.time())
970 date = time.ctime(time.time())
893
971
894 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * 75, colorsnormal,
972 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * 75, colorsnormal,
895 exc, ' ' * (75 - len(str(etype)) - len(pyver)),
973 exc, ' ' * (75 - len(str(etype)) - len(pyver)),
896 pyver, date.rjust(75) )
974 pyver, date.rjust(75) )
897 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
975 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
898 "\ncalls leading up to the error, with the most recent (innermost) call last."
976 "\ncalls leading up to the error, with the most recent (innermost) call last."
899 else:
977 else:
900 # Simplified header
978 # Simplified header
901 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
979 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
902 rjust(75 - len(str(etype))) )
980 rjust(75 - len(str(etype))) )
903
981
904 return head
982 return head
905
983
906 def format_exception(self, etype, evalue):
984 def format_exception(self, etype, evalue):
907 colors = self.Colors # just a shorthand + quicker name lookup
985 colors = self.Colors # just a shorthand + quicker name lookup
908 colorsnormal = colors.Normal # used a lot
986 colorsnormal = colors.Normal # used a lot
909 indent = ' ' * INDENT_SIZE
987 indent = ' ' * INDENT_SIZE
910 # Get (safely) a string form of the exception info
988 # Get (safely) a string form of the exception info
911 try:
989 try:
912 etype_str, evalue_str = map(str, (etype, evalue))
990 etype_str, evalue_str = map(str, (etype, evalue))
913 except:
991 except:
914 # User exception is improperly defined.
992 # User exception is improperly defined.
915 etype, evalue = str, sys.exc_info()[:2]
993 etype, evalue = str, sys.exc_info()[:2]
916 etype_str, evalue_str = map(str, (etype, evalue))
994 etype_str, evalue_str = map(str, (etype, evalue))
917 # ... and format it
995 # ... and format it
918 exception = ['%s%s%s: %s' % (colors.excName, etype_str,
996 exception = ['%s%s%s: %s' % (colors.excName, etype_str,
919 colorsnormal, py3compat.cast_unicode(evalue_str))]
997 colorsnormal, py3compat.cast_unicode(evalue_str))]
920
998
921 if (not py3compat.PY3) and type(evalue) is types.InstanceType:
999 if (not py3compat.PY3) and type(evalue) is types.InstanceType:
922 try:
1000 try:
923 names = [w for w in dir(evalue) if isinstance(w, py3compat.string_types)]
1001 names = [w for w in dir(evalue) if isinstance(w, py3compat.string_types)]
924 except:
1002 except:
925 # Every now and then, an object with funny internals blows up
1003 # Every now and then, an object with funny internals blows up
926 # when dir() is called on it. We do the best we can to report
1004 # when dir() is called on it. We do the best we can to report
927 # the problem and continue
1005 # the problem and continue
928 _m = '%sException reporting error (object with broken dir())%s:'
1006 _m = '%sException reporting error (object with broken dir())%s:'
929 exception.append(_m % (colors.excName, colorsnormal))
1007 exception.append(_m % (colors.excName, colorsnormal))
930 etype_str, evalue_str = map(str, sys.exc_info()[:2])
1008 etype_str, evalue_str = map(str, sys.exc_info()[:2])
931 exception.append('%s%s%s: %s' % (colors.excName, etype_str,
1009 exception.append('%s%s%s: %s' % (colors.excName, etype_str,
932 colorsnormal, py3compat.cast_unicode(evalue_str)))
1010 colorsnormal, py3compat.cast_unicode(evalue_str)))
933 names = []
1011 names = []
934 for name in names:
1012 for name in names:
935 value = text_repr(getattr(evalue, name))
1013 value = text_repr(getattr(evalue, name))
936 exception.append('\n%s%s = %s' % (indent, name, value))
1014 exception.append('\n%s%s = %s' % (indent, name, value))
937
1015
938 return exception
1016 return exception
939
1017
940 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
1018 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
941 # some locals
1019 # some locals
942 try:
1020 try:
943 etype = etype.__name__
1021 etype = etype.__name__
944 except AttributeError:
1022 except AttributeError:
945 pass
1023 pass
946
1024
947 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1025 tb_offset = self.tb_offset if tb_offset is None else tb_offset
948 head = self.prepare_header(etype, self.long_header)
1026 head = self.prepare_header(etype, self.long_header)
949 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
1027 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
950
1028
951 frames = self.format_records(records)
1029 frames = self.format_records(records)
952 if records is None:
1030 if records is None:
953 return ""
1031 return ""
954
1032
955 formatted_exception = self.format_exception(etype, evalue)
1033 formatted_exception = self.format_exception(etype, evalue)
956 if records:
1034 if records:
957 filepath, lnum = records[-1][1:3]
1035 filepath, lnum = records[-1][1:3]
958 filepath = os.path.abspath(filepath)
1036 filepath = os.path.abspath(filepath)
959 ipinst = get_ipython()
1037 ipinst = get_ipython()
960 if ipinst is not None:
1038 if ipinst is not None:
961 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
1039 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
962
1040
963 return [[head] + frames + [''.join(formatted_exception[0])]]
1041 return [[head] + frames + [''.join(formatted_exception[0])]]
964
1042
965 def get_records(self, etb, number_of_lines_of_context, tb_offset):
1043 def get_records(self, etb, number_of_lines_of_context, tb_offset):
966 try:
1044 try:
967 # Try the default getinnerframes and Alex's: Alex's fixes some
1045 # Try the default getinnerframes and Alex's: Alex's fixes some
968 # problems, but it generates empty tracebacks for console errors
1046 # problems, but it generates empty tracebacks for console errors
969 # (5 blanks lines) where none should be returned.
1047 # (5 blanks lines) where none should be returned.
970 return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)
1048 return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)
971 except:
1049 except:
972 # FIXME: I've been getting many crash reports from python 2.3
1050 # FIXME: I've been getting many crash reports from python 2.3
973 # users, traceable to inspect.py. If I can find a small test-case
1051 # users, traceable to inspect.py. If I can find a small test-case
974 # to reproduce this, I should either write a better workaround or
1052 # to reproduce this, I should either write a better workaround or
975 # file a bug report against inspect (if that's the real problem).
1053 # file a bug report against inspect (if that's the real problem).
976 # So far, I haven't been able to find an isolated example to
1054 # So far, I haven't been able to find an isolated example to
977 # reproduce the problem.
1055 # reproduce the problem.
978 inspect_error()
1056 inspect_error()
979 traceback.print_exc(file=self.ostream)
1057 traceback.print_exc(file=self.ostream)
980 info('\nUnfortunately, your original traceback can not be constructed.\n')
1058 info('\nUnfortunately, your original traceback can not be constructed.\n')
981 return None
1059 return None
982
1060
983 def get_parts_of_chained_exception(self, evalue):
1061 def get_parts_of_chained_exception(self, evalue):
984 def get_chained_exception(exception_value):
1062 def get_chained_exception(exception_value):
985 cause = getattr(exception_value, '__cause__', None)
1063 cause = getattr(exception_value, '__cause__', None)
986 if cause:
1064 if cause:
987 return cause
1065 return cause
988 if getattr(exception_value, '__suppress_context__', False):
1066 if getattr(exception_value, '__suppress_context__', False):
989 return None
1067 return None
990 return getattr(exception_value, '__context__', None)
1068 return getattr(exception_value, '__context__', None)
991
1069
992 chained_evalue = get_chained_exception(evalue)
1070 chained_evalue = get_chained_exception(evalue)
993
1071
994 if chained_evalue:
1072 if chained_evalue:
995 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
1073 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
996
1074
997 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
1075 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
998 number_of_lines_of_context=5):
1076 number_of_lines_of_context=5):
999 """Return a nice text document describing the traceback."""
1077 """Return a nice text document describing the traceback."""
1000
1078
1001 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
1079 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
1002 tb_offset)
1080 tb_offset)
1003
1081
1004 colors = self.Colors # just a shorthand + quicker name lookup
1082 colors = self.Colors # just a shorthand + quicker name lookup
1005 colorsnormal = colors.Normal # used a lot
1083 colorsnormal = colors.Normal # used a lot
1006 head = '%s%s%s' % (colors.topline, '-' * 75, colorsnormal)
1084 head = '%s%s%s' % (colors.topline, '-' * 75, colorsnormal)
1007 structured_traceback_parts = [head]
1085 structured_traceback_parts = [head]
1008 if py3compat.PY3:
1086 if py3compat.PY3:
1009 chained_exceptions_tb_offset = 0
1087 chained_exceptions_tb_offset = 0
1010 lines_of_context = 3
1088 lines_of_context = 3
1011 formatted_exceptions = formatted_exception
1089 formatted_exceptions = formatted_exception
1012 exception = self.get_parts_of_chained_exception(evalue)
1090 exception = self.get_parts_of_chained_exception(evalue)
1013 if exception:
1091 if exception:
1014 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1092 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1015 etype, evalue, etb = exception
1093 etype, evalue, etb = exception
1016 else:
1094 else:
1017 evalue = None
1095 evalue = None
1018 while evalue:
1096 while evalue:
1019 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
1097 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
1020 chained_exceptions_tb_offset)
1098 chained_exceptions_tb_offset)
1021 exception = self.get_parts_of_chained_exception(evalue)
1099 exception = self.get_parts_of_chained_exception(evalue)
1022
1100
1023 if exception:
1101 if exception:
1024 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1102 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1025 etype, evalue, etb = exception
1103 etype, evalue, etb = exception
1026 else:
1104 else:
1027 evalue = None
1105 evalue = None
1028
1106
1029 # we want to see exceptions in a reversed order:
1107 # we want to see exceptions in a reversed order:
1030 # the first exception should be on top
1108 # the first exception should be on top
1031 for formatted_exception in reversed(formatted_exceptions):
1109 for formatted_exception in reversed(formatted_exceptions):
1032 structured_traceback_parts += formatted_exception
1110 structured_traceback_parts += formatted_exception
1033 else:
1111 else:
1034 structured_traceback_parts += formatted_exception[0]
1112 structured_traceback_parts += formatted_exception[0]
1035
1113
1036 return structured_traceback_parts
1114 return structured_traceback_parts
1037
1115
1038 def debugger(self, force=False):
1116 def debugger(self, force=False):
1039 """Call up the pdb debugger if desired, always clean up the tb
1117 """Call up the pdb debugger if desired, always clean up the tb
1040 reference.
1118 reference.
1041
1119
1042 Keywords:
1120 Keywords:
1043
1121
1044 - force(False): by default, this routine checks the instance call_pdb
1122 - force(False): by default, this routine checks the instance call_pdb
1045 flag and does not actually invoke the debugger if the flag is false.
1123 flag and does not actually invoke the debugger if the flag is false.
1046 The 'force' option forces the debugger to activate even if the flag
1124 The 'force' option forces the debugger to activate even if the flag
1047 is false.
1125 is false.
1048
1126
1049 If the call_pdb flag is set, the pdb interactive debugger is
1127 If the call_pdb flag is set, the pdb interactive debugger is
1050 invoked. In all cases, the self.tb reference to the current traceback
1128 invoked. In all cases, the self.tb reference to the current traceback
1051 is deleted to prevent lingering references which hamper memory
1129 is deleted to prevent lingering references which hamper memory
1052 management.
1130 management.
1053
1131
1054 Note that each call to pdb() does an 'import readline', so if your app
1132 Note that each call to pdb() does an 'import readline', so if your app
1055 requires a special setup for the readline completers, you'll have to
1133 requires a special setup for the readline completers, you'll have to
1056 fix that by hand after invoking the exception handler."""
1134 fix that by hand after invoking the exception handler."""
1057
1135
1058 if force or self.call_pdb:
1136 if force or self.call_pdb:
1059 if self.pdb is None:
1137 if self.pdb is None:
1060 self.pdb = debugger.Pdb(
1138 self.pdb = debugger.Pdb(
1061 self.color_scheme_table.active_scheme_name)
1139 self.color_scheme_table.active_scheme_name)
1062 # the system displayhook may have changed, restore the original
1140 # the system displayhook may have changed, restore the original
1063 # for pdb
1141 # for pdb
1064 display_trap = DisplayTrap(hook=sys.__displayhook__)
1142 display_trap = DisplayTrap(hook=sys.__displayhook__)
1065 with display_trap:
1143 with display_trap:
1066 self.pdb.reset()
1144 self.pdb.reset()
1067 # Find the right frame so we don't pop up inside ipython itself
1145 # Find the right frame so we don't pop up inside ipython itself
1068 if hasattr(self, 'tb') and self.tb is not None:
1146 if hasattr(self, 'tb') and self.tb is not None:
1069 etb = self.tb
1147 etb = self.tb
1070 else:
1148 else:
1071 etb = self.tb = sys.last_traceback
1149 etb = self.tb = sys.last_traceback
1072 while self.tb is not None and self.tb.tb_next is not None:
1150 while self.tb is not None and self.tb.tb_next is not None:
1073 self.tb = self.tb.tb_next
1151 self.tb = self.tb.tb_next
1074 if etb and etb.tb_next:
1152 if etb and etb.tb_next:
1075 etb = etb.tb_next
1153 etb = etb.tb_next
1076 self.pdb.botframe = etb.tb_frame
1154 self.pdb.botframe = etb.tb_frame
1077 self.pdb.interaction(self.tb.tb_frame, self.tb)
1155 self.pdb.interaction(self.tb.tb_frame, self.tb)
1078
1156
1079 if hasattr(self, 'tb'):
1157 if hasattr(self, 'tb'):
1080 del self.tb
1158 del self.tb
1081
1159
1082 def handler(self, info=None):
1160 def handler(self, info=None):
1083 (etype, evalue, etb) = info or sys.exc_info()
1161 (etype, evalue, etb) = info or sys.exc_info()
1084 self.tb = etb
1162 self.tb = etb
1085 ostream = self.ostream
1163 ostream = self.ostream
1086 ostream.flush()
1164 ostream.flush()
1087 ostream.write(self.text(etype, evalue, etb))
1165 ostream.write(self.text(etype, evalue, etb))
1088 ostream.write('\n')
1166 ostream.write('\n')
1089 ostream.flush()
1167 ostream.flush()
1090
1168
1091 # Changed so an instance can just be called as VerboseTB_inst() and print
1169 # Changed so an instance can just be called as VerboseTB_inst() and print
1092 # out the right info on its own.
1170 # out the right info on its own.
1093 def __call__(self, etype=None, evalue=None, etb=None):
1171 def __call__(self, etype=None, evalue=None, etb=None):
1094 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1172 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1095 if etb is None:
1173 if etb is None:
1096 self.handler()
1174 self.handler()
1097 else:
1175 else:
1098 self.handler((etype, evalue, etb))
1176 self.handler((etype, evalue, etb))
1099 try:
1177 try:
1100 self.debugger()
1178 self.debugger()
1101 except KeyboardInterrupt:
1179 except KeyboardInterrupt:
1102 print("\nKeyboardInterrupt")
1180 print("\nKeyboardInterrupt")
1103
1181
1104
1182
1105 #----------------------------------------------------------------------------
1183 #----------------------------------------------------------------------------
1106 class FormattedTB(VerboseTB, ListTB):
1184 class FormattedTB(VerboseTB, ListTB):
1107 """Subclass ListTB but allow calling with a traceback.
1185 """Subclass ListTB but allow calling with a traceback.
1108
1186
1109 It can thus be used as a sys.excepthook for Python > 2.1.
1187 It can thus be used as a sys.excepthook for Python > 2.1.
1110
1188
1111 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1189 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1112
1190
1113 Allows a tb_offset to be specified. This is useful for situations where
1191 Allows a tb_offset to be specified. This is useful for situations where
1114 one needs to remove a number of topmost frames from the traceback (such as
1192 one needs to remove a number of topmost frames from the traceback (such as
1115 occurs with python programs that themselves execute other python code,
1193 occurs with python programs that themselves execute other python code,
1116 like Python shells). """
1194 like Python shells). """
1117
1195
1118 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1196 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1119 ostream=None,
1197 ostream=None,
1120 tb_offset=0, long_header=False, include_vars=False,
1198 tb_offset=0, long_header=False, include_vars=False,
1121 check_cache=None):
1199 check_cache=None):
1122
1200
1123 # NEVER change the order of this list. Put new modes at the end:
1201 # NEVER change the order of this list. Put new modes at the end:
1124 self.valid_modes = ['Plain', 'Context', 'Verbose']
1202 self.valid_modes = ['Plain', 'Context', 'Verbose']
1125 self.verbose_modes = self.valid_modes[1:3]
1203 self.verbose_modes = self.valid_modes[1:3]
1126
1204
1127 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1205 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1128 ostream=ostream, tb_offset=tb_offset,
1206 ostream=ostream, tb_offset=tb_offset,
1129 long_header=long_header, include_vars=include_vars,
1207 long_header=long_header, include_vars=include_vars,
1130 check_cache=check_cache)
1208 check_cache=check_cache)
1131
1209
1132 # Different types of tracebacks are joined with different separators to
1210 # Different types of tracebacks are joined with different separators to
1133 # form a single string. They are taken from this dict
1211 # form a single string. They are taken from this dict
1134 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1212 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1135 # set_mode also sets the tb_join_char attribute
1213 # set_mode also sets the tb_join_char attribute
1136 self.set_mode(mode)
1214 self.set_mode(mode)
1137
1215
1138 def _extract_tb(self, tb):
1216 def _extract_tb(self, tb):
1139 if tb:
1217 if tb:
1140 return traceback.extract_tb(tb)
1218 return traceback.extract_tb(tb)
1141 else:
1219 else:
1142 return None
1220 return None
1143
1221
1144 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1222 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1145 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1223 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1146 mode = self.mode
1224 mode = self.mode
1147 if mode in self.verbose_modes:
1225 if mode in self.verbose_modes:
1148 # Verbose modes need a full traceback
1226 # Verbose modes need a full traceback
1149 return VerboseTB.structured_traceback(
1227 return VerboseTB.structured_traceback(
1150 self, etype, value, tb, tb_offset, number_of_lines_of_context
1228 self, etype, value, tb, tb_offset, number_of_lines_of_context
1151 )
1229 )
1152 else:
1230 else:
1153 # We must check the source cache because otherwise we can print
1231 # We must check the source cache because otherwise we can print
1154 # out-of-date source code.
1232 # out-of-date source code.
1155 self.check_cache()
1233 self.check_cache()
1156 # Now we can extract and format the exception
1234 # Now we can extract and format the exception
1157 elist = self._extract_tb(tb)
1235 elist = self._extract_tb(tb)
1158 return ListTB.structured_traceback(
1236 return ListTB.structured_traceback(
1159 self, etype, value, elist, tb_offset, number_of_lines_of_context
1237 self, etype, value, elist, tb_offset, number_of_lines_of_context
1160 )
1238 )
1161
1239
1162 def stb2text(self, stb):
1240 def stb2text(self, stb):
1163 """Convert a structured traceback (a list) to a string."""
1241 """Convert a structured traceback (a list) to a string."""
1164 return self.tb_join_char.join(stb)
1242 return self.tb_join_char.join(stb)
1165
1243
1166
1244
1167 def set_mode(self, mode=None):
1245 def set_mode(self, mode=None):
1168 """Switch to the desired mode.
1246 """Switch to the desired mode.
1169
1247
1170 If mode is not specified, cycles through the available modes."""
1248 If mode is not specified, cycles through the available modes."""
1171
1249
1172 if not mode:
1250 if not mode:
1173 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1251 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1174 len(self.valid_modes)
1252 len(self.valid_modes)
1175 self.mode = self.valid_modes[new_idx]
1253 self.mode = self.valid_modes[new_idx]
1176 elif mode not in self.valid_modes:
1254 elif mode not in self.valid_modes:
1177 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
1255 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
1178 'Valid modes: ' + str(self.valid_modes))
1256 'Valid modes: ' + str(self.valid_modes))
1179 else:
1257 else:
1180 self.mode = mode
1258 self.mode = mode
1181 # include variable details only in 'Verbose' mode
1259 # include variable details only in 'Verbose' mode
1182 self.include_vars = (self.mode == self.valid_modes[2])
1260 self.include_vars = (self.mode == self.valid_modes[2])
1183 # Set the join character for generating text tracebacks
1261 # Set the join character for generating text tracebacks
1184 self.tb_join_char = self._join_chars[self.mode]
1262 self.tb_join_char = self._join_chars[self.mode]
1185
1263
1186 # some convenient shortcuts
1264 # some convenient shortcuts
1187 def plain(self):
1265 def plain(self):
1188 self.set_mode(self.valid_modes[0])
1266 self.set_mode(self.valid_modes[0])
1189
1267
1190 def context(self):
1268 def context(self):
1191 self.set_mode(self.valid_modes[1])
1269 self.set_mode(self.valid_modes[1])
1192
1270
1193 def verbose(self):
1271 def verbose(self):
1194 self.set_mode(self.valid_modes[2])
1272 self.set_mode(self.valid_modes[2])
1195
1273
1196
1274
1197 #----------------------------------------------------------------------------
1275 #----------------------------------------------------------------------------
1198 class AutoFormattedTB(FormattedTB):
1276 class AutoFormattedTB(FormattedTB):
1199 """A traceback printer which can be called on the fly.
1277 """A traceback printer which can be called on the fly.
1200
1278
1201 It will find out about exceptions by itself.
1279 It will find out about exceptions by itself.
1202
1280
1203 A brief example::
1281 A brief example::
1204
1282
1205 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1283 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1206 try:
1284 try:
1207 ...
1285 ...
1208 except:
1286 except:
1209 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1287 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1210 """
1288 """
1211
1289
1212 def __call__(self, etype=None, evalue=None, etb=None,
1290 def __call__(self, etype=None, evalue=None, etb=None,
1213 out=None, tb_offset=None):
1291 out=None, tb_offset=None):
1214 """Print out a formatted exception traceback.
1292 """Print out a formatted exception traceback.
1215
1293
1216 Optional arguments:
1294 Optional arguments:
1217 - out: an open file-like object to direct output to.
1295 - out: an open file-like object to direct output to.
1218
1296
1219 - tb_offset: the number of frames to skip over in the stack, on a
1297 - tb_offset: the number of frames to skip over in the stack, on a
1220 per-call basis (this overrides temporarily the instance's tb_offset
1298 per-call basis (this overrides temporarily the instance's tb_offset
1221 given at initialization time. """
1299 given at initialization time. """
1222
1300
1223 if out is None:
1301 if out is None:
1224 out = self.ostream
1302 out = self.ostream
1225 out.flush()
1303 out.flush()
1226 out.write(self.text(etype, evalue, etb, tb_offset))
1304 out.write(self.text(etype, evalue, etb, tb_offset))
1227 out.write('\n')
1305 out.write('\n')
1228 out.flush()
1306 out.flush()
1229 # FIXME: we should remove the auto pdb behavior from here and leave
1307 # FIXME: we should remove the auto pdb behavior from here and leave
1230 # that to the clients.
1308 # that to the clients.
1231 try:
1309 try:
1232 self.debugger()
1310 self.debugger()
1233 except KeyboardInterrupt:
1311 except KeyboardInterrupt:
1234 print("\nKeyboardInterrupt")
1312 print("\nKeyboardInterrupt")
1235
1313
1236 def structured_traceback(self, etype=None, value=None, tb=None,
1314 def structured_traceback(self, etype=None, value=None, tb=None,
1237 tb_offset=None, number_of_lines_of_context=5):
1315 tb_offset=None, number_of_lines_of_context=5):
1238 if etype is None:
1316 if etype is None:
1239 etype, value, tb = sys.exc_info()
1317 etype, value, tb = sys.exc_info()
1240 self.tb = tb
1318 self.tb = tb
1241 return FormattedTB.structured_traceback(
1319 return FormattedTB.structured_traceback(
1242 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1320 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1243
1321
1244
1322
1245 #---------------------------------------------------------------------------
1323 #---------------------------------------------------------------------------
1246
1324
1247 # A simple class to preserve Nathan's original functionality.
1325 # A simple class to preserve Nathan's original functionality.
1248 class ColorTB(FormattedTB):
1326 class ColorTB(FormattedTB):
1249 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1327 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1250
1328
1251 def __init__(self, color_scheme='Linux', call_pdb=0):
1329 def __init__(self, color_scheme='Linux', call_pdb=0):
1252 FormattedTB.__init__(self, color_scheme=color_scheme,
1330 FormattedTB.__init__(self, color_scheme=color_scheme,
1253 call_pdb=call_pdb)
1331 call_pdb=call_pdb)
1254
1332
1255
1333
1256 class SyntaxTB(ListTB):
1334 class SyntaxTB(ListTB):
1257 """Extension which holds some state: the last exception value"""
1335 """Extension which holds some state: the last exception value"""
1258
1336
1259 def __init__(self, color_scheme='NoColor'):
1337 def __init__(self, color_scheme='NoColor'):
1260 ListTB.__init__(self, color_scheme)
1338 ListTB.__init__(self, color_scheme)
1261 self.last_syntax_error = None
1339 self.last_syntax_error = None
1262
1340
1263 def __call__(self, etype, value, elist):
1341 def __call__(self, etype, value, elist):
1264 self.last_syntax_error = value
1342 self.last_syntax_error = value
1265
1343
1266 ListTB.__call__(self, etype, value, elist)
1344 ListTB.__call__(self, etype, value, elist)
1267
1345
1268 def structured_traceback(self, etype, value, elist, tb_offset=None,
1346 def structured_traceback(self, etype, value, elist, tb_offset=None,
1269 context=5):
1347 context=5):
1270 # If the source file has been edited, the line in the syntax error can
1348 # If the source file has been edited, the line in the syntax error can
1271 # be wrong (retrieved from an outdated cache). This replaces it with
1349 # be wrong (retrieved from an outdated cache). This replaces it with
1272 # the current value.
1350 # the current value.
1273 if isinstance(value, SyntaxError) \
1351 if isinstance(value, SyntaxError) \
1274 and isinstance(value.filename, py3compat.string_types) \
1352 and isinstance(value.filename, py3compat.string_types) \
1275 and isinstance(value.lineno, int):
1353 and isinstance(value.lineno, int):
1276 linecache.checkcache(value.filename)
1354 linecache.checkcache(value.filename)
1277 newtext = ulinecache.getline(value.filename, value.lineno)
1355 newtext = ulinecache.getline(value.filename, value.lineno)
1278 if newtext:
1356 if newtext:
1279 value.text = newtext
1357 value.text = newtext
1280 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1358 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1281 tb_offset=tb_offset, context=context)
1359 tb_offset=tb_offset, context=context)
1282
1360
1283 def clear_err_state(self):
1361 def clear_err_state(self):
1284 """Return the current error state and clear it"""
1362 """Return the current error state and clear it"""
1285 e = self.last_syntax_error
1363 e = self.last_syntax_error
1286 self.last_syntax_error = None
1364 self.last_syntax_error = None
1287 return e
1365 return e
1288
1366
1289 def stb2text(self, stb):
1367 def stb2text(self, stb):
1290 """Convert a structured traceback (a list) to a string."""
1368 """Convert a structured traceback (a list) to a string."""
1291 return ''.join(stb)
1369 return ''.join(stb)
1292
1370
1293
1371
1294 # some internal-use functions
1372 # some internal-use functions
1295 def text_repr(value):
1373 def text_repr(value):
1296 """Hopefully pretty robust repr equivalent."""
1374 """Hopefully pretty robust repr equivalent."""
1297 # this is pretty horrible but should always return *something*
1375 # this is pretty horrible but should always return *something*
1298 try:
1376 try:
1299 return pydoc.text.repr(value)
1377 return pydoc.text.repr(value)
1300 except KeyboardInterrupt:
1378 except KeyboardInterrupt:
1301 raise
1379 raise
1302 except:
1380 except:
1303 try:
1381 try:
1304 return repr(value)
1382 return repr(value)
1305 except KeyboardInterrupt:
1383 except KeyboardInterrupt:
1306 raise
1384 raise
1307 except:
1385 except:
1308 try:
1386 try:
1309 # all still in an except block so we catch
1387 # all still in an except block so we catch
1310 # getattr raising
1388 # getattr raising
1311 name = getattr(value, '__name__', None)
1389 name = getattr(value, '__name__', None)
1312 if name:
1390 if name:
1313 # ick, recursion
1391 # ick, recursion
1314 return text_repr(name)
1392 return text_repr(name)
1315 klass = getattr(value, '__class__', None)
1393 klass = getattr(value, '__class__', None)
1316 if klass:
1394 if klass:
1317 return '%s instance' % text_repr(klass)
1395 return '%s instance' % text_repr(klass)
1318 except KeyboardInterrupt:
1396 except KeyboardInterrupt:
1319 raise
1397 raise
1320 except:
1398 except:
1321 return 'UNRECOVERABLE REPR FAILURE'
1399 return 'UNRECOVERABLE REPR FAILURE'
1322
1400
1323
1401
1324 def eqrepr(value, repr=text_repr):
1402 def eqrepr(value, repr=text_repr):
1325 return '=%s' % repr(value)
1403 return '=%s' % repr(value)
1326
1404
1327
1405
1328 def nullrepr(value, repr=text_repr):
1406 def nullrepr(value, repr=text_repr):
1329 return ''
1407 return ''
1330
1408
1331
1409
1332 #----------------------------------------------------------------------------
1410 #----------------------------------------------------------------------------
1333
1411
1334 # module testing (minimal)
1412 # module testing (minimal)
1335 if __name__ == "__main__":
1413 if __name__ == "__main__":
1336 def spam(c, d_e):
1414 def spam(c, d_e):
1337 (d, e) = d_e
1415 (d, e) = d_e
1338 x = c + d
1416 x = c + d
1339 y = c * d
1417 y = c * d
1340 foo(x, y)
1418 foo(x, y)
1341
1419
1342 def foo(a, b, bar=1):
1420 def foo(a, b, bar=1):
1343 eggs(a, b + bar)
1421 eggs(a, b + bar)
1344
1422
1345 def eggs(f, g, z=globals()):
1423 def eggs(f, g, z=globals()):
1346 h = f + g
1424 h = f + g
1347 i = f - g
1425 i = f - g
1348 return h / i
1426 return h / i
1349
1427
1350 print('')
1428 print('')
1351 print('*** Before ***')
1429 print('*** Before ***')
1352 try:
1430 try:
1353 print(spam(1, (2, 3)))
1431 print(spam(1, (2, 3)))
1354 except:
1432 except:
1355 traceback.print_exc()
1433 traceback.print_exc()
1356 print('')
1434 print('')
1357
1435
1358 handler = ColorTB()
1436 handler = ColorTB()
1359 print('*** ColorTB ***')
1437 print('*** ColorTB ***')
1360 try:
1438 try:
1361 print(spam(1, (2, 3)))
1439 print(spam(1, (2, 3)))
1362 except:
1440 except:
1363 handler(*sys.exc_info())
1441 handler(*sys.exc_info())
1364 print('')
1442 print('')
1365
1443
1366 handler = VerboseTB()
1444 handler = VerboseTB()
1367 print('*** VerboseTB ***')
1445 print('*** VerboseTB ***')
1368 try:
1446 try:
1369 print(spam(1, (2, 3)))
1447 print(spam(1, (2, 3)))
1370 except:
1448 except:
1371 handler(*sys.exc_info())
1449 handler(*sys.exc_info())
1372 print('')
1450 print('')
1373
1451
General Comments 0
You need to be logged in to leave comments. Login now