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