"""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.core.iplib import get_ipython from IPython.utils.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 = get_ipython() _ip.alias_manager.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.alias_manager.alias_table) > 10) for key, val in _ip.alias_manager.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.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(): _ip = get_ipython() """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.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.utils import pickleshare from IPython.core.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) # XXX failing for now, until we get clearcmd out of quarantine. But we should # fix this and revert the skip to happen only if numpy is not around. #@dec.skipif_not_numpy @dec.skipknownfailure 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.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__) In [7]: %run "$fname" In [7]: f.close() In [8]: bid2 = id(__builtins__) In [9]: print type(__builtins__) 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('.py')[1] f = open(fname,'w') f.write('pass\n') f.flush() self.tmpfile = f self.fname = fname def run_tmpfile(self): _ip = get_ipython() # 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__ """ _ip = get_ipython() # 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: """ _ip = get_ipython() 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() _ip = get_ipython() p2 = str(_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(): _ip = get_ipython() 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.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.write _ip.write = w.write code = """ a = 100 b = 200""" try: paste(code,'') out = w.getvalue() finally: _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