diff --git a/external-deps/spyder-kernels/.gitrepo b/external-deps/spyder-kernels/.gitrepo index 689db90028d..4330f21a012 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 = master - commit = 529ace9d587e13fc490abc839d7e161750cd7013 - parent = 45caa547953e0359367f5aeee09c8c7a3e354d1b + commit = 82222bbeb8cfa48f20cf762a272eb2aaadaebf2c + parent = fc973c39da8c97bbcd9d1dc1aff5ffcdefe96a32 method = merge - cmdver = 0.4.5 + cmdver = 0.4.3 diff --git a/external-deps/spyder-kernels/spyder_kernels/comms/decorators.py b/external-deps/spyder-kernels/spyder_kernels/comms/decorators.py new file mode 100644 index 00000000000..b2633404a07 --- /dev/null +++ b/external-deps/spyder-kernels/spyder_kernels/comms/decorators.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# +# Copyright © Spyder Project Contributors +# Licensed under the terms of the MIT License +# (see spyder/__init__.py for details) + +""" +Comms decorators. +""" + + +def comm_handler(fun): + """Decorator to mark comm handler methods.""" + fun._is_comm_handler = True + return fun + + +def register_comm_handlers(instance, frontend_comm): + """ + Registers an instance whose methods have been marked with comm_handler. + """ + for method_name in instance.__class__.__dict__: + method = getattr(instance, method_name) + if hasattr(method, '_is_comm_handler'): + frontend_comm.register_call_handler( + method_name, method) + diff --git a/external-deps/spyder-kernels/spyder_kernels/console/kernel.py b/external-deps/spyder-kernels/spyder_kernels/console/kernel.py index d1a585a301a..f35c3fe5e4e 100644 --- a/external-deps/spyder-kernels/spyder_kernels/console/kernel.py +++ b/external-deps/spyder-kernels/spyder_kernels/console/kernel.py @@ -30,6 +30,8 @@ # Local imports from spyder_kernels.comms.frontendcomm import FrontendComm +from spyder_kernels.comms.decorators import ( + register_comm_handlers, comm_handler) from spyder_kernels.utils.iofuncs import iofunctions from spyder_kernels.utils.mpl import ( MPL_BACKENDS_FROM_SPYDER, MPL_BACKENDS_TO_SPYDER, INLINE_FIGURE_FORMATS) @@ -39,7 +41,6 @@ from spyder_kernels.comms.utils import WriteContext - logger = logging.getLogger(__name__) @@ -60,40 +61,8 @@ def __init__(self, *args, **kwargs): self.frontend_comm = FrontendComm(self) # All functions that can be called through the comm - handlers = { - 'set_pdb_configuration': self.shell.set_pdb_configuration, - 'get_value': self.get_value, - 'load_data': self.load_data, - 'save_namespace': self.save_namespace, - 'is_defined': self.is_defined, - 'get_doc': self.get_doc, - 'get_source': self.get_source, - 'set_value': self.set_value, - 'remove_value': self.remove_value, - 'copy_value': self.copy_value, - 'set_cwd': self.set_cwd, - 'get_syspath': self.get_syspath, - 'get_env': self.get_env, - 'close_all_mpl_figures': self.close_all_mpl_figures, - 'show_mpl_backend_errors': self.show_mpl_backend_errors, - 'get_namespace_view': self.get_namespace_view, - 'set_namespace_view_settings': self.set_namespace_view_settings, - 'get_var_properties': self.get_var_properties, - 'set_sympy_forecolor': self.set_sympy_forecolor, - 'update_syspath': self.update_syspath, - 'is_special_kernel_valid': self.is_special_kernel_valid, - 'get_matplotlib_backend': self.get_matplotlib_backend, - 'get_mpl_interactive_backend': self.get_mpl_interactive_backend, - 'pdb_input_reply': self.shell.pdb_input_reply, - 'enable_faulthandler': self.enable_faulthandler, - 'get_current_frames': self.get_current_frames, - 'request_pdb_stop': self.shell.request_pdb_stop, - 'raise_interrupt_signal': self.shell.raise_interrupt_signal, - 'get_fault_text': self.get_fault_text, - } - for call_id in handlers: - self.frontend_comm.register_call_handler( - call_id, handlers[call_id]) + register_comm_handlers(self, self.frontend_comm) + register_comm_handlers(self.shell, self.frontend_comm) self.namespace_view_settings = {} self._mpl_backend_error = None @@ -145,6 +114,7 @@ def publish_state(self): except Exception: pass + @comm_handler def enable_faulthandler(self): """ Open a file to save the faulthandling and identifiers for @@ -170,6 +140,7 @@ def enable_faulthandler(self): faulthandler.enable(self.faulthandler_handle) return self.faulthandler_handle.name, main_id, system_ids + @comm_handler def get_fault_text(self, fault_filename, main_id, ignore_ids): """Get fault text from old run.""" # Read file @@ -263,6 +234,7 @@ def filter_stack(self, stack, is_main): stack = [] return stack + @comm_handler def get_current_frames(self, ignore_internal_threads=True, capture_locals=False): """Get the current frames.""" @@ -292,10 +264,12 @@ def get_current_frames(self, ignore_internal_threads=True, return frames # --- For the Variable Explorer + @comm_handler def set_namespace_view_settings(self, settings): """Set namespace_view_settings.""" self.namespace_view_settings = settings + @comm_handler def get_namespace_view(self, frame=None): """ Return the namespace view @@ -331,6 +305,7 @@ def get_namespace_view(self, frame=None): else: return None + @comm_handler def get_var_properties(self): """ Get some properties of the variables in the current @@ -361,27 +336,32 @@ def get_var_properties(self): else: return None + @comm_handler def get_value(self, name): """Get the value of a variable""" ns = self.shell._get_current_namespace() return ns[name] + @comm_handler def set_value(self, name, value): """Set the value of a variable""" ns = self.shell._get_reference_namespace(name) ns[name] = value self.log.debug(ns) + @comm_handler def remove_value(self, name): """Remove a variable""" ns = self.shell._get_reference_namespace(name) ns.pop(name) + @comm_handler def copy_value(self, orig_name, new_name): """Copy a variable""" ns = self.shell._get_reference_namespace(orig_name) ns[new_name] = ns[orig_name] + @comm_handler def load_data(self, filename, ext, overwrite=False): """ Load data from filename. @@ -418,6 +398,7 @@ def load_data(self, filename, ext, overwrite=False): return None + @comm_handler def save_namespace(self, filename): """Save namespace into filename""" ns = self.shell._get_current_namespace() @@ -471,6 +452,7 @@ def interrupt_eventloop(self): self.loopback_socket, self.session.msg("interrupt_eventloop")) # --- For the Help plugin + @comm_handler def is_defined(self, obj, force_import=False): """Return True if object is defined in current namespace""" from spyder_kernels.utils.dochelpers import isdefined @@ -478,6 +460,7 @@ def is_defined(self, obj, force_import=False): ns = self.shell._get_current_namespace(with_magics=True) return isdefined(obj, force_import=force_import, namespace=ns) + @comm_handler def get_doc(self, objtxt): """Get object documentation dictionary""" try: @@ -491,6 +474,7 @@ def get_doc(self, objtxt): if valid: return getdoc(obj) + @comm_handler def get_source(self, objtxt): """Get object source""" from spyder_kernels.utils.dochelpers import getsource @@ -500,6 +484,7 @@ def get_source(self, objtxt): return getsource(obj) # -- For Matplolib + @comm_handler def get_matplotlib_backend(self): """Get current matplotlib backend.""" try: @@ -508,6 +493,7 @@ def get_matplotlib_backend(self): except Exception: return None + @comm_handler def get_mpl_interactive_backend(self): """ Get current Matplotlib interactive backend. @@ -616,6 +602,7 @@ def set_autocall(self, autocall): self._set_config_option('ZMQInteractiveShell.autocall', autocall) # --- Additional methods + @comm_handler def set_cwd(self, dirname): """Set current working directory.""" self._cwd_initialised = True @@ -629,14 +616,17 @@ def get_cwd(self): except (IOError, OSError): pass + @comm_handler def get_syspath(self): """Return sys.path contents.""" return sys.path[:] + @comm_handler def get_env(self): """Get environment variables.""" return os.environ.copy() + @comm_handler def close_all_mpl_figures(self): """Close all Matplotlib figures.""" try: @@ -645,6 +635,7 @@ def close_all_mpl_figures(self): except: pass + @comm_handler def is_special_kernel_valid(self): """ Check if optional dependencies are available for special consoles. @@ -667,6 +658,7 @@ def is_special_kernel_valid(self): return u'cython' return None + @comm_handler def update_syspath(self, path_dict, new_path_dict): """ Update the PYTHONPATH of the kernel. @@ -888,11 +880,13 @@ def _set_mpl_inline_rc_config(self, option, value): # Needed in case matplolib isn't installed pass + @comm_handler def show_mpl_backend_errors(self): """Show Matplotlib backend errors after the prompt is ready.""" if self._mpl_backend_error is not None: print(self._mpl_backend_error) # spyder: test-skip + @comm_handler def set_sympy_forecolor(self, background_color='dark'): """Set SymPy forecolor depending on console background.""" if os.environ.get('SPY_SYMPY_O') == 'True': diff --git a/external-deps/spyder-kernels/spyder_kernels/console/shell.py b/external-deps/spyder-kernels/spyder_kernels/console/shell.py index 6dbbd7598c6..c641feb8176 100644 --- a/external-deps/spyder-kernels/spyder_kernels/console/shell.py +++ b/external-deps/spyder-kernels/spyder_kernels/console/shell.py @@ -28,6 +28,7 @@ from spyder_kernels.customize.spyderpdb import SpyderPdb from spyder_kernels.customize.code_runner import SpyderCodeRunner from spyder_kernels.comms.frontendcomm import CommError +from spyder_kernels.comms.decorators import comm_handler from spyder_kernels.utils.mpl import automatic_backend @@ -100,6 +101,7 @@ def enable_matplotlib(self, gui=None): return gui, backend # --- For Pdb namespace integration + @comm_handler def set_pdb_configuration(self, pdb_conf): """ Set Pdb configuration. @@ -274,6 +276,7 @@ def register_debugger_sigint(self): """Register sigint handler.""" signal.signal(signal.SIGINT, self.spyderkernel_sigint_handler) + @comm_handler def raise_interrupt_signal(self): """Raise interrupt signal.""" if os.name == "nt": @@ -293,6 +296,7 @@ def raise_interrupt_signal(self): else: self.kernel._send_interrupt_children() + @comm_handler def request_pdb_stop(self): """Request pdb to stop at the next possible position.""" pdb_session = self.pdb_session @@ -351,6 +355,7 @@ async def run_code(self, *args, **kwargs): except KeyboardInterrupt: self.showtraceback() + @comm_handler def pdb_input_reply(self, line, echo_stack_entry=True): """Get a pdb command from the frontend.""" debugger = self.pdb_session diff --git a/external-deps/spyder-kernels/spyder_kernels/customize/spyderpdb.py b/external-deps/spyder-kernels/spyder_kernels/customize/spyderpdb.py index ec505368b4e..b9d76f63adf 100755 --- a/external-deps/spyder-kernels/spyder_kernels/customize/spyderpdb.py +++ b/external-deps/spyder-kernels/spyder_kernels/customize/spyderpdb.py @@ -17,6 +17,7 @@ import traceback import threading from collections import namedtuple +from functools import lru_cache from IPython.core.autocall import ZMQExitAutocall from IPython.core.debugger import Pdb as ipyPdb @@ -678,6 +679,21 @@ def _cmdloop(self): "For copying text while debugging, use Ctrl+Shift+C", file=self.stdout) + @lru_cache + def canonic(self, filename): + """Return canonical form of filename.""" + return super().canonic(filename) + + def do_exitdb(self, arg): + """Exit the debugger""" + self._set_stopinfo(self.botframe, None, -1) + sys.settrace(None) + frame = sys._getframe().f_back + while frame and frame is not self.botframe: + del frame.f_trace + frame = frame.f_back + return 1 + def cmdloop(self, intro=None): """ Repeatedly issue a prompt, accept input, parse an initial prefix