Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 03c097c7c4
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 204 lines (154 sloc) 5.891 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
"""Tests for code execution (%run and related), which is particularly tricky.

Because of how %run manages namespaces, and the fact that we are trying here to
verify subtle object deletion and reference counting issues, the %run tests
will be kept in this separate file. This makes it easier to aggregate in one
place the tricks needed to handle it; most other magics are much easier to test
and we do so in a common test_magic file.
"""
from __future__ import absolute_import

#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------

import os
import sys
import tempfile

import nose.tools as nt

from IPython.testing import decorators as dec
from IPython.testing import tools as tt

#-----------------------------------------------------------------------------
# Test functions begin
#-----------------------------------------------------------------------------

def doctest_refbug():
    """Very nasty problem with references held by multiple runs of a script.
See: https://github.com/ipython/ipython/issues/141

In [1]: _ip.clear_main_mod_cache()
# random
In [2]: %run refbug

In [3]: call_f()
lowercased: hello

In [4]: %run refbug

In [5]: call_f()
lowercased: hello
lowercased: hello
"""


def doctest_run_builtins():
    r"""Check that %run doesn't damage __builtins__.

In [1]: import tempfile

In [2]: bid1 = id(__builtins__)

In [3]: fname = tempfile.mkstemp('.py')[1]

In [3]: f = open(fname,'w')

In [4]: f.write('pass\n')

In [5]: f.flush()

In [6]: t1 = type(__builtins__)

In [7]: %run $fname

In [7]: f.close()

In [8]: bid2 = id(__builtins__)

In [9]: t2 = type(__builtins__)

In [10]: t1 == t2
Out[10]: True

In [10]: bid1 == bid2
Out[10]: True

In [12]: try:
....: os.unlink(fname)
....: except:
....: pass
....:
"""

def doctest_reset_del():
    """Test that resetting doesn't cause errors in __del__ methods.

In [2]: class A(object):
...: def __del__(self):
...: print str("Hi")
...:

In [3]: a = A()

In [4]: get_ipython().reset()
Hi

In [5]: 1+1
Out[5]: 2
"""

# For some tests, it will be handy to organize them in a class with a common
# setup that makes a temp file

class TestMagicRunPass(tt.TempFileMixin):

    def setup(self):
        """Make a valid python temp file."""
        self.mktmp('pass\n')

    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.displayhook.prompt2).strip()
        nt.assert_equals(p2[:3], '...')


class TestMagicRunSimple(tt.TempFileMixin):

    def test_simpledef(self):
        """Test that simple class definitions work."""
        src = ("class foo: pass\n"
               "def f(): return foo()")
        self.mktmp(src)
        _ip.magic('run %s' % self.fname)
        _ip.run_cell('t = isinstance(f(), foo)')
        nt.assert_true(_ip.user_ns['t'])

    def test_obj_del(self):
        """Test that object's __del__ methods are called on exit."""
        
        src = ("class A(object):\n"
               " def __del__(self):\n"
               " print 'object A deleted'\n"
               "a = A()\n")
        self.mktmp(src)
        tt.ipexec_validate(self.fname, 'object A deleted')
    
    @dec.skip_known_failure
    def test_aggressive_namespace_cleanup(self):
        """Test that namespace cleanup is not too aggressive GH-238

Returning from another run magic deletes the namespace"""
        # see ticket https://github.com/ipython/ipython/issues/238
        class secondtmp(tt.TempFileMixin): pass
        empty = secondtmp()
        empty.mktmp('')
        src = ("ip = get_ipython()\n"
               "for i in range(5):\n"
               " try:\n"
               " ip.magic('run %s')\n"
               " except NameError, e:\n"
               " print i;break\n" % empty.fname)
        self.mktmp(src)
        _ip.magic('run %s' % self.fname)
        _ip.run_cell('ip == get_ipython()')
        tt.assert_equals(_ip.user_ns['i'], 5)

    @dec.skip_win32
    def test_tclass(self):
        mydir = os.path.dirname(__file__)
        tc = os.path.join(mydir, 'tclass')
        src = ("%%run '%s' C-first\n"
               "%%run '%s' C-second\n"
               "%%run '%s' C-third\n") % (tc, tc, tc)
        self.mktmp(src, '.ipy')
        out = """\
ARGV 1-: [u'C-first']
ARGV 1-: [u'C-second']
tclass.py: deleting object: C-first
ARGV 1-: [u'C-third']
tclass.py: deleting object: C-second
tclass.py: deleting object: C-third
"""
        tt.ipexec_validate(self.fname, out)
Something went wrong with that request. Please try again.