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