##// END OF EJS Templates
cleanup
Srinivas Reddy Thatiparthy -
Show More
@@ -1,202 +1,197 b''
1 """Tests for various magic functions specific to the terminal frontend.
1 """Tests for various magic functions specific to the terminal frontend.
2
2
3 Needs to be run by nose (to make ipython session available).
3 Needs to be run by nose (to make ipython session available).
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Imports
7 # Imports
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9
9
10 import sys
10 import sys
11 from io import StringIO
11 from unittest import TestCase
12 from unittest import TestCase
12
13
13 import nose.tools as nt
14 import nose.tools as nt
14
15
15 from IPython.testing import tools as tt
16 from IPython.testing import tools as tt
16 from IPython.utils.py3compat import PY3
17
18 if PY3:
19 from io import StringIO
20 else:
21 from StringIO import StringIO
22
17
23 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
24 # Globals
19 # Globals
25 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
26 ip = get_ipython()
21 ip = get_ipython()
27
22
28 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
29 # Test functions begin
24 # Test functions begin
30 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
31
26
32 def check_cpaste(code, should_fail=False):
27 def check_cpaste(code, should_fail=False):
33 """Execute code via 'cpaste' and ensure it was executed, unless
28 """Execute code via 'cpaste' and ensure it was executed, unless
34 should_fail is set.
29 should_fail is set.
35 """
30 """
36 ip.user_ns['code_ran'] = False
31 ip.user_ns['code_ran'] = False
37
32
38 src = StringIO()
33 src = StringIO()
39 if not hasattr(src, 'encoding'):
34 if not hasattr(src, 'encoding'):
40 # IPython expects stdin to have an encoding attribute
35 # IPython expects stdin to have an encoding attribute
41 src.encoding = None
36 src.encoding = None
42 src.write(code)
37 src.write(code)
43 src.write('\n--\n')
38 src.write('\n--\n')
44 src.seek(0)
39 src.seek(0)
45
40
46 stdin_save = sys.stdin
41 stdin_save = sys.stdin
47 sys.stdin = src
42 sys.stdin = src
48
43
49 try:
44 try:
50 context = tt.AssertPrints if should_fail else tt.AssertNotPrints
45 context = tt.AssertPrints if should_fail else tt.AssertNotPrints
51 with context("Traceback (most recent call last)"):
46 with context("Traceback (most recent call last)"):
52 ip.magic('cpaste')
47 ip.magic('cpaste')
53
48
54 if not should_fail:
49 if not should_fail:
55 assert ip.user_ns['code_ran'], "%r failed" % code
50 assert ip.user_ns['code_ran'], "%r failed" % code
56 finally:
51 finally:
57 sys.stdin = stdin_save
52 sys.stdin = stdin_save
58
53
59 def test_cpaste():
54 def test_cpaste():
60 """Test cpaste magic"""
55 """Test cpaste magic"""
61
56
62 def runf():
57 def runf():
63 """Marker function: sets a flag when executed.
58 """Marker function: sets a flag when executed.
64 """
59 """
65 ip.user_ns['code_ran'] = True
60 ip.user_ns['code_ran'] = True
66 return 'runf' # return string so '+ runf()' doesn't result in success
61 return 'runf' # return string so '+ runf()' doesn't result in success
67
62
68 tests = {'pass': ["runf()",
63 tests = {'pass': ["runf()",
69 "In [1]: runf()",
64 "In [1]: runf()",
70 "In [1]: if 1:\n ...: runf()",
65 "In [1]: if 1:\n ...: runf()",
71 "> > > runf()",
66 "> > > runf()",
72 ">>> runf()",
67 ">>> runf()",
73 " >>> runf()",
68 " >>> runf()",
74 ],
69 ],
75
70
76 'fail': ["1 + runf()",
71 'fail': ["1 + runf()",
77 "++ runf()",
72 "++ runf()",
78 ]}
73 ]}
79
74
80 ip.user_ns['runf'] = runf
75 ip.user_ns['runf'] = runf
81
76
82 for code in tests['pass']:
77 for code in tests['pass']:
83 check_cpaste(code)
78 check_cpaste(code)
84
79
85 for code in tests['fail']:
80 for code in tests['fail']:
86 check_cpaste(code, should_fail=True)
81 check_cpaste(code, should_fail=True)
87
82
88
83
89 class PasteTestCase(TestCase):
84 class PasteTestCase(TestCase):
90 """Multiple tests for clipboard pasting"""
85 """Multiple tests for clipboard pasting"""
91
86
92 def paste(self, txt, flags='-q'):
87 def paste(self, txt, flags='-q'):
93 """Paste input text, by default in quiet mode"""
88 """Paste input text, by default in quiet mode"""
94 ip.hooks.clipboard_get = lambda : txt
89 ip.hooks.clipboard_get = lambda : txt
95 ip.magic('paste '+flags)
90 ip.magic('paste '+flags)
96
91
97 def setUp(self):
92 def setUp(self):
98 # Inject fake clipboard hook but save original so we can restore it later
93 # Inject fake clipboard hook but save original so we can restore it later
99 self.original_clip = ip.hooks.clipboard_get
94 self.original_clip = ip.hooks.clipboard_get
100
95
101 def tearDown(self):
96 def tearDown(self):
102 # Restore original hook
97 # Restore original hook
103 ip.hooks.clipboard_get = self.original_clip
98 ip.hooks.clipboard_get = self.original_clip
104
99
105 def test_paste(self):
100 def test_paste(self):
106 ip.user_ns.pop('x', None)
101 ip.user_ns.pop('x', None)
107 self.paste('x = 1')
102 self.paste('x = 1')
108 nt.assert_equal(ip.user_ns['x'], 1)
103 nt.assert_equal(ip.user_ns['x'], 1)
109 ip.user_ns.pop('x')
104 ip.user_ns.pop('x')
110
105
111 def test_paste_pyprompt(self):
106 def test_paste_pyprompt(self):
112 ip.user_ns.pop('x', None)
107 ip.user_ns.pop('x', None)
113 self.paste('>>> x=2')
108 self.paste('>>> x=2')
114 nt.assert_equal(ip.user_ns['x'], 2)
109 nt.assert_equal(ip.user_ns['x'], 2)
115 ip.user_ns.pop('x')
110 ip.user_ns.pop('x')
116
111
117 def test_paste_py_multi(self):
112 def test_paste_py_multi(self):
118 self.paste("""
113 self.paste("""
119 >>> x = [1,2,3]
114 >>> x = [1,2,3]
120 >>> y = []
115 >>> y = []
121 >>> for i in x:
116 >>> for i in x:
122 ... y.append(i**2)
117 ... y.append(i**2)
123 ...
118 ...
124 """)
119 """)
125 nt.assert_equal(ip.user_ns['x'], [1,2,3])
120 nt.assert_equal(ip.user_ns['x'], [1,2,3])
126 nt.assert_equal(ip.user_ns['y'], [1,4,9])
121 nt.assert_equal(ip.user_ns['y'], [1,4,9])
127
122
128 def test_paste_py_multi_r(self):
123 def test_paste_py_multi_r(self):
129 "Now, test that self.paste -r works"
124 "Now, test that self.paste -r works"
130 self.test_paste_py_multi()
125 self.test_paste_py_multi()
131 nt.assert_equal(ip.user_ns.pop('x'), [1,2,3])
126 nt.assert_equal(ip.user_ns.pop('x'), [1,2,3])
132 nt.assert_equal(ip.user_ns.pop('y'), [1,4,9])
127 nt.assert_equal(ip.user_ns.pop('y'), [1,4,9])
133 nt.assert_false('x' in ip.user_ns)
128 nt.assert_false('x' in ip.user_ns)
134 ip.magic('paste -r')
129 ip.magic('paste -r')
135 nt.assert_equal(ip.user_ns['x'], [1,2,3])
130 nt.assert_equal(ip.user_ns['x'], [1,2,3])
136 nt.assert_equal(ip.user_ns['y'], [1,4,9])
131 nt.assert_equal(ip.user_ns['y'], [1,4,9])
137
132
138 def test_paste_email(self):
133 def test_paste_email(self):
139 "Test pasting of email-quoted contents"
134 "Test pasting of email-quoted contents"
140 self.paste("""\
135 self.paste("""\
141 >> def foo(x):
136 >> def foo(x):
142 >> return x + 1
137 >> return x + 1
143 >> xx = foo(1.1)""")
138 >> xx = foo(1.1)""")
144 nt.assert_equal(ip.user_ns['xx'], 2.1)
139 nt.assert_equal(ip.user_ns['xx'], 2.1)
145
140
146 def test_paste_email2(self):
141 def test_paste_email2(self):
147 "Email again; some programs add a space also at each quoting level"
142 "Email again; some programs add a space also at each quoting level"
148 self.paste("""\
143 self.paste("""\
149 > > def foo(x):
144 > > def foo(x):
150 > > return x + 1
145 > > return x + 1
151 > > yy = foo(2.1) """)
146 > > yy = foo(2.1) """)
152 nt.assert_equal(ip.user_ns['yy'], 3.1)
147 nt.assert_equal(ip.user_ns['yy'], 3.1)
153
148
154 def test_paste_email_py(self):
149 def test_paste_email_py(self):
155 "Email quoting of interactive input"
150 "Email quoting of interactive input"
156 self.paste("""\
151 self.paste("""\
157 >> >>> def f(x):
152 >> >>> def f(x):
158 >> ... return x+1
153 >> ... return x+1
159 >> ...
154 >> ...
160 >> >>> zz = f(2.5) """)
155 >> >>> zz = f(2.5) """)
161 nt.assert_equal(ip.user_ns['zz'], 3.5)
156 nt.assert_equal(ip.user_ns['zz'], 3.5)
162
157
163 def test_paste_echo(self):
158 def test_paste_echo(self):
164 "Also test self.paste echoing, by temporarily faking the writer"
159 "Also test self.paste echoing, by temporarily faking the writer"
165 w = StringIO()
160 w = StringIO()
166 writer = ip.write
161 writer = ip.write
167 ip.write = w.write
162 ip.write = w.write
168 code = """
163 code = """
169 a = 100
164 a = 100
170 b = 200"""
165 b = 200"""
171 try:
166 try:
172 self.paste(code,'')
167 self.paste(code,'')
173 out = w.getvalue()
168 out = w.getvalue()
174 finally:
169 finally:
175 ip.write = writer
170 ip.write = writer
176 nt.assert_equal(ip.user_ns['a'], 100)
171 nt.assert_equal(ip.user_ns['a'], 100)
177 nt.assert_equal(ip.user_ns['b'], 200)
172 nt.assert_equal(ip.user_ns['b'], 200)
178 nt.assert_equal(out, code+"\n## -- End pasted text --\n")
173 nt.assert_equal(out, code+"\n## -- End pasted text --\n")
179
174
180 def test_paste_leading_commas(self):
175 def test_paste_leading_commas(self):
181 "Test multiline strings with leading commas"
176 "Test multiline strings with leading commas"
182 tm = ip.magics_manager.registry['TerminalMagics']
177 tm = ip.magics_manager.registry['TerminalMagics']
183 s = '''\
178 s = '''\
184 a = """
179 a = """
185 ,1,2,3
180 ,1,2,3
186 """'''
181 """'''
187 ip.user_ns.pop('foo', None)
182 ip.user_ns.pop('foo', None)
188 tm.store_or_execute(s, 'foo')
183 tm.store_or_execute(s, 'foo')
189 nt.assert_in('foo', ip.user_ns)
184 nt.assert_in('foo', ip.user_ns)
190
185
191
186
192 def test_paste_trailing_question(self):
187 def test_paste_trailing_question(self):
193 "Test pasting sources with trailing question marks"
188 "Test pasting sources with trailing question marks"
194 tm = ip.magics_manager.registry['TerminalMagics']
189 tm = ip.magics_manager.registry['TerminalMagics']
195 s = '''\
190 s = '''\
196 def funcfoo():
191 def funcfoo():
197 if True: #am i true?
192 if True: #am i true?
198 return 'fooresult'
193 return 'fooresult'
199 '''
194 '''
200 ip.user_ns.pop('funcfoo', None)
195 ip.user_ns.pop('funcfoo', None)
201 self.paste(s)
196 self.paste(s)
202 nt.assert_equal(ip.user_ns['funcfoo'](), 'fooresult')
197 nt.assert_equal(ip.user_ns['funcfoo'](), 'fooresult')
@@ -1,351 +1,347 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 sys
5 import sys
6 import os.path
6 import os.path
7 from textwrap import dedent
7 from textwrap import dedent
8 import traceback
8 import traceback
9 import unittest
9 import unittest
10 from unittest import mock
10 from unittest import mock
11
11
12 from ..ultratb import ColorTB, VerboseTB, find_recursion
12 from ..ultratb import ColorTB, VerboseTB, find_recursion
13
13
14
14
15 from IPython.testing import tools as tt
15 from IPython.testing import tools as tt
16 from IPython.testing.decorators import onlyif_unicode_paths
16 from IPython.testing.decorators import onlyif_unicode_paths
17 from IPython.utils.syspathcontext import prepended_to_syspath
17 from IPython.utils.syspathcontext import prepended_to_syspath
18 from IPython.utils.tempdir import TemporaryDirectory
18 from IPython.utils.tempdir import TemporaryDirectory
19 from IPython.utils.py3compat import PY3
20
19
21 ip = get_ipython()
20 ip = get_ipython()
22
21
23 file_1 = """1
22 file_1 = """1
24 2
23 2
25 3
24 3
26 def f():
25 def f():
27 1/0
26 1/0
28 """
27 """
29
28
30 file_2 = """def f():
29 file_2 = """def f():
31 1/0
30 1/0
32 """
31 """
33
32
34 class ChangedPyFileTest(unittest.TestCase):
33 class ChangedPyFileTest(unittest.TestCase):
35 def test_changing_py_file(self):
34 def test_changing_py_file(self):
36 """Traceback produced if the line where the error occurred is missing?
35 """Traceback produced if the line where the error occurred is missing?
37
36
38 https://github.com/ipython/ipython/issues/1456
37 https://github.com/ipython/ipython/issues/1456
39 """
38 """
40 with TemporaryDirectory() as td:
39 with TemporaryDirectory() as td:
41 fname = os.path.join(td, "foo.py")
40 fname = os.path.join(td, "foo.py")
42 with open(fname, "w") as f:
41 with open(fname, "w") as f:
43 f.write(file_1)
42 f.write(file_1)
44
43
45 with prepended_to_syspath(td):
44 with prepended_to_syspath(td):
46 ip.run_cell("import foo")
45 ip.run_cell("import foo")
47
46
48 with tt.AssertPrints("ZeroDivisionError"):
47 with tt.AssertPrints("ZeroDivisionError"):
49 ip.run_cell("foo.f()")
48 ip.run_cell("foo.f()")
50
49
51 # Make the file shorter, so the line of the error is missing.
50 # Make the file shorter, so the line of the error is missing.
52 with open(fname, "w") as f:
51 with open(fname, "w") as f:
53 f.write(file_2)
52 f.write(file_2)
54
53
55 # For some reason, this was failing on the *second* call after
54 # For some reason, this was failing on the *second* call after
56 # changing the file, so we call f() twice.
55 # changing the file, so we call f() twice.
57 with tt.AssertNotPrints("Internal Python error", channel='stderr'):
56 with tt.AssertNotPrints("Internal Python error", channel='stderr'):
58 with tt.AssertPrints("ZeroDivisionError"):
57 with tt.AssertPrints("ZeroDivisionError"):
59 ip.run_cell("foo.f()")
58 ip.run_cell("foo.f()")
60 with tt.AssertPrints("ZeroDivisionError"):
59 with tt.AssertPrints("ZeroDivisionError"):
61 ip.run_cell("foo.f()")
60 ip.run_cell("foo.f()")
62
61
63 iso_8859_5_file = u'''# coding: iso-8859-5
62 iso_8859_5_file = u'''# coding: iso-8859-5
64
63
65 def fail():
64 def fail():
66 """Π΄Π±Π˜Π–"""
65 """Π΄Π±Π˜Π–"""
67 1/0 # Π΄Π±Π˜Π–
66 1/0 # Π΄Π±Π˜Π–
68 '''
67 '''
69
68
70 class NonAsciiTest(unittest.TestCase):
69 class NonAsciiTest(unittest.TestCase):
71 @onlyif_unicode_paths
70 @onlyif_unicode_paths
72 def test_nonascii_path(self):
71 def test_nonascii_path(self):
73 # Non-ascii directory name as well.
72 # Non-ascii directory name as well.
74 with TemporaryDirectory(suffix=u'Γ©') as td:
73 with TemporaryDirectory(suffix=u'Γ©') as td:
75 fname = os.path.join(td, u"fooΓ©.py")
74 fname = os.path.join(td, u"fooΓ©.py")
76 with open(fname, "w") as f:
75 with open(fname, "w") as f:
77 f.write(file_1)
76 f.write(file_1)
78
77
79 with prepended_to_syspath(td):
78 with prepended_to_syspath(td):
80 ip.run_cell("import foo")
79 ip.run_cell("import foo")
81
80
82 with tt.AssertPrints("ZeroDivisionError"):
81 with tt.AssertPrints("ZeroDivisionError"):
83 ip.run_cell("foo.f()")
82 ip.run_cell("foo.f()")
84
83
85 def test_iso8859_5(self):
84 def test_iso8859_5(self):
86 with TemporaryDirectory() as td:
85 with TemporaryDirectory() as td:
87 fname = os.path.join(td, 'dfghjkl.py')
86 fname = os.path.join(td, 'dfghjkl.py')
88
87
89 with io.open(fname, 'w', encoding='iso-8859-5') as f:
88 with io.open(fname, 'w', encoding='iso-8859-5') as f:
90 f.write(iso_8859_5_file)
89 f.write(iso_8859_5_file)
91
90
92 with prepended_to_syspath(td):
91 with prepended_to_syspath(td):
93 ip.run_cell("from dfghjkl import fail")
92 ip.run_cell("from dfghjkl import fail")
94
93
95 with tt.AssertPrints("ZeroDivisionError"):
94 with tt.AssertPrints("ZeroDivisionError"):
96 with tt.AssertPrints(u'Π΄Π±Π˜Π–', suppress=False):
95 with tt.AssertPrints(u'Π΄Π±Π˜Π–', suppress=False):
97 ip.run_cell('fail()')
96 ip.run_cell('fail()')
98
97
99 def test_nonascii_msg(self):
98 def test_nonascii_msg(self):
100 cell = u"raise Exception('Γ©')"
99 cell = u"raise Exception('Γ©')"
101 expected = u"Exception('Γ©')"
100 expected = u"Exception('Γ©')"
102 ip.run_cell("%xmode plain")
101 ip.run_cell("%xmode plain")
103 with tt.AssertPrints(expected):
102 with tt.AssertPrints(expected):
104 ip.run_cell(cell)
103 ip.run_cell(cell)
105
104
106 ip.run_cell("%xmode verbose")
105 ip.run_cell("%xmode verbose")
107 with tt.AssertPrints(expected):
106 with tt.AssertPrints(expected):
108 ip.run_cell(cell)
107 ip.run_cell(cell)
109
108
110 ip.run_cell("%xmode context")
109 ip.run_cell("%xmode context")
111 with tt.AssertPrints(expected):
110 with tt.AssertPrints(expected):
112 ip.run_cell(cell)
111 ip.run_cell(cell)
113
112
114
113
115 class NestedGenExprTestCase(unittest.TestCase):
114 class NestedGenExprTestCase(unittest.TestCase):
116 """
115 """
117 Regression test for the following issues:
116 Regression test for the following issues:
118 https://github.com/ipython/ipython/issues/8293
117 https://github.com/ipython/ipython/issues/8293
119 https://github.com/ipython/ipython/issues/8205
118 https://github.com/ipython/ipython/issues/8205
120 """
119 """
121 def test_nested_genexpr(self):
120 def test_nested_genexpr(self):
122 code = dedent(
121 code = dedent(
123 """\
122 """\
124 class SpecificException(Exception):
123 class SpecificException(Exception):
125 pass
124 pass
126
125
127 def foo(x):
126 def foo(x):
128 raise SpecificException("Success!")
127 raise SpecificException("Success!")
129
128
130 sum(sum(foo(x) for _ in [0]) for x in [0])
129 sum(sum(foo(x) for _ in [0]) for x in [0])
131 """
130 """
132 )
131 )
133 with tt.AssertPrints('SpecificException: Success!', suppress=False):
132 with tt.AssertPrints('SpecificException: Success!', suppress=False):
134 ip.run_cell(code)
133 ip.run_cell(code)
135
134
136
135
137 indentationerror_file = """if True:
136 indentationerror_file = """if True:
138 zoon()
137 zoon()
139 """
138 """
140
139
141 class IndentationErrorTest(unittest.TestCase):
140 class IndentationErrorTest(unittest.TestCase):
142 def test_indentationerror_shows_line(self):
141 def test_indentationerror_shows_line(self):
143 # See issue gh-2398
142 # See issue gh-2398
144 with tt.AssertPrints("IndentationError"):
143 with tt.AssertPrints("IndentationError"):
145 with tt.AssertPrints("zoon()", suppress=False):
144 with tt.AssertPrints("zoon()", suppress=False):
146 ip.run_cell(indentationerror_file)
145 ip.run_cell(indentationerror_file)
147
146
148 with TemporaryDirectory() as td:
147 with TemporaryDirectory() as td:
149 fname = os.path.join(td, "foo.py")
148 fname = os.path.join(td, "foo.py")
150 with open(fname, "w") as f:
149 with open(fname, "w") as f:
151 f.write(indentationerror_file)
150 f.write(indentationerror_file)
152
151
153 with tt.AssertPrints("IndentationError"):
152 with tt.AssertPrints("IndentationError"):
154 with tt.AssertPrints("zoon()", suppress=False):
153 with tt.AssertPrints("zoon()", suppress=False):
155 ip.magic('run %s' % fname)
154 ip.magic('run %s' % fname)
156
155
157 se_file_1 = """1
156 se_file_1 = """1
158 2
157 2
159 7/
158 7/
160 """
159 """
161
160
162 se_file_2 = """7/
161 se_file_2 = """7/
163 """
162 """
164
163
165 class SyntaxErrorTest(unittest.TestCase):
164 class SyntaxErrorTest(unittest.TestCase):
166 def test_syntaxerror_without_lineno(self):
165 def test_syntaxerror_without_lineno(self):
167 with tt.AssertNotPrints("TypeError"):
166 with tt.AssertNotPrints("TypeError"):
168 with tt.AssertPrints("line unknown"):
167 with tt.AssertPrints("line unknown"):
169 ip.run_cell("raise SyntaxError()")
168 ip.run_cell("raise SyntaxError()")
170
169
171 def test_changing_py_file(self):
170 def test_changing_py_file(self):
172 with TemporaryDirectory() as td:
171 with TemporaryDirectory() as td:
173 fname = os.path.join(td, "foo.py")
172 fname = os.path.join(td, "foo.py")
174 with open(fname, 'w') as f:
173 with open(fname, 'w') as f:
175 f.write(se_file_1)
174 f.write(se_file_1)
176
175
177 with tt.AssertPrints(["7/", "SyntaxError"]):
176 with tt.AssertPrints(["7/", "SyntaxError"]):
178 ip.magic("run " + fname)
177 ip.magic("run " + fname)
179
178
180 # Modify the file
179 # Modify the file
181 with open(fname, 'w') as f:
180 with open(fname, 'w') as f:
182 f.write(se_file_2)
181 f.write(se_file_2)
183
182
184 # The SyntaxError should point to the correct line
183 # The SyntaxError should point to the correct line
185 with tt.AssertPrints(["7/", "SyntaxError"]):
184 with tt.AssertPrints(["7/", "SyntaxError"]):
186 ip.magic("run " + fname)
185 ip.magic("run " + fname)
187
186
188 def test_non_syntaxerror(self):
187 def test_non_syntaxerror(self):
189 # SyntaxTB may be called with an error other than a SyntaxError
188 # SyntaxTB may be called with an error other than a SyntaxError
190 # See e.g. gh-4361
189 # See e.g. gh-4361
191 try:
190 try:
192 raise ValueError('QWERTY')
191 raise ValueError('QWERTY')
193 except ValueError:
192 except ValueError:
194 with tt.AssertPrints('QWERTY'):
193 with tt.AssertPrints('QWERTY'):
195 ip.showsyntaxerror()
194 ip.showsyntaxerror()
196
195
197
196
198 class Python3ChainedExceptionsTest(unittest.TestCase):
197 class Python3ChainedExceptionsTest(unittest.TestCase):
199 DIRECT_CAUSE_ERROR_CODE = """
198 DIRECT_CAUSE_ERROR_CODE = """
200 try:
199 try:
201 x = 1 + 2
200 x = 1 + 2
202 print(not_defined_here)
201 print(not_defined_here)
203 except Exception as e:
202 except Exception as e:
204 x += 55
203 x += 55
205 x - 1
204 x - 1
206 y = {}
205 y = {}
207 raise KeyError('uh') from e
206 raise KeyError('uh') from e
208 """
207 """
209
208
210 EXCEPTION_DURING_HANDLING_CODE = """
209 EXCEPTION_DURING_HANDLING_CODE = """
211 try:
210 try:
212 x = 1 + 2
211 x = 1 + 2
213 print(not_defined_here)
212 print(not_defined_here)
214 except Exception as e:
213 except Exception as e:
215 x += 55
214 x += 55
216 x - 1
215 x - 1
217 y = {}
216 y = {}
218 raise KeyError('uh')
217 raise KeyError('uh')
219 """
218 """
220
219
221 SUPPRESS_CHAINING_CODE = """
220 SUPPRESS_CHAINING_CODE = """
222 try:
221 try:
223 1/0
222 1/0
224 except Exception:
223 except Exception:
225 raise ValueError("Yikes") from None
224 raise ValueError("Yikes") from None
226 """
225 """
227
226
228 def test_direct_cause_error(self):
227 def test_direct_cause_error(self):
229 if PY3:
228 with tt.AssertPrints(["KeyError", "NameError", "direct cause"]):
230 with tt.AssertPrints(["KeyError", "NameError", "direct cause"]):
229 ip.run_cell(self.DIRECT_CAUSE_ERROR_CODE)
231 ip.run_cell(self.DIRECT_CAUSE_ERROR_CODE)
232
230
233 def test_exception_during_handling_error(self):
231 def test_exception_during_handling_error(self):
234 if PY3:
232 with tt.AssertPrints(["KeyError", "NameError", "During handling"]):
235 with tt.AssertPrints(["KeyError", "NameError", "During handling"]):
233 ip.run_cell(self.EXCEPTION_DURING_HANDLING_CODE)
236 ip.run_cell(self.EXCEPTION_DURING_HANDLING_CODE)
237
234
238 def test_suppress_exception_chaining(self):
235 def test_suppress_exception_chaining(self):
239 if PY3:
236 with tt.AssertNotPrints("ZeroDivisionError"), \
240 with tt.AssertNotPrints("ZeroDivisionError"), \
237 tt.AssertPrints("ValueError", suppress=False):
241 tt.AssertPrints("ValueError", suppress=False):
238 ip.run_cell(self.SUPPRESS_CHAINING_CODE)
242 ip.run_cell(self.SUPPRESS_CHAINING_CODE)
243
239
244
240
245 class RecursionTest(unittest.TestCase):
241 class RecursionTest(unittest.TestCase):
246 DEFINITIONS = """
242 DEFINITIONS = """
247 def non_recurs():
243 def non_recurs():
248 1/0
244 1/0
249
245
250 def r1():
246 def r1():
251 r1()
247 r1()
252
248
253 def r3a():
249 def r3a():
254 r3b()
250 r3b()
255
251
256 def r3b():
252 def r3b():
257 r3c()
253 r3c()
258
254
259 def r3c():
255 def r3c():
260 r3a()
256 r3a()
261
257
262 def r3o1():
258 def r3o1():
263 r3a()
259 r3a()
264
260
265 def r3o2():
261 def r3o2():
266 r3o1()
262 r3o1()
267 """
263 """
268 def setUp(self):
264 def setUp(self):
269 ip.run_cell(self.DEFINITIONS)
265 ip.run_cell(self.DEFINITIONS)
270
266
271 def test_no_recursion(self):
267 def test_no_recursion(self):
272 with tt.AssertNotPrints("frames repeated"):
268 with tt.AssertNotPrints("frames repeated"):
273 ip.run_cell("non_recurs()")
269 ip.run_cell("non_recurs()")
274
270
275 def test_recursion_one_frame(self):
271 def test_recursion_one_frame(self):
276 with tt.AssertPrints("1 frames repeated"):
272 with tt.AssertPrints("1 frames repeated"):
277 ip.run_cell("r1()")
273 ip.run_cell("r1()")
278
274
279 def test_recursion_three_frames(self):
275 def test_recursion_three_frames(self):
280 with tt.AssertPrints("3 frames repeated"):
276 with tt.AssertPrints("3 frames repeated"):
281 ip.run_cell("r3o2()")
277 ip.run_cell("r3o2()")
282
278
283 def test_find_recursion(self):
279 def test_find_recursion(self):
284 captured = []
280 captured = []
285 def capture_exc(*args, **kwargs):
281 def capture_exc(*args, **kwargs):
286 captured.append(sys.exc_info())
282 captured.append(sys.exc_info())
287 with mock.patch.object(ip, 'showtraceback', capture_exc):
283 with mock.patch.object(ip, 'showtraceback', capture_exc):
288 ip.run_cell("r3o2()")
284 ip.run_cell("r3o2()")
289
285
290 self.assertEqual(len(captured), 1)
286 self.assertEqual(len(captured), 1)
291 etype, evalue, tb = captured[0]
287 etype, evalue, tb = captured[0]
292 self.assertIn("recursion", str(evalue))
288 self.assertIn("recursion", str(evalue))
293
289
294 records = ip.InteractiveTB.get_records(tb, 3, ip.InteractiveTB.tb_offset)
290 records = ip.InteractiveTB.get_records(tb, 3, ip.InteractiveTB.tb_offset)
295 for r in records[:10]:
291 for r in records[:10]:
296 print(r[1:4])
292 print(r[1:4])
297
293
298 # The outermost frames should be:
294 # The outermost frames should be:
299 # 0: the 'cell' that was running when the exception came up
295 # 0: the 'cell' that was running when the exception came up
300 # 1: r3o2()
296 # 1: r3o2()
301 # 2: r3o1()
297 # 2: r3o1()
302 # 3: r3a()
298 # 3: r3a()
303 # Then repeating r3b, r3c, r3a
299 # Then repeating r3b, r3c, r3a
304 last_unique, repeat_length = find_recursion(etype, evalue, records)
300 last_unique, repeat_length = find_recursion(etype, evalue, records)
305 self.assertEqual(last_unique, 2)
301 self.assertEqual(last_unique, 2)
306 self.assertEqual(repeat_length, 3)
302 self.assertEqual(repeat_length, 3)
307
303
308
304
309 #----------------------------------------------------------------------------
305 #----------------------------------------------------------------------------
310
306
311 # module testing (minimal)
307 # module testing (minimal)
312 def test_handlers():
308 def test_handlers():
313 def spam(c, d_e):
309 def spam(c, d_e):
314 (d, e) = d_e
310 (d, e) = d_e
315 x = c + d
311 x = c + d
316 y = c * d
312 y = c * d
317 foo(x, y)
313 foo(x, y)
318
314
319 def foo(a, b, bar=1):
315 def foo(a, b, bar=1):
320 eggs(a, b + bar)
316 eggs(a, b + bar)
321
317
322 def eggs(f, g, z=globals()):
318 def eggs(f, g, z=globals()):
323 h = f + g
319 h = f + g
324 i = f - g
320 i = f - g
325 return h / i
321 return h / i
326
322
327 buff = io.StringIO()
323 buff = io.StringIO()
328
324
329 buff.write('')
325 buff.write('')
330 buff.write('*** Before ***')
326 buff.write('*** Before ***')
331 try:
327 try:
332 buff.write(spam(1, (2, 3)))
328 buff.write(spam(1, (2, 3)))
333 except:
329 except:
334 traceback.print_exc(file=buff)
330 traceback.print_exc(file=buff)
335
331
336 handler = ColorTB(ostream=buff)
332 handler = ColorTB(ostream=buff)
337 buff.write('*** ColorTB ***')
333 buff.write('*** ColorTB ***')
338 try:
334 try:
339 buff.write(spam(1, (2, 3)))
335 buff.write(spam(1, (2, 3)))
340 except:
336 except:
341 handler(*sys.exc_info())
337 handler(*sys.exc_info())
342 buff.write('')
338 buff.write('')
343
339
344 handler = VerboseTB(ostream=buff)
340 handler = VerboseTB(ostream=buff)
345 buff.write('*** VerboseTB ***')
341 buff.write('*** VerboseTB ***')
346 try:
342 try:
347 buff.write(spam(1, (2, 3)))
343 buff.write(spam(1, (2, 3)))
348 except:
344 except:
349 handler(*sys.exc_info())
345 handler(*sys.exc_info())
350 buff.write('')
346 buff.write('')
351
347
General Comments 0
You need to be logged in to leave comments. Login now