##// END OF EJS Templates
Make %paste echo by default, introduce -q for quiet mode.
Make %paste echo by default, introduce -q for quiet mode.

File last commit:

r2189:86a18923
r2189:86a18923
Show More
test_magic.py
326 lines | 8.7 KiB | text/x-python | PythonLexer
"""Tests for various magic functions.
Needs to be run by nose (to make ipython session available).
"""
import os
import sys
import tempfile
import types
from cStringIO import StringIO
import nose.tools as nt
from IPython.platutils import find_cmd, get_long_path_name
from IPython.testing import decorators as dec
from IPython.testing import tools as tt
#-----------------------------------------------------------------------------
# Test functions begin
def test_rehashx():
# clear up everything
_ip.IP.alias_table.clear()
del _ip.db['syscmdlist']
_ip.magic('rehashx')
# Practically ALL ipython development systems will have more than 10 aliases
yield (nt.assert_true, len(_ip.IP.alias_table) > 10)
for key, val in _ip.IP.alias_table.items():
# we must strip dots from alias names
nt.assert_true('.' not in key)
# rehashx must fill up syscmdlist
scoms = _ip.db['syscmdlist']
yield (nt.assert_true, len(scoms) > 10)
def doctest_hist_f():
"""Test %hist -f with temporary filename.
In [9]: import tempfile
In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
In [11]: %hist -n -f $tfile 3
"""
def doctest_hist_r():
"""Test %hist -r
XXX - This test is not recording the output correctly. Not sure why...
In [20]: 'hist' in _ip.IP.lsmagic()
Out[20]: True
In [6]: x=1
In [7]: %hist -n -r 2
x=1 # random
hist -n -r 2 # random
"""
# This test is known to fail on win32.
# See ticket https://bugs.launchpad.net/bugs/366334
def test_obj_del():
"""Test that object's __del__ methods are called on exit."""
test_dir = os.path.dirname(__file__)
del_file = os.path.join(test_dir,'obj_del.py')
ipython_cmd = find_cmd('ipython')
out = _ip.IP.getoutput('%s %s' % (ipython_cmd, del_file))
nt.assert_equals(out,'obj_del.py: object A deleted')
def test_shist():
# Simple tests of ShadowHist class - test generator.
import os, shutil, tempfile
from IPython.Extensions import pickleshare
from IPython.history import ShadowHist
tfile = tempfile.mktemp('','tmp-ipython-')
db = pickleshare.PickleShareDB(tfile)
s = ShadowHist(db)
s.add('hello')
s.add('world')
s.add('hello')
s.add('hello')
s.add('karhu')
yield nt.assert_equals,s.all(),[(1, 'hello'), (2, 'world'), (3, 'karhu')]
yield nt.assert_equal,s.get(2),'world'
shutil.rmtree(tfile)
@dec.skipif_not_numpy
def test_numpy_clear_array_undec():
from IPython.Extensions import clearcmd
_ip.ex('import numpy as np')
_ip.ex('a = np.empty(2)')
yield (nt.assert_true, 'a' in _ip.user_ns)
_ip.magic('clear array')
yield (nt.assert_false, 'a' in _ip.user_ns)
@dec.skip()
def test_fail_dec(*a,**k):
yield nt.assert_true, False
@dec.skip('This one shouldn not run')
def test_fail_dec2(*a,**k):
yield nt.assert_true, False
@dec.skipknownfailure
def test_fail_dec3(*a,**k):
yield nt.assert_true, False
def doctest_refbug():
"""Very nasty problem with references held by multiple runs of a script.
See: https://bugs.launchpad.net/ipython/+bug/269966
In [1]: _ip.IP.clear_main_mod_cache()
In [2]: run refbug
In [3]: call_f()
lowercased: hello
In [4]: run refbug
In [5]: call_f()
lowercased: hello
lowercased: hello
"""
#-----------------------------------------------------------------------------
# Tests for %run
#-----------------------------------------------------------------------------
# %run is critical enough that it's a good idea to have a solid collection of
# tests for it, some as doctests and some as normal tests.
def doctest_run_ns():
"""Classes declared %run scripts must be instantiable afterwards.
In [11]: run tclass foo
In [12]: isinstance(f(),foo)
Out[12]: True
"""
def doctest_run_ns2():
"""Classes declared %run scripts must be instantiable afterwards.
In [4]: run tclass C-first_pass
In [5]: run tclass C-second_pass
tclass.py: deleting object: C-first_pass
"""
def doctest_run_builtins():
"""Check that %run doesn't damage __builtins__ via a doctest.
This is similar to the test_run_builtins, but I want *both* forms of the
test to catch any possible glitches in our testing machinery, since that
modifies %run somewhat. So for this, we have both a normal test (below)
and a doctest (this one).
In [1]: import tempfile
In [2]: bid1 = id(__builtins__)
In [3]: fname = tempfile.mkstemp()[1]
In [3]: f = open(fname,'w')
In [4]: f.write('pass\\n')
In [5]: f.flush()
In [6]: print type(__builtins__)
<type 'module'>
In [7]: %run "$fname"
In [7]: f.close()
In [8]: bid2 = id(__builtins__)
In [9]: print type(__builtins__)
<type 'module'>
In [10]: bid1 == bid2
Out[10]: True
In [12]: try:
....: os.unlink(fname)
....: except:
....: pass
....:
"""
# For some tests, it will be handy to organize them in a class with a common
# setup that makes a temp file
class TestMagicRun(object):
def setup(self):
"""Make a valid python temp file."""
fname = tempfile.mkstemp()[1]
f = open(fname,'w')
f.write('pass\n')
f.flush()
self.tmpfile = f
self.fname = fname
def run_tmpfile(self):
# This fails on Windows if self.tmpfile.name has spaces or "~" in it.
# See below and ticket https://bugs.launchpad.net/bugs/366353
_ip.magic('run "%s"' % self.fname)
def test_builtins_id(self):
"""Check that %run doesn't damage __builtins__ """
# Test that the id of __builtins__ is not modified by %run
bid1 = id(_ip.user_ns['__builtins__'])
self.run_tmpfile()
bid2 = id(_ip.user_ns['__builtins__'])
tt.assert_equals(bid1, bid2)
def test_builtins_type(self):
"""Check that the type of __builtins__ doesn't change with %run.
However, the above could pass if __builtins__ was already modified to
be a dict (it should be a module) by a previous use of %run. So we
also check explicitly that it really is a module:
"""
self.run_tmpfile()
tt.assert_equals(type(_ip.user_ns['__builtins__']),type(sys))
def test_prompts(self):
"""Test that prompts correctly generate after %run"""
self.run_tmpfile()
p2 = str(_ip.IP.outputcache.prompt2).strip()
nt.assert_equals(p2[:3], '...')
def teardown(self):
self.tmpfile.close()
try:
os.unlink(self.fname)
except:
# On Windows, even though we close the file, we still can't delete
# it. I have no clue why
pass
# Multiple tests for clipboard pasting
def test_paste():
def paste(txt, flags='-q'):
"""Paste input text, by default in quiet mode"""
hooks.clipboard_get = lambda : txt
_ip.magic('paste '+flags)
# Inject fake clipboard hook but save original so we can restore it later
hooks = _ip.IP.hooks
user_ns = _ip.user_ns
original_clip = hooks.clipboard_get
try:
# This try/except with an emtpy except clause is here only because
# try/yield/finally is invalid syntax in Python 2.4. This will be
# removed when we drop 2.4-compatibility, and the emtpy except below
# will be changed to a finally.
# Run tests with fake clipboard function
user_ns.pop('x', None)
paste('x=1')
yield (nt.assert_equal, user_ns['x'], 1)
user_ns.pop('x', None)
paste('>>> x=2')
yield (nt.assert_equal, user_ns['x'], 2)
paste("""
>>> x = [1,2,3]
>>> y = []
>>> for i in x:
... y.append(i**2)
...
""")
yield (nt.assert_equal, user_ns['x'], [1,2,3])
yield (nt.assert_equal, user_ns['y'], [1,4,9])
# Now, test that paste -r works
user_ns.pop('x', None)
yield (nt.assert_false, 'x' in user_ns)
_ip.magic('paste -r')
yield (nt.assert_equal, user_ns['x'], [1,2,3])
# Also test paste echoing, by temporarily faking the writer
w = StringIO()
writer = _ip.IP.write
_ip.IP.write = w.write
code = """
a = 100
b = 200"""
try:
paste(code,'')
out = w.getvalue()
finally:
_ip.IP.write = writer
yield (nt.assert_equal, user_ns['a'], 100)
yield (nt.assert_equal, user_ns['b'], 200)
yield (nt.assert_equal, out, code+"\n## -- End pasted text --\n")
finally:
# This should be in a finally clause, instead of the bare except above.
# Restore original hook
hooks.clipboard_get = original_clip