diff --git a/IPython/core/extensions.py b/IPython/core/extensions.py index 0298a8f..f7602dd 100644 --- a/IPython/core/extensions.py +++ b/IPython/core/extensions.py @@ -19,6 +19,8 @@ Authors: import os import sys +from urllib import urlretrieve +from urlparse import urlparse from IPython.config.configurable import Configurable from IPython.utils.traitlets import Instance @@ -123,3 +125,22 @@ class ExtensionManager(Configurable): def _call_unload_ipython_extension(self, mod): if hasattr(mod, 'unload_ipython_extension'): return mod.unload_ipython_extension(self.shell) + + def install_extension(self, url, filename=None): + """Download and install an IPython extension. + + If filename is given, the file will be so named (inside the extension + directory). Otherwise, the name from the URL will be used. The file must + have a .py or .zip extension; otherwise, a ValueError will be raised. + """ + # Ensure the extension directory exists + if not os.path.isdir(self.ipython_extension_dir): + os.makedirs(self.ipython_extension_dir, mode = 0777) + + if filename is None: + filename = urlparse(url).path.split('/')[-1] + if os.path.splitext(filename)[1] not in ('.py', '.zip'): + raise ValueError("The file must have a .py or .zip extension", filename) + + filename = os.path.join(self.ipython_extension_dir, filename) + return urlretrieve(url, filename) diff --git a/IPython/core/magic.py b/IPython/core/magic.py index 2f233fb..4996c20 100644 --- a/IPython/core/magic.py +++ b/IPython/core/magic.py @@ -3457,6 +3457,31 @@ Defaulting color scheme to 'NoColor'""" # print simple error message, rather than traceback if we can't # hook up the GUI error(str(e)) + + def magic_install_ext(self, parameter_s): + """Download and install an extension from a URL, e.g.:: + + %install_ext https://bitbucket.org/birkenfeld/ipython-physics/raw/d1310a2ab15d/physics.py + + The URL should point to an importable Python module - either a .py file + or a .zip file. + + Parameters: + + -n filename : Specify a name for the file, rather than taking it from + the URL. + """ + opts, args = self.parse_options(parameter_s, 'n:') + try: + filename, headers = self.extension_manager.install_extension(args, opts.get('n')) + except ValueError as e: + print e + return + + filename = os.path.basename(filename) + print "Installed %s. To use it, type:" % filename + print " %%load_ext %s" % os.path.splitext(filename)[0] + def magic_load_ext(self, module_str): """Load an IPython extension by its module name."""