##// END OF EJS Templates
Suppress output even when a comment follows ;. Fixes #4525.
Shashi Gowda -
Show More
@@ -1,287 +1,286 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Displayhook for IPython.
2 """Displayhook for IPython.
3
3
4 This defines a callable class that IPython uses for `sys.displayhook`.
4 This defines a callable class that IPython uses for `sys.displayhook`.
5
5
6 Authors:
6 Authors:
7
7
8 * Fernando Perez
8 * Fernando Perez
9 * Brian Granger
9 * Brian Granger
10 * Robert Kern
10 * Robert Kern
11 """
11 """
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Copyright (C) 2008-2011 The IPython Development Team
14 # Copyright (C) 2008-2011 The IPython Development Team
15 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
15 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
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 from __future__ import print_function
24 from __future__ import print_function
25
25
26 import sys
26 import sys
27
27
28 from IPython.core.formatters import _safe_get_formatter_method
28 from IPython.core.formatters import _safe_get_formatter_method
29 from IPython.core import inputsplitter
29 from IPython.config.configurable import Configurable
30 from IPython.config.configurable import Configurable
30 from IPython.utils import io
31 from IPython.utils import io
31 from IPython.utils.py3compat import builtin_mod
32 from IPython.utils.py3compat import builtin_mod
32 from IPython.utils.traitlets import Instance
33 from IPython.utils.traitlets import Instance
33 from IPython.utils.warn import warn
34 from IPython.utils.warn import warn
34
35
35 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
36 # Main displayhook class
37 # Main displayhook class
37 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
38
39
39 # TODO: Move the various attributes (cache_size, [others now moved]). Some
40 # TODO: Move the various attributes (cache_size, [others now moved]). Some
40 # of these are also attributes of InteractiveShell. They should be on ONE object
41 # of these are also attributes of InteractiveShell. They should be on ONE object
41 # only and the other objects should ask that one object for their values.
42 # only and the other objects should ask that one object for their values.
42
43
43 class DisplayHook(Configurable):
44 class DisplayHook(Configurable):
44 """The custom IPython displayhook to replace sys.displayhook.
45 """The custom IPython displayhook to replace sys.displayhook.
45
46
46 This class does many things, but the basic idea is that it is a callable
47 This class does many things, but the basic idea is that it is a callable
47 that gets called anytime user code returns a value.
48 that gets called anytime user code returns a value.
48 """
49 """
49
50
50 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
51 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
51
52
52 def __init__(self, shell=None, cache_size=1000, **kwargs):
53 def __init__(self, shell=None, cache_size=1000, **kwargs):
53 super(DisplayHook, self).__init__(shell=shell, **kwargs)
54 super(DisplayHook, self).__init__(shell=shell, **kwargs)
54
55
55 cache_size_min = 3
56 cache_size_min = 3
56 if cache_size <= 0:
57 if cache_size <= 0:
57 self.do_full_cache = 0
58 self.do_full_cache = 0
58 cache_size = 0
59 cache_size = 0
59 elif cache_size < cache_size_min:
60 elif cache_size < cache_size_min:
60 self.do_full_cache = 0
61 self.do_full_cache = 0
61 cache_size = 0
62 cache_size = 0
62 warn('caching was disabled (min value for cache size is %s).' %
63 warn('caching was disabled (min value for cache size is %s).' %
63 cache_size_min,level=3)
64 cache_size_min,level=3)
64 else:
65 else:
65 self.do_full_cache = 1
66 self.do_full_cache = 1
66
67
67 self.cache_size = cache_size
68 self.cache_size = cache_size
68
69
69 # we need a reference to the user-level namespace
70 # we need a reference to the user-level namespace
70 self.shell = shell
71 self.shell = shell
71
72
72 self._,self.__,self.___ = '','',''
73 self._,self.__,self.___ = '','',''
73
74
74 # these are deliberately global:
75 # these are deliberately global:
75 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
76 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
76 self.shell.user_ns.update(to_user_ns)
77 self.shell.user_ns.update(to_user_ns)
77
78
78 @property
79 @property
79 def prompt_count(self):
80 def prompt_count(self):
80 return self.shell.execution_count
81 return self.shell.execution_count
81
82
82 #-------------------------------------------------------------------------
83 #-------------------------------------------------------------------------
83 # Methods used in __call__. Override these methods to modify the behavior
84 # Methods used in __call__. Override these methods to modify the behavior
84 # of the displayhook.
85 # of the displayhook.
85 #-------------------------------------------------------------------------
86 #-------------------------------------------------------------------------
86
87
87 def check_for_underscore(self):
88 def check_for_underscore(self):
88 """Check if the user has set the '_' variable by hand."""
89 """Check if the user has set the '_' variable by hand."""
89 # If something injected a '_' variable in __builtin__, delete
90 # If something injected a '_' variable in __builtin__, delete
90 # ipython's automatic one so we don't clobber that. gettext() in
91 # ipython's automatic one so we don't clobber that. gettext() in
91 # particular uses _, so we need to stay away from it.
92 # particular uses _, so we need to stay away from it.
92 if '_' in builtin_mod.__dict__:
93 if '_' in builtin_mod.__dict__:
93 try:
94 try:
94 del self.shell.user_ns['_']
95 del self.shell.user_ns['_']
95 except KeyError:
96 except KeyError:
96 pass
97 pass
97
98
98 def quiet(self):
99 def quiet(self):
99 """Should we silence the display hook because of ';'?"""
100 """Should we silence the display hook because of ';'?"""
100 # do not print output if input ends in ';'
101 # do not print output if input ends in ';'
101 try:
102 try:
102 cell = self.shell.history_manager.input_hist_parsed[self.prompt_count]
103 cell = self.shell.history_manager.input_hist_parsed[self.prompt_count]
103 if cell.rstrip().endswith(';'):
104 return inputsplitter.remove_comments(cell).rstrip().endswith(';')
104 return True
105 except IndexError:
105 except IndexError:
106 # some uses of ipshellembed may fail here
106 # some uses of ipshellembed may fail here
107 pass
107 return False
108 return False
109
108
110 def start_displayhook(self):
109 def start_displayhook(self):
111 """Start the displayhook, initializing resources."""
110 """Start the displayhook, initializing resources."""
112 pass
111 pass
113
112
114 def write_output_prompt(self):
113 def write_output_prompt(self):
115 """Write the output prompt.
114 """Write the output prompt.
116
115
117 The default implementation simply writes the prompt to
116 The default implementation simply writes the prompt to
118 ``io.stdout``.
117 ``io.stdout``.
119 """
118 """
120 # Use write, not print which adds an extra space.
119 # Use write, not print which adds an extra space.
121 io.stdout.write(self.shell.separate_out)
120 io.stdout.write(self.shell.separate_out)
122 outprompt = self.shell.prompt_manager.render('out')
121 outprompt = self.shell.prompt_manager.render('out')
123 if self.do_full_cache:
122 if self.do_full_cache:
124 io.stdout.write(outprompt)
123 io.stdout.write(outprompt)
125
124
126 def compute_format_data(self, result):
125 def compute_format_data(self, result):
127 """Compute format data of the object to be displayed.
126 """Compute format data of the object to be displayed.
128
127
129 The format data is a generalization of the :func:`repr` of an object.
128 The format data is a generalization of the :func:`repr` of an object.
130 In the default implementation the format data is a :class:`dict` of
129 In the default implementation the format data is a :class:`dict` of
131 key value pair where the keys are valid MIME types and the values
130 key value pair where the keys are valid MIME types and the values
132 are JSON'able data structure containing the raw data for that MIME
131 are JSON'able data structure containing the raw data for that MIME
133 type. It is up to frontends to determine pick a MIME to to use and
132 type. It is up to frontends to determine pick a MIME to to use and
134 display that data in an appropriate manner.
133 display that data in an appropriate manner.
135
134
136 This method only computes the format data for the object and should
135 This method only computes the format data for the object and should
137 NOT actually print or write that to a stream.
136 NOT actually print or write that to a stream.
138
137
139 Parameters
138 Parameters
140 ----------
139 ----------
141 result : object
140 result : object
142 The Python object passed to the display hook, whose format will be
141 The Python object passed to the display hook, whose format will be
143 computed.
142 computed.
144
143
145 Returns
144 Returns
146 -------
145 -------
147 (format_dict, md_dict) : dict
146 (format_dict, md_dict) : dict
148 format_dict is a :class:`dict` whose keys are valid MIME types and values are
147 format_dict is a :class:`dict` whose keys are valid MIME types and values are
149 JSON'able raw data for that MIME type. It is recommended that
148 JSON'able raw data for that MIME type. It is recommended that
150 all return values of this should always include the "text/plain"
149 all return values of this should always include the "text/plain"
151 MIME type representation of the object.
150 MIME type representation of the object.
152 md_dict is a :class:`dict` with the same MIME type keys
151 md_dict is a :class:`dict` with the same MIME type keys
153 of metadata associated with each output.
152 of metadata associated with each output.
154
153
155 """
154 """
156 return self.shell.display_formatter.format(result)
155 return self.shell.display_formatter.format(result)
157
156
158 def write_format_data(self, format_dict, md_dict=None):
157 def write_format_data(self, format_dict, md_dict=None):
159 """Write the format data dict to the frontend.
158 """Write the format data dict to the frontend.
160
159
161 This default version of this method simply writes the plain text
160 This default version of this method simply writes the plain text
162 representation of the object to ``io.stdout``. Subclasses should
161 representation of the object to ``io.stdout``. Subclasses should
163 override this method to send the entire `format_dict` to the
162 override this method to send the entire `format_dict` to the
164 frontends.
163 frontends.
165
164
166 Parameters
165 Parameters
167 ----------
166 ----------
168 format_dict : dict
167 format_dict : dict
169 The format dict for the object passed to `sys.displayhook`.
168 The format dict for the object passed to `sys.displayhook`.
170 md_dict : dict (optional)
169 md_dict : dict (optional)
171 The metadata dict to be associated with the display data.
170 The metadata dict to be associated with the display data.
172 """
171 """
173 # We want to print because we want to always make sure we have a
172 # We want to print because we want to always make sure we have a
174 # newline, even if all the prompt separators are ''. This is the
173 # newline, even if all the prompt separators are ''. This is the
175 # standard IPython behavior.
174 # standard IPython behavior.
176 result_repr = format_dict['text/plain']
175 result_repr = format_dict['text/plain']
177 if '\n' in result_repr:
176 if '\n' in result_repr:
178 # So that multi-line strings line up with the left column of
177 # So that multi-line strings line up with the left column of
179 # the screen, instead of having the output prompt mess up
178 # the screen, instead of having the output prompt mess up
180 # their first line.
179 # their first line.
181 # We use the prompt template instead of the expanded prompt
180 # We use the prompt template instead of the expanded prompt
182 # because the expansion may add ANSI escapes that will interfere
181 # because the expansion may add ANSI escapes that will interfere
183 # with our ability to determine whether or not we should add
182 # with our ability to determine whether or not we should add
184 # a newline.
183 # a newline.
185 prompt_template = self.shell.prompt_manager.out_template
184 prompt_template = self.shell.prompt_manager.out_template
186 if prompt_template and not prompt_template.endswith('\n'):
185 if prompt_template and not prompt_template.endswith('\n'):
187 # But avoid extraneous empty lines.
186 # But avoid extraneous empty lines.
188 result_repr = '\n' + result_repr
187 result_repr = '\n' + result_repr
189
188
190 print(result_repr, file=io.stdout)
189 print(result_repr, file=io.stdout)
191
190
192 def update_user_ns(self, result):
191 def update_user_ns(self, result):
193 """Update user_ns with various things like _, __, _1, etc."""
192 """Update user_ns with various things like _, __, _1, etc."""
194
193
195 # Avoid recursive reference when displaying _oh/Out
194 # Avoid recursive reference when displaying _oh/Out
196 if result is not self.shell.user_ns['_oh']:
195 if result is not self.shell.user_ns['_oh']:
197 if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
196 if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
198 warn('Output cache limit (currently '+
197 warn('Output cache limit (currently '+
199 repr(self.cache_size)+' entries) hit.\n'
198 repr(self.cache_size)+' entries) hit.\n'
200 'Flushing cache and resetting history counter...\n'
199 'Flushing cache and resetting history counter...\n'
201 'The only history variables available will be _,__,___ and _1\n'
200 'The only history variables available will be _,__,___ and _1\n'
202 'with the current result.')
201 'with the current result.')
203
202
204 self.flush()
203 self.flush()
205 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
204 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
206 # we cause buggy behavior for things like gettext).
205 # we cause buggy behavior for things like gettext).
207
206
208 if '_' not in builtin_mod.__dict__:
207 if '_' not in builtin_mod.__dict__:
209 self.___ = self.__
208 self.___ = self.__
210 self.__ = self._
209 self.__ = self._
211 self._ = result
210 self._ = result
212 self.shell.push({'_':self._,
211 self.shell.push({'_':self._,
213 '__':self.__,
212 '__':self.__,
214 '___':self.___}, interactive=False)
213 '___':self.___}, interactive=False)
215
214
216 # hackish access to top-level namespace to create _1,_2... dynamically
215 # hackish access to top-level namespace to create _1,_2... dynamically
217 to_main = {}
216 to_main = {}
218 if self.do_full_cache:
217 if self.do_full_cache:
219 new_result = '_'+repr(self.prompt_count)
218 new_result = '_'+repr(self.prompt_count)
220 to_main[new_result] = result
219 to_main[new_result] = result
221 self.shell.push(to_main, interactive=False)
220 self.shell.push(to_main, interactive=False)
222 self.shell.user_ns['_oh'][self.prompt_count] = result
221 self.shell.user_ns['_oh'][self.prompt_count] = result
223
222
224 def log_output(self, format_dict):
223 def log_output(self, format_dict):
225 """Log the output."""
224 """Log the output."""
226 if self.shell.logger.log_output:
225 if self.shell.logger.log_output:
227 self.shell.logger.log_write(format_dict['text/plain'], 'output')
226 self.shell.logger.log_write(format_dict['text/plain'], 'output')
228 self.shell.history_manager.output_hist_reprs[self.prompt_count] = \
227 self.shell.history_manager.output_hist_reprs[self.prompt_count] = \
229 format_dict['text/plain']
228 format_dict['text/plain']
230
229
231 def finish_displayhook(self):
230 def finish_displayhook(self):
232 """Finish up all displayhook activities."""
231 """Finish up all displayhook activities."""
233 io.stdout.write(self.shell.separate_out2)
232 io.stdout.write(self.shell.separate_out2)
234 io.stdout.flush()
233 io.stdout.flush()
235
234
236 def __call__(self, result=None):
235 def __call__(self, result=None):
237 """Printing with history cache management.
236 """Printing with history cache management.
238
237
239 This is invoked everytime the interpreter needs to print, and is
238 This is invoked everytime the interpreter needs to print, and is
240 activated by setting the variable sys.displayhook to it.
239 activated by setting the variable sys.displayhook to it.
241 """
240 """
242 self.check_for_underscore()
241 self.check_for_underscore()
243 if result is not None and not self.quiet():
242 if result is not None and not self.quiet():
244 # If _ipython_display_ is defined, use that to display this object.
243 # If _ipython_display_ is defined, use that to display this object.
245 display_method = _safe_get_formatter_method(result, '_ipython_display_')
244 display_method = _safe_get_formatter_method(result, '_ipython_display_')
246 if display_method is not None:
245 if display_method is not None:
247 try:
246 try:
248 return display_method()
247 return display_method()
249 except NotImplementedError:
248 except NotImplementedError:
250 pass
249 pass
251
250
252 self.start_displayhook()
251 self.start_displayhook()
253 self.write_output_prompt()
252 self.write_output_prompt()
254 format_dict, md_dict = self.compute_format_data(result)
253 format_dict, md_dict = self.compute_format_data(result)
255 self.write_format_data(format_dict, md_dict)
254 self.write_format_data(format_dict, md_dict)
256 self.update_user_ns(result)
255 self.update_user_ns(result)
257 self.log_output(format_dict)
256 self.log_output(format_dict)
258 self.finish_displayhook()
257 self.finish_displayhook()
259
258
260 def flush(self):
259 def flush(self):
261 if not self.do_full_cache:
260 if not self.do_full_cache:
262 raise ValueError("You shouldn't have reached the cache flush "
261 raise ValueError("You shouldn't have reached the cache flush "
263 "if full caching is not enabled!")
262 "if full caching is not enabled!")
264 # delete auto-generated vars from global namespace
263 # delete auto-generated vars from global namespace
265
264
266 for n in range(1,self.prompt_count + 1):
265 for n in range(1,self.prompt_count + 1):
267 key = '_'+repr(n)
266 key = '_'+repr(n)
268 try:
267 try:
269 del self.shell.user_ns[key]
268 del self.shell.user_ns[key]
270 except: pass
269 except: pass
271 # In some embedded circumstances, the user_ns doesn't have the
270 # In some embedded circumstances, the user_ns doesn't have the
272 # '_oh' key set up.
271 # '_oh' key set up.
273 oh = self.shell.user_ns.get('_oh', None)
272 oh = self.shell.user_ns.get('_oh', None)
274 if oh is not None:
273 if oh is not None:
275 oh.clear()
274 oh.clear()
276
275
277 # Release our own references to objects:
276 # Release our own references to objects:
278 self._, self.__, self.___ = '', '', ''
277 self._, self.__, self.___ = '', '', ''
279
278
280 if '_' not in builtin_mod.__dict__:
279 if '_' not in builtin_mod.__dict__:
281 self.shell.user_ns.update({'_':None,'__':None, '___':None})
280 self.shell.user_ns.update({'_':None,'__':None, '___':None})
282 import gc
281 import gc
283 # TODO: Is this really needed?
282 # TODO: Is this really needed?
284 # IronPython blocks here forever
283 # IronPython blocks here forever
285 if sys.platform != "cli":
284 if sys.platform != "cli":
286 gc.collect()
285 gc.collect()
287
286
@@ -1,730 +1,734 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for the key interactiveshell module.
2 """Tests for the key interactiveshell module.
3
3
4 Historically the main classes in interactiveshell have been under-tested. This
4 Historically the main classes in interactiveshell have been under-tested. This
5 module should grow as many single-method tests as possible to trap many of the
5 module should grow as many single-method tests as possible to trap many of the
6 recurring bugs we seem to encounter with high-level interaction.
6 recurring bugs we seem to encounter with high-level interaction.
7
7
8 Authors
8 Authors
9 -------
9 -------
10 * Fernando Perez
10 * Fernando Perez
11 """
11 """
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Copyright (C) 2011 The IPython Development Team
13 # Copyright (C) 2011 The IPython Development Team
14 #
14 #
15 # Distributed under the terms of the BSD License. The full license is in
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
16 # the file COPYING, distributed as part of this software.
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Imports
20 # Imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # stdlib
22 # stdlib
23 import ast
23 import ast
24 import os
24 import os
25 import signal
25 import signal
26 import shutil
26 import shutil
27 import sys
27 import sys
28 import tempfile
28 import tempfile
29 import unittest
29 import unittest
30 try:
30 try:
31 from unittest import mock
31 from unittest import mock
32 except ImportError:
32 except ImportError:
33 import mock
33 import mock
34 from os.path import join
34 from os.path import join
35
35
36 # third-party
36 # third-party
37 import nose.tools as nt
37 import nose.tools as nt
38
38
39 # Our own
39 # Our own
40 from IPython.core.inputtransformer import InputTransformer
40 from IPython.core.inputtransformer import InputTransformer
41 from IPython.testing.decorators import skipif, skip_win32, onlyif_unicode_paths
41 from IPython.testing.decorators import skipif, skip_win32, onlyif_unicode_paths
42 from IPython.testing import tools as tt
42 from IPython.testing import tools as tt
43 from IPython.utils import io
43 from IPython.utils import io
44 from IPython.utils import py3compat
44 from IPython.utils import py3compat
45 from IPython.utils.py3compat import unicode_type, PY3
45 from IPython.utils.py3compat import unicode_type, PY3
46
46
47 if PY3:
47 if PY3:
48 from io import StringIO
48 from io import StringIO
49 else:
49 else:
50 from StringIO import StringIO
50 from StringIO import StringIO
51
51
52 #-----------------------------------------------------------------------------
52 #-----------------------------------------------------------------------------
53 # Globals
53 # Globals
54 #-----------------------------------------------------------------------------
54 #-----------------------------------------------------------------------------
55 # This is used by every single test, no point repeating it ad nauseam
55 # This is used by every single test, no point repeating it ad nauseam
56 ip = get_ipython()
56 ip = get_ipython()
57
57
58 #-----------------------------------------------------------------------------
58 #-----------------------------------------------------------------------------
59 # Tests
59 # Tests
60 #-----------------------------------------------------------------------------
60 #-----------------------------------------------------------------------------
61
61
62 class InteractiveShellTestCase(unittest.TestCase):
62 class InteractiveShellTestCase(unittest.TestCase):
63 def test_naked_string_cells(self):
63 def test_naked_string_cells(self):
64 """Test that cells with only naked strings are fully executed"""
64 """Test that cells with only naked strings are fully executed"""
65 # First, single-line inputs
65 # First, single-line inputs
66 ip.run_cell('"a"\n')
66 ip.run_cell('"a"\n')
67 self.assertEqual(ip.user_ns['_'], 'a')
67 self.assertEqual(ip.user_ns['_'], 'a')
68 # And also multi-line cells
68 # And also multi-line cells
69 ip.run_cell('"""a\nb"""\n')
69 ip.run_cell('"""a\nb"""\n')
70 self.assertEqual(ip.user_ns['_'], 'a\nb')
70 self.assertEqual(ip.user_ns['_'], 'a\nb')
71
71
72 def test_run_empty_cell(self):
72 def test_run_empty_cell(self):
73 """Just make sure we don't get a horrible error with a blank
73 """Just make sure we don't get a horrible error with a blank
74 cell of input. Yes, I did overlook that."""
74 cell of input. Yes, I did overlook that."""
75 old_xc = ip.execution_count
75 old_xc = ip.execution_count
76 ip.run_cell('')
76 ip.run_cell('')
77 self.assertEqual(ip.execution_count, old_xc)
77 self.assertEqual(ip.execution_count, old_xc)
78
78
79 def test_run_cell_multiline(self):
79 def test_run_cell_multiline(self):
80 """Multi-block, multi-line cells must execute correctly.
80 """Multi-block, multi-line cells must execute correctly.
81 """
81 """
82 src = '\n'.join(["x=1",
82 src = '\n'.join(["x=1",
83 "y=2",
83 "y=2",
84 "if 1:",
84 "if 1:",
85 " x += 1",
85 " x += 1",
86 " y += 1",])
86 " y += 1",])
87 ip.run_cell(src)
87 ip.run_cell(src)
88 self.assertEqual(ip.user_ns['x'], 2)
88 self.assertEqual(ip.user_ns['x'], 2)
89 self.assertEqual(ip.user_ns['y'], 3)
89 self.assertEqual(ip.user_ns['y'], 3)
90
90
91 def test_multiline_string_cells(self):
91 def test_multiline_string_cells(self):
92 "Code sprinkled with multiline strings should execute (GH-306)"
92 "Code sprinkled with multiline strings should execute (GH-306)"
93 ip.run_cell('tmp=0')
93 ip.run_cell('tmp=0')
94 self.assertEqual(ip.user_ns['tmp'], 0)
94 self.assertEqual(ip.user_ns['tmp'], 0)
95 ip.run_cell('tmp=1;"""a\nb"""\n')
95 ip.run_cell('tmp=1;"""a\nb"""\n')
96 self.assertEqual(ip.user_ns['tmp'], 1)
96 self.assertEqual(ip.user_ns['tmp'], 1)
97
97
98 def test_dont_cache_with_semicolon(self):
98 def test_dont_cache_with_semicolon(self):
99 "Ending a line with semicolon should not cache the returned object (GH-307)"
99 "Ending a line with semicolon should not cache the returned object (GH-307)"
100 oldlen = len(ip.user_ns['Out'])
100 oldlen = len(ip.user_ns['Out'])
101 a = ip.run_cell('1;', store_history=True)
101 for cell in ['1;', '1; #a', '1;1;']:
102 newlen = len(ip.user_ns['Out'])
102 ip.run_cell(cell, store_history=True)
103 self.assertEqual(oldlen, newlen)
103 newlen = len(ip.user_ns['Out'])
104 self.assertEqual(oldlen, newlen)
105 i = 0
104 #also test the default caching behavior
106 #also test the default caching behavior
105 ip.run_cell('1', store_history=True)
107 for cell in ['1', '1 #;', '1;1']:
106 newlen = len(ip.user_ns['Out'])
108 ip.run_cell(cell, store_history=True)
107 self.assertEqual(oldlen+1, newlen)
109 newlen = len(ip.user_ns['Out'])
110 i += 1
111 self.assertEqual(oldlen+i, newlen)
108
112
109 def test_In_variable(self):
113 def test_In_variable(self):
110 "Verify that In variable grows with user input (GH-284)"
114 "Verify that In variable grows with user input (GH-284)"
111 oldlen = len(ip.user_ns['In'])
115 oldlen = len(ip.user_ns['In'])
112 ip.run_cell('1;', store_history=True)
116 ip.run_cell('1;', store_history=True)
113 newlen = len(ip.user_ns['In'])
117 newlen = len(ip.user_ns['In'])
114 self.assertEqual(oldlen+1, newlen)
118 self.assertEqual(oldlen+1, newlen)
115 self.assertEqual(ip.user_ns['In'][-1],'1;')
119 self.assertEqual(ip.user_ns['In'][-1],'1;')
116
120
117 def test_magic_names_in_string(self):
121 def test_magic_names_in_string(self):
118 ip.run_cell('a = """\n%exit\n"""')
122 ip.run_cell('a = """\n%exit\n"""')
119 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
123 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
120
124
121 def test_trailing_newline(self):
125 def test_trailing_newline(self):
122 """test that running !(command) does not raise a SyntaxError"""
126 """test that running !(command) does not raise a SyntaxError"""
123 ip.run_cell('!(true)\n', False)
127 ip.run_cell('!(true)\n', False)
124 ip.run_cell('!(true)\n\n\n', False)
128 ip.run_cell('!(true)\n\n\n', False)
125
129
126 def test_gh_597(self):
130 def test_gh_597(self):
127 """Pretty-printing lists of objects with non-ascii reprs may cause
131 """Pretty-printing lists of objects with non-ascii reprs may cause
128 problems."""
132 problems."""
129 class Spam(object):
133 class Spam(object):
130 def __repr__(self):
134 def __repr__(self):
131 return "\xe9"*50
135 return "\xe9"*50
132 import IPython.core.formatters
136 import IPython.core.formatters
133 f = IPython.core.formatters.PlainTextFormatter()
137 f = IPython.core.formatters.PlainTextFormatter()
134 f([Spam(),Spam()])
138 f([Spam(),Spam()])
135
139
136
140
137 def test_future_flags(self):
141 def test_future_flags(self):
138 """Check that future flags are used for parsing code (gh-777)"""
142 """Check that future flags are used for parsing code (gh-777)"""
139 ip.run_cell('from __future__ import print_function')
143 ip.run_cell('from __future__ import print_function')
140 try:
144 try:
141 ip.run_cell('prfunc_return_val = print(1,2, sep=" ")')
145 ip.run_cell('prfunc_return_val = print(1,2, sep=" ")')
142 assert 'prfunc_return_val' in ip.user_ns
146 assert 'prfunc_return_val' in ip.user_ns
143 finally:
147 finally:
144 # Reset compiler flags so we don't mess up other tests.
148 # Reset compiler flags so we don't mess up other tests.
145 ip.compile.reset_compiler_flags()
149 ip.compile.reset_compiler_flags()
146
150
147 def test_future_unicode(self):
151 def test_future_unicode(self):
148 """Check that unicode_literals is imported from __future__ (gh #786)"""
152 """Check that unicode_literals is imported from __future__ (gh #786)"""
149 try:
153 try:
150 ip.run_cell(u'byte_str = "a"')
154 ip.run_cell(u'byte_str = "a"')
151 assert isinstance(ip.user_ns['byte_str'], str) # string literals are byte strings by default
155 assert isinstance(ip.user_ns['byte_str'], str) # string literals are byte strings by default
152 ip.run_cell('from __future__ import unicode_literals')
156 ip.run_cell('from __future__ import unicode_literals')
153 ip.run_cell(u'unicode_str = "a"')
157 ip.run_cell(u'unicode_str = "a"')
154 assert isinstance(ip.user_ns['unicode_str'], unicode_type) # strings literals are now unicode
158 assert isinstance(ip.user_ns['unicode_str'], unicode_type) # strings literals are now unicode
155 finally:
159 finally:
156 # Reset compiler flags so we don't mess up other tests.
160 # Reset compiler flags so we don't mess up other tests.
157 ip.compile.reset_compiler_flags()
161 ip.compile.reset_compiler_flags()
158
162
159 def test_can_pickle(self):
163 def test_can_pickle(self):
160 "Can we pickle objects defined interactively (GH-29)"
164 "Can we pickle objects defined interactively (GH-29)"
161 ip = get_ipython()
165 ip = get_ipython()
162 ip.reset()
166 ip.reset()
163 ip.run_cell(("class Mylist(list):\n"
167 ip.run_cell(("class Mylist(list):\n"
164 " def __init__(self,x=[]):\n"
168 " def __init__(self,x=[]):\n"
165 " list.__init__(self,x)"))
169 " list.__init__(self,x)"))
166 ip.run_cell("w=Mylist([1,2,3])")
170 ip.run_cell("w=Mylist([1,2,3])")
167
171
168 from pickle import dumps
172 from pickle import dumps
169
173
170 # We need to swap in our main module - this is only necessary
174 # We need to swap in our main module - this is only necessary
171 # inside the test framework, because IPython puts the interactive module
175 # inside the test framework, because IPython puts the interactive module
172 # in place (but the test framework undoes this).
176 # in place (but the test framework undoes this).
173 _main = sys.modules['__main__']
177 _main = sys.modules['__main__']
174 sys.modules['__main__'] = ip.user_module
178 sys.modules['__main__'] = ip.user_module
175 try:
179 try:
176 res = dumps(ip.user_ns["w"])
180 res = dumps(ip.user_ns["w"])
177 finally:
181 finally:
178 sys.modules['__main__'] = _main
182 sys.modules['__main__'] = _main
179 self.assertTrue(isinstance(res, bytes))
183 self.assertTrue(isinstance(res, bytes))
180
184
181 def test_global_ns(self):
185 def test_global_ns(self):
182 "Code in functions must be able to access variables outside them."
186 "Code in functions must be able to access variables outside them."
183 ip = get_ipython()
187 ip = get_ipython()
184 ip.run_cell("a = 10")
188 ip.run_cell("a = 10")
185 ip.run_cell(("def f(x):\n"
189 ip.run_cell(("def f(x):\n"
186 " return x + a"))
190 " return x + a"))
187 ip.run_cell("b = f(12)")
191 ip.run_cell("b = f(12)")
188 self.assertEqual(ip.user_ns["b"], 22)
192 self.assertEqual(ip.user_ns["b"], 22)
189
193
190 def test_bad_custom_tb(self):
194 def test_bad_custom_tb(self):
191 """Check that InteractiveShell is protected from bad custom exception handlers"""
195 """Check that InteractiveShell is protected from bad custom exception handlers"""
192 from IPython.utils import io
196 from IPython.utils import io
193 save_stderr = io.stderr
197 save_stderr = io.stderr
194 try:
198 try:
195 # capture stderr
199 # capture stderr
196 io.stderr = StringIO()
200 io.stderr = StringIO()
197 ip.set_custom_exc((IOError,), lambda etype,value,tb: 1/0)
201 ip.set_custom_exc((IOError,), lambda etype,value,tb: 1/0)
198 self.assertEqual(ip.custom_exceptions, (IOError,))
202 self.assertEqual(ip.custom_exceptions, (IOError,))
199 ip.run_cell(u'raise IOError("foo")')
203 ip.run_cell(u'raise IOError("foo")')
200 self.assertEqual(ip.custom_exceptions, ())
204 self.assertEqual(ip.custom_exceptions, ())
201 self.assertTrue("Custom TB Handler failed" in io.stderr.getvalue())
205 self.assertTrue("Custom TB Handler failed" in io.stderr.getvalue())
202 finally:
206 finally:
203 io.stderr = save_stderr
207 io.stderr = save_stderr
204
208
205 def test_bad_custom_tb_return(self):
209 def test_bad_custom_tb_return(self):
206 """Check that InteractiveShell is protected from bad return types in custom exception handlers"""
210 """Check that InteractiveShell is protected from bad return types in custom exception handlers"""
207 from IPython.utils import io
211 from IPython.utils import io
208 save_stderr = io.stderr
212 save_stderr = io.stderr
209 try:
213 try:
210 # capture stderr
214 # capture stderr
211 io.stderr = StringIO()
215 io.stderr = StringIO()
212 ip.set_custom_exc((NameError,),lambda etype,value,tb, tb_offset=None: 1)
216 ip.set_custom_exc((NameError,),lambda etype,value,tb, tb_offset=None: 1)
213 self.assertEqual(ip.custom_exceptions, (NameError,))
217 self.assertEqual(ip.custom_exceptions, (NameError,))
214 ip.run_cell(u'a=abracadabra')
218 ip.run_cell(u'a=abracadabra')
215 self.assertEqual(ip.custom_exceptions, ())
219 self.assertEqual(ip.custom_exceptions, ())
216 self.assertTrue("Custom TB Handler failed" in io.stderr.getvalue())
220 self.assertTrue("Custom TB Handler failed" in io.stderr.getvalue())
217 finally:
221 finally:
218 io.stderr = save_stderr
222 io.stderr = save_stderr
219
223
220 def test_drop_by_id(self):
224 def test_drop_by_id(self):
221 myvars = {"a":object(), "b":object(), "c": object()}
225 myvars = {"a":object(), "b":object(), "c": object()}
222 ip.push(myvars, interactive=False)
226 ip.push(myvars, interactive=False)
223 for name in myvars:
227 for name in myvars:
224 assert name in ip.user_ns, name
228 assert name in ip.user_ns, name
225 assert name in ip.user_ns_hidden, name
229 assert name in ip.user_ns_hidden, name
226 ip.user_ns['b'] = 12
230 ip.user_ns['b'] = 12
227 ip.drop_by_id(myvars)
231 ip.drop_by_id(myvars)
228 for name in ["a", "c"]:
232 for name in ["a", "c"]:
229 assert name not in ip.user_ns, name
233 assert name not in ip.user_ns, name
230 assert name not in ip.user_ns_hidden, name
234 assert name not in ip.user_ns_hidden, name
231 assert ip.user_ns['b'] == 12
235 assert ip.user_ns['b'] == 12
232 ip.reset()
236 ip.reset()
233
237
234 def test_var_expand(self):
238 def test_var_expand(self):
235 ip.user_ns['f'] = u'Ca\xf1o'
239 ip.user_ns['f'] = u'Ca\xf1o'
236 self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
240 self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
237 self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o')
241 self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o')
238 self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1')
242 self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1')
239 self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2')
243 self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2')
240
244
241 ip.user_ns['f'] = b'Ca\xc3\xb1o'
245 ip.user_ns['f'] = b'Ca\xc3\xb1o'
242 # This should not raise any exception:
246 # This should not raise any exception:
243 ip.var_expand(u'echo $f')
247 ip.var_expand(u'echo $f')
244
248
245 def test_var_expand_local(self):
249 def test_var_expand_local(self):
246 """Test local variable expansion in !system and %magic calls"""
250 """Test local variable expansion in !system and %magic calls"""
247 # !system
251 # !system
248 ip.run_cell('def test():\n'
252 ip.run_cell('def test():\n'
249 ' lvar = "ttt"\n'
253 ' lvar = "ttt"\n'
250 ' ret = !echo {lvar}\n'
254 ' ret = !echo {lvar}\n'
251 ' return ret[0]\n')
255 ' return ret[0]\n')
252 res = ip.user_ns['test']()
256 res = ip.user_ns['test']()
253 nt.assert_in('ttt', res)
257 nt.assert_in('ttt', res)
254
258
255 # %magic
259 # %magic
256 ip.run_cell('def makemacro():\n'
260 ip.run_cell('def makemacro():\n'
257 ' macroname = "macro_var_expand_locals"\n'
261 ' macroname = "macro_var_expand_locals"\n'
258 ' %macro {macroname} codestr\n')
262 ' %macro {macroname} codestr\n')
259 ip.user_ns['codestr'] = "str(12)"
263 ip.user_ns['codestr'] = "str(12)"
260 ip.run_cell('makemacro()')
264 ip.run_cell('makemacro()')
261 nt.assert_in('macro_var_expand_locals', ip.user_ns)
265 nt.assert_in('macro_var_expand_locals', ip.user_ns)
262
266
263 def test_var_expand_self(self):
267 def test_var_expand_self(self):
264 """Test variable expansion with the name 'self', which was failing.
268 """Test variable expansion with the name 'self', which was failing.
265
269
266 See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
270 See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
267 """
271 """
268 ip.run_cell('class cTest:\n'
272 ip.run_cell('class cTest:\n'
269 ' classvar="see me"\n'
273 ' classvar="see me"\n'
270 ' def test(self):\n'
274 ' def test(self):\n'
271 ' res = !echo Variable: {self.classvar}\n'
275 ' res = !echo Variable: {self.classvar}\n'
272 ' return res[0]\n')
276 ' return res[0]\n')
273 nt.assert_in('see me', ip.user_ns['cTest']().test())
277 nt.assert_in('see me', ip.user_ns['cTest']().test())
274
278
275 def test_bad_var_expand(self):
279 def test_bad_var_expand(self):
276 """var_expand on invalid formats shouldn't raise"""
280 """var_expand on invalid formats shouldn't raise"""
277 # SyntaxError
281 # SyntaxError
278 self.assertEqual(ip.var_expand(u"{'a':5}"), u"{'a':5}")
282 self.assertEqual(ip.var_expand(u"{'a':5}"), u"{'a':5}")
279 # NameError
283 # NameError
280 self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
284 self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
281 # ZeroDivisionError
285 # ZeroDivisionError
282 self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
286 self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
283
287
284 def test_silent_postexec(self):
288 def test_silent_postexec(self):
285 """run_cell(silent=True) doesn't invoke pre/post_run_cell callbacks"""
289 """run_cell(silent=True) doesn't invoke pre/post_run_cell callbacks"""
286 pre_explicit = mock.Mock()
290 pre_explicit = mock.Mock()
287 pre_always = mock.Mock()
291 pre_always = mock.Mock()
288 post_explicit = mock.Mock()
292 post_explicit = mock.Mock()
289 post_always = mock.Mock()
293 post_always = mock.Mock()
290
294
291 ip.events.register('pre_run_cell', pre_explicit)
295 ip.events.register('pre_run_cell', pre_explicit)
292 ip.events.register('pre_execute', pre_always)
296 ip.events.register('pre_execute', pre_always)
293 ip.events.register('post_run_cell', post_explicit)
297 ip.events.register('post_run_cell', post_explicit)
294 ip.events.register('post_execute', post_always)
298 ip.events.register('post_execute', post_always)
295
299
296 try:
300 try:
297 ip.run_cell("1", silent=True)
301 ip.run_cell("1", silent=True)
298 assert pre_always.called
302 assert pre_always.called
299 assert not pre_explicit.called
303 assert not pre_explicit.called
300 assert post_always.called
304 assert post_always.called
301 assert not post_explicit.called
305 assert not post_explicit.called
302 # double-check that non-silent exec did what we expected
306 # double-check that non-silent exec did what we expected
303 # silent to avoid
307 # silent to avoid
304 ip.run_cell("1")
308 ip.run_cell("1")
305 assert pre_explicit.called
309 assert pre_explicit.called
306 assert post_explicit.called
310 assert post_explicit.called
307 finally:
311 finally:
308 # remove post-exec
312 # remove post-exec
309 ip.events.reset_all()
313 ip.events.reset_all()
310
314
311 def test_silent_noadvance(self):
315 def test_silent_noadvance(self):
312 """run_cell(silent=True) doesn't advance execution_count"""
316 """run_cell(silent=True) doesn't advance execution_count"""
313 ec = ip.execution_count
317 ec = ip.execution_count
314 # silent should force store_history=False
318 # silent should force store_history=False
315 ip.run_cell("1", store_history=True, silent=True)
319 ip.run_cell("1", store_history=True, silent=True)
316
320
317 self.assertEqual(ec, ip.execution_count)
321 self.assertEqual(ec, ip.execution_count)
318 # double-check that non-silent exec did what we expected
322 # double-check that non-silent exec did what we expected
319 # silent to avoid
323 # silent to avoid
320 ip.run_cell("1", store_history=True)
324 ip.run_cell("1", store_history=True)
321 self.assertEqual(ec+1, ip.execution_count)
325 self.assertEqual(ec+1, ip.execution_count)
322
326
323 def test_silent_nodisplayhook(self):
327 def test_silent_nodisplayhook(self):
324 """run_cell(silent=True) doesn't trigger displayhook"""
328 """run_cell(silent=True) doesn't trigger displayhook"""
325 d = dict(called=False)
329 d = dict(called=False)
326
330
327 trap = ip.display_trap
331 trap = ip.display_trap
328 save_hook = trap.hook
332 save_hook = trap.hook
329
333
330 def failing_hook(*args, **kwargs):
334 def failing_hook(*args, **kwargs):
331 d['called'] = True
335 d['called'] = True
332
336
333 try:
337 try:
334 trap.hook = failing_hook
338 trap.hook = failing_hook
335 ip.run_cell("1", silent=True)
339 ip.run_cell("1", silent=True)
336 self.assertFalse(d['called'])
340 self.assertFalse(d['called'])
337 # double-check that non-silent exec did what we expected
341 # double-check that non-silent exec did what we expected
338 # silent to avoid
342 # silent to avoid
339 ip.run_cell("1")
343 ip.run_cell("1")
340 self.assertTrue(d['called'])
344 self.assertTrue(d['called'])
341 finally:
345 finally:
342 trap.hook = save_hook
346 trap.hook = save_hook
343
347
344 @skipif(sys.version_info[0] >= 3, "softspace removed in py3")
348 @skipif(sys.version_info[0] >= 3, "softspace removed in py3")
345 def test_print_softspace(self):
349 def test_print_softspace(self):
346 """Verify that softspace is handled correctly when executing multiple
350 """Verify that softspace is handled correctly when executing multiple
347 statements.
351 statements.
348
352
349 In [1]: print 1; print 2
353 In [1]: print 1; print 2
350 1
354 1
351 2
355 2
352
356
353 In [2]: print 1,; print 2
357 In [2]: print 1,; print 2
354 1 2
358 1 2
355 """
359 """
356
360
357 def test_ofind_line_magic(self):
361 def test_ofind_line_magic(self):
358 from IPython.core.magic import register_line_magic
362 from IPython.core.magic import register_line_magic
359
363
360 @register_line_magic
364 @register_line_magic
361 def lmagic(line):
365 def lmagic(line):
362 "A line magic"
366 "A line magic"
363
367
364 # Get info on line magic
368 # Get info on line magic
365 lfind = ip._ofind('lmagic')
369 lfind = ip._ofind('lmagic')
366 info = dict(found=True, isalias=False, ismagic=True,
370 info = dict(found=True, isalias=False, ismagic=True,
367 namespace = 'IPython internal', obj= lmagic.__wrapped__,
371 namespace = 'IPython internal', obj= lmagic.__wrapped__,
368 parent = None)
372 parent = None)
369 nt.assert_equal(lfind, info)
373 nt.assert_equal(lfind, info)
370
374
371 def test_ofind_cell_magic(self):
375 def test_ofind_cell_magic(self):
372 from IPython.core.magic import register_cell_magic
376 from IPython.core.magic import register_cell_magic
373
377
374 @register_cell_magic
378 @register_cell_magic
375 def cmagic(line, cell):
379 def cmagic(line, cell):
376 "A cell magic"
380 "A cell magic"
377
381
378 # Get info on cell magic
382 # Get info on cell magic
379 find = ip._ofind('cmagic')
383 find = ip._ofind('cmagic')
380 info = dict(found=True, isalias=False, ismagic=True,
384 info = dict(found=True, isalias=False, ismagic=True,
381 namespace = 'IPython internal', obj= cmagic.__wrapped__,
385 namespace = 'IPython internal', obj= cmagic.__wrapped__,
382 parent = None)
386 parent = None)
383 nt.assert_equal(find, info)
387 nt.assert_equal(find, info)
384
388
385 def test_custom_exception(self):
389 def test_custom_exception(self):
386 called = []
390 called = []
387 def my_handler(shell, etype, value, tb, tb_offset=None):
391 def my_handler(shell, etype, value, tb, tb_offset=None):
388 called.append(etype)
392 called.append(etype)
389 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
393 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
390
394
391 ip.set_custom_exc((ValueError,), my_handler)
395 ip.set_custom_exc((ValueError,), my_handler)
392 try:
396 try:
393 ip.run_cell("raise ValueError('test')")
397 ip.run_cell("raise ValueError('test')")
394 # Check that this was called, and only once.
398 # Check that this was called, and only once.
395 self.assertEqual(called, [ValueError])
399 self.assertEqual(called, [ValueError])
396 finally:
400 finally:
397 # Reset the custom exception hook
401 # Reset the custom exception hook
398 ip.set_custom_exc((), None)
402 ip.set_custom_exc((), None)
399
403
400 @skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
404 @skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
401 def test_future_environment(self):
405 def test_future_environment(self):
402 "Can we run code with & without the shell's __future__ imports?"
406 "Can we run code with & without the shell's __future__ imports?"
403 ip.run_cell("from __future__ import division")
407 ip.run_cell("from __future__ import division")
404 ip.run_cell("a = 1/2", shell_futures=True)
408 ip.run_cell("a = 1/2", shell_futures=True)
405 self.assertEqual(ip.user_ns['a'], 0.5)
409 self.assertEqual(ip.user_ns['a'], 0.5)
406 ip.run_cell("b = 1/2", shell_futures=False)
410 ip.run_cell("b = 1/2", shell_futures=False)
407 self.assertEqual(ip.user_ns['b'], 0)
411 self.assertEqual(ip.user_ns['b'], 0)
408
412
409 ip.compile.reset_compiler_flags()
413 ip.compile.reset_compiler_flags()
410 # This shouldn't leak to the shell's compiler
414 # This shouldn't leak to the shell's compiler
411 ip.run_cell("from __future__ import division \nc=1/2", shell_futures=False)
415 ip.run_cell("from __future__ import division \nc=1/2", shell_futures=False)
412 self.assertEqual(ip.user_ns['c'], 0.5)
416 self.assertEqual(ip.user_ns['c'], 0.5)
413 ip.run_cell("d = 1/2", shell_futures=True)
417 ip.run_cell("d = 1/2", shell_futures=True)
414 self.assertEqual(ip.user_ns['d'], 0)
418 self.assertEqual(ip.user_ns['d'], 0)
415
419
416
420
417 class TestSafeExecfileNonAsciiPath(unittest.TestCase):
421 class TestSafeExecfileNonAsciiPath(unittest.TestCase):
418
422
419 @onlyif_unicode_paths
423 @onlyif_unicode_paths
420 def setUp(self):
424 def setUp(self):
421 self.BASETESTDIR = tempfile.mkdtemp()
425 self.BASETESTDIR = tempfile.mkdtemp()
422 self.TESTDIR = join(self.BASETESTDIR, u"Γ₯Àâ")
426 self.TESTDIR = join(self.BASETESTDIR, u"Γ₯Àâ")
423 os.mkdir(self.TESTDIR)
427 os.mkdir(self.TESTDIR)
424 with open(join(self.TESTDIR, u"Γ₯Àâtestscript.py"), "w") as sfile:
428 with open(join(self.TESTDIR, u"Γ₯Àâtestscript.py"), "w") as sfile:
425 sfile.write("pass\n")
429 sfile.write("pass\n")
426 self.oldpath = py3compat.getcwd()
430 self.oldpath = py3compat.getcwd()
427 os.chdir(self.TESTDIR)
431 os.chdir(self.TESTDIR)
428 self.fname = u"Γ₯Àâtestscript.py"
432 self.fname = u"Γ₯Àâtestscript.py"
429
433
430 def tearDown(self):
434 def tearDown(self):
431 os.chdir(self.oldpath)
435 os.chdir(self.oldpath)
432 shutil.rmtree(self.BASETESTDIR)
436 shutil.rmtree(self.BASETESTDIR)
433
437
434 @onlyif_unicode_paths
438 @onlyif_unicode_paths
435 def test_1(self):
439 def test_1(self):
436 """Test safe_execfile with non-ascii path
440 """Test safe_execfile with non-ascii path
437 """
441 """
438 ip.safe_execfile(self.fname, {}, raise_exceptions=True)
442 ip.safe_execfile(self.fname, {}, raise_exceptions=True)
439
443
440 class ExitCodeChecks(tt.TempFileMixin):
444 class ExitCodeChecks(tt.TempFileMixin):
441 def test_exit_code_ok(self):
445 def test_exit_code_ok(self):
442 self.system('exit 0')
446 self.system('exit 0')
443 self.assertEqual(ip.user_ns['_exit_code'], 0)
447 self.assertEqual(ip.user_ns['_exit_code'], 0)
444
448
445 def test_exit_code_error(self):
449 def test_exit_code_error(self):
446 self.system('exit 1')
450 self.system('exit 1')
447 self.assertEqual(ip.user_ns['_exit_code'], 1)
451 self.assertEqual(ip.user_ns['_exit_code'], 1)
448
452
449 @skipif(not hasattr(signal, 'SIGALRM'))
453 @skipif(not hasattr(signal, 'SIGALRM'))
450 def test_exit_code_signal(self):
454 def test_exit_code_signal(self):
451 self.mktmp("import signal, time\n"
455 self.mktmp("import signal, time\n"
452 "signal.setitimer(signal.ITIMER_REAL, 0.1)\n"
456 "signal.setitimer(signal.ITIMER_REAL, 0.1)\n"
453 "time.sleep(1)\n")
457 "time.sleep(1)\n")
454 self.system("%s %s" % (sys.executable, self.fname))
458 self.system("%s %s" % (sys.executable, self.fname))
455 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM)
459 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM)
456
460
457 class TestSystemRaw(unittest.TestCase, ExitCodeChecks):
461 class TestSystemRaw(unittest.TestCase, ExitCodeChecks):
458 system = ip.system_raw
462 system = ip.system_raw
459
463
460 @onlyif_unicode_paths
464 @onlyif_unicode_paths
461 def test_1(self):
465 def test_1(self):
462 """Test system_raw with non-ascii cmd
466 """Test system_raw with non-ascii cmd
463 """
467 """
464 cmd = u'''python -c "'Γ₯Àâ'" '''
468 cmd = u'''python -c "'Γ₯Àâ'" '''
465 ip.system_raw(cmd)
469 ip.system_raw(cmd)
466
470
467 # TODO: Exit codes are currently ignored on Windows.
471 # TODO: Exit codes are currently ignored on Windows.
468 class TestSystemPipedExitCode(unittest.TestCase, ExitCodeChecks):
472 class TestSystemPipedExitCode(unittest.TestCase, ExitCodeChecks):
469 system = ip.system_piped
473 system = ip.system_piped
470
474
471 @skip_win32
475 @skip_win32
472 def test_exit_code_ok(self):
476 def test_exit_code_ok(self):
473 ExitCodeChecks.test_exit_code_ok(self)
477 ExitCodeChecks.test_exit_code_ok(self)
474
478
475 @skip_win32
479 @skip_win32
476 def test_exit_code_error(self):
480 def test_exit_code_error(self):
477 ExitCodeChecks.test_exit_code_error(self)
481 ExitCodeChecks.test_exit_code_error(self)
478
482
479 @skip_win32
483 @skip_win32
480 def test_exit_code_signal(self):
484 def test_exit_code_signal(self):
481 ExitCodeChecks.test_exit_code_signal(self)
485 ExitCodeChecks.test_exit_code_signal(self)
482
486
483 class TestModules(unittest.TestCase, tt.TempFileMixin):
487 class TestModules(unittest.TestCase, tt.TempFileMixin):
484 def test_extraneous_loads(self):
488 def test_extraneous_loads(self):
485 """Test we're not loading modules on startup that we shouldn't.
489 """Test we're not loading modules on startup that we shouldn't.
486 """
490 """
487 self.mktmp("import sys\n"
491 self.mktmp("import sys\n"
488 "print('numpy' in sys.modules)\n"
492 "print('numpy' in sys.modules)\n"
489 "print('IPython.parallel' in sys.modules)\n"
493 "print('IPython.parallel' in sys.modules)\n"
490 "print('IPython.kernel.zmq' in sys.modules)\n"
494 "print('IPython.kernel.zmq' in sys.modules)\n"
491 )
495 )
492 out = "False\nFalse\nFalse\n"
496 out = "False\nFalse\nFalse\n"
493 tt.ipexec_validate(self.fname, out)
497 tt.ipexec_validate(self.fname, out)
494
498
495 class Negator(ast.NodeTransformer):
499 class Negator(ast.NodeTransformer):
496 """Negates all number literals in an AST."""
500 """Negates all number literals in an AST."""
497 def visit_Num(self, node):
501 def visit_Num(self, node):
498 node.n = -node.n
502 node.n = -node.n
499 return node
503 return node
500
504
501 class TestAstTransform(unittest.TestCase):
505 class TestAstTransform(unittest.TestCase):
502 def setUp(self):
506 def setUp(self):
503 self.negator = Negator()
507 self.negator = Negator()
504 ip.ast_transformers.append(self.negator)
508 ip.ast_transformers.append(self.negator)
505
509
506 def tearDown(self):
510 def tearDown(self):
507 ip.ast_transformers.remove(self.negator)
511 ip.ast_transformers.remove(self.negator)
508
512
509 def test_run_cell(self):
513 def test_run_cell(self):
510 with tt.AssertPrints('-34'):
514 with tt.AssertPrints('-34'):
511 ip.run_cell('print (12 + 22)')
515 ip.run_cell('print (12 + 22)')
512
516
513 # A named reference to a number shouldn't be transformed.
517 # A named reference to a number shouldn't be transformed.
514 ip.user_ns['n'] = 55
518 ip.user_ns['n'] = 55
515 with tt.AssertNotPrints('-55'):
519 with tt.AssertNotPrints('-55'):
516 ip.run_cell('print (n)')
520 ip.run_cell('print (n)')
517
521
518 def test_timeit(self):
522 def test_timeit(self):
519 called = set()
523 called = set()
520 def f(x):
524 def f(x):
521 called.add(x)
525 called.add(x)
522 ip.push({'f':f})
526 ip.push({'f':f})
523
527
524 with tt.AssertPrints("best of "):
528 with tt.AssertPrints("best of "):
525 ip.run_line_magic("timeit", "-n1 f(1)")
529 ip.run_line_magic("timeit", "-n1 f(1)")
526 self.assertEqual(called, set([-1]))
530 self.assertEqual(called, set([-1]))
527 called.clear()
531 called.clear()
528
532
529 with tt.AssertPrints("best of "):
533 with tt.AssertPrints("best of "):
530 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
534 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
531 self.assertEqual(called, set([-2, -3]))
535 self.assertEqual(called, set([-2, -3]))
532
536
533 def test_time(self):
537 def test_time(self):
534 called = []
538 called = []
535 def f(x):
539 def f(x):
536 called.append(x)
540 called.append(x)
537 ip.push({'f':f})
541 ip.push({'f':f})
538
542
539 # Test with an expression
543 # Test with an expression
540 with tt.AssertPrints("Wall time: "):
544 with tt.AssertPrints("Wall time: "):
541 ip.run_line_magic("time", "f(5+9)")
545 ip.run_line_magic("time", "f(5+9)")
542 self.assertEqual(called, [-14])
546 self.assertEqual(called, [-14])
543 called[:] = []
547 called[:] = []
544
548
545 # Test with a statement (different code path)
549 # Test with a statement (different code path)
546 with tt.AssertPrints("Wall time: "):
550 with tt.AssertPrints("Wall time: "):
547 ip.run_line_magic("time", "a = f(-3 + -2)")
551 ip.run_line_magic("time", "a = f(-3 + -2)")
548 self.assertEqual(called, [5])
552 self.assertEqual(called, [5])
549
553
550 def test_macro(self):
554 def test_macro(self):
551 ip.push({'a':10})
555 ip.push({'a':10})
552 # The AST transformation makes this do a+=-1
556 # The AST transformation makes this do a+=-1
553 ip.define_macro("amacro", "a+=1\nprint(a)")
557 ip.define_macro("amacro", "a+=1\nprint(a)")
554
558
555 with tt.AssertPrints("9"):
559 with tt.AssertPrints("9"):
556 ip.run_cell("amacro")
560 ip.run_cell("amacro")
557 with tt.AssertPrints("8"):
561 with tt.AssertPrints("8"):
558 ip.run_cell("amacro")
562 ip.run_cell("amacro")
559
563
560 class IntegerWrapper(ast.NodeTransformer):
564 class IntegerWrapper(ast.NodeTransformer):
561 """Wraps all integers in a call to Integer()"""
565 """Wraps all integers in a call to Integer()"""
562 def visit_Num(self, node):
566 def visit_Num(self, node):
563 if isinstance(node.n, int):
567 if isinstance(node.n, int):
564 return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
568 return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
565 args=[node], keywords=[])
569 args=[node], keywords=[])
566 return node
570 return node
567
571
568 class TestAstTransform2(unittest.TestCase):
572 class TestAstTransform2(unittest.TestCase):
569 def setUp(self):
573 def setUp(self):
570 self.intwrapper = IntegerWrapper()
574 self.intwrapper = IntegerWrapper()
571 ip.ast_transformers.append(self.intwrapper)
575 ip.ast_transformers.append(self.intwrapper)
572
576
573 self.calls = []
577 self.calls = []
574 def Integer(*args):
578 def Integer(*args):
575 self.calls.append(args)
579 self.calls.append(args)
576 return args
580 return args
577 ip.push({"Integer": Integer})
581 ip.push({"Integer": Integer})
578
582
579 def tearDown(self):
583 def tearDown(self):
580 ip.ast_transformers.remove(self.intwrapper)
584 ip.ast_transformers.remove(self.intwrapper)
581 del ip.user_ns['Integer']
585 del ip.user_ns['Integer']
582
586
583 def test_run_cell(self):
587 def test_run_cell(self):
584 ip.run_cell("n = 2")
588 ip.run_cell("n = 2")
585 self.assertEqual(self.calls, [(2,)])
589 self.assertEqual(self.calls, [(2,)])
586
590
587 # This shouldn't throw an error
591 # This shouldn't throw an error
588 ip.run_cell("o = 2.0")
592 ip.run_cell("o = 2.0")
589 self.assertEqual(ip.user_ns['o'], 2.0)
593 self.assertEqual(ip.user_ns['o'], 2.0)
590
594
591 def test_timeit(self):
595 def test_timeit(self):
592 called = set()
596 called = set()
593 def f(x):
597 def f(x):
594 called.add(x)
598 called.add(x)
595 ip.push({'f':f})
599 ip.push({'f':f})
596
600
597 with tt.AssertPrints("best of "):
601 with tt.AssertPrints("best of "):
598 ip.run_line_magic("timeit", "-n1 f(1)")
602 ip.run_line_magic("timeit", "-n1 f(1)")
599 self.assertEqual(called, set([(1,)]))
603 self.assertEqual(called, set([(1,)]))
600 called.clear()
604 called.clear()
601
605
602 with tt.AssertPrints("best of "):
606 with tt.AssertPrints("best of "):
603 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
607 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
604 self.assertEqual(called, set([(2,), (3,)]))
608 self.assertEqual(called, set([(2,), (3,)]))
605
609
606 class ErrorTransformer(ast.NodeTransformer):
610 class ErrorTransformer(ast.NodeTransformer):
607 """Throws an error when it sees a number."""
611 """Throws an error when it sees a number."""
608 def visit_Num(self):
612 def visit_Num(self):
609 raise ValueError("test")
613 raise ValueError("test")
610
614
611 class TestAstTransformError(unittest.TestCase):
615 class TestAstTransformError(unittest.TestCase):
612 def test_unregistering(self):
616 def test_unregistering(self):
613 err_transformer = ErrorTransformer()
617 err_transformer = ErrorTransformer()
614 ip.ast_transformers.append(err_transformer)
618 ip.ast_transformers.append(err_transformer)
615
619
616 with tt.AssertPrints("unregister", channel='stderr'):
620 with tt.AssertPrints("unregister", channel='stderr'):
617 ip.run_cell("1 + 2")
621 ip.run_cell("1 + 2")
618
622
619 # This should have been removed.
623 # This should have been removed.
620 nt.assert_not_in(err_transformer, ip.ast_transformers)
624 nt.assert_not_in(err_transformer, ip.ast_transformers)
621
625
622 def test__IPYTHON__():
626 def test__IPYTHON__():
623 # This shouldn't raise a NameError, that's all
627 # This shouldn't raise a NameError, that's all
624 __IPYTHON__
628 __IPYTHON__
625
629
626
630
627 class DummyRepr(object):
631 class DummyRepr(object):
628 def __repr__(self):
632 def __repr__(self):
629 return "DummyRepr"
633 return "DummyRepr"
630
634
631 def _repr_html_(self):
635 def _repr_html_(self):
632 return "<b>dummy</b>"
636 return "<b>dummy</b>"
633
637
634 def _repr_javascript_(self):
638 def _repr_javascript_(self):
635 return "console.log('hi');", {'key': 'value'}
639 return "console.log('hi');", {'key': 'value'}
636
640
637
641
638 def test_user_variables():
642 def test_user_variables():
639 # enable all formatters
643 # enable all formatters
640 ip.display_formatter.active_types = ip.display_formatter.format_types
644 ip.display_formatter.active_types = ip.display_formatter.format_types
641
645
642 ip.user_ns['dummy'] = d = DummyRepr()
646 ip.user_ns['dummy'] = d = DummyRepr()
643 keys = set(['dummy', 'doesnotexist'])
647 keys = set(['dummy', 'doesnotexist'])
644 r = ip.user_variables(keys)
648 r = ip.user_variables(keys)
645
649
646 nt.assert_equal(keys, set(r.keys()))
650 nt.assert_equal(keys, set(r.keys()))
647 dummy = r['dummy']
651 dummy = r['dummy']
648 nt.assert_equal(set(['status', 'data', 'metadata']), set(dummy.keys()))
652 nt.assert_equal(set(['status', 'data', 'metadata']), set(dummy.keys()))
649 nt.assert_equal(dummy['status'], 'ok')
653 nt.assert_equal(dummy['status'], 'ok')
650 data = dummy['data']
654 data = dummy['data']
651 metadata = dummy['metadata']
655 metadata = dummy['metadata']
652 nt.assert_equal(data.get('text/html'), d._repr_html_())
656 nt.assert_equal(data.get('text/html'), d._repr_html_())
653 js, jsmd = d._repr_javascript_()
657 js, jsmd = d._repr_javascript_()
654 nt.assert_equal(data.get('application/javascript'), js)
658 nt.assert_equal(data.get('application/javascript'), js)
655 nt.assert_equal(metadata.get('application/javascript'), jsmd)
659 nt.assert_equal(metadata.get('application/javascript'), jsmd)
656
660
657 dne = r['doesnotexist']
661 dne = r['doesnotexist']
658 nt.assert_equal(dne['status'], 'error')
662 nt.assert_equal(dne['status'], 'error')
659 nt.assert_equal(dne['ename'], 'KeyError')
663 nt.assert_equal(dne['ename'], 'KeyError')
660
664
661 # back to text only
665 # back to text only
662 ip.display_formatter.active_types = ['text/plain']
666 ip.display_formatter.active_types = ['text/plain']
663
667
664 def test_user_expression():
668 def test_user_expression():
665 # enable all formatters
669 # enable all formatters
666 ip.display_formatter.active_types = ip.display_formatter.format_types
670 ip.display_formatter.active_types = ip.display_formatter.format_types
667 query = {
671 query = {
668 'a' : '1 + 2',
672 'a' : '1 + 2',
669 'b' : '1/0',
673 'b' : '1/0',
670 }
674 }
671 r = ip.user_expressions(query)
675 r = ip.user_expressions(query)
672 import pprint
676 import pprint
673 pprint.pprint(r)
677 pprint.pprint(r)
674 nt.assert_equal(set(r.keys()), set(query.keys()))
678 nt.assert_equal(set(r.keys()), set(query.keys()))
675 a = r['a']
679 a = r['a']
676 nt.assert_equal(set(['status', 'data', 'metadata']), set(a.keys()))
680 nt.assert_equal(set(['status', 'data', 'metadata']), set(a.keys()))
677 nt.assert_equal(a['status'], 'ok')
681 nt.assert_equal(a['status'], 'ok')
678 data = a['data']
682 data = a['data']
679 metadata = a['metadata']
683 metadata = a['metadata']
680 nt.assert_equal(data.get('text/plain'), '3')
684 nt.assert_equal(data.get('text/plain'), '3')
681
685
682 b = r['b']
686 b = r['b']
683 nt.assert_equal(b['status'], 'error')
687 nt.assert_equal(b['status'], 'error')
684 nt.assert_equal(b['ename'], 'ZeroDivisionError')
688 nt.assert_equal(b['ename'], 'ZeroDivisionError')
685
689
686 # back to text only
690 # back to text only
687 ip.display_formatter.active_types = ['text/plain']
691 ip.display_formatter.active_types = ['text/plain']
688
692
689
693
690
694
691
695
692
696
693 class TestSyntaxErrorTransformer(unittest.TestCase):
697 class TestSyntaxErrorTransformer(unittest.TestCase):
694 """Check that SyntaxError raised by an input transformer is handled by run_cell()"""
698 """Check that SyntaxError raised by an input transformer is handled by run_cell()"""
695
699
696 class SyntaxErrorTransformer(InputTransformer):
700 class SyntaxErrorTransformer(InputTransformer):
697
701
698 def push(self, line):
702 def push(self, line):
699 pos = line.find('syntaxerror')
703 pos = line.find('syntaxerror')
700 if pos >= 0:
704 if pos >= 0:
701 e = SyntaxError('input contains "syntaxerror"')
705 e = SyntaxError('input contains "syntaxerror"')
702 e.text = line
706 e.text = line
703 e.offset = pos + 1
707 e.offset = pos + 1
704 raise e
708 raise e
705 return line
709 return line
706
710
707 def reset(self):
711 def reset(self):
708 pass
712 pass
709
713
710 def setUp(self):
714 def setUp(self):
711 self.transformer = TestSyntaxErrorTransformer.SyntaxErrorTransformer()
715 self.transformer = TestSyntaxErrorTransformer.SyntaxErrorTransformer()
712 ip.input_splitter.python_line_transforms.append(self.transformer)
716 ip.input_splitter.python_line_transforms.append(self.transformer)
713 ip.input_transformer_manager.python_line_transforms.append(self.transformer)
717 ip.input_transformer_manager.python_line_transforms.append(self.transformer)
714
718
715 def tearDown(self):
719 def tearDown(self):
716 ip.input_splitter.python_line_transforms.remove(self.transformer)
720 ip.input_splitter.python_line_transforms.remove(self.transformer)
717 ip.input_transformer_manager.python_line_transforms.remove(self.transformer)
721 ip.input_transformer_manager.python_line_transforms.remove(self.transformer)
718
722
719 def test_syntaxerror_input_transformer(self):
723 def test_syntaxerror_input_transformer(self):
720 with tt.AssertPrints('1234'):
724 with tt.AssertPrints('1234'):
721 ip.run_cell('1234')
725 ip.run_cell('1234')
722 with tt.AssertPrints('SyntaxError: invalid syntax'):
726 with tt.AssertPrints('SyntaxError: invalid syntax'):
723 ip.run_cell('1 2 3') # plain python syntax error
727 ip.run_cell('1 2 3') # plain python syntax error
724 with tt.AssertPrints('SyntaxError: input contains "syntaxerror"'):
728 with tt.AssertPrints('SyntaxError: input contains "syntaxerror"'):
725 ip.run_cell('2345 # syntaxerror') # input transformer syntax error
729 ip.run_cell('2345 # syntaxerror') # input transformer syntax error
726 with tt.AssertPrints('3456'):
730 with tt.AssertPrints('3456'):
727 ip.run_cell('3456')
731 ip.run_cell('3456')
728
732
729
733
730
734
General Comments 0
You need to be logged in to leave comments. Login now