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