forked from ipython/ipython
-
Notifications
You must be signed in to change notification settings - Fork 2
/
test_interactivshell.py
153 lines (120 loc) · 4.79 KB
/
test_interactivshell.py
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
# -*- coding: utf-8 -*-
"""Tests for the TerminalInteractiveShell and related pieces."""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
import sys
import unittest
from IPython.core.inputtransformer import InputTransformer
from IPython.testing import tools as tt
from IPython.utils.capture import capture_output
# Decorator for interaction loop tests -----------------------------------------
class mock_input_helper(object):
"""Machinery for tests of the main interact loop.
Used by the mock_input decorator.
"""
def __init__(self, testgen):
self.testgen = testgen
self.exception = None
self.ip = get_ipython()
def __enter__(self):
self.orig_prompt_for_code = self.ip.prompt_for_code
self.ip.prompt_for_code = self.fake_input
return self
def __exit__(self, etype, value, tb):
self.ip.prompt_for_code = self.orig_prompt_for_code
def fake_input(self):
try:
return next(self.testgen)
except StopIteration:
self.ip.keep_running = False
return u''
except:
self.exception = sys.exc_info()
self.ip.keep_running = False
return u''
def mock_input(testfunc):
"""Decorator for tests of the main interact loop.
Write the test as a generator, yield-ing the input strings, which IPython
will see as if they were typed in at the prompt.
"""
def test_method(self):
testgen = testfunc(self)
with mock_input_helper(testgen) as mih:
mih.ip.interact()
if mih.exception is not None:
# Re-raise captured exception
etype, value, tb = mih.exception
import traceback
traceback.print_tb(tb, file=sys.stdout)
del tb # Avoid reference loop
raise value
return test_method
# Test classes -----------------------------------------------------------------
class InteractiveShellTestCase(unittest.TestCase):
def rl_hist_entries(self, rl, n):
"""Get last n readline history entries as a list"""
return [rl.get_history_item(rl.get_current_history_length() - x)
for x in range(n - 1, -1, -1)]
@mock_input
def test_inputtransformer_syntaxerror(self):
ip = get_ipython()
transformer = SyntaxErrorTransformer()
ip.input_splitter.python_line_transforms.append(transformer)
ip.input_transformer_manager.python_line_transforms.append(transformer)
try:
#raise Exception
with tt.AssertPrints('4', suppress=False):
yield u'print(2*2)'
with tt.AssertPrints('SyntaxError: input contains', suppress=False):
yield u'print(2345) # syntaxerror'
with tt.AssertPrints('16', suppress=False):
yield u'print(4*4)'
finally:
ip.input_splitter.python_line_transforms.remove(transformer)
ip.input_transformer_manager.python_line_transforms.remove(transformer)
def test_plain_text_only(self):
ip = get_ipython()
formatter = ip.display_formatter
assert formatter.active_types == ['text/plain']
assert not formatter.ipython_display_formatter.enabled
class Test(object):
def __repr__(self):
return "<Test %i>" % id(self)
def _repr_html_(self):
return '<html>'
# verify that HTML repr isn't computed
obj = Test()
data, _ = formatter.format(obj)
self.assertEqual(data, {'text/plain': repr(obj)})
class Test2(Test):
def _ipython_display_(self):
from IPython.display import display
display('<custom>')
# verify that _ipython_display_ shortcut isn't called
obj = Test2()
with capture_output() as captured:
data, _ = formatter.format(obj)
self.assertEqual(data, {'text/plain': repr(obj)})
assert captured.stdout == ''
class SyntaxErrorTransformer(InputTransformer):
def push(self, line):
pos = line.find('syntaxerror')
if pos >= 0:
e = SyntaxError('input contains "syntaxerror"')
e.text = line
e.offset = pos + 1
raise e
return line
def reset(self):
pass
class TerminalMagicsTestCase(unittest.TestCase):
def test_paste_magics_blankline(self):
"""Test that code with a blank line doesn't get split (gh-3246)."""
ip = get_ipython()
s = ('def pasted_func(a):\n'
' b = a+1\n'
'\n'
' return b')
tm = ip.magics_manager.registry['TerminalMagics']
tm.store_or_execute(s, name=None)
self.assertEqual(ip.user_ns['pasted_func'](54), 55)