test_magic_terminal.py
204 lines
| 6.0 KiB
| text/x-python
|
PythonLexer
Fernando Perez
|
r5436 | """Tests for various magic functions specific to the terminal frontend. | ||
Needs to be run by nose (to make ipython session available). | ||||
""" | ||||
from __future__ import absolute_import | ||||
#----------------------------------------------------------------------------- | ||||
# Imports | ||||
#----------------------------------------------------------------------------- | ||||
import sys | ||||
from StringIO import StringIO | ||||
Fernando Perez
|
r7662 | from unittest import TestCase | ||
Fernando Perez
|
r5436 | |||
import nose.tools as nt | ||||
from IPython.testing import tools as tt | ||||
#----------------------------------------------------------------------------- | ||||
Fernando Perez
|
r7662 | # Globals | ||
#----------------------------------------------------------------------------- | ||||
ip = get_ipython() | ||||
#----------------------------------------------------------------------------- | ||||
Fernando Perez
|
r5436 | # Test functions begin | ||
#----------------------------------------------------------------------------- | ||||
def check_cpaste(code, should_fail=False): | ||||
"""Execute code via 'cpaste' and ensure it was executed, unless | ||||
should_fail is set. | ||||
""" | ||||
Fernando Perez
|
r7735 | ip.user_ns['code_ran'] = False | ||
Fernando Perez
|
r5436 | |||
src = StringIO() | ||||
if not hasattr(src, 'encoding'): | ||||
# IPython expects stdin to have an encoding attribute | ||||
src.encoding = None | ||||
src.write(code) | ||||
src.write('\n--\n') | ||||
src.seek(0) | ||||
stdin_save = sys.stdin | ||||
sys.stdin = src | ||||
try: | ||||
context = tt.AssertPrints if should_fail else tt.AssertNotPrints | ||||
with context("Traceback (most recent call last)"): | ||||
Fernando Perez
|
r7735 | ip.magic('cpaste') | ||
Fernando Perez
|
r5436 | |||
if not should_fail: | ||||
Fernando Perez
|
r7735 | assert ip.user_ns['code_ran'] | ||
Fernando Perez
|
r5436 | finally: | ||
sys.stdin = stdin_save | ||||
Thomas Kluyver
|
r5935 | PY31 = sys.version_info[:2] == (3,1) | ||
Fernando Perez
|
r5436 | |||
def test_cpaste(): | ||||
"""Test cpaste magic""" | ||||
Fernando Perez
|
r7716 | def runf(): | ||
Fernando Perez
|
r5436 | """Marker function: sets a flag when executed. | ||
""" | ||||
Fernando Perez
|
r7735 | ip.user_ns['code_ran'] = True | ||
Fernando Perez
|
r7716 | return 'runf' # return string so '+ runf()' doesn't result in success | ||
tests = {'pass': ["runf()", | ||||
"In [1]: runf()", | ||||
"In [1]: if 1:\n ...: runf()", | ||||
"> > > runf()", | ||||
">>> runf()", | ||||
" >>> runf()", | ||||
Fernando Perez
|
r5436 | ], | ||
Fernando Perez
|
r7716 | 'fail': ["1 + runf()", | ||
Thomas Kluyver
|
r5935 | ]} | ||
# I don't know why this is failing specifically on Python 3.1. I've | ||||
# checked it manually interactively, but we don't care enough about 3.1 | ||||
# to spend time fiddling with the tests, so we just skip it. | ||||
if not PY31: | ||||
Fernando Perez
|
r7716 | tests['fail'].append("++ runf()") | ||
Fernando Perez
|
r5436 | |||
Fernando Perez
|
r7735 | ip.user_ns['runf'] = runf | ||
Fernando Perez
|
r5436 | |||
for code in tests['pass']: | ||||
check_cpaste(code) | ||||
for code in tests['fail']: | ||||
check_cpaste(code, should_fail=True) | ||||
Fernando Perez
|
r7662 | class PasteTestCase(TestCase): | ||
"""Multiple tests for clipboard pasting""" | ||||
Fernando Perez
|
r5436 | |||
Fernando Perez
|
r7662 | def paste(self, txt, flags='-q'): | ||
Fernando Perez
|
r5436 | """Paste input text, by default in quiet mode""" | ||
Fernando Perez
|
r7662 | ip.hooks.clipboard_get = lambda : txt | ||
ip.magic('paste '+flags) | ||||
Fernando Perez
|
r5436 | |||
Fernando Perez
|
r7662 | def setUp(self): | ||
# Inject fake clipboard hook but save original so we can restore it later | ||||
self.original_clip = ip.hooks.clipboard_get | ||||
Fernando Perez
|
r5436 | |||
Fernando Perez
|
r7662 | def tearDown(self): | ||
# Restore original hook | ||||
ip.hooks.clipboard_get = self.original_clip | ||||
def test_paste(self): | ||||
ip.user_ns.pop('x', None) | ||||
Fernando Perez
|
r7716 | self.paste('x = 1') | ||
Fernando Perez
|
r7662 | nt.assert_equal(ip.user_ns['x'], 1) | ||
Fernando Perez
|
r7716 | ip.user_ns.pop('x') | ||
Fernando Perez
|
r7662 | |||
def test_paste_pyprompt(self): | ||||
ip.user_ns.pop('x', None) | ||||
self.paste('>>> x=2') | ||||
nt.assert_equal(ip.user_ns['x'], 2) | ||||
Fernando Perez
|
r7716 | ip.user_ns.pop('x') | ||
Fernando Perez
|
r7662 | |||
def test_paste_py_multi(self): | ||||
self.paste(""" | ||||
Fernando Perez
|
r5436 | >>> x = [1,2,3] | ||
>>> y = [] | ||||
>>> for i in x: | ||||
... y.append(i**2) | ||||
Fernando Perez
|
r7716 | ... | ||
Fernando Perez
|
r5436 | """) | ||
Fernando Perez
|
r7662 | nt.assert_equal(ip.user_ns['x'], [1,2,3]) | ||
nt.assert_equal(ip.user_ns['y'], [1,4,9]) | ||||
def test_paste_py_multi_r(self): | ||||
"Now, test that self.paste -r works" | ||||
Fernando Perez
|
r7716 | nt.assert_equal(ip.user_ns.pop('x'), [1,2,3]) | ||
nt.assert_equal(ip.user_ns.pop('y'), [1,4,9]) | ||||
Fernando Perez
|
r7662 | nt.assert_false('x' in ip.user_ns) | ||
ip.magic('paste -r') | ||||
nt.assert_equal(ip.user_ns['x'], [1,2,3]) | ||||
Fernando Perez
|
r7716 | nt.assert_equal(ip.user_ns['y'], [1,4,9]) | ||
Fernando Perez
|
r7662 | |||
def test_paste_email(self): | ||||
"Test pasting of email-quoted contents" | ||||
Fernando Perez
|
r7716 | self.paste("""\ | ||
Fernando Perez
|
r5436 | >> def foo(x): | ||
>> return x + 1 | ||||
Fernando Perez
|
r7716 | >> xx = foo(1.1)""") | ||
nt.assert_equal(ip.user_ns['xx'], 2.1) | ||||
Fernando Perez
|
r5436 | |||
Fernando Perez
|
r7662 | def test_paste_email2(self): | ||
"Email again; some programs add a space also at each quoting level" | ||||
Fernando Perez
|
r7716 | self.paste("""\ | ||
Fernando Perez
|
r5436 | > > def foo(x): | ||
> > return x + 1 | ||||
Fernando Perez
|
r7716 | > > yy = foo(2.1) """) | ||
nt.assert_equal(ip.user_ns['yy'], 3.1) | ||||
Fernando Perez
|
r5436 | |||
Fernando Perez
|
r7662 | def test_paste_email_py(self): | ||
"Email quoting of interactive input" | ||||
Fernando Perez
|
r7716 | self.paste("""\ | ||
Fernando Perez
|
r5436 | >> >>> def f(x): | ||
>> ... return x+1 | ||||
Fernando Perez
|
r7716 | >> ... | ||
>> >>> zz = f(2.5) """) | ||||
nt.assert_equal(ip.user_ns['zz'], 3.5) | ||||
Fernando Perez
|
r5436 | |||
Fernando Perez
|
r7662 | def test_paste_echo(self): | ||
"Also test self.paste echoing, by temporarily faking the writer" | ||||
Fernando Perez
|
r5436 | w = StringIO() | ||
Fernando Perez
|
r7662 | writer = ip.write | ||
ip.write = w.write | ||||
Fernando Perez
|
r5436 | code = """ | ||
a = 100 | ||||
b = 200""" | ||||
try: | ||||
Fernando Perez
|
r7662 | self.paste(code,'') | ||
Fernando Perez
|
r5436 | out = w.getvalue() | ||
finally: | ||||
Fernando Perez
|
r7662 | ip.write = writer | ||
nt.assert_equal(ip.user_ns['a'], 100) | ||||
nt.assert_equal(ip.user_ns['b'], 200) | ||||
Fernando Perez
|
r5436 | nt.assert_equal(out, code+"\n## -- End pasted text --\n") | ||
Fernando Perez
|
r7663 | def test_paste_leading_commas(self): | ||
"Test multiline strings with leading commas" | ||||
tm = ip.magics_manager.registry['TerminalMagics'] | ||||
Fernando Perez
|
r7703 | s = '''\ | ||
Fernando Perez
|
r7663 | a = """ | ||
,1,2,3 | ||||
"""''' | ||||
ip.user_ns.pop('foo', None) | ||||
tm.store_or_execute(s, 'foo') | ||||
nt.assert_in('foo', ip.user_ns) | ||||
Fernando Perez
|
r7703 | |||
def test_paste_trailing_question(self): | ||||
"Test pasting sources with trailing question marks" | ||||
tm = ip.magics_manager.registry['TerminalMagics'] | ||||
s = '''\ | ||||
def funcfoo(): | ||||
if True: #am i true? | ||||
return 'fooresult' | ||||
''' | ||||
ip.user_ns.pop('funcfoo', None) | ||||
Fernando Perez
|
r7716 | self.paste(s) | ||
Fernando Perez
|
r7703 | nt.assert_equals(ip.user_ns['funcfoo'](), 'fooresult') | ||