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