diff --git a/spyder_kernels/comms/frontendcomm.py b/spyder_kernels/comms/frontendcomm.py index 1e7e86f4..9eaf2ee1 100644 --- a/spyder_kernels/comms/frontendcomm.py +++ b/spyder_kernels/comms/frontendcomm.py @@ -130,9 +130,11 @@ def _check_comm_reply(self): """ Send comm message to frontend to check if the iopub channel is ready """ - if len(self._pending_comms) == 0: + # Make sure the length doesn't change during iteration + pending_comms = list(self._pending_comms.values()) + if len(pending_comms) == 0: return - for comm in self._pending_comms.values(): + for comm in pending_comms: self._notify_comm_ready(comm) self.kernel.io_loop.call_later(1, self._check_comm_reply) diff --git a/spyder_kernels/comms/utils.py b/spyder_kernels/comms/utils.py index 68ea8c57..dc6b8c99 100644 --- a/spyder_kernels/comms/utils.py +++ b/spyder_kernels/comms/utils.py @@ -67,11 +67,8 @@ def __call__(self, string): if not self._warning_shown: self._warning_shown = True - # Don't print handler name for `show_mpl_backend_errors` - # because we have a specific message for it. # request_pdb_stop is expected to print messages. - if self._name not in [ - 'show_mpl_backend_errors', 'request_pdb_stop']: + if self._name not in ['request_pdb_stop']: self._write( "\nOutput from spyder call " + repr(self._name) + ":\n" ) diff --git a/spyder_kernels/console/kernel.py b/spyder_kernels/console/kernel.py index d900d8a7..0585077a 100644 --- a/spyder_kernels/console/kernel.py +++ b/spyder_kernels/console/kernel.py @@ -29,12 +29,12 @@ from zmq.utils.garbage import gc # Local imports +import spyder_kernels 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) +from spyder_kernels.utils.mpl import automatic_backend, MPL_BACKENDS_TO_SPYDER from spyder_kernels.utils.nsview import ( get_remote_data, make_remote_view, get_size) from spyder_kernels.console.shell import SpyderShell @@ -65,7 +65,6 @@ def __init__(self, *args, **kwargs): register_comm_handlers(self.shell, self.frontend_comm) self.namespace_view_settings = {} - self._mpl_backend_error = None self.faulthandler_handle = None self._cwd_initialised = False @@ -77,6 +76,18 @@ def __init__(self, *args, **kwargs): # Socket to signal shell_stream locally self.loopback_socket = None + @property + def kernel_info(self): + # Used for checking correct version by spyder + infos = super().kernel_info + infos.update({ + "spyder_kernels_info": ( + spyder_kernels.__version__, + sys.executable + ) + }) + return infos + # -- Public API ----------------------------------------------------------- def frontend_call(self, blocking=False, broadcast=True, timeout=None, callback=None, display_error=False): @@ -114,7 +125,6 @@ def publish_state(self): except Exception: pass - @comm_handler def enable_faulthandler(self): """ Open a file to save the faulthandling and identifiers for @@ -140,6 +150,11 @@ def enable_faulthandler(self): faulthandler.enable(self.faulthandler_handle) return self.faulthandler_handle.name, main_id, system_ids + @comm_handler + def safe_exec(self, filename): + """Safely execute a file using IPKernelApp._exec_file.""" + self.parent._exec_file(filename) + @comm_handler def get_fault_text(self, fault_filename, main_id, ignore_ids): """Get fault text from old run.""" @@ -260,11 +275,6 @@ 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): """ @@ -529,7 +539,7 @@ def get_mpl_interactive_backend(self): if framework is None: # Since no interactive backend has been set yet, this is # equivalent to having the inline one. - return 0 + return 'inline' elif framework in mapping: return MPL_BACKENDS_TO_SPYDER[mapping[framework]] else: @@ -538,25 +548,42 @@ def get_mpl_interactive_backend(self): # magic but not through our Preferences. return -1 - def set_matplotlib_backend(self, backend, pylab=False): - """Set matplotlib backend given a Spyder backend option.""" - mpl_backend = MPL_BACKENDS_FROM_SPYDER[str(backend)] - self._set_mpl_backend(mpl_backend, pylab=pylab) - - def set_mpl_inline_figure_format(self, figure_format): - """Set the inline figure format to use with matplotlib.""" - mpl_figure_format = INLINE_FIGURE_FORMATS[figure_format] - self._set_config_option( - 'InlineBackend.figure_format', mpl_figure_format) - - def set_mpl_inline_resolution(self, resolution): - """Set inline figure resolution.""" - self._set_mpl_inline_rc_config('figure.dpi', resolution) + @comm_handler + def set_matplotlib_conf(self, conf): + """Set matplotlib configuration""" + pylab_autoload_n = 'pylab/autoload' + pylab_backend_n = 'pylab/backend' + figure_format_n = 'pylab/inline/figure_format' + resolution_n = 'pylab/inline/resolution' + width_n = 'pylab/inline/width' + height_n = 'pylab/inline/height' + bbox_inches_n = 'pylab/inline/bbox_inches' + inline_backend = 'inline' + + if pylab_autoload_n in conf or pylab_backend_n in conf: + self._set_mpl_backend( + conf.get(pylab_backend_n, inline_backend), + pylab=conf.get(pylab_autoload_n, False) + ) + + if figure_format_n in conf: + self._set_config_option( + 'InlineBackend.figure_format', + conf[figure_format_n] + ) + + if resolution_n in conf: + self._set_mpl_inline_rc_config('figure.dpi', conf[resolution_n]) + + if width_n in conf and height_n in conf: + self._set_mpl_inline_rc_config( + 'figure.figsize', + (conf[width_n], conf[height_n]) + ) + + if bbox_inches_n in conf: + self.set_mpl_inline_bbox_inches(conf[bbox_inches_n]) - def set_mpl_inline_figure_size(self, width, height): - """Set inline figure size.""" - value = (width, height) - self._set_mpl_inline_rc_config('figure.figsize', value) def set_mpl_inline_bbox_inches(self, bbox_inches): """ @@ -599,11 +626,54 @@ def set_autocall(self, autocall): # --- Additional methods @comm_handler - def set_cwd(self, dirname): - """Set current working directory.""" - self._cwd_initialised = True - os.chdir(dirname) - self.publish_state() + def set_configuration(self, conf): + """Set kernel configuration""" + ret = {} + for key, value in conf.items(): + if key == "cwd": + self._cwd_initialised = True + os.chdir(value) + self.publish_state() + elif key == "namespace_view_settings": + self.namespace_view_settings = value + self.publish_state() + elif key == "pdb": + self.shell.set_pdb_configuration(value) + elif key == "faulthandler": + if value: + ret[key] = self.enable_faulthandler() + elif key == "special_kernel": + try: + self.set_special_kernel(value) + except Exception: + ret["special_kernel_error"] = value + elif key == "color scheme": + self.set_color_scheme(value) + elif key == "jedi_completer": + self.set_jedi_completer(value) + elif key == "greedy_completer": + self.set_greedy_completer(value) + elif key == "autocall": + self.set_autocall(value) + elif key == "matplotlib": + self.set_matplotlib_conf(value) + elif key == "update_gui": + self.shell.update_gui_frontend = value + elif key == "wurlitzer": + if value: + self._load_wurlitzer() + elif key == "autoreload_magic": + self._autoreload_magic(value) + return ret + + def set_color_scheme(self, color_scheme): + if color_scheme == "dark": + # Needed to change the colors of tracebacks + self.shell.run_line_magic("colors", "linux") + self.set_sympy_forecolor(background_color='dark') + elif color_scheme == "light": + self.shell.run_line_magic("colors", "lightbg") + self.set_sympy_forecolor(background_color='light') def get_cwd(self): """Get current working directory.""" @@ -631,28 +701,57 @@ def close_all_mpl_figures(self): except: pass - @comm_handler - def is_special_kernel_valid(self): + def set_special_kernel(self, special): """ Check if optional dependencies are available for special consoles. """ - try: - if os.environ.get('SPY_AUTOLOAD_PYLAB_O') == 'True': - import matplotlib - elif os.environ.get('SPY_SYMPY_O') == 'True': - import sympy - elif os.environ.get('SPY_RUN_CYTHON') == 'True': - import cython - except Exception: - # Use Exception instead of ImportError here because modules can - # fail to be imported due to a lot of issues. - if os.environ.get('SPY_AUTOLOAD_PYLAB_O') == 'True': - return u'matplotlib' - elif os.environ.get('SPY_SYMPY_O') == 'True': - return u'sympy' - elif os.environ.get('SPY_RUN_CYTHON') == 'True': - return u'cython' - return None + self.shell.special = None + if special is None: + return + + if special == "pylab": + import matplotlib + exec("from pylab import *", self.shell.user_ns) + self.shell.special = special + return + + if special == "sympy": + import sympy + sympy_init = "\n".join([ + "from sympy import *", + "x, y, z, t = symbols('x y z t')", + "k, m, n = symbols('k m n', integer=True)", + "f, g, h = symbols('f g h', cls=Function)", + "init_printing()", + ]) + exec(sympy_init, self.shell.user_ns) + self.shell.special = special + return + + if special == "cython": + import cython + + # Import pyximport to enable Cython files support for + # import statement + import pyximport + pyx_setup_args = {} + + # Add Numpy include dir to pyximport/distutils + try: + import numpy + pyx_setup_args['include_dirs'] = numpy.get_include() + except Exception: + pass + + # Setup pyximport and enable Cython files reload + pyximport.install(setup_args=pyx_setup_args, + reload_support=True) + + self.shell.run_line_magic("reload_ext", "Cython") + self.shell.special = special + return + + raise NotImplementedError(f"{special}") @comm_handler def update_syspath(self, path_dict, new_path_dict): @@ -805,6 +904,9 @@ def _set_mpl_backend(self, backend, pylab=False): magic = 'pylab' if pylab else 'matplotlib' + if backend == "auto": + backend = automatic_backend() + error = None try: # This prevents Matplotlib to automatically set the backend, which @@ -843,8 +945,8 @@ def _set_mpl_backend(self, backend, pylab=False): error = generic_error.format(err) + '\n\n' + additional_info except Exception: error = generic_error.format(traceback.format_exc()) - - self._mpl_backend_error = error + if error: + print(error) def _set_config_option(self, option, value): """ @@ -876,31 +978,30 @@ 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': - try: - from sympy import init_printing - if background_color == 'dark': - init_printing(forecolor='White', ip=self.shell) - elif background_color == 'light': - init_printing(forecolor='Black', ip=self.shell) - except Exception: - pass + if self.shell.special != "sympy": + return + + try: + from sympy import init_printing + if background_color == 'dark': + init_printing(forecolor='White', ip=self.shell) + elif background_color == 'light': + init_printing(forecolor='Black', ip=self.shell) + except Exception: + pass # --- Others - def _load_autoreload_magic(self): + def _autoreload_magic(self, enable): """Load %autoreload magic.""" try: - self.shell.run_line_magic('reload_ext', 'autoreload') - self.shell.run_line_magic('autoreload', '2') + if enable: + self.shell.run_line_magic('reload_ext', 'autoreload') + self.shell.run_line_magic('autoreload', "2") + else: + self.shell.run_line_magic('autoreload', "off") + except Exception: pass diff --git a/spyder_kernels/console/shell.py b/spyder_kernels/console/shell.py index 49cde462..5256bb67 100644 --- a/spyder_kernels/console/shell.py +++ b/spyder_kernels/console/shell.py @@ -23,11 +23,9 @@ from ipykernel.zmqshell import ZMQInteractiveShell # Local imports -import spyder_kernels from spyder_kernels.customize.namespace_manager import NamespaceManager 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 @@ -51,16 +49,12 @@ def __init__(self, *args, **kwargs): # Create _namespace_stack before __init__ self._namespace_stack = [] self._request_pdb_stop = False + self.special = None self._pdb_conf = {} super(SpyderShell, self).__init__(*args, **kwargs) self._allow_kbdint = False self.register_debugger_sigint() - - # Used for checking correct version by spyder - self._spyder_kernels_version = ( - spyder_kernels.__version__, - sys.executable - ) + self.update_gui_frontend = False # register post_execute self.events.register('post_execute', self.do_post_execute) @@ -94,14 +88,16 @@ def enable_matplotlib(self, gui=None): if gui is None or gui.lower() == "auto": gui = automatic_backend() gui, backend = super(SpyderShell, self).enable_matplotlib(gui) - try: - self.kernel.frontend_call(blocking=False).update_matplotlib_gui(gui) - except Exception: - pass + if self.update_gui_frontend: + try: + self.kernel.frontend_call( + blocking=False + ).update_matplotlib_gui(gui) + except Exception: + pass return gui, backend # --- For Pdb namespace integration - @comm_handler def set_pdb_configuration(self, pdb_conf): """ Set Pdb configuration. diff --git a/spyder_kernels/console/start.py b/spyder_kernels/console/start.py index 708319c0..eb910305 100644 --- a/spyder_kernels/console/start.py +++ b/spyder_kernels/console/start.py @@ -21,8 +21,6 @@ # Local imports from spyder_kernels.utils.misc import is_module_installed -from spyder_kernels.utils.mpl import ( - MPL_BACKENDS_FROM_SPYDER, INLINE_FIGURE_FORMATS) def import_spydercustomize(): @@ -48,24 +46,6 @@ def import_spydercustomize(): except ValueError: pass - -def sympy_config(mpl_backend): - """Sympy configuration""" - if mpl_backend is not None: - lines = """ -from sympy.interactive import init_session -init_session() -%matplotlib {0} -""".format(mpl_backend) - else: - lines = """ -from sympy.interactive import init_session -init_session() -""" - - return lines - - def kernel_config(): """Create a config object with IPython kernel options.""" from IPython.core.application import get_ipython_dir @@ -113,21 +93,6 @@ def kernel_config(): "del sys; del pdb" ) - # Run lines of code at startup - run_lines_o = os.environ.get('SPY_RUN_LINES_O') - if run_lines_o is not None: - spy_cfg.IPKernelApp.exec_lines += ( - [x.strip() for x in run_lines_o.split(';')] - ) - - # Load %autoreload magic - spy_cfg.IPKernelApp.exec_lines.append( - "get_ipython().kernel._load_autoreload_magic()") - - # Load wurlitzer extension - spy_cfg.IPKernelApp.exec_lines.append( - "get_ipython().kernel._load_wurlitzer()") - # Default inline backend configuration. # This is useful to have when people doesn't # use our config system to configure the @@ -150,63 +115,8 @@ def kernel_config(): 'figure.edgecolor': 'white' } - # Pylab configuration - mpl_backend = None if is_module_installed('matplotlib'): - # Set Matplotlib backend with Spyder options - pylab_o = os.environ.get('SPY_PYLAB_O') - backend_o = os.environ.get('SPY_BACKEND_O') - if pylab_o == 'True' and backend_o is not None: - mpl_backend = MPL_BACKENDS_FROM_SPYDER[backend_o] - # Inline backend configuration - if mpl_backend == 'inline': - # Figure format - format_o = os.environ.get('SPY_FORMAT_O') - formats = INLINE_FIGURE_FORMATS - if format_o is not None: - spy_cfg.InlineBackend.figure_format = formats[format_o] - - # Resolution - resolution_o = os.environ.get('SPY_RESOLUTION_O') - if resolution_o is not None: - spy_cfg.InlineBackend.rc['figure.dpi'] = float( - resolution_o) - - # Figure size - width_o = float(os.environ.get('SPY_WIDTH_O')) - height_o = float(os.environ.get('SPY_HEIGHT_O')) - if width_o is not None and height_o is not None: - spy_cfg.InlineBackend.rc['figure.figsize'] = (width_o, - height_o) - - # Print figure kwargs - bbox_inches_o = os.environ.get('SPY_BBOX_INCHES_O') - bbox_inches = 'tight' if bbox_inches_o == 'True' else None - spy_cfg.InlineBackend.print_figure_kwargs.update( - {'bbox_inches': bbox_inches}) - else: - # Set Matplotlib backend to inline for external kernels. - # Fixes issue 108 - mpl_backend = 'inline' - - # Automatically load Pylab and Numpy, or only set Matplotlib - # backend - autoload_pylab_o = os.environ.get('SPY_AUTOLOAD_PYLAB_O') == 'True' - command = "get_ipython().kernel._set_mpl_backend('{0}', {1})" - spy_cfg.IPKernelApp.exec_lines.append( - command.format(mpl_backend, autoload_pylab_o)) - - # Enable Cython magic - run_cython = os.environ.get('SPY_RUN_CYTHON') == 'True' - if run_cython and is_module_installed('Cython'): - spy_cfg.IPKernelApp.exec_lines.append('%reload_ext Cython') - - # Run a file at startup - use_file_o = os.environ.get('SPY_USE_FILE_O') - run_file_o = os.environ.get('SPY_RUN_FILE_O') - if use_file_o == 'True' and run_file_o is not None: - if osp.exists(run_file_o): - spy_cfg.IPKernelApp.file_to_run = run_file_o + spy_cfg.IPKernelApp.matplotlib = "inline" # Autocall autocall_o = os.environ.get('SPY_AUTOCALL_O') @@ -220,12 +130,6 @@ def kernel_config(): greedy_o = os.environ.get('SPY_GREEDY_O') == 'True' spy_cfg.IPCompleter.greedy = greedy_o - # Sympy loading - sympy_o = os.environ.get('SPY_SYMPY_O') == 'True' - if sympy_o and is_module_installed('sympy'): - lines = sympy_config(mpl_backend) - spy_cfg.IPKernelApp.exec_lines.append(lines) - # Disable the new mechanism to capture and forward low-level output # in IPykernel 6. For that we have Wurlitzer. spy_cfg.IPKernelApp.capture_fd_output = False diff --git a/spyder_kernels/console/tests/test_console_kernel.py b/spyder_kernels/console/tests/test_console_kernel.py index 65870f02..a9564feb 100644 --- a/spyder_kernels/console/tests/test_console_kernel.py +++ b/spyder_kernels/console/tests/test_console_kernel.py @@ -32,7 +32,6 @@ # Local imports from spyder_kernels.utils.iofuncs import iofunctions -from spyder_kernels.utils.mpl import MPL_BACKENDS_FROM_SPYDER from spyder_kernels.utils.test_utils import get_kernel, get_log_text from spyder_kernels.customize.spyderpdb import SpyderPdb from spyder_kernels.comms.commbase import CommBase @@ -1138,7 +1137,7 @@ def test_locals_globals_in_pdb(kernel): @flaky(max_runs=3) -@pytest.mark.parametrize("backend", [None, 'inline', 'tk', 'qt5']) +@pytest.mark.parametrize("backend", [None, 'inline', 'tk', 'qt']) @pytest.mark.skipif( os.environ.get('USE_CONDA') != 'true', reason="Doesn't work with pip packages") @@ -1169,11 +1168,14 @@ def test_get_interactive_backend(backend): user_expressions = reply['content']['user_expressions'] value = user_expressions['output']['data']['text/plain'] + # remove quotes + value = value[1:-1] + # Assert we got the right interactive backend if backend is not None: - assert MPL_BACKENDS_FROM_SPYDER[value] == backend + assert value == backend else: - assert value == '0' + assert value == 'inline' def test_global_message(tmpdir): diff --git a/spyder_kernels/customize/code_runner.py b/spyder_kernels/customize/code_runner.py index f4321eaa..a2c7fde4 100644 --- a/spyder_kernels/customize/code_runner.py +++ b/spyder_kernels/customize/code_runner.py @@ -266,7 +266,7 @@ def _exec_file( """ Execute a file. """ - if self.umr.enabled: + if self.umr.enabled and self.shell.special != "cython": self.umr.run() if args is not None and not isinstance(args, str): raise TypeError("expected a character buffer object") @@ -324,7 +324,7 @@ def _exec_file( print("Working directory {} doesn't exist.\n".format(wdir)) try: - if self.umr.has_cython: + if self.shell.special == "cython": # Cython files with io.open(filename, encoding="utf-8") as f: self.shell.run_cell_magic("cython", "", f.read()) diff --git a/spyder_kernels/customize/tests/test_umr.py b/spyder_kernels/customize/tests/test_umr.py index 438f7eff..fe84791b 100644 --- a/spyder_kernels/customize/tests/test_umr.py +++ b/spyder_kernels/customize/tests/test_umr.py @@ -39,27 +39,6 @@ def square(x): return create_module -def test_umr_skip_cython(user_module): - """ - Test that the UMR doesn't try to reload modules when Cython - support is active. - """ - # Create user module - user_module('foo') - - # Activate Cython support - os.environ['SPY_RUN_CYTHON'] = 'True' - - # Create UMR - umr = UserModuleReloader() - - import foo - assert umr.is_module_reloadable(foo, 'foo') == False - - # Deactivate Cython support - os.environ['SPY_RUN_CYTHON'] = 'False' - - def test_umr_run(user_module): """Test that UMR's run method is working correctly.""" # Create user module @@ -72,12 +51,11 @@ def test_umr_run(user_module): umr = UserModuleReloader() from foo1.bar import square - umr.run() - umr.modnames_to_reload == ['foo', 'foo.bar'] + assert umr.run() == ['foo1', 'foo1.bar'] def test_umr_previous_modules(user_module): - """Test that UMR's previos_modules is working as expected.""" + """Test that UMR's previous_modules is working as expected.""" # Create user module user_module('foo2') diff --git a/spyder_kernels/customize/umr.py b/spyder_kernels/customize/umr.py index fa140020..e779ec33 100644 --- a/spyder_kernels/customize/umr.py +++ b/spyder_kernels/customize/umr.py @@ -49,13 +49,6 @@ def __init__(self, namelist=None, pathlist=None): # List of previously loaded modules self.previous_modules = list(sys.modules.keys()) - # List of module names to reload - self.modnames_to_reload = [] - - # Activate Cython support - self.has_cython = False - self.activate_cython() - # Check if the UMR is enabled or not enabled = os.environ.get("SPY_UMR_ENABLED", "") self.enabled = enabled.lower() == "true" @@ -66,54 +59,18 @@ def __init__(self, namelist=None, pathlist=None): def is_module_reloadable(self, module, modname): """Decide if a module is reloadable or not.""" - if self.has_cython: - # Don't return cached inline compiled .PYX files + if ( + path_is_library(getattr(module, '__file__', None), self.pathlist) + or self.is_module_in_namelist(modname) + ): return False else: - if (path_is_library(getattr(module, '__file__', None), - self.pathlist) or - self.is_module_in_namelist(modname)): - return False - else: - return True + return True def is_module_in_namelist(self, modname): """Decide if a module can be reloaded or not according to its name.""" return set(modname.split('.')) & set(self.namelist) - def activate_cython(self): - """ - Activate Cython support. - - We need to run this here because if the support is - active, we don't to run the UMR at all. - """ - run_cython = os.environ.get("SPY_RUN_CYTHON") == "True" - - if run_cython: - try: - __import__('Cython') - self.has_cython = True - except Exception: - pass - - if self.has_cython: - # Import pyximport to enable Cython files support for - # import statement - import pyximport - pyx_setup_args = {} - - # Add Numpy include dir to pyximport/distutils - try: - import numpy - pyx_setup_args['include_dirs'] = numpy.get_include() - except Exception: - pass - - # Setup pyximport and enable Cython files reload - pyximport.install(setup_args=pyx_setup_args, - reload_support=True) - def run(self): """ Delete user modules to force Python to deeply reload them @@ -122,18 +79,20 @@ def run(self): modules installed in subdirectories of Python interpreter's binary Do not del C modules """ - self.modnames_to_reload = [] + modnames_to_reload = [] for modname, module in list(sys.modules.items()): if modname not in self.previous_modules: # Decide if a module can be reloaded or not if self.is_module_reloadable(module, modname): - self.modnames_to_reload.append(modname) + modnames_to_reload.append(modname) del sys.modules[modname] else: continue # Report reloaded modules - if self.verbose and self.modnames_to_reload: - modnames = self.modnames_to_reload + if self.verbose and modnames_to_reload: + modnames = modnames_to_reload print("\x1b[4;33m%s\x1b[24m%s\x1b[0m" % ("Reloaded modules", ": "+", ".join(modnames))) + + return modnames_to_reload diff --git a/spyder_kernels/utils/mpl.py b/spyder_kernels/utils/mpl.py index 7927e49d..00f47bac 100644 --- a/spyder_kernels/utils/mpl.py +++ b/spyder_kernels/utils/mpl.py @@ -11,13 +11,6 @@ from spyder_kernels.utils.misc import is_module_installed -# Mapping of inline figure formats -INLINE_FIGURE_FORMATS = { - '0': 'png', - '1': 'svg' -} - - # Inline backend if is_module_installed('matplotlib_inline'): inline_backend = 'module://matplotlib_inline.backend_inline' @@ -27,30 +20,20 @@ # Mapping of matlotlib backends options to Spyder MPL_BACKENDS_TO_SPYDER = { - inline_backend: 0, - 'Qt5Agg': 2, - 'QtAgg': 2, # For Matplotlib 3.5+ - 'TkAgg': 3, - 'MacOSX': 4, + inline_backend: "inline", + 'Qt5Agg': 'qt', + 'QtAgg': 'qt', # For Matplotlib 3.5+ + 'TkAgg': 'tk', + 'MacOSX': 'osx', } def automatic_backend(): """Get Matplolib automatic backend option.""" if is_module_installed('PyQt5'): - auto_backend = 'qt5' + auto_backend = 'qt' elif is_module_installed('_tkinter'): auto_backend = 'tk' else: auto_backend = 'inline' return auto_backend - - -# Mapping of Spyder options to backends -MPL_BACKENDS_FROM_SPYDER = { - '0': 'inline', - '1': automatic_backend(), - '2': 'qt5', - '3': 'tk', - '4': 'osx' -}