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