##// END OF EJS Templates
Remove old mentions and uses of ipython_extension_dir (#14310)...
M Bussonnier -
r28600:93ffc153 merge
parent child Browse files
Show More
@@ -1,150 +1,135 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
13 from IPython.utils.path import ensure_dir_exists
14 from traitlets import Instance
14 from traitlets import Instance
15
15
16
16
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 # Main class
18 # Main class
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 BUILTINS_EXTS = {"storemagic": False, "autoreload": False}
21 BUILTINS_EXTS = {"storemagic": False, "autoreload": False}
22
22
23
23
24 class ExtensionManager(Configurable):
24 class ExtensionManager(Configurable):
25 """A class to manage IPython extensions.
25 """A class to manage IPython extensions.
26
26
27 An IPython extension is an importable Python module that has
27 An IPython extension is an importable Python module that has
28 a function with the signature::
28 a function with the signature::
29
29
30 def load_ipython_extension(ipython):
30 def load_ipython_extension(ipython):
31 # Do things with ipython
31 # Do things with ipython
32
32
33 This function is called after your extension is imported and the
33 This function is called after your extension is imported and the
34 currently active :class:`InteractiveShell` instance is passed as
34 currently active :class:`InteractiveShell` instance is passed as
35 the only argument. You can do anything you want with IPython at
35 the only argument. You can do anything you want with IPython at
36 that point, including defining new magic and aliases, adding new
36 that point, including defining new magic and aliases, adding new
37 components, etc.
37 components, etc.
38
38
39 You can also optionally define an :func:`unload_ipython_extension(ipython)`
39 You can also optionally define an :func:`unload_ipython_extension(ipython)`
40 function, which will be called if the user unloads or reloads the extension.
40 function, which will be called if the user unloads or reloads the extension.
41 The extension manager will only call :func:`load_ipython_extension` again
41 The extension manager will only call :func:`load_ipython_extension` again
42 if the extension is reloaded.
42 if the extension is reloaded.
43
43
44 You can put your extension modules anywhere you want, as long as
44 You can put your extension modules anywhere you want, as long as
45 they can be imported by Python's standard import mechanism. However,
45 they can be imported by Python's standard import mechanism.
46 to make it easy to write extensions, you can also put your extensions
47 in ``os.path.join(self.ipython_dir, 'extensions')``. This directory
48 is added to ``sys.path`` automatically.
49 """
46 """
50
47
51 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
48 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
52
49
53 def __init__(self, shell=None, **kwargs):
50 def __init__(self, shell=None, **kwargs):
54 super(ExtensionManager, self).__init__(shell=shell, **kwargs)
51 super(ExtensionManager, self).__init__(shell=shell, **kwargs)
55 self.shell.observe(
56 self._on_ipython_dir_changed, names=('ipython_dir',)
57 )
58 self.loaded = set()
52 self.loaded = set()
59
53
60 @property
61 def ipython_extension_dir(self):
62 return os.path.join(self.shell.ipython_dir, u'extensions')
63
64 def _on_ipython_dir_changed(self, change):
65 ensure_dir_exists(self.ipython_extension_dir)
66
67 def load_extension(self, module_str: str):
54 def load_extension(self, module_str: str):
68 """Load an IPython extension by its module name.
55 """Load an IPython extension by its module name.
69
56
70 Returns the string "already loaded" if the extension is already loaded,
57 Returns the string "already loaded" if the extension is already loaded,
71 "no load function" if the module doesn't have a load_ipython_extension
58 "no load function" if the module doesn't have a load_ipython_extension
72 function, or None if it succeeded.
59 function, or None if it succeeded.
73 """
60 """
74 try:
61 try:
75 return self._load_extension(module_str)
62 return self._load_extension(module_str)
76 except ModuleNotFoundError:
63 except ModuleNotFoundError:
77 if module_str in BUILTINS_EXTS:
64 if module_str in BUILTINS_EXTS:
78 BUILTINS_EXTS[module_str] = True
65 BUILTINS_EXTS[module_str] = True
79 return self._load_extension("IPython.extensions." + module_str)
66 return self._load_extension("IPython.extensions." + module_str)
80 raise
67 raise
81
68
82 def _load_extension(self, module_str: str):
69 def _load_extension(self, module_str: str):
83 if module_str in self.loaded:
70 if module_str in self.loaded:
84 return "already loaded"
71 return "already loaded"
85
72
86 assert self.shell is not None
73 assert self.shell is not None
87
74
88 with self.shell.builtin_trap:
75 with self.shell.builtin_trap:
89 if module_str not in sys.modules:
76 if module_str not in sys.modules:
90 mod = import_module(module_str)
77 mod = import_module(module_str)
91 mod = sys.modules[module_str]
78 mod = sys.modules[module_str]
92 if self._call_load_ipython_extension(mod):
79 if self._call_load_ipython_extension(mod):
93 self.loaded.add(module_str)
80 self.loaded.add(module_str)
94 else:
81 else:
95 return "no load function"
82 return "no load function"
96
83
97 def unload_extension(self, module_str: str):
84 def unload_extension(self, module_str: str):
98 """Unload an IPython extension by its module name.
85 """Unload an IPython extension by its module name.
99
86
100 This function looks up the extension's name in ``sys.modules`` and
87 This function looks up the extension's name in ``sys.modules`` and
101 simply calls ``mod.unload_ipython_extension(self)``.
88 simply calls ``mod.unload_ipython_extension(self)``.
102
89
103 Returns the string "no unload function" if the extension doesn't define
90 Returns the string "no unload function" if the extension doesn't define
104 a function to unload itself, "not loaded" if the extension isn't loaded,
91 a function to unload itself, "not loaded" if the extension isn't loaded,
105 otherwise None.
92 otherwise None.
106 """
93 """
107 if BUILTINS_EXTS.get(module_str, False) is True:
94 if BUILTINS_EXTS.get(module_str, False) is True:
108 module_str = "IPython.extensions." + module_str
95 module_str = "IPython.extensions." + module_str
109 if module_str not in self.loaded:
96 if module_str not in self.loaded:
110 return "not loaded"
97 return "not loaded"
111
98
112 if module_str in sys.modules:
99 if module_str in sys.modules:
113 mod = sys.modules[module_str]
100 mod = sys.modules[module_str]
114 if self._call_unload_ipython_extension(mod):
101 if self._call_unload_ipython_extension(mod):
115 self.loaded.discard(module_str)
102 self.loaded.discard(module_str)
116 else:
103 else:
117 return "no unload function"
104 return "no unload function"
118
105
119 def reload_extension(self, module_str: str):
106 def reload_extension(self, module_str: str):
120 """Reload an IPython extension by calling reload.
107 """Reload an IPython extension by calling reload.
121
108
122 If the module has not been loaded before,
109 If the module has not been loaded before,
123 :meth:`InteractiveShell.load_extension` is called. Otherwise
110 :meth:`InteractiveShell.load_extension` is called. Otherwise
124 :func:`reload` is called and then the :func:`load_ipython_extension`
111 :func:`reload` is called and then the :func:`load_ipython_extension`
125 function of the module, if it exists is called.
112 function of the module, if it exists is called.
126 """
113 """
127 from IPython.utils.syspathcontext import prepended_to_syspath
128
114
129 if BUILTINS_EXTS.get(module_str, False) is True:
115 if BUILTINS_EXTS.get(module_str, False) is True:
130 module_str = "IPython.extensions." + module_str
116 module_str = "IPython.extensions." + module_str
131
117
132 if (module_str in self.loaded) and (module_str in sys.modules):
118 if (module_str in self.loaded) and (module_str in sys.modules):
133 self.unload_extension(module_str)
119 self.unload_extension(module_str)
134 mod = sys.modules[module_str]
120 mod = sys.modules[module_str]
135 with prepended_to_syspath(self.ipython_extension_dir):
121 reload(mod)
136 reload(mod)
137 if self._call_load_ipython_extension(mod):
122 if self._call_load_ipython_extension(mod):
138 self.loaded.add(module_str)
123 self.loaded.add(module_str)
139 else:
124 else:
140 self.load_extension(module_str)
125 self.load_extension(module_str)
141
126
142 def _call_load_ipython_extension(self, mod):
127 def _call_load_ipython_extension(self, mod):
143 if hasattr(mod, 'load_ipython_extension'):
128 if hasattr(mod, 'load_ipython_extension'):
144 mod.load_ipython_extension(self.shell)
129 mod.load_ipython_extension(self.shell)
145 return True
130 return True
146
131
147 def _call_unload_ipython_extension(self, mod):
132 def _call_unload_ipython_extension(self, mod):
148 if hasattr(mod, 'unload_ipython_extension'):
133 if hasattr(mod, 'unload_ipython_extension'):
149 mod.unload_ipython_extension(self.shell)
134 mod.unload_ipython_extension(self.shell)
150 return True
135 return True
General Comments 0
You need to be logged in to leave comments. Login now