From 75ecfe932fc9ca3505efbebc016b046ffc7d0d68 2023-02-22 08:20:15 From: Matthias Bussonnier Date: 2023-02-22 08:20:15 Subject: [PATCH] capture_output does not respect trailing semicolon (#13940) This change tests whether the Python code inside the `%%capture` magic ends with a `';'`. If it does, the code no longer creates the object that is supposed to store the cell output. If such object already exists, it is deleted. Please review and suggest changes if you think they can improve the solution. Thanks. --- diff --git a/IPython/core/magics/execution.py b/IPython/core/magics/execution.py index 7b558d5..c4c3a4b 100644 --- a/IPython/core/magics/execution.py +++ b/IPython/core/magics/execution.py @@ -47,6 +47,7 @@ from IPython.utils.ipstruct import Struct from IPython.utils.module_paths import find_mod from IPython.utils.path import get_py_filename, shellglob from IPython.utils.timing import clock, clock2 +from IPython.core.displayhook import DisplayHook #----------------------------------------------------------------------------- # Magic implementation classes @@ -1461,7 +1462,10 @@ class ExecutionMagics(Magics): disp = not args.no_display with capture_output(out, err, disp) as io: self.shell.run_cell(cell) - if args.output: + if DisplayHook.semicolon_at_end_of_expression(cell): + if args.output in self.shell.user_ns: + del self.shell.user_ns[args.output] + elif args.output: self.shell.user_ns[args.output] = io def parse_breakpoint(text, current_file): diff --git a/IPython/core/tests/test_magic.py b/IPython/core/tests/test_magic.py index 09c6748..8963705 100644 --- a/IPython/core/tests/test_magic.py +++ b/IPython/core/tests/test_magic.py @@ -530,6 +530,25 @@ def test_time_local_ns(): del ip.user_ns["myvar"] +# Test %%capture magic. Added to test issue #13926 +def test_capture(): + ip = get_ipython() + + # Test %%capture nominal case + ip.run_cell("%%capture abc\n1+2") + with tt.AssertPrints("True", suppress=False): + ip.run_cell("'abc' in locals()") + with tt.AssertPrints("True", suppress=False): + ip.run_cell("'outputs' in dir(abc)") + with tt.AssertPrints("3", suppress=False): + ip.run_cell("abc.outputs[0]") + + # Test %%capture with ';' at end of expression + ip.run_cell("%%capture abc\n7+8;") + with tt.AssertPrints("False", suppress=False): + ip.run_cell("'abc' in locals()") + + def test_doctest_mode(): "Toggle doctest_mode twice, it should be a no-op and run without error" _ip.run_line_magic("doctest_mode", "")