Spaces:
Runtime error
Runtime error
| # encoding: utf-8 | |
| """A class for managing IPython extensions.""" | |
| # Copyright (c) IPython Development Team. | |
| # Distributed under the terms of the Modified BSD License. | |
| import os | |
| import os.path | |
| import sys | |
| from importlib import import_module, reload | |
| from traitlets.config.configurable import Configurable | |
| from IPython.utils.path import ensure_dir_exists | |
| from traitlets import Instance | |
| #----------------------------------------------------------------------------- | |
| # Main class | |
| #----------------------------------------------------------------------------- | |
| BUILTINS_EXTS = {"storemagic": False, "autoreload": False} | |
| class ExtensionManager(Configurable): | |
| """A class to manage IPython extensions. | |
| An IPython extension is an importable Python module that has | |
| a function with the signature:: | |
| def load_ipython_extension(ipython): | |
| # Do things with ipython | |
| This function is called after your extension is imported and the | |
| currently active :class:`InteractiveShell` instance is passed as | |
| the only argument. You can do anything you want with IPython at | |
| that point, including defining new magic and aliases, adding new | |
| components, etc. | |
| You can also optionally define an :func:`unload_ipython_extension(ipython)` | |
| function, which will be called if the user unloads or reloads the extension. | |
| The extension manager will only call :func:`load_ipython_extension` again | |
| if the extension is reloaded. | |
| You can put your extension modules anywhere you want, as long as | |
| they can be imported by Python's standard import mechanism. | |
| """ | |
| shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True) | |
| def __init__(self, shell=None, **kwargs): | |
| super(ExtensionManager, self).__init__(shell=shell, **kwargs) | |
| self.loaded = set() | |
| def load_extension(self, module_str: str): | |
| """Load an IPython extension by its module name. | |
| Returns the string "already loaded" if the extension is already loaded, | |
| "no load function" if the module doesn't have a load_ipython_extension | |
| function, or None if it succeeded. | |
| """ | |
| try: | |
| return self._load_extension(module_str) | |
| except ModuleNotFoundError: | |
| if module_str in BUILTINS_EXTS: | |
| BUILTINS_EXTS[module_str] = True | |
| return self._load_extension("IPython.extensions." + module_str) | |
| raise | |
| def _load_extension(self, module_str: str): | |
| if module_str in self.loaded: | |
| return "already loaded" | |
| assert self.shell is not None | |
| with self.shell.builtin_trap: | |
| if module_str not in sys.modules: | |
| mod = import_module(module_str) | |
| mod = sys.modules[module_str] | |
| if self._call_load_ipython_extension(mod): | |
| self.loaded.add(module_str) | |
| else: | |
| return "no load function" | |
| def unload_extension(self, module_str: str): | |
| """Unload an IPython extension by its module name. | |
| This function looks up the extension's name in ``sys.modules`` and | |
| simply calls ``mod.unload_ipython_extension(self)``. | |
| Returns the string "no unload function" if the extension doesn't define | |
| a function to unload itself, "not loaded" if the extension isn't loaded, | |
| otherwise None. | |
| """ | |
| if BUILTINS_EXTS.get(module_str, False) is True: | |
| module_str = "IPython.extensions." + module_str | |
| if module_str not in self.loaded: | |
| return "not loaded" | |
| if module_str in sys.modules: | |
| mod = sys.modules[module_str] | |
| if self._call_unload_ipython_extension(mod): | |
| self.loaded.discard(module_str) | |
| else: | |
| return "no unload function" | |
| def reload_extension(self, module_str: str): | |
| """Reload an IPython extension by calling reload. | |
| If the module has not been loaded before, | |
| :meth:`InteractiveShell.load_extension` is called. Otherwise | |
| :func:`reload` is called and then the :func:`load_ipython_extension` | |
| function of the module, if it exists is called. | |
| """ | |
| if BUILTINS_EXTS.get(module_str, False) is True: | |
| module_str = "IPython.extensions." + module_str | |
| if (module_str in self.loaded) and (module_str in sys.modules): | |
| self.unload_extension(module_str) | |
| mod = sys.modules[module_str] | |
| reload(mod) | |
| if self._call_load_ipython_extension(mod): | |
| self.loaded.add(module_str) | |
| else: | |
| self.load_extension(module_str) | |
| def _call_load_ipython_extension(self, mod): | |
| if hasattr(mod, 'load_ipython_extension'): | |
| mod.load_ipython_extension(self.shell) | |
| return True | |
| def _call_unload_ipython_extension(self, mod): | |
| if hasattr(mod, 'unload_ipython_extension'): | |
| mod.unload_ipython_extension(self.shell) | |
| return True | |