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