Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Add %install_ext magic function. #1419

Merged
merged 3 commits into from

2 participants

@takluyver
Owner

As I mentioned on #953, I think an %install_ext magic would make it easier to use extensions that aren't shipped with IPython. This adds that.

@minrk
Owner

Sounds and looks good to me. Add a simple test that installs an extension into the temporary IPython dir?

@takluyver
Owner

Good point - in fact I couldn't see any tests for extensions at all, so I've made a test to install, load and unload a simple extension.

@minrk
Owner

Great, thanks!

@minrk minrk merged commit dbf3bdc into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
21 IPython/core/extensions.py
@@ -19,6 +19,8 @@
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 @@ def _call_load_ipython_extension(self, mod):
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)
View
25 IPython/core/magic.py
@@ -3457,6 +3457,31 @@ def magic_gui(self, parameter_s=''):
# 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."""
View
12 IPython/core/tests/daft_extension.py
@@ -0,0 +1,12 @@
+# -*- coding: utf-8 -*-
+"""
+Useless IPython extension to test installing and loading extensions.
+"""
+some_vars = {'arq': 185}
+
+def load_ipython_extension(ip):
+ # set up simplified quantity input
+ ip.push(some_vars)
+
+def unload_ipython_extension(ip):
+ ip.drop_by_id(some_vars)
View
18 IPython/core/tests/test_magic.py
@@ -15,6 +15,7 @@
from IPython.testing import decorators as dec
from IPython.testing import tools as tt
from IPython.utils import py3compat
+from IPython.utils.tempdir import TemporaryDirectory
#-----------------------------------------------------------------------------
# Test functions begin
@@ -394,3 +395,20 @@ def test_prun_quotes():
"Test that prun does not clobber string escapes (GH #1302)"
_ip.magic("prun -q x = '\t'")
nt.assert_equal(_ip.user_ns['x'], '\t')
+
+def test_extension():
+ tmpdir = TemporaryDirectory()
+ orig_ipython_dir = _ip.ipython_dir
+ try:
+ _ip.ipython_dir = tmpdir.name
+ nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
+ url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
+ _ip.magic("install_ext %s" % url)
+ _ip.user_ns.pop('arq', None)
+ _ip.magic("load_ext daft_extension")
+ tt.assert_equal(_ip.user_ns['arq'], 185)
+ _ip.magic("unload_ext daft_extension")
+ assert 'arq' not in _ip.user_ns
+ finally:
+ _ip.ipython_dir = orig_ipython_dir
+
View
12 docs/source/whatsnew/development.txt
@@ -4,3 +4,15 @@
This document describes in-flight development work.
+Redesigned IPython notebook user interface
+------------------------------------------
+
+.. add details
+
+Other new features
+------------------
+
+* **%install_ext**: A new magic function to install an IPython extension from
+ a URL. E.g. ``%install_ext https://bitbucket.org/birkenfeld/ipython-physics/raw/d1310a2ab15d/physics.py``.
+
+
Something went wrong with that request. Please try again.