##// END OF EJS Templates
Fix installing extension from local file on Windows....
Thomas Kluyver -
Show More
@@ -1,146 +1,154 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 Authors:
4 Authors:
5
5
6 * Brian Granger
6 * Brian Granger
7 """
7 """
8
8
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10 # Copyright (C) 2010-2011 The IPython Development Team
10 # Copyright (C) 2010-2011 The IPython Development Team
11 #
11 #
12 # Distributed under the terms of the BSD License. The full license is in
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
13 # the file COPYING, distributed as part of this software.
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15
15
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 # Imports
17 # Imports
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20 import os
20 import os
21 from shutil import copyfile
21 import sys
22 import sys
22 from urllib import urlretrieve
23 from urllib import urlretrieve
23 from urlparse import urlparse
24 from urlparse import urlparse
24
25
25 from IPython.config.configurable import Configurable
26 from IPython.config.configurable import Configurable
26 from IPython.utils.traitlets import Instance
27 from IPython.utils.traitlets import Instance
27
28
28 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
29 # Main class
30 # Main class
30 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
31
32
32 class ExtensionManager(Configurable):
33 class ExtensionManager(Configurable):
33 """A class to manage IPython extensions.
34 """A class to manage IPython extensions.
34
35
35 An IPython extension is an importable Python module that has
36 An IPython extension is an importable Python module that has
36 a function with the signature::
37 a function with the signature::
37
38
38 def load_ipython_extension(ipython):
39 def load_ipython_extension(ipython):
39 # Do things with ipython
40 # Do things with ipython
40
41
41 This function is called after your extension is imported and the
42 This function is called after your extension is imported and the
42 currently active :class:`InteractiveShell` instance is passed as
43 currently active :class:`InteractiveShell` instance is passed as
43 the only argument. You can do anything you want with IPython at
44 the only argument. You can do anything you want with IPython at
44 that point, including defining new magic and aliases, adding new
45 that point, including defining new magic and aliases, adding new
45 components, etc.
46 components, etc.
46
47
47 The :func:`load_ipython_extension` will be called again is you
48 The :func:`load_ipython_extension` will be called again is you
48 load or reload the extension again. It is up to the extension
49 load or reload the extension again. It is up to the extension
49 author to add code to manage that.
50 author to add code to manage that.
50
51
51 You can put your extension modules anywhere you want, as long as
52 You can put your extension modules anywhere you want, as long as
52 they can be imported by Python's standard import mechanism. However,
53 they can be imported by Python's standard import mechanism. However,
53 to make it easy to write extensions, you can also put your extensions
54 to make it easy to write extensions, you can also put your extensions
54 in ``os.path.join(self.ipython_dir, 'extensions')``. This directory
55 in ``os.path.join(self.ipython_dir, 'extensions')``. This directory
55 is added to ``sys.path`` automatically.
56 is added to ``sys.path`` automatically.
56 """
57 """
57
58
58 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
59 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
59
60
60 def __init__(self, shell=None, config=None):
61 def __init__(self, shell=None, config=None):
61 super(ExtensionManager, self).__init__(shell=shell, config=config)
62 super(ExtensionManager, self).__init__(shell=shell, config=config)
62 self.shell.on_trait_change(
63 self.shell.on_trait_change(
63 self._on_ipython_dir_changed, 'ipython_dir'
64 self._on_ipython_dir_changed, 'ipython_dir'
64 )
65 )
65
66
66 def __del__(self):
67 def __del__(self):
67 self.shell.on_trait_change(
68 self.shell.on_trait_change(
68 self._on_ipython_dir_changed, 'ipython_dir', remove=True
69 self._on_ipython_dir_changed, 'ipython_dir', remove=True
69 )
70 )
70
71
71 @property
72 @property
72 def ipython_extension_dir(self):
73 def ipython_extension_dir(self):
73 return os.path.join(self.shell.ipython_dir, u'extensions')
74 return os.path.join(self.shell.ipython_dir, u'extensions')
74
75
75 def _on_ipython_dir_changed(self):
76 def _on_ipython_dir_changed(self):
76 if not os.path.isdir(self.ipython_extension_dir):
77 if not os.path.isdir(self.ipython_extension_dir):
77 os.makedirs(self.ipython_extension_dir, mode = 0777)
78 os.makedirs(self.ipython_extension_dir, mode = 0777)
78
79
79 def load_extension(self, module_str):
80 def load_extension(self, module_str):
80 """Load an IPython extension by its module name.
81 """Load an IPython extension by its module name.
81
82
82 If :func:`load_ipython_extension` returns anything, this function
83 If :func:`load_ipython_extension` returns anything, this function
83 will return that object.
84 will return that object.
84 """
85 """
85 from IPython.utils.syspathcontext import prepended_to_syspath
86 from IPython.utils.syspathcontext import prepended_to_syspath
86
87
87 if module_str not in sys.modules:
88 if module_str not in sys.modules:
88 with prepended_to_syspath(self.ipython_extension_dir):
89 with prepended_to_syspath(self.ipython_extension_dir):
89 __import__(module_str)
90 __import__(module_str)
90 mod = sys.modules[module_str]
91 mod = sys.modules[module_str]
91 return self._call_load_ipython_extension(mod)
92 return self._call_load_ipython_extension(mod)
92
93
93 def unload_extension(self, module_str):
94 def unload_extension(self, module_str):
94 """Unload an IPython extension by its module name.
95 """Unload an IPython extension by its module name.
95
96
96 This function looks up the extension's name in ``sys.modules`` and
97 This function looks up the extension's name in ``sys.modules`` and
97 simply calls ``mod.unload_ipython_extension(self)``.
98 simply calls ``mod.unload_ipython_extension(self)``.
98 """
99 """
99 if module_str in sys.modules:
100 if module_str in sys.modules:
100 mod = sys.modules[module_str]
101 mod = sys.modules[module_str]
101 self._call_unload_ipython_extension(mod)
102 self._call_unload_ipython_extension(mod)
102
103
103 def reload_extension(self, module_str):
104 def reload_extension(self, module_str):
104 """Reload an IPython extension by calling reload.
105 """Reload an IPython extension by calling reload.
105
106
106 If the module has not been loaded before,
107 If the module has not been loaded before,
107 :meth:`InteractiveShell.load_extension` is called. Otherwise
108 :meth:`InteractiveShell.load_extension` is called. Otherwise
108 :func:`reload` is called and then the :func:`load_ipython_extension`
109 :func:`reload` is called and then the :func:`load_ipython_extension`
109 function of the module, if it exists is called.
110 function of the module, if it exists is called.
110 """
111 """
111 from IPython.utils.syspathcontext import prepended_to_syspath
112 from IPython.utils.syspathcontext import prepended_to_syspath
112
113
113 with prepended_to_syspath(self.ipython_extension_dir):
114 with prepended_to_syspath(self.ipython_extension_dir):
114 if module_str in sys.modules:
115 if module_str in sys.modules:
115 mod = sys.modules[module_str]
116 mod = sys.modules[module_str]
116 reload(mod)
117 reload(mod)
117 self._call_load_ipython_extension(mod)
118 self._call_load_ipython_extension(mod)
118 else:
119 else:
119 self.load_extension(module_str)
120 self.load_extension(module_str)
120
121
121 def _call_load_ipython_extension(self, mod):
122 def _call_load_ipython_extension(self, mod):
122 if hasattr(mod, 'load_ipython_extension'):
123 if hasattr(mod, 'load_ipython_extension'):
123 return mod.load_ipython_extension(self.shell)
124 return mod.load_ipython_extension(self.shell)
124
125
125 def _call_unload_ipython_extension(self, mod):
126 def _call_unload_ipython_extension(self, mod):
126 if hasattr(mod, 'unload_ipython_extension'):
127 if hasattr(mod, 'unload_ipython_extension'):
127 return mod.unload_ipython_extension(self.shell)
128 return mod.unload_ipython_extension(self.shell)
128
129
129 def install_extension(self, url, filename=None):
130 def install_extension(self, url, filename=None):
130 """Download and install an IPython extension.
131 """Download and install an IPython extension.
131
132
132 If filename is given, the file will be so named (inside the extension
133 If filename is given, the file will be so named (inside the extension
133 directory). Otherwise, the name from the URL will be used. The file must
134 directory). Otherwise, the name from the URL will be used. The file must
134 have a .py or .zip extension; otherwise, a ValueError will be raised.
135 have a .py or .zip extension; otherwise, a ValueError will be raised.
135 """
136 """
136 # Ensure the extension directory exists
137 # Ensure the extension directory exists
137 if not os.path.isdir(self.ipython_extension_dir):
138 if not os.path.isdir(self.ipython_extension_dir):
138 os.makedirs(self.ipython_extension_dir, mode = 0777)
139 os.makedirs(self.ipython_extension_dir, mode = 0777)
139
140
141 if os.path.isfile(url):
142 src_filename = os.path.basename(url)
143 copy = copyfile
144 else:
145 src_filename = urlparse(url).path.split('/')[-1]
146 copy = urlretrieve
147
140 if filename is None:
148 if filename is None:
141 filename = urlparse(url).path.split('/')[-1]
149 filename = src_filename
142 if os.path.splitext(filename)[1] not in ('.py', '.zip'):
150 if os.path.splitext(filename)[1] not in ('.py', '.zip'):
143 raise ValueError("The file must have a .py or .zip extension", filename)
151 raise ValueError("The file must have a .py or .zip extension", filename)
144
152
145 filename = os.path.join(self.ipython_extension_dir, filename)
153 filename = os.path.join(self.ipython_extension_dir, filename)
146 return urlretrieve(url, filename)
154 return urlretrieve(url, filename)
General Comments 0
You need to be logged in to leave comments. Login now