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