##// END OF EJS Templates
hardcode builtins extensions
Matthias Bussonnier -
Show More
@@ -1,150 +1,167 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """A class for managing IPython extensions."""
2 """A class for managing IPython extensions."""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 import os
7 import os
8 import os.path
8 import os.path
9 import sys
9 import sys
10 from importlib import import_module, reload
10 from importlib import import_module, reload
11
11
12 from traitlets.config.configurable import Configurable
12 from traitlets.config.configurable import Configurable
13 from IPython.utils.path import ensure_dir_exists, compress_user
13 from IPython.utils.path import ensure_dir_exists, compress_user
14 from IPython.utils.decorators import undoc
14 from IPython.utils.decorators import undoc
15 from traitlets import Instance
15 from traitlets import Instance
16
16
17
17
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 # Main class
19 # Main class
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 BUILTINS_EXTS = {"storemagic": False, "autoreload": False}
23
24
22 class ExtensionManager(Configurable):
25 class ExtensionManager(Configurable):
23 """A class to manage IPython extensions.
26 """A class to manage IPython extensions.
24
27
25 An IPython extension is an importable Python module that has
28 An IPython extension is an importable Python module that has
26 a function with the signature::
29 a function with the signature::
27
30
28 def load_ipython_extension(ipython):
31 def load_ipython_extension(ipython):
29 # Do things with ipython
32 # Do things with ipython
30
33
31 This function is called after your extension is imported and the
34 This function is called after your extension is imported and the
32 currently active :class:`InteractiveShell` instance is passed as
35 currently active :class:`InteractiveShell` instance is passed as
33 the only argument. You can do anything you want with IPython at
36 the only argument. You can do anything you want with IPython at
34 that point, including defining new magic and aliases, adding new
37 that point, including defining new magic and aliases, adding new
35 components, etc.
38 components, etc.
36
39
37 You can also optionally define an :func:`unload_ipython_extension(ipython)`
40 You can also optionally define an :func:`unload_ipython_extension(ipython)`
38 function, which will be called if the user unloads or reloads the extension.
41 function, which will be called if the user unloads or reloads the extension.
39 The extension manager will only call :func:`load_ipython_extension` again
42 The extension manager will only call :func:`load_ipython_extension` again
40 if the extension is reloaded.
43 if the extension is reloaded.
41
44
42 You can put your extension modules anywhere you want, as long as
45 You can put your extension modules anywhere you want, as long as
43 they can be imported by Python's standard import mechanism. However,
46 they can be imported by Python's standard import mechanism. However,
44 to make it easy to write extensions, you can also put your extensions
47 to make it easy to write extensions, you can also put your extensions
45 in ``os.path.join(self.ipython_dir, 'extensions')``. This directory
48 in ``os.path.join(self.ipython_dir, 'extensions')``. This directory
46 is added to ``sys.path`` automatically.
49 is added to ``sys.path`` automatically.
47 """
50 """
48
51
49 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
52 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
50
53
51 def __init__(self, shell=None, **kwargs):
54 def __init__(self, shell=None, **kwargs):
52 super(ExtensionManager, self).__init__(shell=shell, **kwargs)
55 super(ExtensionManager, self).__init__(shell=shell, **kwargs)
53 self.shell.observe(
56 self.shell.observe(
54 self._on_ipython_dir_changed, names=('ipython_dir',)
57 self._on_ipython_dir_changed, names=('ipython_dir',)
55 )
58 )
56 self.loaded = set()
59 self.loaded = set()
57
60
58 @property
61 @property
59 def ipython_extension_dir(self):
62 def ipython_extension_dir(self):
60 return os.path.join(self.shell.ipython_dir, u'extensions')
63 return os.path.join(self.shell.ipython_dir, u'extensions')
61
64
62 def _on_ipython_dir_changed(self, change):
65 def _on_ipython_dir_changed(self, change):
63 ensure_dir_exists(self.ipython_extension_dir)
66 ensure_dir_exists(self.ipython_extension_dir)
64
67
65 def load_extension(self, module_str):
68 def load_extension(self, module_str: str):
66 """Load an IPython extension by its module name.
69 """Load an IPython extension by its module name.
67
70
68 Returns the string "already loaded" if the extension is already loaded,
71 Returns the string "already loaded" if the extension is already loaded,
69 "no load function" if the module doesn't have a load_ipython_extension
72 "no load function" if the module doesn't have a load_ipython_extension
70 function, or None if it succeeded.
73 function, or None if it succeeded.
71 """
74 """
75 try:
76 return self._load_extension(module_str)
77 except ModuleNotFoundError:
78 if module_str in BUILTINS_EXTS:
79 BUILTINS_EXTS[module_str] = True
80 return self._load_extension("IPython.extensions." + module_str)
81 raise
82
83 def _load_extension(self, module_str: str):
72 if module_str in self.loaded:
84 if module_str in self.loaded:
73 return "already loaded"
85 return "already loaded"
74
86
75 from IPython.utils.syspathcontext import prepended_to_syspath
87 from IPython.utils.syspathcontext import prepended_to_syspath
76
88
77 with self.shell.builtin_trap:
89 with self.shell.builtin_trap:
78 if module_str not in sys.modules:
90 if module_str not in sys.modules:
79 with prepended_to_syspath(self.ipython_extension_dir):
91 with prepended_to_syspath(self.ipython_extension_dir):
80 mod = import_module(module_str)
92 mod = import_module(module_str)
81 if mod.__file__.startswith(self.ipython_extension_dir):
93 if mod.__file__.startswith(self.ipython_extension_dir):
82 print(("Loading extensions from {dir} is deprecated. "
94 print(("Loading extensions from {dir} is deprecated. "
83 "We recommend managing extensions like any "
95 "We recommend managing extensions like any "
84 "other Python packages, in site-packages.").format(
96 "other Python packages, in site-packages.").format(
85 dir=compress_user(self.ipython_extension_dir)))
97 dir=compress_user(self.ipython_extension_dir)))
86 mod = sys.modules[module_str]
98 mod = sys.modules[module_str]
87 if self._call_load_ipython_extension(mod):
99 if self._call_load_ipython_extension(mod):
88 self.loaded.add(module_str)
100 self.loaded.add(module_str)
89 else:
101 else:
90 return "no load function"
102 return "no load function"
91
103
92 def unload_extension(self, module_str):
104 def unload_extension(self, module_str: str):
93 """Unload an IPython extension by its module name.
105 """Unload an IPython extension by its module name.
94
106
95 This function looks up the extension's name in ``sys.modules`` and
107 This function looks up the extension's name in ``sys.modules`` and
96 simply calls ``mod.unload_ipython_extension(self)``.
108 simply calls ``mod.unload_ipython_extension(self)``.
97
109
98 Returns the string "no unload function" if the extension doesn't define
110 Returns the string "no unload function" if the extension doesn't define
99 a function to unload itself, "not loaded" if the extension isn't loaded,
111 a function to unload itself, "not loaded" if the extension isn't loaded,
100 otherwise None.
112 otherwise None.
101 """
113 """
114 if BUILTINS_EXTS.get(module_str, False) is True:
115 module_str = "IPython.extensions." + module_str
102 if module_str not in self.loaded:
116 if module_str not in self.loaded:
103 return "not loaded"
117 return "not loaded"
104
118
105 if module_str in sys.modules:
119 if module_str in sys.modules:
106 mod = sys.modules[module_str]
120 mod = sys.modules[module_str]
107 if self._call_unload_ipython_extension(mod):
121 if self._call_unload_ipython_extension(mod):
108 self.loaded.discard(module_str)
122 self.loaded.discard(module_str)
109 else:
123 else:
110 return "no unload function"
124 return "no unload function"
111
125
112 def reload_extension(self, module_str):
126 def reload_extension(self, module_str: str):
113 """Reload an IPython extension by calling reload.
127 """Reload an IPython extension by calling reload.
114
128
115 If the module has not been loaded before,
129 If the module has not been loaded before,
116 :meth:`InteractiveShell.load_extension` is called. Otherwise
130 :meth:`InteractiveShell.load_extension` is called. Otherwise
117 :func:`reload` is called and then the :func:`load_ipython_extension`
131 :func:`reload` is called and then the :func:`load_ipython_extension`
118 function of the module, if it exists is called.
132 function of the module, if it exists is called.
119 """
133 """
120 from IPython.utils.syspathcontext import prepended_to_syspath
134 from IPython.utils.syspathcontext import prepended_to_syspath
121
135
136 if BUILTINS_EXTS.get(module_str, False) is True:
137 module_str = "IPython.extensions." + module_str
138
122 if (module_str in self.loaded) and (module_str in sys.modules):
139 if (module_str in self.loaded) and (module_str in sys.modules):
123 self.unload_extension(module_str)
140 self.unload_extension(module_str)
124 mod = sys.modules[module_str]
141 mod = sys.modules[module_str]
125 with prepended_to_syspath(self.ipython_extension_dir):
142 with prepended_to_syspath(self.ipython_extension_dir):
126 reload(mod)
143 reload(mod)
127 if self._call_load_ipython_extension(mod):
144 if self._call_load_ipython_extension(mod):
128 self.loaded.add(module_str)
145 self.loaded.add(module_str)
129 else:
146 else:
130 self.load_extension(module_str)
147 self.load_extension(module_str)
131
148
132 def _call_load_ipython_extension(self, mod):
149 def _call_load_ipython_extension(self, mod):
133 if hasattr(mod, 'load_ipython_extension'):
150 if hasattr(mod, 'load_ipython_extension'):
134 mod.load_ipython_extension(self.shell)
151 mod.load_ipython_extension(self.shell)
135 return True
152 return True
136
153
137 def _call_unload_ipython_extension(self, mod):
154 def _call_unload_ipython_extension(self, mod):
138 if hasattr(mod, 'unload_ipython_extension'):
155 if hasattr(mod, 'unload_ipython_extension'):
139 mod.unload_ipython_extension(self.shell)
156 mod.unload_ipython_extension(self.shell)
140 return True
157 return True
141
158
142 @undoc
159 @undoc
143 def install_extension(self, url, filename=None):
160 def install_extension(self, url, filename=None):
144 """
161 """
145 Deprecated.
162 Deprecated.
146 """
163 """
147 # Ensure the extension directory exists
164 # Ensure the extension directory exists
148 raise DeprecationWarning(
165 raise DeprecationWarning(
149 '`install_extension` and the `install_ext` magic have been deprecated since IPython 4.0'
166 '`install_extension` and the `install_ext` magic have been deprecated since IPython 4.0'
150 'Use pip or other package managers to manage ipython extensions.')
167 'Use pip or other package managers to manage ipython extensions.')
General Comments 0
You need to be logged in to leave comments. Login now