##// END OF EJS Templates
Update %guiref with a note about Ctrl-R style history searching.
Update %guiref with a note about Ctrl-R style history searching.

File last commit:

r4251:b8d87c25
r4482:b63d2de7
Show More
test_inputsplitter.py
698 lines | 23.5 KiB | text/x-python | PythonLexer
/ IPython / core / tests / test_inputsplitter.py
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 # -*- coding: utf-8 -*-
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 """Tests for the inputsplitter module.
Fernando Perez
Improve docs and comments of some internal tools, and of testing code
r3297
Authors
-------
* Fernando Perez
* Robert Kern
Fernando Perez
Split blockbreaker tests into a separate file and clean up api....
r2633 """
#-----------------------------------------------------------------------------
# Copyright (C) 2010 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.
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
# stdlib
import unittest
Fernando Perez
Add test for missing input encoding. Back to 100% coverage.
r2718 import sys
Fernando Perez
Split blockbreaker tests into a separate file and clean up api....
r2633
# Third party
import nose.tools as nt
# Our own
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 from IPython.core import inputsplitter as isp
Thomas Kluyver
Return command to the next prompt if help was called halfway through a command. Also, ? at the end of a comment should not trigger help.
r4080 from IPython.testing import tools as tt
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663
#-----------------------------------------------------------------------------
# Semi-complete examples (also used as tests)
#-----------------------------------------------------------------------------
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780
# Note: at the bottom, there's a slightly more complete version of this that
# can be useful during development of code here.
Thomas Kluyver
Rename misleading use of raw_input so it's not automatically converted to input by 2to3.
r3119 def mini_interactive_loop(input_func):
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 """Minimal example of the logic of an interactive interpreter loop.
This serves as an example, and it is used by the test system with a fake
raw_input that simulates interactive input."""
from IPython.core.inputsplitter import InputSplitter
isp = InputSplitter()
# In practice, this input loop would be wrapped in an outside loop to read
# input indefinitely, until some exit/quit command was issued. Here we
# only illustrate the basic inner loop.
while isp.push_accepts_more():
indent = ' '*isp.indent_spaces
prompt = '>>> ' + indent
Thomas Kluyver
Rename misleading use of raw_input so it's not automatically converted to input by 2to3.
r3119 line = indent + input_func(prompt)
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 isp.push(line)
# Here we just return input so we can use it in a test suite, but a real
# interpreter would instead send it for execution somewhere.
src = isp.source_reset()
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 #print 'Input source was:\n', src # dbg
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 return src
Fernando Perez
Split blockbreaker tests into a separate file and clean up api....
r2633
#-----------------------------------------------------------------------------
Fernando Perez
Completed full block splitting for block-based frontends.
r2645 # Test utilities, just for local use
#-----------------------------------------------------------------------------
def assemble(block):
"""Assemble a block into multi-line sub-blocks."""
return ['\n'.join(sub_block)+'\n' for sub_block in block]
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663
def pseudo_input(lines):
"""Return a function that acts like raw_input but feeds the input list."""
ilines = iter(lines)
def raw_in(prompt):
try:
return next(ilines)
except StopIteration:
return ''
return raw_in
Fernando Perez
Completed full block splitting for block-based frontends.
r2645 #-----------------------------------------------------------------------------
Fernando Perez
Split blockbreaker tests into a separate file and clean up api....
r2633 # Tests
#-----------------------------------------------------------------------------
def test_spaces():
tests = [('', 0),
(' ', 1),
('\n', 0),
(' \n', 1),
('x', 0),
(' x', 1),
(' x',2),
(' x',4),
# Note: tabs are counted as a single whitespace!
('\tx', 1),
('\t x', 2),
]
Thomas Kluyver
Return command to the next prompt if help was called halfway through a command. Also, ? at the end of a comment should not trigger help.
r4080 tt.check_pairs(isp.num_ini_spaces, tests)
Fernando Perez
Split blockbreaker tests into a separate file and clean up api....
r2633
def test_remove_comments():
tests = [('text', 'text'),
('text # comment', 'text '),
('text # comment\n', 'text \n'),
('text # comment \n', 'text \n'),
('line # c \nline\n','line \nline\n'),
('line # c \nline#c2 \nline\nline #c\n\n',
'line \nline\nline\nline \n\n'),
]
Thomas Kluyver
Return command to the next prompt if help was called halfway through a command. Also, ? at the end of a comment should not trigger help.
r4080 tt.check_pairs(isp.remove_comments, tests)
def test_has_comment():
tests = [('text', False),
('text #comment', True),
('text #comment\n', True),
('#comment', True),
('#comment\n', True),
('a = "#string"', False),
('a = "#string" # comment', True),
('a #comment not "string"', True),
]
tt.check_pairs(isp.has_comment, tests)
Fernando Perez
Split blockbreaker tests into a separate file and clean up api....
r2633
def test_get_input_encoding():
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 encoding = isp.get_input_encoding()
Fernando Perez
Split blockbreaker tests into a separate file and clean up api....
r2633 nt.assert_true(isinstance(encoding, basestring))
# simple-minded check that at least encoding a simple string works with the
# encoding we got.
nt.assert_equal('test'.encode(encoding), 'test')
Fernando Perez
Add test for missing input encoding. Back to 100% coverage.
r2718 class NoInputEncodingTestCase(unittest.TestCase):
def setUp(self):
self.old_stdin = sys.stdin
class X: pass
fake_stdin = X()
sys.stdin = fake_stdin
def test(self):
# Verify that if sys.stdin has no 'encoding' attribute we do the right
# thing
enc = isp.get_input_encoding()
self.assertEqual(enc, 'ascii')
def tearDown(self):
sys.stdin = self.old_stdin
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 class InputSplitterTestCase(unittest.TestCase):
Fernando Perez
Split blockbreaker tests into a separate file and clean up api....
r2633 def setUp(self):
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 self.isp = isp.InputSplitter()
Fernando Perez
Split blockbreaker tests into a separate file and clean up api....
r2633
def test_reset(self):
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 isp = self.isp
isp.push('x=1')
isp.reset()
self.assertEqual(isp._buffer, [])
self.assertEqual(isp.indent_spaces, 0)
self.assertEqual(isp.source, '')
self.assertEqual(isp.code, None)
self.assertEqual(isp._is_complete, False)
Fernando Perez
Split blockbreaker tests into a separate file and clean up api....
r2633
def test_source(self):
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 self.isp._store('1')
self.isp._store('2')
self.assertEqual(self.isp.source, '1\n2\n')
self.assertTrue(len(self.isp._buffer)>0)
self.assertEqual(self.isp.source_reset(), '1\n2\n')
self.assertEqual(self.isp._buffer, [])
self.assertEqual(self.isp.source, '')
Fernando Perez
Split blockbreaker tests into a separate file and clean up api....
r2633
def test_indent(self):
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 isp = self.isp # shorthand
isp.push('x=1')
self.assertEqual(isp.indent_spaces, 0)
isp.push('if 1:\n x=1')
self.assertEqual(isp.indent_spaces, 4)
isp.push('y=2\n')
self.assertEqual(isp.indent_spaces, 0)
Fernando Perez
Continue refactoring input handling across clients....
r3085
def test_indent2(self):
# In cell mode, inputs must be fed in whole blocks, so skip this test
if self.isp.input_mode == 'cell': return
isp = self.isp
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 isp.push('if 1:')
self.assertEqual(isp.indent_spaces, 4)
isp.push(' x=1')
self.assertEqual(isp.indent_spaces, 4)
Fernando Perez
Split blockbreaker tests into a separate file and clean up api....
r2633 # Blank lines shouldn't change the indent level
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 isp.push(' '*2)
self.assertEqual(isp.indent_spaces, 4)
Fernando Perez
Split blockbreaker tests into a separate file and clean up api....
r2633
Fernando Perez
Continue refactoring input handling across clients....
r3085 def test_indent3(self):
# In cell mode, inputs must be fed in whole blocks, so skip this test
if self.isp.input_mode == 'cell': return
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 isp = self.isp
Fernando Perez
Split blockbreaker tests into a separate file and clean up api....
r2633 # When a multiline statement contains parens or multiline strings, we
# shouldn't get confused.
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 isp.push("if 1:")
isp.push(" x = (1+\n 2)")
self.assertEqual(isp.indent_spaces, 4)
Paul Ivanov
fix trailing whitespace from reseting indentation
r4204
def test_indent4(self):
# In cell mode, inputs must be fed in whole blocks, so skip this test
if self.isp.input_mode == 'cell': return
isp = self.isp
# whitespace after ':' should not screw up indent level
isp.push('if 1: \n x=1')
self.assertEqual(isp.indent_spaces, 4)
isp.push('y=2\n')
self.assertEqual(isp.indent_spaces, 0)
isp.push('if 1:\t\n x=1')
self.assertEqual(isp.indent_spaces, 4)
isp.push('y=2\n')
self.assertEqual(isp.indent_spaces, 0)
Fernando Perez
Split blockbreaker tests into a separate file and clean up api....
r2633
David Warde-Farley
New tests related to issue #142.
r3693 def test_dedent_pass(self):
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 isp = self.isp # shorthand
David Warde-Farley
New tests related to issue #142.
r3693 # should NOT cause dedent
isp.push('if 1:\n passes = 5')
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 self.assertEqual(isp.indent_spaces, 4)
David Warde-Farley
New tests related to issue #142.
r3693 isp.push('if 1:\n pass')
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 self.assertEqual(isp.indent_spaces, 0)
David Warde-Farley
New tests related to issue #142.
r3693 isp.push('if 1:\n pass ')
self.assertEqual(isp.indent_spaces, 0)
def test_dedent_raise(self):
isp = self.isp # shorthand
# should NOT cause dedent
isp.push('if 1:\n raised = 4')
self.assertEqual(isp.indent_spaces, 4)
isp.push('if 1:\n raise TypeError()')
self.assertEqual(isp.indent_spaces, 0)
isp.push('if 1:\n raise')
self.assertEqual(isp.indent_spaces, 0)
isp.push('if 1:\n raise ')
self.assertEqual(isp.indent_spaces, 0)
def test_dedent_return(self):
isp = self.isp # shorthand
# should NOT cause dedent
isp.push('if 1:\n returning = 4')
self.assertEqual(isp.indent_spaces, 4)
isp.push('if 1:\n return 5 + 493')
self.assertEqual(isp.indent_spaces, 0)
isp.push('if 1:\n return')
self.assertEqual(isp.indent_spaces, 0)
isp.push('if 1:\n return ')
self.assertEqual(isp.indent_spaces, 0)
isp.push('if 1:\n return(0)')
self.assertEqual(isp.indent_spaces, 0)
Fernando Perez
Split blockbreaker tests into a separate file and clean up api....
r2633 def test_push(self):
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 isp = self.isp
self.assertTrue(isp.push('x=1'))
Fernando Perez
Split blockbreaker tests into a separate file and clean up api....
r2633
def test_push2(self):
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 isp = self.isp
self.assertFalse(isp.push('if 1:'))
Fernando Perez
Split blockbreaker tests into a separate file and clean up api....
r2633 for line in [' x=1', '# a comment', ' y=2']:
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 self.assertTrue(isp.push(line))
Fernando Perez
Split blockbreaker tests into a separate file and clean up api....
r2633
Thomas Kluyver
Add test for inputsplitter bug.
r3747 def test_push3(self):
isp = self.isp
isp.push('if True:')
isp.push(' a = 1')
self.assertFalse(isp.push('b = [1,'))
Fernando Perez
Add support for append/replace mode after discussion with Evan....
r2634 def test_replace_mode(self):
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 isp = self.isp
Fernando Perez
Implement support for 'cell' mode with Ctrl-Enter....
r3004 isp.input_mode = 'cell'
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 isp.push('x=1')
self.assertEqual(isp.source, 'x=1\n')
isp.push('x=2')
self.assertEqual(isp.source, 'x=2\n')
def test_push_accepts_more(self):
isp = self.isp
isp.push('x=1')
self.assertFalse(isp.push_accepts_more())
def test_push_accepts_more2(self):
Fernando Perez
Continue refactoring input handling across clients....
r3085 # In cell mode, inputs must be fed in whole blocks, so skip this test
if self.isp.input_mode == 'cell': return
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 isp = self.isp
isp.push('if 1:')
self.assertTrue(isp.push_accepts_more())
isp.push(' x=1')
self.assertTrue(isp.push_accepts_more())
isp.push('')
self.assertFalse(isp.push_accepts_more())
Fernando Perez
Split blockbreaker tests into a separate file and clean up api....
r2633
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 def test_push_accepts_more3(self):
isp = self.isp
isp.push("x = (2+\n3)")
self.assertFalse(isp.push_accepts_more())
Fernando Perez
Split blockbreaker tests into a separate file and clean up api....
r2633
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 def test_push_accepts_more4(self):
Fernando Perez
Continue refactoring input handling across clients....
r3085 # In cell mode, inputs must be fed in whole blocks, so skip this test
if self.isp.input_mode == 'cell': return
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 isp = self.isp
Fernando Perez
Split blockbreaker tests into a separate file and clean up api....
r2633 # When a multiline statement contains parens or multiline strings, we
# shouldn't get confused.
# FIXME: we should be able to better handle de-dents in statements like
# multiline strings and multiline expressions (continued with \ or
# parens). Right now we aren't handling the indentation tracking quite
# correctly with this, though in practice it may not be too much of a
# problem. We'll need to see.
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 isp.push("if 1:")
isp.push(" x = (2+")
isp.push(" 3)")
self.assertTrue(isp.push_accepts_more())
isp.push(" y = 3")
self.assertTrue(isp.push_accepts_more())
isp.push('')
self.assertFalse(isp.push_accepts_more())
Thomas Kluyver
Require blank line to end input cell immediately after dedenting....
r3461
def test_push_accepts_more5(self):
# In cell mode, inputs must be fed in whole blocks, so skip this test
if self.isp.input_mode == 'cell': return
isp = self.isp
isp.push('try:')
isp.push(' a = 5')
isp.push('except:')
isp.push(' raise')
self.assertTrue(isp.push_accepts_more())
Fernando Perez
Fix bug with lines ending in continuation markers (\)....
r3013
def test_continuation(self):
isp = self.isp
isp.push("import os, \\")
self.assertTrue(isp.push_accepts_more())
isp.push("sys")
self.assertFalse(isp.push_accepts_more())
Fernando Perez
push() now swallows syntax errors and immediately produces a 'ready'...
r2635
def test_syntax_error(self):
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 isp = self.isp
Fernando Perez
push() now swallows syntax errors and immediately produces a 'ready'...
r2635 # Syntax errors immediately produce a 'ready' block, so the invalid
# Python can be sent to the kernel for evaluation with possible ipython
# special-syntax conversion.
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 isp.push('run foo')
self.assertFalse(isp.push_accepts_more())
Fernando Perez
Completed full block splitting for block-based frontends.
r2645
Fernando Perez
Stop-gap fix for crash with unicode input....
r3126 def test_unicode(self):
self.isp.push(u"Pérez")
self.isp.push(u'\xc3\xa9')
Thomas Kluyver
Further fixes and tweaks for inputsplitter.
r3455 self.isp.push(u"u'\xc3\xa9'")
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663
class InteractiveLoopTestCase(unittest.TestCase):
"""Tests for an interactive loop like a python shell.
"""
def check_ns(self, lines, ns):
"""Validate that the given input lines produce the resulting namespace.
Note: the input lines are given exactly as they would be typed in an
auto-indenting environment, as mini_interactive_loop above already does
auto-indenting and prepends spaces to the input.
"""
src = mini_interactive_loop(pseudo_input(lines))
test_ns = {}
exec src in test_ns
# We can't check that the provided ns is identical to the test_ns,
# because Python fills test_ns with extra keys (copyright, etc). But
# we can check that the given dict is *contained* in test_ns
Thomas Kluyver
Replacing some .items() calls with .iteritems() for cleaner conversion with 2to3.
r3114 for k,v in ns.iteritems():
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 self.assertEqual(test_ns[k], v)
Fernando Perez
Completed full block splitting for block-based frontends.
r2645
Fernando Perez
Renamed to inputsplitter, added more tests and examples....
r2663 def test_simple(self):
self.check_ns(['x=1'], dict(x=1))
def test_simple2(self):
self.check_ns(['if 1:', 'x=2'], dict(x=2))
def test_xy(self):
self.check_ns(['x=1; y=2'], dict(x=1, y=2))
def test_abc(self):
self.check_ns(['if 1:','a=1','b=2','c=3'], dict(a=1, b=2, c=3))
def test_multi(self):
self.check_ns(['x =(1+','1+','2)'], dict(x=4))
Fernando Perez
First pass of input syntax transformation support
r2719
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 def test_LineInfo():
"""Simple test for LineInfo construction and str()"""
linfo = isp.LineInfo(' %cd /home')
nt.assert_equals(str(linfo), 'LineInfo [ |%|cd|/home]')
def test_split_user_input():
"""Unicode test - split_user_input already has good doctests"""
line = u"Pérez Fernando"
parts = isp.split_user_input(line)
parts_expected = (u'', u'', u'', line)
nt.assert_equal(parts, parts_expected)
Fernando Perez
First pass of input syntax transformation support
r2719
# Transformer tests
def transform_checker(tests, func):
"""Utility to loop over test inputs"""
for inp, tr in tests:
nt.assert_equals(func(inp), tr)
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780
# Data for all the syntax tests in the form of lists of pairs of
# raw/transformed input. We store it here as a global dict so that we can use
# it both within single-function tests and also to validate the behavior of the
# larger objects
syntax = \
dict(assign_system =
Thomas Kluyver
Modify tests to expect unicode. Now all tests pass again.
r3471 [('a =! ls', 'a = get_ipython().getoutput(u"ls")'),
('b = !ls', 'b = get_ipython().getoutput(u"ls")'),
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 ('x=1', 'x=1'), # normal input is unmodified
(' ',' '), # blank lines are kept intact
],
assign_magic =
Thomas Kluyver
Modify tests to expect unicode. Now all tests pass again.
r3471 [('a =% who', 'a = get_ipython().magic(u"who")'),
('b = %who', 'b = get_ipython().magic(u"who")'),
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 ('x=1', 'x=1'), # normal input is unmodified
(' ',' '), # blank lines are kept intact
],
classic_prompt =
[('>>> x=1', 'x=1'),
('x=1', 'x=1'), # normal input is unmodified
Fernando Perez
Fix bug with IPythonInputSplitter in block input mode.
r2861 (' ', ' '), # blank lines are kept intact
('... ', ''), # continuation prompts
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 ],
ipy_prompt =
[('In [1]: x=1', 'x=1'),
('x=1', 'x=1'), # normal input is unmodified
(' ',' '), # blank lines are kept intact
Fernando Perez
Fix bug with IPythonInputSplitter in block input mode.
r2861 (' ....: ', ''), # continuation prompts
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 ],
# Tests for the escape transformer to leave normal code alone
escaped_noesc =
[ (' ', ' '),
('x=1', 'x=1'),
],
# System calls
escaped_shell =
Thomas Kluyver
Modify tests to expect unicode. Now all tests pass again.
r3471 [ ('!ls', 'get_ipython().system(u"ls")'),
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 # Double-escape shell, this means to capture the output of the
# subprocess and return it
Thomas Kluyver
Modify tests to expect unicode. Now all tests pass again.
r3471 ('!!ls', 'get_ipython().getoutput(u"ls")'),
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 ],
# Help/object info
escaped_help =
[ ('?', 'get_ipython().show_usage()'),
Thomas Kluyver
Modify tests to expect unicode. Now all tests pass again.
r3471 ('?x1', 'get_ipython().magic(u"pinfo x1")'),
('??x2', 'get_ipython().magic(u"pinfo2 x2")'),
Thomas Kluyver
Allow getting help mid-way through a command (e.g. a = abc.def?).
r4076 ('?a.*s', 'get_ipython().magic(u"psearch a.*s")'),
('?%hist', 'get_ipython().magic(u"pinfo %hist")'),
('?abc = qwe', 'get_ipython().magic(u"pinfo abc")'),
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 ],
Thomas Kluyver
Allow getting help mid-way through a command (e.g. a = abc.def?).
r4076
end_help =
[ ('x3?', 'get_ipython().magic(u"pinfo x3")'),
('x4??', 'get_ipython().magic(u"pinfo2 x4")'),
('%hist?', 'get_ipython().magic(u"pinfo %hist")'),
('f*?', 'get_ipython().magic(u"psearch f*")'),
('ax.*aspe*?', 'get_ipython().magic(u"psearch ax.*aspe*")'),
Thomas Kluyver
Tidier way of returning enterted command to the prompt when doing
r4081 ('a = abc?', 'get_ipython().magic(u"pinfo abc", next_input=u"a = abc")'),
('a = abc.qe??', 'get_ipython().magic(u"pinfo2 abc.qe", next_input=u"a = abc.qe")'),
('a = *.items?', 'get_ipython().magic(u"psearch *.items", next_input=u"a = *.items")'),
Thomas Kluyver
Handle tokenizing errors when checking if the ? at the end of the line is in a comment....
r4251 ('plot(a?', 'get_ipython().magic(u"pinfo a", next_input=u"plot(a")'),
Thomas Kluyver
Return command to the next prompt if help was called halfway through a command. Also, ? at the end of a comment should not trigger help.
r4080 ('a*2 #comment?', 'a*2 #comment?'),
Thomas Kluyver
Allow getting help mid-way through a command (e.g. a = abc.def?).
r4076 ],
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780
# Explicit magic calls
escaped_magic =
Thomas Kluyver
Modify tests to expect unicode. Now all tests pass again.
r3471 [ ('%cd', 'get_ipython().magic(u"cd")'),
('%cd /home', 'get_ipython().magic(u"cd /home")'),
(' %magic', ' get_ipython().magic(u"magic")'),
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 ],
# Quoting with separate arguments
escaped_quote =
[ (',f', 'f("")'),
(',f x', 'f("x")'),
(' ,f y', ' f("y")'),
(',f a b', 'f("a", "b")'),
],
# Quoting with single argument
escaped_quote2 =
[ (';f', 'f("")'),
(';f x', 'f("x")'),
(' ;f y', ' f("y")'),
(';f a b', 'f("a b")'),
],
# Simply apply parens
escaped_paren =
[ ('/f', 'f()'),
('/f x', 'f(x)'),
(' /f y', ' f(y)'),
('/f a b', 'f(a, b)'),
],
Thomas Kluyver
Reorder inputsplitter transformers so that prompts pasted into the input are removed before other transforms are applied.
r4078
# Check that we transform prompts before other transforms
mixed =
[ ('In [1]: %lsmagic', 'get_ipython().magic(u"lsmagic")'),
('>>> %lsmagic', 'get_ipython().magic(u"lsmagic")'),
('In [2]: !ls', 'get_ipython().system(u"ls")'),
('In [3]: abs?', 'get_ipython().magic(u"pinfo abs")'),
('In [4]: b = %who', 'b = get_ipython().magic(u"who")'),
],
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 )
# multiline syntax examples. Each of these should be a list of lists, with
# each entry itself having pairs of raw/transformed input. The union (with
# '\n'.join() of the transformed inputs is what the splitter should produce
# when fed the raw lines one at a time via push.
syntax_ml = \
dict(classic_prompt =
[ [('>>> for i in range(10):','for i in range(10):'),
('... print i',' print i'),
('... ', ''),
],
],
ipy_prompt =
[ [('In [24]: for i in range(10):','for i in range(10):'),
(' ....: print i',' print i'),
(' ....: ', ''),
],
],
)
Fernando Perez
First pass of input syntax transformation support
r2719
def test_assign_system():
Thomas Kluyver
Return command to the next prompt if help was called halfway through a command. Also, ? at the end of a comment should not trigger help.
r4080 tt.check_pairs(isp.transform_assign_system, syntax['assign_system'])
Fernando Perez
First pass of input syntax transformation support
r2719
def test_assign_magic():
Thomas Kluyver
Return command to the next prompt if help was called halfway through a command. Also, ? at the end of a comment should not trigger help.
r4080 tt.check_pairs(isp.transform_assign_magic, syntax['assign_magic'])
Fernando Perez
First pass of input syntax transformation support
r2719
def test_classic_prompt():
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 transform_checker(syntax['classic_prompt'], isp.transform_classic_prompt)
for example in syntax_ml['classic_prompt']:
transform_checker(example, isp.transform_classic_prompt)
Fernando Perez
First pass of input syntax transformation support
r2719
def test_ipy_prompt():
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 transform_checker(syntax['ipy_prompt'], isp.transform_ipy_prompt)
for example in syntax_ml['ipy_prompt']:
transform_checker(example, isp.transform_ipy_prompt)
Thomas Kluyver
Allow getting help mid-way through a command (e.g. a = abc.def?).
r4076
def test_end_help():
Thomas Kluyver
Return command to the next prompt if help was called halfway through a command. Also, ? at the end of a comment should not trigger help.
r4080 tt.check_pairs(isp.transform_help_end, syntax['end_help'])
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780
def test_escaped_noesc():
Thomas Kluyver
Return command to the next prompt if help was called halfway through a command. Also, ? at the end of a comment should not trigger help.
r4080 tt.check_pairs(isp.transform_escaped, syntax['escaped_noesc'])
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780
def test_escaped_shell():
Thomas Kluyver
Return command to the next prompt if help was called halfway through a command. Also, ? at the end of a comment should not trigger help.
r4080 tt.check_pairs(isp.transform_escaped, syntax['escaped_shell'])
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780
def test_escaped_help():
Thomas Kluyver
Return command to the next prompt if help was called halfway through a command. Also, ? at the end of a comment should not trigger help.
r4080 tt.check_pairs(isp.transform_escaped, syntax['escaped_help'])
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780
def test_escaped_magic():
Thomas Kluyver
Return command to the next prompt if help was called halfway through a command. Also, ? at the end of a comment should not trigger help.
r4080 tt.check_pairs(isp.transform_escaped, syntax['escaped_magic'])
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780
def test_escaped_quote():
Thomas Kluyver
Return command to the next prompt if help was called halfway through a command. Also, ? at the end of a comment should not trigger help.
r4080 tt.check_pairs(isp.transform_escaped, syntax['escaped_quote'])
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780
def test_escaped_quote2():
Thomas Kluyver
Return command to the next prompt if help was called halfway through a command. Also, ? at the end of a comment should not trigger help.
r4080 tt.check_pairs(isp.transform_escaped, syntax['escaped_quote2'])
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780
def test_escaped_paren():
Thomas Kluyver
Return command to the next prompt if help was called halfway through a command. Also, ? at the end of a comment should not trigger help.
r4080 tt.check_pairs(isp.transform_escaped, syntax['escaped_paren'])
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780
class IPythonInputTestCase(InputSplitterTestCase):
"""By just creating a new class whose .isp is a different instance, we
re-run the same test battery on the new input splitter.
In addition, this runs the tests over the syntax and syntax_ml dicts that
were tested by individual functions, as part of the OO interface.
Fernando Perez
Add support for accessing raw data to inputsplitter....
r3080
It also makes some checks on the raw buffer storage.
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 """
Fernando Perez
Fix bug with IPythonInputSplitter in block input mode.
r2861
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 def setUp(self):
Fernando Perez
Rename input modes of input splitter to 'line' and 'block'....
r2862 self.isp = isp.IPythonInputSplitter(input_mode='line')
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780
def test_syntax(self):
"""Call all single-line syntax tests from the main object"""
isp = self.isp
for example in syntax.itervalues():
for raw, out_t in example:
if raw.startswith(' '):
continue
isp.push(raw)
Fernando Perez
Add support for accessing raw data to inputsplitter....
r3080 out, out_raw = isp.source_raw_reset()
self.assertEqual(out.rstrip(), out_t)
self.assertEqual(out_raw.rstrip(), raw.rstrip())
Fernando Perez
Fix bug with IPythonInputSplitter in block input mode.
r2861
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 def test_syntax_multiline(self):
isp = self.isp
for example in syntax_ml.itervalues():
out_t_parts = []
Fernando Perez
Add support for accessing raw data to inputsplitter....
r3080 raw_parts = []
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 for line_pairs in example:
Fernando Perez
Add support for accessing raw data to inputsplitter....
r3080 for lraw, out_t_part in line_pairs:
isp.push(lraw)
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 out_t_parts.append(out_t_part)
Fernando Perez
Add support for accessing raw data to inputsplitter....
r3080 raw_parts.append(lraw)
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780
Fernando Perez
Add support for accessing raw data to inputsplitter....
r3080 out, out_raw = isp.source_raw_reset()
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 out_t = '\n'.join(out_t_parts).rstrip()
Fernando Perez
Add support for accessing raw data to inputsplitter....
r3080 raw = '\n'.join(raw_parts).rstrip()
self.assertEqual(out.rstrip(), out_t)
self.assertEqual(out_raw.rstrip(), raw)
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780
Fernando Perez
Fix bug with IPythonInputSplitter in block input mode.
r2861
class BlockIPythonInputTestCase(IPythonInputTestCase):
# Deactivate tests that don't make sense for the block mode
test_push3 = test_split = lambda s: None
def setUp(self):
Fernando Perez
Implement support for 'cell' mode with Ctrl-Enter....
r3004 self.isp = isp.IPythonInputSplitter(input_mode='cell')
Fernando Perez
Fix bug with IPythonInputSplitter in block input mode.
r2861
def test_syntax_multiline(self):
isp = self.isp
for example in syntax_ml.itervalues():
raw_parts = []
out_t_parts = []
for line_pairs in example:
for raw, out_t_part in line_pairs:
raw_parts.append(raw)
out_t_parts.append(out_t_part)
raw = '\n'.join(raw_parts)
out_t = '\n'.join(out_t_parts)
isp.push(raw)
Fernando Perez
Add support for accessing raw data to inputsplitter....
r3080 out, out_raw = isp.source_raw_reset()
Fernando Perez
Fix bug with IPythonInputSplitter in block input mode.
r2861 # Match ignoring trailing whitespace
self.assertEqual(out.rstrip(), out_t.rstrip())
Fernando Perez
Add support for accessing raw data to inputsplitter....
r3080 self.assertEqual(out_raw.rstrip(), raw.rstrip())
Fernando Perez
Fix bug with IPythonInputSplitter in block input mode.
r2861
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 #-----------------------------------------------------------------------------
Fernando Perez
Fix bug with IPythonInputSplitter in block input mode.
r2861 # Main - use as a script, mostly for developer experiments
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 #-----------------------------------------------------------------------------
if __name__ == '__main__':
# A simple demo for interactive experimentation. This code will not get
Fernando Perez
Fix bug with IPythonInputSplitter in block input mode.
r2861 # picked up by any test suite.
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 from IPython.core.inputsplitter import InputSplitter, IPythonInputSplitter
Fernando Perez
Final cleanups responding to Brian's code review....
r2782
# configure here the syntax to use, prompt and whether to autoindent
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 #isp, start_prompt = InputSplitter(), '>>> '
isp, start_prompt = IPythonInputSplitter(), 'In> '
autoindent = True
#autoindent = False
try:
while True:
prompt = start_prompt
while isp.push_accepts_more():
indent = ' '*isp.indent_spaces
if autoindent:
line = indent + raw_input(prompt+indent)
else:
line = raw_input(prompt)
isp.push(line)
prompt = '... '
# Here we just return input so we can use it in a test suite, but a
# real interpreter would instead send it for execution somewhere.
Fernando Perez
Final documentation changes from code review with Brian, ready to merge.
r2828 #src = isp.source; raise EOFError # dbg
Fernando Perez
Add support for accessing raw data to inputsplitter....
r3080 src, raw = isp.source_raw_reset()
Fernando Perez
Final cleanups responding to Brian's code review....
r2782 print 'Input source was:\n', src
Fernando Perez
Add support for accessing raw data to inputsplitter....
r3080 print 'Raw source was:\n', raw
Fernando Perez
Completed first pass of inputsplitter with IPython syntax....
r2780 except EOFError:
print 'Bye'