Skip to content

Commit f521d9d

Browse files
committed
fix-time-magic-interrupt-handling
1 parent b854379 commit f521d9d

1 file changed

Lines changed: 31 additions & 10 deletions

File tree

IPython/core/magics/execution.py

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import sys
2121
import time
2222
import timeit
23+
import signal
2324
from typing import Dict, Any
2425
from ast import (
2526
Assign,
@@ -1257,6 +1258,13 @@ def timeit(self, line='', cell=None, local_ns=None):
12571258
if return_result:
12581259
return timeit_result
12591260

1261+
@magic_arguments.magic_arguments()
1262+
@magic_arguments.argument(
1263+
"--no-raise-error",
1264+
action="store_true",
1265+
dest="no_raise_error",
1266+
help="If given, don't re-raise exceptions",
1267+
)
12601268
@skip_doctest
12611269
@no_var_expand
12621270
@needs_local_scope
@@ -1329,10 +1337,7 @@ def time(self, line="", cell=None, local_ns=None):
13291337
Wall time: 0.00 s
13301338
Compiler : 0.78 s
13311339
"""
1332-
# fail immediately if the given expression can't be compiled
1333-
1334-
if line and cell:
1335-
raise UsageError("Can't use statement directly after '%%time'!")
1340+
args = magic_arguments.parse_argstring(self.time, line)
13361341

13371342
if cell:
13381343
expr = self.shell.transform_cell(cell)
@@ -1376,13 +1381,21 @@ def time(self, line="", cell=None, local_ns=None):
13761381
wtime = time.time
13771382
# time execution
13781383
wall_st = wtime()
1384+
# Track whether to propagate exceptions or exit
1385+
exit_on_interrupt = False
1386+
interrupt_occured = False
1387+
13791388
if mode == "eval":
13801389
st = clock2()
13811390
try:
13821391
out = eval(code, glob, local_ns)
1392+
except KeyboardInterrupt:
1393+
interrupt_occured = True
1394+
exit_on_interrupt = True
13831395
except Exception:
1384-
self.shell.showtraceback()
1385-
return
1396+
interrupt_occured = True
1397+
if not args.no_raise_error:
1398+
exit_on_interrupt = True
13861399
end = clock2()
13871400
else:
13881401
st = clock2()
@@ -1393,11 +1406,14 @@ def time(self, line="", cell=None, local_ns=None):
13931406
if expr_val is not None:
13941407
code_2 = self.shell.compile(expr_val, source, 'eval')
13951408
out = eval(code_2, glob, local_ns)
1409+
except KeyboardInterrupt:
1410+
interrupt_occured = True
1411+
exit_on_interrupt = True
13961412
except Exception:
1397-
self.shell.showtraceback()
1398-
return
1413+
interrupt_occured = True
1414+
if not args.no_raise_error:
1415+
exit_on_interrupt = True
13991416
end = clock2()
1400-
14011417
wall_end = wtime()
14021418
# Compute actual times and report
14031419
wall_time = wall_end - wall_st
@@ -1416,6 +1432,11 @@ def time(self, line="", cell=None, local_ns=None):
14161432
print(f"Compiler : {_format_time(tc)}")
14171433
if tp > tp_min:
14181434
print(f"Parser : {_format_time(tp)}")
1435+
if interrupt_occured:
1436+
if exit_on_interrupt:
1437+
self.shell.showtraceback()
1438+
sys.exit(signal.SIGINT)
1439+
return
14191440
return out
14201441

14211442
@skip_doctest
@@ -1514,7 +1535,7 @@ def macro(self, parameter_s=''):
15141535
default="",
15151536
nargs="?",
15161537
help="""
1517-
1538+
15181539
The name of the variable in which to store output.
15191540
This is a ``utils.io.CapturedIO`` object with stdout/err attributes
15201541
for the text of the captured output.

0 commit comments

Comments
 (0)