|
|
# encoding: utf-8
|
|
|
"""
|
|
|
Test process execution and IO redirection.
|
|
|
"""
|
|
|
|
|
|
__docformat__ = "restructuredtext en"
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
# Copyright (C) 2008 The IPython Development Team
|
|
|
#
|
|
|
# Distributed under the terms of the BSD License. The full license is
|
|
|
# in the file COPYING, distributed as part of this software.
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
|
|
from copy import copy, deepcopy
|
|
|
from cStringIO import StringIO
|
|
|
import string
|
|
|
import sys
|
|
|
|
|
|
from nose.tools import assert_equal
|
|
|
|
|
|
from IPython.frontend.prefilterfrontend import PrefilterFrontEnd
|
|
|
from IPython.core.ipapi import get as get_ipython0
|
|
|
from IPython.testing.plugin.ipdoctest import default_argv
|
|
|
|
|
|
|
|
|
class TestPrefilterFrontEnd(PrefilterFrontEnd):
|
|
|
|
|
|
input_prompt_template = string.Template('')
|
|
|
output_prompt_template = string.Template('')
|
|
|
banner = ''
|
|
|
|
|
|
def __init__(self):
|
|
|
self.out = StringIO()
|
|
|
PrefilterFrontEnd.__init__(self,argv=default_argv())
|
|
|
# Some more code for isolation (yeah, crazy)
|
|
|
self._on_enter()
|
|
|
self.out.flush()
|
|
|
self.out.reset()
|
|
|
self.out.truncate()
|
|
|
|
|
|
def write(self, string, *args, **kwargs):
|
|
|
self.out.write(string)
|
|
|
|
|
|
def _on_enter(self):
|
|
|
self.input_buffer += '\n'
|
|
|
PrefilterFrontEnd._on_enter(self)
|
|
|
|
|
|
|
|
|
def isolate_ipython0(func):
|
|
|
""" Decorator to isolate execution that involves an iptyhon0.
|
|
|
|
|
|
Notes
|
|
|
-----
|
|
|
|
|
|
Apply only to functions with no arguments. Nose skips functions
|
|
|
with arguments.
|
|
|
"""
|
|
|
def my_func():
|
|
|
ip0 = get_ipython0()
|
|
|
if ip0 is None:
|
|
|
return func()
|
|
|
# We have a real ipython running...
|
|
|
user_ns = ip0.IP.user_ns
|
|
|
user_global_ns = ip0.IP.user_global_ns
|
|
|
|
|
|
# Previously the isolation was attempted with a deep copy of the user
|
|
|
# dicts, but we found cases where this didn't work correctly. I'm not
|
|
|
# quite sure why, but basically it did damage the user namespace, such
|
|
|
# that later tests stopped working correctly. Instead we use a simpler
|
|
|
# approach, just computing the list of added keys to the namespace and
|
|
|
# eliminating those afterwards. Existing keys that may have been
|
|
|
# modified remain modified. So far this has proven to be robust.
|
|
|
|
|
|
# Compute set of old local/global keys
|
|
|
old_locals = set(user_ns.keys())
|
|
|
old_globals = set(user_global_ns.keys())
|
|
|
try:
|
|
|
out = func()
|
|
|
finally:
|
|
|
# Find new keys, and if any, remove them
|
|
|
new_locals = set(user_ns.keys()) - old_locals
|
|
|
new_globals = set(user_global_ns.keys()) - old_globals
|
|
|
for k in new_locals:
|
|
|
del user_ns[k]
|
|
|
for k in new_globals:
|
|
|
del user_global_ns[k]
|
|
|
# Undo the hack at creation of PrefilterFrontEnd
|
|
|
from IPython.core import iplib
|
|
|
iplib.InteractiveShell.isthreaded = False
|
|
|
return out
|
|
|
|
|
|
my_func.__name__ = func.__name__
|
|
|
return my_func
|
|
|
|
|
|
|
|
|
@isolate_ipython0
|
|
|
def test_execution():
|
|
|
""" Test execution of a command.
|
|
|
"""
|
|
|
f = TestPrefilterFrontEnd()
|
|
|
f.input_buffer = 'print(1)'
|
|
|
f._on_enter()
|
|
|
out_value = f.out.getvalue()
|
|
|
assert_equal(out_value, '1\n')
|
|
|
|
|
|
|
|
|
@isolate_ipython0
|
|
|
def test_multiline():
|
|
|
""" Test execution of a multiline command.
|
|
|
"""
|
|
|
f = TestPrefilterFrontEnd()
|
|
|
f.input_buffer = 'if True:'
|
|
|
f._on_enter()
|
|
|
f.input_buffer += 'print 1'
|
|
|
f._on_enter()
|
|
|
out_value = f.out.getvalue()
|
|
|
yield assert_equal, out_value, ''
|
|
|
f._on_enter()
|
|
|
out_value = f.out.getvalue()
|
|
|
yield assert_equal, out_value, '1\n'
|
|
|
f = TestPrefilterFrontEnd()
|
|
|
f.input_buffer='(1 +'
|
|
|
f._on_enter()
|
|
|
f.input_buffer += '0)'
|
|
|
f._on_enter()
|
|
|
out_value = f.out.getvalue()
|
|
|
yield assert_equal, out_value, ''
|
|
|
f._on_enter()
|
|
|
out_value = f.out.getvalue()
|
|
|
yield assert_equal, out_value, '1\n'
|
|
|
|
|
|
|
|
|
@isolate_ipython0
|
|
|
def test_capture():
|
|
|
""" Test the capture of output in different channels.
|
|
|
"""
|
|
|
# Test on the OS-level stdout, stderr.
|
|
|
f = TestPrefilterFrontEnd()
|
|
|
f.input_buffer = \
|
|
|
'import os; out=os.fdopen(1, "w"); out.write("1") ; out.flush()'
|
|
|
f._on_enter()
|
|
|
out_value = f.out.getvalue()
|
|
|
yield assert_equal, out_value, '1'
|
|
|
f = TestPrefilterFrontEnd()
|
|
|
f.input_buffer = \
|
|
|
'import os; out=os.fdopen(2, "w"); out.write("1") ; out.flush()'
|
|
|
f._on_enter()
|
|
|
out_value = f.out.getvalue()
|
|
|
yield assert_equal, out_value, '1'
|
|
|
|
|
|
|
|
|
@isolate_ipython0
|
|
|
def test_magic():
|
|
|
""" Test the magic expansion and history.
|
|
|
|
|
|
This test is fairly fragile and will break when magics change.
|
|
|
"""
|
|
|
f = TestPrefilterFrontEnd()
|
|
|
# Before checking the interactive namespace, make sure it's clear (it can
|
|
|
# otherwise pick up things stored in the user's local db)
|
|
|
f.input_buffer += '%reset -f'
|
|
|
f._on_enter()
|
|
|
f.complete_current_input()
|
|
|
# Now, run the %who magic and check output
|
|
|
f.input_buffer += '%who'
|
|
|
f._on_enter()
|
|
|
out_value = f.out.getvalue()
|
|
|
assert_equal(out_value, 'Interactive namespace is empty.\n')
|
|
|
|
|
|
|
|
|
@isolate_ipython0
|
|
|
def test_help():
|
|
|
""" Test object inspection.
|
|
|
"""
|
|
|
f = TestPrefilterFrontEnd()
|
|
|
f.input_buffer += "def f():"
|
|
|
f._on_enter()
|
|
|
f.input_buffer += "'foobar'"
|
|
|
f._on_enter()
|
|
|
f.input_buffer += "pass"
|
|
|
f._on_enter()
|
|
|
f._on_enter()
|
|
|
f.input_buffer += "f?"
|
|
|
f._on_enter()
|
|
|
assert 'traceback' not in f.last_result
|
|
|
## XXX: ipython doctest magic breaks this. I have no clue why
|
|
|
#out_value = f.out.getvalue()
|
|
|
#assert out_value.split()[-1] == 'foobar'
|
|
|
|
|
|
|
|
|
@isolate_ipython0
|
|
|
def test_completion_simple():
|
|
|
""" Test command-line completion on trivial examples.
|
|
|
"""
|
|
|
f = TestPrefilterFrontEnd()
|
|
|
f.input_buffer = 'zzza = 1'
|
|
|
f._on_enter()
|
|
|
f.input_buffer = 'zzzb = 2'
|
|
|
f._on_enter()
|
|
|
f.input_buffer = 'zz'
|
|
|
f.complete_current_input()
|
|
|
out_value = f.out.getvalue()
|
|
|
yield assert_equal, out_value, '\nzzza zzzb '
|
|
|
yield assert_equal, f.input_buffer, 'zzz'
|
|
|
|
|
|
|
|
|
@isolate_ipython0
|
|
|
def test_completion_parenthesis():
|
|
|
""" Test command-line completion when a parenthesis is open.
|
|
|
"""
|
|
|
f = TestPrefilterFrontEnd()
|
|
|
f.input_buffer = 'zzza = 1'
|
|
|
f._on_enter()
|
|
|
f.input_buffer = 'zzzb = 2'
|
|
|
f._on_enter()
|
|
|
f.input_buffer = 'map(zz'
|
|
|
f.complete_current_input()
|
|
|
out_value = f.out.getvalue()
|
|
|
yield assert_equal, out_value, '\nzzza zzzb '
|
|
|
yield assert_equal, f.input_buffer, 'map(zzz'
|
|
|
|
|
|
|
|
|
@isolate_ipython0
|
|
|
def test_completion_indexing():
|
|
|
""" Test command-line completion when indexing on objects.
|
|
|
"""
|
|
|
f = TestPrefilterFrontEnd()
|
|
|
f.input_buffer = 'a = [0]'
|
|
|
f._on_enter()
|
|
|
f.input_buffer = 'a[0].'
|
|
|
f.complete_current_input()
|
|
|
|
|
|
if sys.version_info[:2] >= (2,6):
|
|
|
# In Python 2.6, ints picked up a few non __ methods, so now there are
|
|
|
# no completions.
|
|
|
assert_equal(f.input_buffer, 'a[0].')
|
|
|
else:
|
|
|
# Right answer for 2.4/2.5
|
|
|
assert_equal(f.input_buffer, 'a[0].__')
|
|
|
|
|
|
|
|
|
@isolate_ipython0
|
|
|
def test_completion_equal():
|
|
|
""" Test command-line completion when the delimiter is "=", not " ".
|
|
|
"""
|
|
|
f = TestPrefilterFrontEnd()
|
|
|
f.input_buffer = 'a=1.'
|
|
|
f.complete_current_input()
|
|
|
if sys.version_info[:2] >= (2,6):
|
|
|
# In Python 2.6, ints picked up a few non __ methods, so now there are
|
|
|
# no completions.
|
|
|
assert_equal(f.input_buffer, 'a=1.')
|
|
|
else:
|
|
|
# Right answer for 2.4/2.5
|
|
|
assert_equal(f.input_buffer, 'a=1.__')
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
test_magic()
|
|
|
test_help()
|
|
|
test_execution()
|
|
|
test_multiline()
|
|
|
test_capture()
|
|
|
test_completion_simple()
|
|
|
test_completion_complex()
|
|
|
|