Skip to content

Commit

Permalink
Merge pull request ipython#1419 from takluyver/install-ext
Browse files Browse the repository at this point in the history
Add %install_ext magic function

and associated extension-loading tests
  • Loading branch information
minrk committed Mar 7, 2012
2 parents bb83abd + ce3e3b0 commit 2fab5d0
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 0 deletions.
21 changes: 21 additions & 0 deletions IPython/core/extensions.py
Expand Up @@ -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
Expand Down Expand Up @@ -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)
25 changes: 25 additions & 0 deletions IPython/core/magic.py
Expand Up @@ -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."""
Expand Down
12 changes: 12 additions & 0 deletions 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)
18 changes: 18 additions & 0 deletions IPython/core/tests/test_magic.py
Expand Up @@ -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
Expand Down Expand Up @@ -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

12 changes: 12 additions & 0 deletions docs/source/whatsnew/development.txt
Expand Up @@ -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``.


0 comments on commit 2fab5d0

Please sign in to comment.