##// END OF EJS Templates
Merge: fixes to testing for wx frontend.
Gael Varoquaux -
r1536:c3c75c6c merge
parent child Browse files
Show More
@@ -1,221 +1,223 b''
1 """
1 """
2 Frontend class that uses IPython0 to prefilter the inputs.
2 Frontend class that uses IPython0 to prefilter the inputs.
3
3
4 Using the IPython0 mechanism gives us access to the magics.
4 Using the IPython0 mechanism gives us access to the magics.
5
5
6 This is a transitory class, used here to do the transition between
6 This is a transitory class, used here to do the transition between
7 ipython0 and ipython1. This class is meant to be short-lived as more
7 ipython0 and ipython1. This class is meant to be short-lived as more
8 functionnality is abstracted out of ipython0 in reusable functions and
8 functionnality is abstracted out of ipython0 in reusable functions and
9 is added on the interpreter. This class can be a used to guide this
9 is added on the interpreter. This class can be a used to guide this
10 refactoring.
10 refactoring.
11 """
11 """
12 __docformat__ = "restructuredtext en"
12 __docformat__ = "restructuredtext en"
13
13
14 #-------------------------------------------------------------------------------
14 #-------------------------------------------------------------------------------
15 # Copyright (C) 2008 The IPython Development Team
15 # Copyright (C) 2008 The IPython Development Team
16 #
16 #
17 # Distributed under the terms of the BSD License. The full license is in
17 # Distributed under the terms of the BSD License. The full license is in
18 # the file COPYING, distributed as part of this software.
18 # the file COPYING, distributed as part of this software.
19 #-------------------------------------------------------------------------------
19 #-------------------------------------------------------------------------------
20
20
21 #-------------------------------------------------------------------------------
21 #-------------------------------------------------------------------------------
22 # Imports
22 # Imports
23 #-------------------------------------------------------------------------------
23 #-------------------------------------------------------------------------------
24 import sys
24 import sys
25
25
26 from linefrontendbase import LineFrontEndBase, common_prefix
26 from linefrontendbase import LineFrontEndBase, common_prefix
27
27
28 from IPython.ipmaker import make_IPython
28 from IPython.ipmaker import make_IPython
29 from IPython.ipapi import IPApi
29 from IPython.ipapi import IPApi
30 from IPython.kernel.core.redirector_output_trap import RedirectorOutputTrap
30 from IPython.kernel.core.redirector_output_trap import RedirectorOutputTrap
31
31
32 from IPython.kernel.core.sync_traceback_trap import SyncTracebackTrap
32 from IPython.kernel.core.sync_traceback_trap import SyncTracebackTrap
33
33
34 from IPython.genutils import Term
34 from IPython.genutils import Term
35 import pydoc
35 import pydoc
36 import os
36 import os
37
37
38
38
39 def mk_system_call(system_call_function, command):
39 def mk_system_call(system_call_function, command):
40 """ given a os.system replacement, and a leading string command,
40 """ given a os.system replacement, and a leading string command,
41 returns a function that will execute the command with the given
41 returns a function that will execute the command with the given
42 argument string.
42 argument string.
43 """
43 """
44 def my_system_call(args):
44 def my_system_call(args):
45 system_call_function("%s %s" % (command, args))
45 system_call_function("%s %s" % (command, args))
46 return my_system_call
46 return my_system_call
47
47
48 #-------------------------------------------------------------------------------
48 #-------------------------------------------------------------------------------
49 # Frontend class using ipython0 to do the prefiltering.
49 # Frontend class using ipython0 to do the prefiltering.
50 #-------------------------------------------------------------------------------
50 #-------------------------------------------------------------------------------
51 class PrefilterFrontEnd(LineFrontEndBase):
51 class PrefilterFrontEnd(LineFrontEndBase):
52 """ Class that uses ipython0 to do prefilter the input, do the
52 """ Class that uses ipython0 to do prefilter the input, do the
53 completion and the magics.
53 completion and the magics.
54
54
55 The core trick is to use an ipython0 instance to prefilter the
55 The core trick is to use an ipython0 instance to prefilter the
56 input, and share the namespace between the interpreter instance used
56 input, and share the namespace between the interpreter instance used
57 to execute the statements and the ipython0 used for code
57 to execute the statements and the ipython0 used for code
58 completion...
58 completion...
59 """
59 """
60
60
61 def __init__(self, ipython0=None, *args, **kwargs):
61 def __init__(self, ipython0=None, *args, **kwargs):
62 """ Parameters:
62 """ Parameters:
63 -----------
63 -----------
64
64
65 ipython0: an optional ipython0 instance to use for command
65 ipython0: an optional ipython0 instance to use for command
66 prefiltering and completion.
66 prefiltering and completion.
67 """
67 """
68 self.save_output_hooks()
68 self.save_output_hooks()
69 if ipython0 is None:
69 if ipython0 is None:
70 # Instanciate an IPython0 interpreter to be able to use the
70 # Instanciate an IPython0 interpreter to be able to use the
71 # prefiltering.
71 # prefiltering.
72 # XXX: argv=[] is a bit bold.
72 # XXX: argv=[] is a bit bold.
73 ipython0 = make_IPython(argv=[])
73 ipython0 = make_IPython(argv=[])
74 self.ipython0 = ipython0
74 self.ipython0 = ipython0
75 # Set the pager:
75 # Set the pager:
76 self.ipython0.set_hook('show_in_pager',
76 self.ipython0.set_hook('show_in_pager',
77 lambda s, string: self.write("\n" + string))
77 lambda s, string: self.write("\n" + string))
78 self.ipython0.write = self.write
78 self.ipython0.write = self.write
79 self._ip = _ip = IPApi(self.ipython0)
79 self._ip = _ip = IPApi(self.ipython0)
80 # Make sure the raw system call doesn't get called, as we don't
80 # Make sure the raw system call doesn't get called, as we don't
81 # have a stdin accessible.
81 # have a stdin accessible.
82 self._ip.system = self.system_call
82 self._ip.system = self.system_call
83 # XXX: Muck around with magics so that they work better
83 # XXX: Muck around with magics so that they work better
84 # in our environment
84 # in our environment
85 self.ipython0.magic_ls = mk_system_call(self.system_call,
85 self.ipython0.magic_ls = mk_system_call(self.system_call,
86 'ls -CF')
86 'ls -CF')
87 # And now clean up the mess created by ipython0
87 # And now clean up the mess created by ipython0
88 self.release_output()
88 self.release_output()
89 if not 'banner' in kwargs and self.banner is None:
89 if not 'banner' in kwargs and self.banner is None:
90 kwargs['banner'] = self.ipython0.BANNER + """
90 kwargs['banner'] = self.ipython0.BANNER + """
91 This is the wx frontend, by Gael Varoquaux. This is EXPERIMENTAL code."""
91 This is the wx frontend, by Gael Varoquaux. This is EXPERIMENTAL code."""
92
92
93 LineFrontEndBase.__init__(self, *args, **kwargs)
93 LineFrontEndBase.__init__(self, *args, **kwargs)
94 # XXX: Hack: mix the two namespaces
94 # XXX: Hack: mix the two namespaces
95 self.shell.user_ns = self.ipython0.user_ns
95 self.shell.user_ns.update(self.ipython0.user_ns)
96 self.shell.user_global_ns = self.ipython0.user_global_ns
96 self.ipython0.user_ns = self.shell.user_ns
97 self.shell.user_global_ns.update(self.ipython0.user_global_ns)
98 self.ipython0.user_global_ns = self.shell.user_global_ns
97
99
98 self.shell.output_trap = RedirectorOutputTrap(
100 self.shell.output_trap = RedirectorOutputTrap(
99 out_callback=self.write,
101 out_callback=self.write,
100 err_callback=self.write,
102 err_callback=self.write,
101 )
103 )
102 self.shell.traceback_trap = SyncTracebackTrap(
104 self.shell.traceback_trap = SyncTracebackTrap(
103 formatters=self.shell.traceback_trap.formatters,
105 formatters=self.shell.traceback_trap.formatters,
104 )
106 )
105
107
106 #--------------------------------------------------------------------------
108 #--------------------------------------------------------------------------
107 # FrontEndBase interface
109 # FrontEndBase interface
108 #--------------------------------------------------------------------------
110 #--------------------------------------------------------------------------
109
111
110 def show_traceback(self):
112 def show_traceback(self):
111 """ Use ipython0 to capture the last traceback and display it.
113 """ Use ipython0 to capture the last traceback and display it.
112 """
114 """
113 self.capture_output()
115 self.capture_output()
114 self.ipython0.showtraceback()
116 self.ipython0.showtraceback()
115 self.release_output()
117 self.release_output()
116
118
117
119
118 def execute(self, python_string, raw_string=None):
120 def execute(self, python_string, raw_string=None):
119 if self.debug:
121 if self.debug:
120 print 'Executing Python code:', repr(python_string)
122 print 'Executing Python code:', repr(python_string)
121 self.capture_output()
123 self.capture_output()
122 LineFrontEndBase.execute(self, python_string,
124 LineFrontEndBase.execute(self, python_string,
123 raw_string=raw_string)
125 raw_string=raw_string)
124 self.release_output()
126 self.release_output()
125
127
126
128
127 def save_output_hooks(self):
129 def save_output_hooks(self):
128 """ Store all the output hooks we can think of, to be able to
130 """ Store all the output hooks we can think of, to be able to
129 restore them.
131 restore them.
130
132
131 We need to do this early, as starting the ipython0 instance will
133 We need to do this early, as starting the ipython0 instance will
132 screw ouput hooks.
134 screw ouput hooks.
133 """
135 """
134 self.__old_cout_write = Term.cout.write
136 self.__old_cout_write = Term.cout.write
135 self.__old_cerr_write = Term.cerr.write
137 self.__old_cerr_write = Term.cerr.write
136 self.__old_stdout = sys.stdout
138 self.__old_stdout = sys.stdout
137 self.__old_stderr= sys.stderr
139 self.__old_stderr= sys.stderr
138 self.__old_help_output = pydoc.help.output
140 self.__old_help_output = pydoc.help.output
139 self.__old_display_hook = sys.displayhook
141 self.__old_display_hook = sys.displayhook
140
142
141
143
142 def capture_output(self):
144 def capture_output(self):
143 """ Capture all the output mechanisms we can think of.
145 """ Capture all the output mechanisms we can think of.
144 """
146 """
145 self.save_output_hooks()
147 self.save_output_hooks()
146 Term.cout.write = self.write
148 Term.cout.write = self.write
147 Term.cerr.write = self.write
149 Term.cerr.write = self.write
148 sys.stdout = Term.cout
150 sys.stdout = Term.cout
149 sys.stderr = Term.cerr
151 sys.stderr = Term.cerr
150 pydoc.help.output = self.shell.output_trap.out
152 pydoc.help.output = self.shell.output_trap.out
151
153
152
154
153 def release_output(self):
155 def release_output(self):
154 """ Release all the different captures we have made.
156 """ Release all the different captures we have made.
155 """
157 """
156 Term.cout.write = self.__old_cout_write
158 Term.cout.write = self.__old_cout_write
157 Term.cerr.write = self.__old_cerr_write
159 Term.cerr.write = self.__old_cerr_write
158 sys.stdout = self.__old_stdout
160 sys.stdout = self.__old_stdout
159 sys.stderr = self.__old_stderr
161 sys.stderr = self.__old_stderr
160 pydoc.help.output = self.__old_help_output
162 pydoc.help.output = self.__old_help_output
161 sys.displayhook = self.__old_display_hook
163 sys.displayhook = self.__old_display_hook
162
164
163
165
164 def complete(self, line):
166 def complete(self, line):
165 word = line.split('\n')[-1].split(' ')[-1]
167 word = line.split('\n')[-1].split(' ')[-1]
166 completions = self.ipython0.complete(word)
168 completions = self.ipython0.complete(word)
167 # FIXME: The proper sort should be done in the complete method.
169 # FIXME: The proper sort should be done in the complete method.
168 key = lambda x: x.replace('_', '')
170 key = lambda x: x.replace('_', '')
169 completions.sort(key=key)
171 completions.sort(key=key)
170 if completions:
172 if completions:
171 prefix = common_prefix(completions)
173 prefix = common_prefix(completions)
172 line = line[:-len(word)] + prefix
174 line = line[:-len(word)] + prefix
173 return line, completions
175 return line, completions
174
176
175
177
176 #--------------------------------------------------------------------------
178 #--------------------------------------------------------------------------
177 # LineFrontEndBase interface
179 # LineFrontEndBase interface
178 #--------------------------------------------------------------------------
180 #--------------------------------------------------------------------------
179
181
180 def prefilter_input(self, input_string):
182 def prefilter_input(self, input_string):
181 """ Using IPython0 to prefilter the commands to turn them
183 """ Using IPython0 to prefilter the commands to turn them
182 in executable statements that are valid Python strings.
184 in executable statements that are valid Python strings.
183 """
185 """
184 input_string = LineFrontEndBase.prefilter_input(self, input_string)
186 input_string = LineFrontEndBase.prefilter_input(self, input_string)
185 filtered_lines = []
187 filtered_lines = []
186 # The IPython0 prefilters sometime produce output. We need to
188 # The IPython0 prefilters sometime produce output. We need to
187 # capture it.
189 # capture it.
188 self.capture_output()
190 self.capture_output()
189 self.last_result = dict(number=self.prompt_number)
191 self.last_result = dict(number=self.prompt_number)
190 try:
192 try:
191 for line in input_string.split('\n'):
193 for line in input_string.split('\n'):
192 filtered_lines.append(
194 filtered_lines.append(
193 self.ipython0.prefilter(line, False).rstrip())
195 self.ipython0.prefilter(line, False).rstrip())
194 except:
196 except:
195 # XXX: probably not the right thing to do.
197 # XXX: probably not the right thing to do.
196 self.ipython0.showsyntaxerror()
198 self.ipython0.showsyntaxerror()
197 self.after_execute()
199 self.after_execute()
198 finally:
200 finally:
199 self.release_output()
201 self.release_output()
200
202
201 # Clean up the trailing whitespace, to avoid indentation errors
203 # Clean up the trailing whitespace, to avoid indentation errors
202 filtered_string = '\n'.join(filtered_lines)
204 filtered_string = '\n'.join(filtered_lines)
203 return filtered_string
205 return filtered_string
204
206
205
207
206 #--------------------------------------------------------------------------
208 #--------------------------------------------------------------------------
207 # PrefilterFrontEnd interface
209 # PrefilterFrontEnd interface
208 #--------------------------------------------------------------------------
210 #--------------------------------------------------------------------------
209
211
210 def system_call(self, command_string):
212 def system_call(self, command_string):
211 """ Allows for frontend to define their own system call, to be
213 """ Allows for frontend to define their own system call, to be
212 able capture output and redirect input.
214 able capture output and redirect input.
213 """
215 """
214 return os.system(command_string)
216 return os.system(command_string)
215
217
216
218
217 def do_exit(self):
219 def do_exit(self):
218 """ Exit the shell, cleanup and save the history.
220 """ Exit the shell, cleanup and save the history.
219 """
221 """
220 self.ipython0.atexit_operations()
222 self.ipython0.atexit_operations()
221
223
@@ -1,157 +1,180 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Test process execution and IO redirection.
3 Test process execution and IO redirection.
4 """
4 """
5
5
6 __docformat__ = "restructuredtext en"
6 __docformat__ = "restructuredtext en"
7
7
8 #-------------------------------------------------------------------------------
8 #-------------------------------------------------------------------------------
9 # Copyright (C) 2008 The IPython Development Team
9 # Copyright (C) 2008 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is
11 # Distributed under the terms of the BSD License. The full license is
12 # in the file COPYING, distributed as part of this software.
12 # in the file COPYING, distributed as part of this software.
13 #-------------------------------------------------------------------------------
13 #-------------------------------------------------------------------------------
14
14
15 from cStringIO import StringIO
15 from cStringIO import StringIO
16 import string
16 import string
17
17
18 from IPython.ipapi import get as get_ipython0
18 from IPython.ipapi import get as get_ipython0
19 from IPython.frontend.prefilterfrontend import PrefilterFrontEnd
19 from IPython.frontend.prefilterfrontend import PrefilterFrontEnd
20 from copy import deepcopy
20
21
21 class TestPrefilterFrontEnd(PrefilterFrontEnd):
22 class TestPrefilterFrontEnd(PrefilterFrontEnd):
22
23
23 input_prompt_template = string.Template('')
24 input_prompt_template = string.Template('')
24 output_prompt_template = string.Template('')
25 output_prompt_template = string.Template('')
25 banner = ''
26 banner = ''
26
27
27 def __init__(self):
28 def __init__(self):
28 ipython0 = get_ipython0().IP
29 ipython0 = get_ipython0().IP
29 self.out = StringIO()
30 self.out = StringIO()
30 PrefilterFrontEnd.__init__(self, ipython0=ipython0)
31 PrefilterFrontEnd.__init__(self, ipython0=ipython0)
31 # Clean up the namespace for isolation between tests
32 # Clean up the namespace for isolation between tests
32 user_ns = self.ipython0.user_ns
33 user_ns = self.ipython0.user_ns
33 # We need to keep references to things so that they don't
34 # We need to keep references to things so that they don't
34 # get garbage collected (this stinks).
35 # get garbage collected (this stinks).
35 self.shadow_ns = dict()
36 self.shadow_ns = dict()
36 for i in self.ipython0.magic_who_ls():
37 for i in self.ipython0.magic_who_ls():
37 self.shadow_ns[i] = user_ns.pop(i)
38 self.shadow_ns[i] = user_ns.pop(i)
38 # Some more code for isolation (yeah, crazy)
39 # Some more code for isolation (yeah, crazy)
39 self._on_enter()
40 self._on_enter()
40 self.out.flush()
41 self.out.flush()
41 self.out.reset()
42 self.out.reset()
42 self.out.truncate()
43 self.out.truncate()
43
44
44 def write(self, string, *args, **kwargs):
45 def write(self, string, *args, **kwargs):
45 self.out.write(string)
46 self.out.write(string)
46
47
47 def _on_enter(self):
48 def _on_enter(self):
48 self.input_buffer += '\n'
49 self.input_buffer += '\n'
49 PrefilterFrontEnd._on_enter(self)
50 PrefilterFrontEnd._on_enter(self)
50
51
51
52
53 def isolate_ipython0(func):
54 """ Decorator to isolate execution that involves an iptyhon0.
55 """
56 def my_func(*args, **kwargs):
57 ipython0 = get_ipython0().IP
58 user_ns = deepcopy(ipython0.user_ns)
59 global_ns = deepcopy(ipython0.global_ns)
60 try:
61 func(*args, **kwargs)
62 finally:
63 ipython0.user_ns = user_ns
64 ipython0.global_ns = global_ns
65
66 return my_func
67
68
69 @isolate_ipython0
52 def test_execution():
70 def test_execution():
53 """ Test execution of a command.
71 """ Test execution of a command.
54 """
72 """
55 f = TestPrefilterFrontEnd()
73 f = TestPrefilterFrontEnd()
56 f.input_buffer = 'print 1'
74 f.input_buffer = 'print 1'
57 f._on_enter()
75 f._on_enter()
58 out_value = f.out.getvalue()
76 out_value = f.out.getvalue()
59 assert out_value == '1\n'
77 assert out_value == '1\n'
60
78
61
79
80 @isolate_ipython0
62 def test_multiline():
81 def test_multiline():
63 """ Test execution of a multiline command.
82 """ Test execution of a multiline command.
64 """
83 """
65 f = TestPrefilterFrontEnd()
84 f = TestPrefilterFrontEnd()
66 f.input_buffer = 'if True:'
85 f.input_buffer = 'if True:'
67 f._on_enter()
86 f._on_enter()
68 f.input_buffer += 'print 1'
87 f.input_buffer += 'print 1'
69 f._on_enter()
88 f._on_enter()
70 out_value = f.out.getvalue()
89 out_value = f.out.getvalue()
71 assert out_value == ''
90 assert out_value == ''
72 f._on_enter()
91 f._on_enter()
73 out_value = f.out.getvalue()
92 out_value = f.out.getvalue()
74 assert out_value == '1\n'
93 assert out_value == '1\n'
75 f = TestPrefilterFrontEnd()
94 f = TestPrefilterFrontEnd()
76 f.input_buffer='(1 +'
95 f.input_buffer='(1 +'
77 f._on_enter()
96 f._on_enter()
78 f.input_buffer += '0)'
97 f.input_buffer += '0)'
79 f._on_enter()
98 f._on_enter()
80 out_value = f.out.getvalue()
99 out_value = f.out.getvalue()
81 assert out_value == ''
100 assert out_value == ''
82 f._on_enter()
101 f._on_enter()
83 out_value = f.out.getvalue()
102 out_value = f.out.getvalue()
84 assert out_value == '1\n'
103 assert out_value == '1\n'
85
104
86
105
106 @isolate_ipython0
87 def test_capture():
107 def test_capture():
88 """ Test the capture of output in different channels.
108 """ Test the capture of output in different channels.
89 """
109 """
90 # Test on the OS-level stdout, stderr.
110 # Test on the OS-level stdout, stderr.
91 f = TestPrefilterFrontEnd()
111 f = TestPrefilterFrontEnd()
92 f.input_buffer = \
112 f.input_buffer = \
93 'import os; out=os.fdopen(1, "w"); out.write("1") ; out.flush()'
113 'import os; out=os.fdopen(1, "w"); out.write("1") ; out.flush()'
94 f._on_enter()
114 f._on_enter()
95 out_value = f.out.getvalue()
115 out_value = f.out.getvalue()
96 assert out_value == '1'
116 assert out_value == '1'
97 f = TestPrefilterFrontEnd()
117 f = TestPrefilterFrontEnd()
98 f.input_buffer = \
118 f.input_buffer = \
99 'import os; out=os.fdopen(2, "w"); out.write("1") ; out.flush()'
119 'import os; out=os.fdopen(2, "w"); out.write("1") ; out.flush()'
100 f._on_enter()
120 f._on_enter()
101 out_value = f.out.getvalue()
121 out_value = f.out.getvalue()
102 assert out_value == '1'
122 assert out_value == '1'
103
123
104
124
125 @isolate_ipython0
105 def test_magic():
126 def test_magic():
106 """ Test the magic expansion and history.
127 """ Test the magic expansion and history.
107
128
108 This test is fairly fragile and will break when magics change.
129 This test is fairly fragile and will break when magics change.
109 """
130 """
110 f = TestPrefilterFrontEnd()
131 f = TestPrefilterFrontEnd()
111 f.input_buffer += '%who'
132 f.input_buffer += '%who'
112 f._on_enter()
133 f._on_enter()
113 out_value = f.out.getvalue()
134 out_value = f.out.getvalue()
114 assert out_value == 'Interactive namespace is empty.\n'
135 assert out_value == 'Interactive namespace is empty.\n'
115
136
116
137
138 @isolate_ipython0
117 def test_help():
139 def test_help():
118 """ Test object inspection.
140 """ Test object inspection.
119 """
141 """
120 f = TestPrefilterFrontEnd()
142 f = TestPrefilterFrontEnd()
121 f.input_buffer += "def f():"
143 f.input_buffer += "def f():"
122 f._on_enter()
144 f._on_enter()
123 f.input_buffer += "'foobar'"
145 f.input_buffer += "'foobar'"
124 f._on_enter()
146 f._on_enter()
125 f.input_buffer += "pass"
147 f.input_buffer += "pass"
126 f._on_enter()
148 f._on_enter()
127 f._on_enter()
149 f._on_enter()
128 f.input_buffer += "f?"
150 f.input_buffer += "f?"
129 f._on_enter()
151 f._on_enter()
130 assert 'traceback' not in f.last_result
152 assert 'traceback' not in f.last_result
131 ## XXX: ipython doctest magic breaks this. I have no clue why
153 ## XXX: ipython doctest magic breaks this. I have no clue why
132 #out_value = f.out.getvalue()
154 #out_value = f.out.getvalue()
133 #assert out_value.split()[-1] == 'foobar'
155 #assert out_value.split()[-1] == 'foobar'
134
156
135
157
158 @isolate_ipython0
136 def test_completion():
159 def test_completion():
137 """ Test command-line completion.
160 """ Test command-line completion.
138 """
161 """
139 f = TestPrefilterFrontEnd()
162 f = TestPrefilterFrontEnd()
140 f.input_buffer = 'zzza = 1'
163 f.input_buffer = 'zzza = 1'
141 f._on_enter()
164 f._on_enter()
142 f.input_buffer = 'zzzb = 2'
165 f.input_buffer = 'zzzb = 2'
143 f._on_enter()
166 f._on_enter()
144 f.input_buffer = 'zz'
167 f.input_buffer = 'zz'
145 f.complete_current_input()
168 f.complete_current_input()
146 out_value = f.out.getvalue()
169 out_value = f.out.getvalue()
147 assert out_value == '\nzzza zzzb '
170 assert out_value == '\nzzza zzzb '
148 assert f.input_buffer == 'zzz'
171 assert f.input_buffer == 'zzz'
149
172
150
173
151 if __name__ == '__main__':
174 if __name__ == '__main__':
152 test_magic()
175 test_magic()
153 test_help()
176 test_help()
154 test_execution()
177 test_execution()
155 test_multiline()
178 test_multiline()
156 test_capture()
179 test_capture()
157 test_completion()
180 test_completion()
General Comments 0
You need to be logged in to leave comments. Login now