##// END OF EJS Templates
TEST: Add a regression test.
Scott Sanderson -
Show More
@@ -1,197 +1,222 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for IPython.core.ultratb
2 """Tests for IPython.core.ultratb
3 """
3 """
4 import io
4 import io
5 import os.path
5 import os.path
6 from textwrap import dedent
6 import unittest
7 import unittest
7
8
9
8 from IPython.testing import tools as tt
10 from IPython.testing import tools as tt
9 from IPython.testing.decorators import onlyif_unicode_paths
11 from IPython.testing.decorators import onlyif_unicode_paths
10 from IPython.utils.syspathcontext import prepended_to_syspath
12 from IPython.utils.syspathcontext import prepended_to_syspath
11 from IPython.utils.tempdir import TemporaryDirectory
13 from IPython.utils.tempdir import TemporaryDirectory
12 from IPython.utils.py3compat import PY3
14 from IPython.utils.py3compat import PY3
13
15
14 ip = get_ipython()
16 ip = get_ipython()
15
17
16 file_1 = """1
18 file_1 = """1
17 2
19 2
18 3
20 3
19 def f():
21 def f():
20 1/0
22 1/0
21 """
23 """
22
24
23 file_2 = """def f():
25 file_2 = """def f():
24 1/0
26 1/0
25 """
27 """
26
28
27 class ChangedPyFileTest(unittest.TestCase):
29 class ChangedPyFileTest(unittest.TestCase):
28 def test_changing_py_file(self):
30 def test_changing_py_file(self):
29 """Traceback produced if the line where the error occurred is missing?
31 """Traceback produced if the line where the error occurred is missing?
30
32
31 https://github.com/ipython/ipython/issues/1456
33 https://github.com/ipython/ipython/issues/1456
32 """
34 """
33 with TemporaryDirectory() as td:
35 with TemporaryDirectory() as td:
34 fname = os.path.join(td, "foo.py")
36 fname = os.path.join(td, "foo.py")
35 with open(fname, "w") as f:
37 with open(fname, "w") as f:
36 f.write(file_1)
38 f.write(file_1)
37
39
38 with prepended_to_syspath(td):
40 with prepended_to_syspath(td):
39 ip.run_cell("import foo")
41 ip.run_cell("import foo")
40
42
41 with tt.AssertPrints("ZeroDivisionError"):
43 with tt.AssertPrints("ZeroDivisionError"):
42 ip.run_cell("foo.f()")
44 ip.run_cell("foo.f()")
43
45
44 # Make the file shorter, so the line of the error is missing.
46 # Make the file shorter, so the line of the error is missing.
45 with open(fname, "w") as f:
47 with open(fname, "w") as f:
46 f.write(file_2)
48 f.write(file_2)
47
49
48 # For some reason, this was failing on the *second* call after
50 # For some reason, this was failing on the *second* call after
49 # changing the file, so we call f() twice.
51 # changing the file, so we call f() twice.
50 with tt.AssertNotPrints("Internal Python error", channel='stderr'):
52 with tt.AssertNotPrints("Internal Python error", channel='stderr'):
51 with tt.AssertPrints("ZeroDivisionError"):
53 with tt.AssertPrints("ZeroDivisionError"):
52 ip.run_cell("foo.f()")
54 ip.run_cell("foo.f()")
53 with tt.AssertPrints("ZeroDivisionError"):
55 with tt.AssertPrints("ZeroDivisionError"):
54 ip.run_cell("foo.f()")
56 ip.run_cell("foo.f()")
55
57
56 iso_8859_5_file = u'''# coding: iso-8859-5
58 iso_8859_5_file = u'''# coding: iso-8859-5
57
59
58 def fail():
60 def fail():
59 """Π΄Π±Π˜Π–"""
61 """Π΄Π±Π˜Π–"""
60 1/0 # Π΄Π±Π˜Π–
62 1/0 # Π΄Π±Π˜Π–
61 '''
63 '''
62
64
63 class NonAsciiTest(unittest.TestCase):
65 class NonAsciiTest(unittest.TestCase):
64 @onlyif_unicode_paths
66 @onlyif_unicode_paths
65 def test_nonascii_path(self):
67 def test_nonascii_path(self):
66 # Non-ascii directory name as well.
68 # Non-ascii directory name as well.
67 with TemporaryDirectory(suffix=u'Γ©') as td:
69 with TemporaryDirectory(suffix=u'Γ©') as td:
68 fname = os.path.join(td, u"fooΓ©.py")
70 fname = os.path.join(td, u"fooΓ©.py")
69 with open(fname, "w") as f:
71 with open(fname, "w") as f:
70 f.write(file_1)
72 f.write(file_1)
71
73
72 with prepended_to_syspath(td):
74 with prepended_to_syspath(td):
73 ip.run_cell("import foo")
75 ip.run_cell("import foo")
74
76
75 with tt.AssertPrints("ZeroDivisionError"):
77 with tt.AssertPrints("ZeroDivisionError"):
76 ip.run_cell("foo.f()")
78 ip.run_cell("foo.f()")
77
79
78 def test_iso8859_5(self):
80 def test_iso8859_5(self):
79 with TemporaryDirectory() as td:
81 with TemporaryDirectory() as td:
80 fname = os.path.join(td, 'dfghjkl.py')
82 fname = os.path.join(td, 'dfghjkl.py')
81
83
82 with io.open(fname, 'w', encoding='iso-8859-5') as f:
84 with io.open(fname, 'w', encoding='iso-8859-5') as f:
83 f.write(iso_8859_5_file)
85 f.write(iso_8859_5_file)
84
86
85 with prepended_to_syspath(td):
87 with prepended_to_syspath(td):
86 ip.run_cell("from dfghjkl import fail")
88 ip.run_cell("from dfghjkl import fail")
87
89
88 with tt.AssertPrints("ZeroDivisionError"):
90 with tt.AssertPrints("ZeroDivisionError"):
89 with tt.AssertPrints(u'Π΄Π±Π˜Π–', suppress=False):
91 with tt.AssertPrints(u'Π΄Π±Π˜Π–', suppress=False):
90 ip.run_cell('fail()')
92 ip.run_cell('fail()')
91
93
94
95 class NestedGenExprTestCase(unittest.TestCase):
96 """
97 Regression test for the following issues:
98 https://github.com/ipython/ipython/issues/8293
99 https://github.com/ipython/ipython/issues/8205
100 """
101 def test_nested_genexpr(self):
102 code = dedent(
103 """\
104 class SpecificException(Exception):
105 pass
106
107 def foo(x):
108 raise SpecificException("Success!")
109
110 sum(sum(foo(x) for _ in [0]) for x in [0])
111 """
112 )
113 with tt.AssertPrints('SpecificException: Success!', suppress=False):
114 ip.run_cell(code)
115
116
92 indentationerror_file = """if True:
117 indentationerror_file = """if True:
93 zoon()
118 zoon()
94 """
119 """
95
120
96 class IndentationErrorTest(unittest.TestCase):
121 class IndentationErrorTest(unittest.TestCase):
97 def test_indentationerror_shows_line(self):
122 def test_indentationerror_shows_line(self):
98 # See issue gh-2398
123 # See issue gh-2398
99 with tt.AssertPrints("IndentationError"):
124 with tt.AssertPrints("IndentationError"):
100 with tt.AssertPrints("zoon()", suppress=False):
125 with tt.AssertPrints("zoon()", suppress=False):
101 ip.run_cell(indentationerror_file)
126 ip.run_cell(indentationerror_file)
102
127
103 with TemporaryDirectory() as td:
128 with TemporaryDirectory() as td:
104 fname = os.path.join(td, "foo.py")
129 fname = os.path.join(td, "foo.py")
105 with open(fname, "w") as f:
130 with open(fname, "w") as f:
106 f.write(indentationerror_file)
131 f.write(indentationerror_file)
107
132
108 with tt.AssertPrints("IndentationError"):
133 with tt.AssertPrints("IndentationError"):
109 with tt.AssertPrints("zoon()", suppress=False):
134 with tt.AssertPrints("zoon()", suppress=False):
110 ip.magic('run %s' % fname)
135 ip.magic('run %s' % fname)
111
136
112 se_file_1 = """1
137 se_file_1 = """1
113 2
138 2
114 7/
139 7/
115 """
140 """
116
141
117 se_file_2 = """7/
142 se_file_2 = """7/
118 """
143 """
119
144
120 class SyntaxErrorTest(unittest.TestCase):
145 class SyntaxErrorTest(unittest.TestCase):
121 def test_syntaxerror_without_lineno(self):
146 def test_syntaxerror_without_lineno(self):
122 with tt.AssertNotPrints("TypeError"):
147 with tt.AssertNotPrints("TypeError"):
123 with tt.AssertPrints("line unknown"):
148 with tt.AssertPrints("line unknown"):
124 ip.run_cell("raise SyntaxError()")
149 ip.run_cell("raise SyntaxError()")
125
150
126 def test_changing_py_file(self):
151 def test_changing_py_file(self):
127 with TemporaryDirectory() as td:
152 with TemporaryDirectory() as td:
128 fname = os.path.join(td, "foo.py")
153 fname = os.path.join(td, "foo.py")
129 with open(fname, 'w') as f:
154 with open(fname, 'w') as f:
130 f.write(se_file_1)
155 f.write(se_file_1)
131
156
132 with tt.AssertPrints(["7/", "SyntaxError"]):
157 with tt.AssertPrints(["7/", "SyntaxError"]):
133 ip.magic("run " + fname)
158 ip.magic("run " + fname)
134
159
135 # Modify the file
160 # Modify the file
136 with open(fname, 'w') as f:
161 with open(fname, 'w') as f:
137 f.write(se_file_2)
162 f.write(se_file_2)
138
163
139 # The SyntaxError should point to the correct line
164 # The SyntaxError should point to the correct line
140 with tt.AssertPrints(["7/", "SyntaxError"]):
165 with tt.AssertPrints(["7/", "SyntaxError"]):
141 ip.magic("run " + fname)
166 ip.magic("run " + fname)
142
167
143 def test_non_syntaxerror(self):
168 def test_non_syntaxerror(self):
144 # SyntaxTB may be called with an error other than a SyntaxError
169 # SyntaxTB may be called with an error other than a SyntaxError
145 # See e.g. gh-4361
170 # See e.g. gh-4361
146 try:
171 try:
147 raise ValueError('QWERTY')
172 raise ValueError('QWERTY')
148 except ValueError:
173 except ValueError:
149 with tt.AssertPrints('QWERTY'):
174 with tt.AssertPrints('QWERTY'):
150 ip.showsyntaxerror()
175 ip.showsyntaxerror()
151
176
152
177
153 class Python3ChainedExceptionsTest(unittest.TestCase):
178 class Python3ChainedExceptionsTest(unittest.TestCase):
154 DIRECT_CAUSE_ERROR_CODE = """
179 DIRECT_CAUSE_ERROR_CODE = """
155 try:
180 try:
156 x = 1 + 2
181 x = 1 + 2
157 print(not_defined_here)
182 print(not_defined_here)
158 except Exception as e:
183 except Exception as e:
159 x += 55
184 x += 55
160 x - 1
185 x - 1
161 y = {}
186 y = {}
162 raise KeyError('uh') from e
187 raise KeyError('uh') from e
163 """
188 """
164
189
165 EXCEPTION_DURING_HANDLING_CODE = """
190 EXCEPTION_DURING_HANDLING_CODE = """
166 try:
191 try:
167 x = 1 + 2
192 x = 1 + 2
168 print(not_defined_here)
193 print(not_defined_here)
169 except Exception as e:
194 except Exception as e:
170 x += 55
195 x += 55
171 x - 1
196 x - 1
172 y = {}
197 y = {}
173 raise KeyError('uh')
198 raise KeyError('uh')
174 """
199 """
175
200
176 SUPPRESS_CHAINING_CODE = """
201 SUPPRESS_CHAINING_CODE = """
177 try:
202 try:
178 1/0
203 1/0
179 except Exception:
204 except Exception:
180 raise ValueError("Yikes") from None
205 raise ValueError("Yikes") from None
181 """
206 """
182
207
183 def test_direct_cause_error(self):
208 def test_direct_cause_error(self):
184 if PY3:
209 if PY3:
185 with tt.AssertPrints(["KeyError", "NameError", "direct cause"]):
210 with tt.AssertPrints(["KeyError", "NameError", "direct cause"]):
186 ip.run_cell(self.DIRECT_CAUSE_ERROR_CODE)
211 ip.run_cell(self.DIRECT_CAUSE_ERROR_CODE)
187
212
188 def test_exception_during_handling_error(self):
213 def test_exception_during_handling_error(self):
189 if PY3:
214 if PY3:
190 with tt.AssertPrints(["KeyError", "NameError", "During handling"]):
215 with tt.AssertPrints(["KeyError", "NameError", "During handling"]):
191 ip.run_cell(self.EXCEPTION_DURING_HANDLING_CODE)
216 ip.run_cell(self.EXCEPTION_DURING_HANDLING_CODE)
192
217
193 def test_suppress_exception_chaining(self):
218 def test_suppress_exception_chaining(self):
194 if PY3:
219 if PY3:
195 with tt.AssertNotPrints("ZeroDivisionError"), \
220 with tt.AssertNotPrints("ZeroDivisionError"), \
196 tt.AssertPrints("ValueError", suppress=False):
221 tt.AssertPrints("ValueError", suppress=False):
197 ip.run_cell(self.SUPPRESS_CHAINING_CODE)
222 ip.run_cell(self.SUPPRESS_CHAINING_CODE)
General Comments 0
You need to be logged in to leave comments. Login now