From e814f71f137120ac50790cec1bd910e1545c660e Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Mon, 7 Oct 2024 10:02:22 -0500 Subject: [PATCH 1/2] Backport of pull request #22633 --- .../plugins/ipythonconsole/tests/conftest.py | 38 ++++++++++++++++-- .../tests/test_ipythonconsole.py | 39 +++++++++++++++++++ 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/spyder/plugins/ipythonconsole/tests/conftest.py b/spyder/plugins/ipythonconsole/tests/conftest.py index dcae4b351f4..65134d3d8fa 100644 --- a/spyder/plugins/ipythonconsole/tests/conftest.py +++ b/spyder/plugins/ipythonconsole/tests/conftest.py @@ -8,6 +8,7 @@ # Standard library imports import os import os.path as osp +from pathlib import Path import sys import threading import traceback @@ -203,9 +204,39 @@ def get_plugin(name): debugger.get_plugin = get_plugin debugger.on_ipython_console_available() + + # Plugin setup console.on_initialize() console._register() console.get_widget().matplotlib_status.register_ipythonconsole(console) + + # Register handlers to run cells. + def get_file_code(fname, save_all=True): + """ + Get code from a file. + + save_all is necessary to keep consistency with the handler registered + in the editor. + """ + path = Path(fname) + return path.read_text() + + def get_cell(cell_id, fname): + """ + Get cell code from a file. + + For now this only works with unnamed cells and cell separators of the + form `# %%`. + """ + path = Path(fname) + contents = path.read_text() + cells = contents.split("# %%") + return cells[int(cell_id)] + + console.register_spyder_kernel_call_handler('get_file_code', get_file_code) + console.register_spyder_kernel_call_handler('run_cell', get_cell) + + # Start client and show window console.create_new_client( special=special, given_name=given_name, @@ -213,9 +244,6 @@ def get_plugin(name): ) window.setCentralWidget(console.get_widget()) - # Set exclamation mark to True - configuration.set('debugger', 'pdb_use_exclamation_mark', True) - if os.name == 'nt': qtbot.addWidget(window) @@ -223,6 +251,10 @@ def get_plugin(name): window.resize(640, 480) window.show() + # Set exclamation mark to True + configuration.set('debugger', 'pdb_use_exclamation_mark', True) + + # Create new client for Matplotlb backend tests if auto_backend or tk_backend: qtbot.wait(SHELL_TIMEOUT) console.create_new_client() diff --git a/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py b/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py index 931d196c2f1..e139e512eff 100644 --- a/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py +++ b/spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py @@ -1656,6 +1656,45 @@ def test_recursive_pdb(ipyconsole, qtbot): assert control.toPlainText().split()[-2:] == ["In", "[3]:"] +def test_pdb_magics_are_recursive(ipyconsole, qtbot, tmp_path): + """ + Check that calls to Pdb magics start a recursive debugger when called in + a debugging session. + """ + shell = ipyconsole.get_current_shellwidget() + control = ipyconsole.get_widget().get_focus_widget() + + # Code to run + code = "a = 10\n\n# %%\n\nb = 20" + + # Write code to file on disk + file = tmp_path / 'test_pdb_magics.py' + file.write_text(code) + + # Filename in the format used when running magics from the main toolbar + fname = str(file).replace('\\', '/') + + # Run file + with qtbot.waitSignal(shell.executed): + shell.execute(f"%debugfile {fname}") + + # Run %debugfile in debugger + with qtbot.waitSignal(shell.executed): + shell.pdb_execute(f"%debugfile {fname}") + + # Check that there are no errors and we started a recursive debugger + assert "error" not in control.toPlainText().lower() + assert "(IPdb [1]):" in control.toPlainText() + + # Run %debugcell in debugger + with qtbot.waitSignal(shell.executed): + shell.pdb_execute(f"%debugcell -i 0 {fname}") + + # Check that there are no errors and we started a recursive debugger + assert "error" not in control.toPlainText().lower() + assert "((IPdb [1])):" in control.toPlainText() + + @flaky(max_runs=3) @pytest.mark.skipif(os.name == 'nt', reason="Doesn't work on windows") def test_stop_pdb(ipyconsole, qtbot): From fa4e9ff9ec2099ace0fd7474ed052b6251872668 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Mon, 7 Oct 2024 10:29:42 -0500 Subject: [PATCH 2/2] git subrepo pull external-deps/spyder-kernels subrepo: subdir: "external-deps/spyder-kernels" merged: "cb12edabd6" upstream: origin: "https://github.com/spyder-ide/spyder-kernels.git" branch: "3.x" commit: "cb12edabd6" git-subrepo: version: "0.4.9" origin: "https://github.com/ingydotnet/git-subrepo" commit: "ea10886" --- external-deps/spyder-kernels/.gitrepo | 4 ++-- .../spyder-kernels/spyder_kernels/customize/code_runner.py | 2 +- .../spyder-kernels/spyder_kernels/customize/utils.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/external-deps/spyder-kernels/.gitrepo b/external-deps/spyder-kernels/.gitrepo index 2ad7f0b08de..5d80de2ef64 100644 --- a/external-deps/spyder-kernels/.gitrepo +++ b/external-deps/spyder-kernels/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/spyder-ide/spyder-kernels.git branch = 3.x - commit = 51fbb9d19129a7e63d2ec376402b42bc8e2f483e - parent = 498219387b5507447bbddf67269777c1d3e9487b + commit = cb12edabd6bd5955131c1a958c40d9cb23c11ecb + parent = e814f71f137120ac50790cec1bd910e1545c660e method = merge cmdver = 0.4.9 diff --git a/external-deps/spyder-kernels/spyder_kernels/customize/code_runner.py b/external-deps/spyder-kernels/spyder_kernels/customize/code_runner.py index d3cc7a1f485..9917abb9999 100644 --- a/external-deps/spyder-kernels/spyder_kernels/customize/code_runner.py +++ b/external-deps/spyder-kernels/spyder_kernels/customize/code_runner.py @@ -247,7 +247,7 @@ def _debugger_exec(self, filename, continue_if_has_breakpoints): debugger.set_remote_filename(filename) debugger.continue_if_has_breakpoints = continue_if_has_breakpoints - def debug_exec(code, glob, loc): + def debug_exec(code, glob=None, loc=None): return sys.call_tracing(debugger.run, (code, glob, loc)) # Enter recursive debugger diff --git a/external-deps/spyder-kernels/spyder_kernels/customize/utils.py b/external-deps/spyder-kernels/spyder_kernels/customize/utils.py index fff18581b2c..23e3c37e0f1 100644 --- a/external-deps/spyder-kernels/spyder_kernels/customize/utils.py +++ b/external-deps/spyder-kernels/spyder_kernels/customize/utils.py @@ -206,7 +206,7 @@ def exec_encapsulate_locals( exec_fun = exec if filename is None: filename = "" - exec_fun(compile(code_ast, filename, "exec"), globals) + exec_fun(compile(code_ast, filename, "exec"), globals, None) finally: if use_locals_hack: # Cleanup code