##// END OF EJS Templates
DEBUG: on pexpect failure show 1000 chars buffer
Matthias Bussonnier -
Show More
@@ -1,579 +1,580 b''
1 """Tests for debugging machinery.
1 """Tests for debugging machinery.
2 """
2 """
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 import bdb
7 import bdb
8 import builtins
8 import builtins
9 import os
9 import os
10 import signal
10 import signal
11 import subprocess
11 import subprocess
12 import sys
12 import sys
13 import time
13 import time
14 import warnings
14 import warnings
15
15
16 from subprocess import PIPE, CalledProcessError, check_output
16 from subprocess import PIPE, CalledProcessError, check_output
17 from tempfile import NamedTemporaryFile
17 from tempfile import NamedTemporaryFile
18 from textwrap import dedent
18 from textwrap import dedent
19 from unittest.mock import patch
19 from unittest.mock import patch
20
20
21 import nose.tools as nt
21 import nose.tools as nt
22
22
23 from IPython.core import debugger
23 from IPython.core import debugger
24 from IPython.testing import IPYTHON_TESTING_TIMEOUT_SCALE
24 from IPython.testing import IPYTHON_TESTING_TIMEOUT_SCALE
25 from IPython.testing.decorators import skip_win32
25 from IPython.testing.decorators import skip_win32
26
26
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28 # Helper classes, from CPython's Pdb test suite
28 # Helper classes, from CPython's Pdb test suite
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30
30
31 class _FakeInput(object):
31 class _FakeInput(object):
32 """
32 """
33 A fake input stream for pdb's interactive debugger. Whenever a
33 A fake input stream for pdb's interactive debugger. Whenever a
34 line is read, print it (to simulate the user typing it), and then
34 line is read, print it (to simulate the user typing it), and then
35 return it. The set of lines to return is specified in the
35 return it. The set of lines to return is specified in the
36 constructor; they should not have trailing newlines.
36 constructor; they should not have trailing newlines.
37 """
37 """
38 def __init__(self, lines):
38 def __init__(self, lines):
39 self.lines = iter(lines)
39 self.lines = iter(lines)
40
40
41 def readline(self):
41 def readline(self):
42 line = next(self.lines)
42 line = next(self.lines)
43 print(line)
43 print(line)
44 return line+'\n'
44 return line+'\n'
45
45
46 class PdbTestInput(object):
46 class PdbTestInput(object):
47 """Context manager that makes testing Pdb in doctests easier."""
47 """Context manager that makes testing Pdb in doctests easier."""
48
48
49 def __init__(self, input):
49 def __init__(self, input):
50 self.input = input
50 self.input = input
51
51
52 def __enter__(self):
52 def __enter__(self):
53 self.real_stdin = sys.stdin
53 self.real_stdin = sys.stdin
54 sys.stdin = _FakeInput(self.input)
54 sys.stdin = _FakeInput(self.input)
55
55
56 def __exit__(self, *exc):
56 def __exit__(self, *exc):
57 sys.stdin = self.real_stdin
57 sys.stdin = self.real_stdin
58
58
59 #-----------------------------------------------------------------------------
59 #-----------------------------------------------------------------------------
60 # Tests
60 # Tests
61 #-----------------------------------------------------------------------------
61 #-----------------------------------------------------------------------------
62
62
63 def test_longer_repr():
63 def test_longer_repr():
64 try:
64 try:
65 from reprlib import repr as trepr # Py 3
65 from reprlib import repr as trepr # Py 3
66 except ImportError:
66 except ImportError:
67 from repr import repr as trepr # Py 2
67 from repr import repr as trepr # Py 2
68
68
69 a = '1234567890'* 7
69 a = '1234567890'* 7
70 ar = "'1234567890123456789012345678901234567890123456789012345678901234567890'"
70 ar = "'1234567890123456789012345678901234567890123456789012345678901234567890'"
71 a_trunc = "'123456789012...8901234567890'"
71 a_trunc = "'123456789012...8901234567890'"
72 nt.assert_equal(trepr(a), a_trunc)
72 nt.assert_equal(trepr(a), a_trunc)
73 # The creation of our tracer modifies the repr module's repr function
73 # The creation of our tracer modifies the repr module's repr function
74 # in-place, since that global is used directly by the stdlib's pdb module.
74 # in-place, since that global is used directly by the stdlib's pdb module.
75 with warnings.catch_warnings():
75 with warnings.catch_warnings():
76 warnings.simplefilter('ignore', DeprecationWarning)
76 warnings.simplefilter('ignore', DeprecationWarning)
77 debugger.Tracer()
77 debugger.Tracer()
78 nt.assert_equal(trepr(a), ar)
78 nt.assert_equal(trepr(a), ar)
79
79
80 def test_ipdb_magics():
80 def test_ipdb_magics():
81 '''Test calling some IPython magics from ipdb.
81 '''Test calling some IPython magics from ipdb.
82
82
83 First, set up some test functions and classes which we can inspect.
83 First, set up some test functions and classes which we can inspect.
84
84
85 >>> class ExampleClass(object):
85 >>> class ExampleClass(object):
86 ... """Docstring for ExampleClass."""
86 ... """Docstring for ExampleClass."""
87 ... def __init__(self):
87 ... def __init__(self):
88 ... """Docstring for ExampleClass.__init__"""
88 ... """Docstring for ExampleClass.__init__"""
89 ... pass
89 ... pass
90 ... def __str__(self):
90 ... def __str__(self):
91 ... return "ExampleClass()"
91 ... return "ExampleClass()"
92
92
93 >>> def example_function(x, y, z="hello"):
93 >>> def example_function(x, y, z="hello"):
94 ... """Docstring for example_function."""
94 ... """Docstring for example_function."""
95 ... pass
95 ... pass
96
96
97 >>> old_trace = sys.gettrace()
97 >>> old_trace = sys.gettrace()
98
98
99 Create a function which triggers ipdb.
99 Create a function which triggers ipdb.
100
100
101 >>> def trigger_ipdb():
101 >>> def trigger_ipdb():
102 ... a = ExampleClass()
102 ... a = ExampleClass()
103 ... debugger.Pdb().set_trace()
103 ... debugger.Pdb().set_trace()
104
104
105 >>> with PdbTestInput([
105 >>> with PdbTestInput([
106 ... 'pdef example_function',
106 ... 'pdef example_function',
107 ... 'pdoc ExampleClass',
107 ... 'pdoc ExampleClass',
108 ... 'up',
108 ... 'up',
109 ... 'down',
109 ... 'down',
110 ... 'list',
110 ... 'list',
111 ... 'pinfo a',
111 ... 'pinfo a',
112 ... 'll',
112 ... 'll',
113 ... 'continue',
113 ... 'continue',
114 ... ]):
114 ... ]):
115 ... trigger_ipdb()
115 ... trigger_ipdb()
116 --Return--
116 --Return--
117 None
117 None
118 > <doctest ...>(3)trigger_ipdb()
118 > <doctest ...>(3)trigger_ipdb()
119 1 def trigger_ipdb():
119 1 def trigger_ipdb():
120 2 a = ExampleClass()
120 2 a = ExampleClass()
121 ----> 3 debugger.Pdb().set_trace()
121 ----> 3 debugger.Pdb().set_trace()
122 <BLANKLINE>
122 <BLANKLINE>
123 ipdb> pdef example_function
123 ipdb> pdef example_function
124 example_function(x, y, z='hello')
124 example_function(x, y, z='hello')
125 ipdb> pdoc ExampleClass
125 ipdb> pdoc ExampleClass
126 Class docstring:
126 Class docstring:
127 Docstring for ExampleClass.
127 Docstring for ExampleClass.
128 Init docstring:
128 Init docstring:
129 Docstring for ExampleClass.__init__
129 Docstring for ExampleClass.__init__
130 ipdb> up
130 ipdb> up
131 > <doctest ...>(11)<module>()
131 > <doctest ...>(11)<module>()
132 7 'pinfo a',
132 7 'pinfo a',
133 8 'll',
133 8 'll',
134 9 'continue',
134 9 'continue',
135 10 ]):
135 10 ]):
136 ---> 11 trigger_ipdb()
136 ---> 11 trigger_ipdb()
137 <BLANKLINE>
137 <BLANKLINE>
138 ipdb> down
138 ipdb> down
139 None
139 None
140 > <doctest ...>(3)trigger_ipdb()
140 > <doctest ...>(3)trigger_ipdb()
141 1 def trigger_ipdb():
141 1 def trigger_ipdb():
142 2 a = ExampleClass()
142 2 a = ExampleClass()
143 ----> 3 debugger.Pdb().set_trace()
143 ----> 3 debugger.Pdb().set_trace()
144 <BLANKLINE>
144 <BLANKLINE>
145 ipdb> list
145 ipdb> list
146 1 def trigger_ipdb():
146 1 def trigger_ipdb():
147 2 a = ExampleClass()
147 2 a = ExampleClass()
148 ----> 3 debugger.Pdb().set_trace()
148 ----> 3 debugger.Pdb().set_trace()
149 <BLANKLINE>
149 <BLANKLINE>
150 ipdb> pinfo a
150 ipdb> pinfo a
151 Type: ExampleClass
151 Type: ExampleClass
152 String form: ExampleClass()
152 String form: ExampleClass()
153 Namespace: Local...
153 Namespace: Local...
154 Docstring: Docstring for ExampleClass.
154 Docstring: Docstring for ExampleClass.
155 Init docstring: Docstring for ExampleClass.__init__
155 Init docstring: Docstring for ExampleClass.__init__
156 ipdb> ll
156 ipdb> ll
157 1 def trigger_ipdb():
157 1 def trigger_ipdb():
158 2 a = ExampleClass()
158 2 a = ExampleClass()
159 ----> 3 debugger.Pdb().set_trace()
159 ----> 3 debugger.Pdb().set_trace()
160 <BLANKLINE>
160 <BLANKLINE>
161 ipdb> continue
161 ipdb> continue
162
162
163 Restore previous trace function, e.g. for coverage.py
163 Restore previous trace function, e.g. for coverage.py
164
164
165 >>> sys.settrace(old_trace)
165 >>> sys.settrace(old_trace)
166 '''
166 '''
167
167
168 def test_ipdb_magics2():
168 def test_ipdb_magics2():
169 '''Test ipdb with a very short function.
169 '''Test ipdb with a very short function.
170
170
171 >>> old_trace = sys.gettrace()
171 >>> old_trace = sys.gettrace()
172
172
173 >>> def bar():
173 >>> def bar():
174 ... pass
174 ... pass
175
175
176 Run ipdb.
176 Run ipdb.
177
177
178 >>> with PdbTestInput([
178 >>> with PdbTestInput([
179 ... 'continue',
179 ... 'continue',
180 ... ]):
180 ... ]):
181 ... debugger.Pdb().runcall(bar)
181 ... debugger.Pdb().runcall(bar)
182 > <doctest ...>(2)bar()
182 > <doctest ...>(2)bar()
183 1 def bar():
183 1 def bar():
184 ----> 2 pass
184 ----> 2 pass
185 <BLANKLINE>
185 <BLANKLINE>
186 ipdb> continue
186 ipdb> continue
187
187
188 Restore previous trace function, e.g. for coverage.py
188 Restore previous trace function, e.g. for coverage.py
189
189
190 >>> sys.settrace(old_trace)
190 >>> sys.settrace(old_trace)
191 '''
191 '''
192
192
193 def can_quit():
193 def can_quit():
194 '''Test that quit work in ipydb
194 '''Test that quit work in ipydb
195
195
196 >>> old_trace = sys.gettrace()
196 >>> old_trace = sys.gettrace()
197
197
198 >>> def bar():
198 >>> def bar():
199 ... pass
199 ... pass
200
200
201 >>> with PdbTestInput([
201 >>> with PdbTestInput([
202 ... 'quit',
202 ... 'quit',
203 ... ]):
203 ... ]):
204 ... debugger.Pdb().runcall(bar)
204 ... debugger.Pdb().runcall(bar)
205 > <doctest ...>(2)bar()
205 > <doctest ...>(2)bar()
206 1 def bar():
206 1 def bar():
207 ----> 2 pass
207 ----> 2 pass
208 <BLANKLINE>
208 <BLANKLINE>
209 ipdb> quit
209 ipdb> quit
210
210
211 Restore previous trace function, e.g. for coverage.py
211 Restore previous trace function, e.g. for coverage.py
212
212
213 >>> sys.settrace(old_trace)
213 >>> sys.settrace(old_trace)
214 '''
214 '''
215
215
216
216
217 def can_exit():
217 def can_exit():
218 '''Test that quit work in ipydb
218 '''Test that quit work in ipydb
219
219
220 >>> old_trace = sys.gettrace()
220 >>> old_trace = sys.gettrace()
221
221
222 >>> def bar():
222 >>> def bar():
223 ... pass
223 ... pass
224
224
225 >>> with PdbTestInput([
225 >>> with PdbTestInput([
226 ... 'exit',
226 ... 'exit',
227 ... ]):
227 ... ]):
228 ... debugger.Pdb().runcall(bar)
228 ... debugger.Pdb().runcall(bar)
229 > <doctest ...>(2)bar()
229 > <doctest ...>(2)bar()
230 1 def bar():
230 1 def bar():
231 ----> 2 pass
231 ----> 2 pass
232 <BLANKLINE>
232 <BLANKLINE>
233 ipdb> exit
233 ipdb> exit
234
234
235 Restore previous trace function, e.g. for coverage.py
235 Restore previous trace function, e.g. for coverage.py
236
236
237 >>> sys.settrace(old_trace)
237 >>> sys.settrace(old_trace)
238 '''
238 '''
239
239
240
240
241 def test_interruptible_core_debugger():
241 def test_interruptible_core_debugger():
242 """The debugger can be interrupted.
242 """The debugger can be interrupted.
243
243
244 The presumption is there is some mechanism that causes a KeyboardInterrupt
244 The presumption is there is some mechanism that causes a KeyboardInterrupt
245 (this is implemented in ipykernel). We want to ensure the
245 (this is implemented in ipykernel). We want to ensure the
246 KeyboardInterrupt cause debugging to cease.
246 KeyboardInterrupt cause debugging to cease.
247 """
247 """
248 def raising_input(msg="", called=[0]):
248 def raising_input(msg="", called=[0]):
249 called[0] += 1
249 called[0] += 1
250 if called[0] == 1:
250 if called[0] == 1:
251 raise KeyboardInterrupt()
251 raise KeyboardInterrupt()
252 else:
252 else:
253 raise AssertionError("input() should only be called once!")
253 raise AssertionError("input() should only be called once!")
254
254
255 with patch.object(builtins, "input", raising_input):
255 with patch.object(builtins, "input", raising_input):
256 debugger.InterruptiblePdb().set_trace()
256 debugger.InterruptiblePdb().set_trace()
257 # The way this test will fail is by set_trace() never exiting,
257 # The way this test will fail is by set_trace() never exiting,
258 # resulting in a timeout by the test runner. The alternative
258 # resulting in a timeout by the test runner. The alternative
259 # implementation would involve a subprocess, but that adds issues with
259 # implementation would involve a subprocess, but that adds issues with
260 # interrupting subprocesses that are rather complex, so it's simpler
260 # interrupting subprocesses that are rather complex, so it's simpler
261 # just to do it this way.
261 # just to do it this way.
262
262
263 @skip_win32
263 @skip_win32
264 def test_xmode_skip():
264 def test_xmode_skip():
265 """that xmode skip frames
265 """that xmode skip frames
266
266
267 Not as a doctest as pytest does not run doctests.
267 Not as a doctest as pytest does not run doctests.
268 """
268 """
269 import pexpect
269 import pexpect
270 env = os.environ.copy()
270 env = os.environ.copy()
271 env["IPY_TEST_SIMPLE_PROMPT"] = "1"
271 env["IPY_TEST_SIMPLE_PROMPT"] = "1"
272
272
273 child = pexpect.spawn(
273 child = pexpect.spawn(
274 sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
274 sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
275 )
275 )
276 child.timeout = 15 * IPYTHON_TESTING_TIMEOUT_SCALE
276 child.timeout = 15 * IPYTHON_TESTING_TIMEOUT_SCALE
277
277
278 child.expect("IPython")
278 child.expect("IPython")
279 child.expect("\n")
279 child.expect("\n")
280 child.expect_exact("In [1]")
280 child.expect_exact("In [1]")
281
281
282 block = dedent(
282 block = dedent(
283 """
283 """
284 def f():
284 def f():
285 __tracebackhide__ = True
285 __tracebackhide__ = True
286 g()
286 g()
287
287
288 def g():
288 def g():
289 raise ValueError
289 raise ValueError
290
290
291 f()
291 f()
292 """
292 """
293 )
293 )
294
294
295 for line in block.splitlines():
295 for line in block.splitlines():
296 child.sendline(line)
296 child.sendline(line)
297 child.expect_exact(line)
297 child.expect_exact(line)
298 child.expect_exact("skipping")
298 child.expect_exact("skipping")
299
299
300 block = dedent(
300 block = dedent(
301 """
301 """
302 def f():
302 def f():
303 __tracebackhide__ = True
303 __tracebackhide__ = True
304 g()
304 g()
305
305
306 def g():
306 def g():
307 from IPython.core.debugger import set_trace
307 from IPython.core.debugger import set_trace
308 set_trace()
308 set_trace()
309
309
310 f()
310 f()
311 """
311 """
312 )
312 )
313
313
314 for line in block.splitlines():
314 for line in block.splitlines():
315 child.sendline(line)
315 child.sendline(line)
316 child.expect_exact(line)
316 child.expect_exact(line)
317
317
318 child.expect("ipdb>")
318 child.expect("ipdb>")
319 child.sendline("w")
319 child.sendline("w")
320 child.expect("hidden")
320 child.expect("hidden")
321 child.expect("ipdb>")
321 child.expect("ipdb>")
322 child.sendline("skip_hidden false")
322 child.sendline("skip_hidden false")
323 child.sendline("w")
323 child.sendline("w")
324 child.expect("__traceba")
324 child.expect("__traceba")
325 child.expect("ipdb>")
325 child.expect("ipdb>")
326
326
327 child.close()
327 child.close()
328
328
329
329
330 skip_decorators_blocks = (
330 skip_decorators_blocks = (
331 """
331 """
332 def helpers_helper():
332 def helpers_helper():
333 pass # should not stop here except breakpoint
333 pass # should not stop here except breakpoint
334 """,
334 """,
335 """
335 """
336 def helper_1():
336 def helper_1():
337 helpers_helper() # should not stop here
337 helpers_helper() # should not stop here
338 """,
338 """,
339 """
339 """
340 def helper_2():
340 def helper_2():
341 pass # should not stop here
341 pass # should not stop here
342 """,
342 """,
343 """
343 """
344 def pdb_skipped_decorator2(function):
344 def pdb_skipped_decorator2(function):
345 def wrapped_fn(*args, **kwargs):
345 def wrapped_fn(*args, **kwargs):
346 __debuggerskip__ = True
346 __debuggerskip__ = True
347 helper_2()
347 helper_2()
348 __debuggerskip__ = False
348 __debuggerskip__ = False
349 result = function(*args, **kwargs)
349 result = function(*args, **kwargs)
350 __debuggerskip__ = True
350 __debuggerskip__ = True
351 helper_2()
351 helper_2()
352 return result
352 return result
353 return wrapped_fn
353 return wrapped_fn
354 """,
354 """,
355 """
355 """
356 def pdb_skipped_decorator(function):
356 def pdb_skipped_decorator(function):
357 def wrapped_fn(*args, **kwargs):
357 def wrapped_fn(*args, **kwargs):
358 __debuggerskip__ = True
358 __debuggerskip__ = True
359 helper_1()
359 helper_1()
360 __debuggerskip__ = False
360 __debuggerskip__ = False
361 result = function(*args, **kwargs)
361 result = function(*args, **kwargs)
362 __debuggerskip__ = True
362 __debuggerskip__ = True
363 helper_2()
363 helper_2()
364 return result
364 return result
365 return wrapped_fn
365 return wrapped_fn
366 """,
366 """,
367 """
367 """
368 @pdb_skipped_decorator
368 @pdb_skipped_decorator
369 @pdb_skipped_decorator2
369 @pdb_skipped_decorator2
370 def bar(x, y):
370 def bar(x, y):
371 return x * y
371 return x * y
372 """,
372 """,
373 """import IPython.terminal.debugger as ipdb""",
373 """import IPython.terminal.debugger as ipdb""",
374 """
374 """
375 def f():
375 def f():
376 ipdb.set_trace()
376 ipdb.set_trace()
377 bar(3, 4)
377 bar(3, 4)
378 """,
378 """,
379 """
379 """
380 f()
380 f()
381 """,
381 """,
382 )
382 )
383
383
384
384
385 def _decorator_skip_setup():
385 def _decorator_skip_setup():
386 import pexpect
386 import pexpect
387
387
388 env = os.environ.copy()
388 env = os.environ.copy()
389 env["IPY_TEST_SIMPLE_PROMPT"] = "1"
389 env["IPY_TEST_SIMPLE_PROMPT"] = "1"
390
390
391 child = pexpect.spawn(
391 child = pexpect.spawn(
392 sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
392 sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
393 )
393 )
394 child.str_last_chars = 1000
394 child.timeout = 5 * IPYTHON_TESTING_TIMEOUT_SCALE
395 child.timeout = 5 * IPYTHON_TESTING_TIMEOUT_SCALE
395
396
396 child.expect("IPython")
397 child.expect("IPython")
397 child.expect("\n")
398 child.expect("\n")
398
399
399 dedented_blocks = [dedent(b).strip() for b in skip_decorators_blocks]
400 dedented_blocks = [dedent(b).strip() for b in skip_decorators_blocks]
400 in_prompt_number = 1
401 in_prompt_number = 1
401 for cblock in dedented_blocks:
402 for cblock in dedented_blocks:
402 child.expect_exact(f"In [{in_prompt_number}]:")
403 child.expect_exact(f"In [{in_prompt_number}]:")
403 in_prompt_number += 1
404 in_prompt_number += 1
404 for line in cblock.splitlines():
405 for line in cblock.splitlines():
405 child.sendline(line)
406 child.sendline(line)
406 child.expect_exact(line)
407 child.expect_exact(line)
407 child.sendline("")
408 child.sendline("")
408 return child
409 return child
409
410
410
411
411 @skip_win32
412 @skip_win32
412 def test_decorator_skip():
413 def test_decorator_skip():
413 """test that decorator frames can be skipped."""
414 """test that decorator frames can be skipped."""
414
415
415 child = _decorator_skip_setup()
416 child = _decorator_skip_setup()
416
417
417 child.expect_exact("3 bar(3, 4)")
418 child.expect_exact("3 bar(3, 4)")
418 child.expect("ipdb>")
419 child.expect("ipdb>")
419
420
420 child.expect("ipdb>")
421 child.expect("ipdb>")
421 child.sendline("step")
422 child.sendline("step")
422 child.expect_exact("step")
423 child.expect_exact("step")
423
424
424 child.expect_exact("1 @pdb_skipped_decorator")
425 child.expect_exact("1 @pdb_skipped_decorator")
425
426
426 child.sendline("s")
427 child.sendline("s")
427 child.expect_exact("return x * y")
428 child.expect_exact("return x * y")
428
429
429 child.close()
430 child.close()
430
431
431
432
432 @skip_win32
433 @skip_win32
433 def test_decorator_skip_disabled():
434 def test_decorator_skip_disabled():
434 """test that decorator frame skipping can be disabled"""
435 """test that decorator frame skipping can be disabled"""
435
436
436 child = _decorator_skip_setup()
437 child = _decorator_skip_setup()
437
438
438 child.expect_exact("3 bar(3, 4)")
439 child.expect_exact("3 bar(3, 4)")
439
440
440 for input_, expected in [
441 for input_, expected in [
441 ("skip_predicates debuggerskip False", ""),
442 ("skip_predicates debuggerskip False", ""),
442 ("skip_predicates", "debuggerskip : False"),
443 ("skip_predicates", "debuggerskip : False"),
443 ("step", "---> 2 def wrapped_fn"),
444 ("step", "---> 2 def wrapped_fn"),
444 ("step", "----> 3 __debuggerskip__"),
445 ("step", "----> 3 __debuggerskip__"),
445 ("step", "----> 4 helper_1()"),
446 ("step", "----> 4 helper_1()"),
446 ("step", "---> 1 def helper_1():"),
447 ("step", "---> 1 def helper_1():"),
447 ("next", "----> 2 helpers_helper()"),
448 ("next", "----> 2 helpers_helper()"),
448 ("next", "--Return--"),
449 ("next", "--Return--"),
449 ("next", "----> 5 __debuggerskip__ = False"),
450 ("next", "----> 5 __debuggerskip__ = False"),
450 ]:
451 ]:
451 child.expect("ipdb>")
452 child.expect("ipdb>")
452 child.sendline(input_)
453 child.sendline(input_)
453 child.expect_exact(input_)
454 child.expect_exact(input_)
454 child.expect_exact(expected)
455 child.expect_exact(expected)
455
456
456 child.close()
457 child.close()
457
458
458
459
459 @skip_win32
460 @skip_win32
460 def test_decorator_skip_with_breakpoint():
461 def test_decorator_skip_with_breakpoint():
461 """test that decorator frame skipping can be disabled"""
462 """test that decorator frame skipping can be disabled"""
462
463
463 import pexpect
464 import pexpect
464
465
465 env = os.environ.copy()
466 env = os.environ.copy()
466 env["IPY_TEST_SIMPLE_PROMPT"] = "1"
467 env["IPY_TEST_SIMPLE_PROMPT"] = "1"
467
468
468 child = pexpect.spawn(
469 child = pexpect.spawn(
469 sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
470 sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
470 )
471 )
471 child.timeout = 5 * IPYTHON_TESTING_TIMEOUT_SCALE
472 child.timeout = 5 * IPYTHON_TESTING_TIMEOUT_SCALE
472
473
473 child.expect("IPython")
474 child.expect("IPython")
474 child.expect("\n")
475 child.expect("\n")
475
476
476 ### we need a filename, so we need to exec the full block with a filename
477 ### we need a filename, so we need to exec the full block with a filename
477 with NamedTemporaryFile(suffix=".py", dir=".", delete=True) as tf:
478 with NamedTemporaryFile(suffix=".py", dir=".", delete=True) as tf:
478
479
479 name = tf.name[:-3].split("/")[-1]
480 name = tf.name[:-3].split("/")[-1]
480 tf.write("\n".join([dedent(x) for x in skip_decorators_blocks[:-1]]).encode())
481 tf.write("\n".join([dedent(x) for x in skip_decorators_blocks[:-1]]).encode())
481 tf.flush()
482 tf.flush()
482 codeblock = f"from {name} import f"
483 codeblock = f"from {name} import f"
483
484
484 dedented_blocks = [
485 dedented_blocks = [
485 codeblock,
486 codeblock,
486 "f()",
487 "f()",
487 ]
488 ]
488
489
489 in_prompt_number = 1
490 in_prompt_number = 1
490 for cblock in dedented_blocks:
491 for cblock in dedented_blocks:
491 child.expect_exact(f"In [{in_prompt_number}]:")
492 child.expect_exact(f"In [{in_prompt_number}]:")
492 in_prompt_number += 1
493 in_prompt_number += 1
493 for line in cblock.splitlines():
494 for line in cblock.splitlines():
494 child.sendline(line)
495 child.sendline(line)
495 child.expect_exact(line)
496 child.expect_exact(line)
496 child.sendline("")
497 child.sendline("")
497
498
498 # as the filename does not exists, we'll rely on the filename prompt
499 # as the filename does not exists, we'll rely on the filename prompt
499 child.expect_exact("47 bar(3, 4)")
500 child.expect_exact("47 bar(3, 4)")
500
501
501 for input_, expected in [
502 for input_, expected in [
502 (f"b {name}.py:3", ""),
503 (f"b {name}.py:3", ""),
503 ("step", "1---> 3 pass # should not stop here except"),
504 ("step", "1---> 3 pass # should not stop here except"),
504 ("step", "---> 38 @pdb_skipped_decorator"),
505 ("step", "---> 38 @pdb_skipped_decorator"),
505 ("continue", ""),
506 ("continue", ""),
506 ]:
507 ]:
507 child.expect("ipdb>")
508 child.expect("ipdb>")
508 child.sendline(input_)
509 child.sendline(input_)
509 child.expect_exact(input_)
510 child.expect_exact(input_)
510 child.expect_exact(expected)
511 child.expect_exact(expected)
511
512
512 child.close()
513 child.close()
513
514
514
515
515 @skip_win32
516 @skip_win32
516 def test_where_erase_value():
517 def test_where_erase_value():
517 """Test that `where` does not access f_locals and erase values."""
518 """Test that `where` does not access f_locals and erase values."""
518 import pexpect
519 import pexpect
519
520
520 env = os.environ.copy()
521 env = os.environ.copy()
521 env["IPY_TEST_SIMPLE_PROMPT"] = "1"
522 env["IPY_TEST_SIMPLE_PROMPT"] = "1"
522
523
523 child = pexpect.spawn(
524 child = pexpect.spawn(
524 sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
525 sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
525 )
526 )
526 child.timeout = 15 * IPYTHON_TESTING_TIMEOUT_SCALE
527 child.timeout = 15 * IPYTHON_TESTING_TIMEOUT_SCALE
527
528
528 child.expect("IPython")
529 child.expect("IPython")
529 child.expect("\n")
530 child.expect("\n")
530 child.expect_exact("In [1]")
531 child.expect_exact("In [1]")
531
532
532 block = dedent(
533 block = dedent(
533 """
534 """
534 def simple_f():
535 def simple_f():
535 myvar = 1
536 myvar = 1
536 print(myvar)
537 print(myvar)
537 1/0
538 1/0
538 print(myvar)
539 print(myvar)
539 simple_f() """
540 simple_f() """
540 )
541 )
541
542
542 for line in block.splitlines():
543 for line in block.splitlines():
543 child.sendline(line)
544 child.sendline(line)
544 child.expect_exact(line)
545 child.expect_exact(line)
545 child.expect_exact("ZeroDivisionError")
546 child.expect_exact("ZeroDivisionError")
546 child.expect_exact("In [2]:")
547 child.expect_exact("In [2]:")
547
548
548 child.sendline("%debug")
549 child.sendline("%debug")
549
550
550 ##
551 ##
551 child.expect("ipdb>")
552 child.expect("ipdb>")
552
553
553 child.sendline("myvar")
554 child.sendline("myvar")
554 child.expect("1")
555 child.expect("1")
555
556
556 ##
557 ##
557 child.expect("ipdb>")
558 child.expect("ipdb>")
558
559
559 child.sendline("myvar = 2")
560 child.sendline("myvar = 2")
560
561
561 ##
562 ##
562 child.expect_exact("ipdb>")
563 child.expect_exact("ipdb>")
563
564
564 child.sendline("myvar")
565 child.sendline("myvar")
565
566
566 child.expect_exact("2")
567 child.expect_exact("2")
567
568
568 ##
569 ##
569 child.expect("ipdb>")
570 child.expect("ipdb>")
570 child.sendline("where")
571 child.sendline("where")
571
572
572 ##
573 ##
573 child.expect("ipdb>")
574 child.expect("ipdb>")
574 child.sendline("myvar")
575 child.sendline("myvar")
575
576
576 child.expect_exact("2")
577 child.expect_exact("2")
577 child.expect("ipdb>")
578 child.expect("ipdb>")
578
579
579 child.close()
580 child.close()
General Comments 0
You need to be logged in to leave comments. Login now