##// END OF EJS Templates
Don't use nbformat.current in core
MinRK -
Show More

The requested changes are too big and content was truncated. Show full diff

1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,609 +1,611 b''
1 """Implementation of basic magic functions."""
1 """Implementation of basic magic functions."""
2
2
3 from __future__ import print_function
3 from __future__ import print_function
4
4
5 import io
5 import io
6 import json
6 import json
7 import sys
7 import sys
8 from pprint import pformat
8 from pprint import pformat
9
9
10 from IPython.core import magic_arguments, page
10 from IPython.core import magic_arguments, page
11 from IPython.core.error import UsageError
11 from IPython.core.error import UsageError
12 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
12 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
13 from IPython.utils.text import format_screen, dedent, indent
13 from IPython.utils.text import format_screen, dedent, indent
14 from IPython.testing.skipdoctest import skip_doctest
14 from IPython.testing.skipdoctest import skip_doctest
15 from IPython.utils.ipstruct import Struct
15 from IPython.utils.ipstruct import Struct
16 from IPython.utils.path import unquote_filename
16 from IPython.utils.path import unquote_filename
17 from IPython.utils.py3compat import unicode_type
17 from IPython.utils.py3compat import unicode_type
18 from IPython.utils.warn import warn, error
18 from IPython.utils.warn import warn, error
19
19
20
20
21 class MagicsDisplay(object):
21 class MagicsDisplay(object):
22 def __init__(self, magics_manager):
22 def __init__(self, magics_manager):
23 self.magics_manager = magics_manager
23 self.magics_manager = magics_manager
24
24
25 def _lsmagic(self):
25 def _lsmagic(self):
26 """The main implementation of the %lsmagic"""
26 """The main implementation of the %lsmagic"""
27 mesc = magic_escapes['line']
27 mesc = magic_escapes['line']
28 cesc = magic_escapes['cell']
28 cesc = magic_escapes['cell']
29 mman = self.magics_manager
29 mman = self.magics_manager
30 magics = mman.lsmagic()
30 magics = mman.lsmagic()
31 out = ['Available line magics:',
31 out = ['Available line magics:',
32 mesc + (' '+mesc).join(sorted(magics['line'])),
32 mesc + (' '+mesc).join(sorted(magics['line'])),
33 '',
33 '',
34 'Available cell magics:',
34 'Available cell magics:',
35 cesc + (' '+cesc).join(sorted(magics['cell'])),
35 cesc + (' '+cesc).join(sorted(magics['cell'])),
36 '',
36 '',
37 mman.auto_status()]
37 mman.auto_status()]
38 return '\n'.join(out)
38 return '\n'.join(out)
39
39
40 def _repr_pretty_(self, p, cycle):
40 def _repr_pretty_(self, p, cycle):
41 p.text(self._lsmagic())
41 p.text(self._lsmagic())
42
42
43 def __str__(self):
43 def __str__(self):
44 return self._lsmagic()
44 return self._lsmagic()
45
45
46 def _jsonable(self):
46 def _jsonable(self):
47 """turn magics dict into jsonable dict of the same structure
47 """turn magics dict into jsonable dict of the same structure
48
48
49 replaces object instances with their class names as strings
49 replaces object instances with their class names as strings
50 """
50 """
51 magic_dict = {}
51 magic_dict = {}
52 mman = self.magics_manager
52 mman = self.magics_manager
53 magics = mman.lsmagic()
53 magics = mman.lsmagic()
54 for key, subdict in magics.items():
54 for key, subdict in magics.items():
55 d = {}
55 d = {}
56 magic_dict[key] = d
56 magic_dict[key] = d
57 for name, obj in subdict.items():
57 for name, obj in subdict.items():
58 try:
58 try:
59 classname = obj.__self__.__class__.__name__
59 classname = obj.__self__.__class__.__name__
60 except AttributeError:
60 except AttributeError:
61 classname = 'Other'
61 classname = 'Other'
62
62
63 d[name] = classname
63 d[name] = classname
64 return magic_dict
64 return magic_dict
65
65
66 def _repr_json_(self):
66 def _repr_json_(self):
67 return json.dumps(self._jsonable())
67 return json.dumps(self._jsonable())
68
68
69
69
70 @magics_class
70 @magics_class
71 class BasicMagics(Magics):
71 class BasicMagics(Magics):
72 """Magics that provide central IPython functionality.
72 """Magics that provide central IPython functionality.
73
73
74 These are various magics that don't fit into specific categories but that
74 These are various magics that don't fit into specific categories but that
75 are all part of the base 'IPython experience'."""
75 are all part of the base 'IPython experience'."""
76
76
77 @magic_arguments.magic_arguments()
77 @magic_arguments.magic_arguments()
78 @magic_arguments.argument(
78 @magic_arguments.argument(
79 '-l', '--line', action='store_true',
79 '-l', '--line', action='store_true',
80 help="""Create a line magic alias."""
80 help="""Create a line magic alias."""
81 )
81 )
82 @magic_arguments.argument(
82 @magic_arguments.argument(
83 '-c', '--cell', action='store_true',
83 '-c', '--cell', action='store_true',
84 help="""Create a cell magic alias."""
84 help="""Create a cell magic alias."""
85 )
85 )
86 @magic_arguments.argument(
86 @magic_arguments.argument(
87 'name',
87 'name',
88 help="""Name of the magic to be created."""
88 help="""Name of the magic to be created."""
89 )
89 )
90 @magic_arguments.argument(
90 @magic_arguments.argument(
91 'target',
91 'target',
92 help="""Name of the existing line or cell magic."""
92 help="""Name of the existing line or cell magic."""
93 )
93 )
94 @line_magic
94 @line_magic
95 def alias_magic(self, line=''):
95 def alias_magic(self, line=''):
96 """Create an alias for an existing line or cell magic.
96 """Create an alias for an existing line or cell magic.
97
97
98 Examples
98 Examples
99 --------
99 --------
100 ::
100 ::
101
101
102 In [1]: %alias_magic t timeit
102 In [1]: %alias_magic t timeit
103 Created `%t` as an alias for `%timeit`.
103 Created `%t` as an alias for `%timeit`.
104 Created `%%t` as an alias for `%%timeit`.
104 Created `%%t` as an alias for `%%timeit`.
105
105
106 In [2]: %t -n1 pass
106 In [2]: %t -n1 pass
107 1 loops, best of 3: 954 ns per loop
107 1 loops, best of 3: 954 ns per loop
108
108
109 In [3]: %%t -n1
109 In [3]: %%t -n1
110 ...: pass
110 ...: pass
111 ...:
111 ...:
112 1 loops, best of 3: 954 ns per loop
112 1 loops, best of 3: 954 ns per loop
113
113
114 In [4]: %alias_magic --cell whereami pwd
114 In [4]: %alias_magic --cell whereami pwd
115 UsageError: Cell magic function `%%pwd` not found.
115 UsageError: Cell magic function `%%pwd` not found.
116 In [5]: %alias_magic --line whereami pwd
116 In [5]: %alias_magic --line whereami pwd
117 Created `%whereami` as an alias for `%pwd`.
117 Created `%whereami` as an alias for `%pwd`.
118
118
119 In [6]: %whereami
119 In [6]: %whereami
120 Out[6]: u'/home/testuser'
120 Out[6]: u'/home/testuser'
121 """
121 """
122 args = magic_arguments.parse_argstring(self.alias_magic, line)
122 args = magic_arguments.parse_argstring(self.alias_magic, line)
123 shell = self.shell
123 shell = self.shell
124 mman = self.shell.magics_manager
124 mman = self.shell.magics_manager
125 escs = ''.join(magic_escapes.values())
125 escs = ''.join(magic_escapes.values())
126
126
127 target = args.target.lstrip(escs)
127 target = args.target.lstrip(escs)
128 name = args.name.lstrip(escs)
128 name = args.name.lstrip(escs)
129
129
130 # Find the requested magics.
130 # Find the requested magics.
131 m_line = shell.find_magic(target, 'line')
131 m_line = shell.find_magic(target, 'line')
132 m_cell = shell.find_magic(target, 'cell')
132 m_cell = shell.find_magic(target, 'cell')
133 if args.line and m_line is None:
133 if args.line and m_line is None:
134 raise UsageError('Line magic function `%s%s` not found.' %
134 raise UsageError('Line magic function `%s%s` not found.' %
135 (magic_escapes['line'], target))
135 (magic_escapes['line'], target))
136 if args.cell and m_cell is None:
136 if args.cell and m_cell is None:
137 raise UsageError('Cell magic function `%s%s` not found.' %
137 raise UsageError('Cell magic function `%s%s` not found.' %
138 (magic_escapes['cell'], target))
138 (magic_escapes['cell'], target))
139
139
140 # If --line and --cell are not specified, default to the ones
140 # If --line and --cell are not specified, default to the ones
141 # that are available.
141 # that are available.
142 if not args.line and not args.cell:
142 if not args.line and not args.cell:
143 if not m_line and not m_cell:
143 if not m_line and not m_cell:
144 raise UsageError(
144 raise UsageError(
145 'No line or cell magic with name `%s` found.' % target
145 'No line or cell magic with name `%s` found.' % target
146 )
146 )
147 args.line = bool(m_line)
147 args.line = bool(m_line)
148 args.cell = bool(m_cell)
148 args.cell = bool(m_cell)
149
149
150 if args.line:
150 if args.line:
151 mman.register_alias(name, target, 'line')
151 mman.register_alias(name, target, 'line')
152 print('Created `%s%s` as an alias for `%s%s`.' % (
152 print('Created `%s%s` as an alias for `%s%s`.' % (
153 magic_escapes['line'], name,
153 magic_escapes['line'], name,
154 magic_escapes['line'], target))
154 magic_escapes['line'], target))
155
155
156 if args.cell:
156 if args.cell:
157 mman.register_alias(name, target, 'cell')
157 mman.register_alias(name, target, 'cell')
158 print('Created `%s%s` as an alias for `%s%s`.' % (
158 print('Created `%s%s` as an alias for `%s%s`.' % (
159 magic_escapes['cell'], name,
159 magic_escapes['cell'], name,
160 magic_escapes['cell'], target))
160 magic_escapes['cell'], target))
161
161
162 @line_magic
162 @line_magic
163 def lsmagic(self, parameter_s=''):
163 def lsmagic(self, parameter_s=''):
164 """List currently available magic functions."""
164 """List currently available magic functions."""
165 return MagicsDisplay(self.shell.magics_manager)
165 return MagicsDisplay(self.shell.magics_manager)
166
166
167 def _magic_docs(self, brief=False, rest=False):
167 def _magic_docs(self, brief=False, rest=False):
168 """Return docstrings from magic functions."""
168 """Return docstrings from magic functions."""
169 mman = self.shell.magics_manager
169 mman = self.shell.magics_manager
170 docs = mman.lsmagic_docs(brief, missing='No documentation')
170 docs = mman.lsmagic_docs(brief, missing='No documentation')
171
171
172 if rest:
172 if rest:
173 format_string = '**%s%s**::\n\n%s\n\n'
173 format_string = '**%s%s**::\n\n%s\n\n'
174 else:
174 else:
175 format_string = '%s%s:\n%s\n'
175 format_string = '%s%s:\n%s\n'
176
176
177 return ''.join(
177 return ''.join(
178 [format_string % (magic_escapes['line'], fname,
178 [format_string % (magic_escapes['line'], fname,
179 indent(dedent(fndoc)))
179 indent(dedent(fndoc)))
180 for fname, fndoc in sorted(docs['line'].items())]
180 for fname, fndoc in sorted(docs['line'].items())]
181 +
181 +
182 [format_string % (magic_escapes['cell'], fname,
182 [format_string % (magic_escapes['cell'], fname,
183 indent(dedent(fndoc)))
183 indent(dedent(fndoc)))
184 for fname, fndoc in sorted(docs['cell'].items())]
184 for fname, fndoc in sorted(docs['cell'].items())]
185 )
185 )
186
186
187 @line_magic
187 @line_magic
188 def magic(self, parameter_s=''):
188 def magic(self, parameter_s=''):
189 """Print information about the magic function system.
189 """Print information about the magic function system.
190
190
191 Supported formats: -latex, -brief, -rest
191 Supported formats: -latex, -brief, -rest
192 """
192 """
193
193
194 mode = ''
194 mode = ''
195 try:
195 try:
196 mode = parameter_s.split()[0][1:]
196 mode = parameter_s.split()[0][1:]
197 if mode == 'rest':
197 if mode == 'rest':
198 rest_docs = []
198 rest_docs = []
199 except IndexError:
199 except IndexError:
200 pass
200 pass
201
201
202 brief = (mode == 'brief')
202 brief = (mode == 'brief')
203 rest = (mode == 'rest')
203 rest = (mode == 'rest')
204 magic_docs = self._magic_docs(brief, rest)
204 magic_docs = self._magic_docs(brief, rest)
205
205
206 if mode == 'latex':
206 if mode == 'latex':
207 print(self.format_latex(magic_docs))
207 print(self.format_latex(magic_docs))
208 return
208 return
209 else:
209 else:
210 magic_docs = format_screen(magic_docs)
210 magic_docs = format_screen(magic_docs)
211
211
212 out = ["""
212 out = ["""
213 IPython's 'magic' functions
213 IPython's 'magic' functions
214 ===========================
214 ===========================
215
215
216 The magic function system provides a series of functions which allow you to
216 The magic function system provides a series of functions which allow you to
217 control the behavior of IPython itself, plus a lot of system-type
217 control the behavior of IPython itself, plus a lot of system-type
218 features. There are two kinds of magics, line-oriented and cell-oriented.
218 features. There are two kinds of magics, line-oriented and cell-oriented.
219
219
220 Line magics are prefixed with the % character and work much like OS
220 Line magics are prefixed with the % character and work much like OS
221 command-line calls: they get as an argument the rest of the line, where
221 command-line calls: they get as an argument the rest of the line, where
222 arguments are passed without parentheses or quotes. For example, this will
222 arguments are passed without parentheses or quotes. For example, this will
223 time the given statement::
223 time the given statement::
224
224
225 %timeit range(1000)
225 %timeit range(1000)
226
226
227 Cell magics are prefixed with a double %%, and they are functions that get as
227 Cell magics are prefixed with a double %%, and they are functions that get as
228 an argument not only the rest of the line, but also the lines below it in a
228 an argument not only the rest of the line, but also the lines below it in a
229 separate argument. These magics are called with two arguments: the rest of the
229 separate argument. These magics are called with two arguments: the rest of the
230 call line and the body of the cell, consisting of the lines below the first.
230 call line and the body of the cell, consisting of the lines below the first.
231 For example::
231 For example::
232
232
233 %%timeit x = numpy.random.randn((100, 100))
233 %%timeit x = numpy.random.randn((100, 100))
234 numpy.linalg.svd(x)
234 numpy.linalg.svd(x)
235
235
236 will time the execution of the numpy svd routine, running the assignment of x
236 will time the execution of the numpy svd routine, running the assignment of x
237 as part of the setup phase, which is not timed.
237 as part of the setup phase, which is not timed.
238
238
239 In a line-oriented client (the terminal or Qt console IPython), starting a new
239 In a line-oriented client (the terminal or Qt console IPython), starting a new
240 input with %% will automatically enter cell mode, and IPython will continue
240 input with %% will automatically enter cell mode, and IPython will continue
241 reading input until a blank line is given. In the notebook, simply type the
241 reading input until a blank line is given. In the notebook, simply type the
242 whole cell as one entity, but keep in mind that the %% escape can only be at
242 whole cell as one entity, but keep in mind that the %% escape can only be at
243 the very start of the cell.
243 the very start of the cell.
244
244
245 NOTE: If you have 'automagic' enabled (via the command line option or with the
245 NOTE: If you have 'automagic' enabled (via the command line option or with the
246 %automagic function), you don't need to type in the % explicitly for line
246 %automagic function), you don't need to type in the % explicitly for line
247 magics; cell magics always require an explicit '%%' escape. By default,
247 magics; cell magics always require an explicit '%%' escape. By default,
248 IPython ships with automagic on, so you should only rarely need the % escape.
248 IPython ships with automagic on, so you should only rarely need the % escape.
249
249
250 Example: typing '%cd mydir' (without the quotes) changes you working directory
250 Example: typing '%cd mydir' (without the quotes) changes you working directory
251 to 'mydir', if it exists.
251 to 'mydir', if it exists.
252
252
253 For a list of the available magic functions, use %lsmagic. For a description
253 For a list of the available magic functions, use %lsmagic. For a description
254 of any of them, type %magic_name?, e.g. '%cd?'.
254 of any of them, type %magic_name?, e.g. '%cd?'.
255
255
256 Currently the magic system has the following functions:""",
256 Currently the magic system has the following functions:""",
257 magic_docs,
257 magic_docs,
258 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
258 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
259 str(self.lsmagic()),
259 str(self.lsmagic()),
260 ]
260 ]
261 page.page('\n'.join(out))
261 page.page('\n'.join(out))
262
262
263
263
264 @line_magic
264 @line_magic
265 def page(self, parameter_s=''):
265 def page(self, parameter_s=''):
266 """Pretty print the object and display it through a pager.
266 """Pretty print the object and display it through a pager.
267
267
268 %page [options] OBJECT
268 %page [options] OBJECT
269
269
270 If no object is given, use _ (last output).
270 If no object is given, use _ (last output).
271
271
272 Options:
272 Options:
273
273
274 -r: page str(object), don't pretty-print it."""
274 -r: page str(object), don't pretty-print it."""
275
275
276 # After a function contributed by Olivier Aubert, slightly modified.
276 # After a function contributed by Olivier Aubert, slightly modified.
277
277
278 # Process options/args
278 # Process options/args
279 opts, args = self.parse_options(parameter_s, 'r')
279 opts, args = self.parse_options(parameter_s, 'r')
280 raw = 'r' in opts
280 raw = 'r' in opts
281
281
282 oname = args and args or '_'
282 oname = args and args or '_'
283 info = self.shell._ofind(oname)
283 info = self.shell._ofind(oname)
284 if info['found']:
284 if info['found']:
285 txt = (raw and str or pformat)( info['obj'] )
285 txt = (raw and str or pformat)( info['obj'] )
286 page.page(txt)
286 page.page(txt)
287 else:
287 else:
288 print('Object `%s` not found' % oname)
288 print('Object `%s` not found' % oname)
289
289
290 @line_magic
290 @line_magic
291 def profile(self, parameter_s=''):
291 def profile(self, parameter_s=''):
292 """Print your currently active IPython profile.
292 """Print your currently active IPython profile.
293
293
294 See Also
294 See Also
295 --------
295 --------
296 prun : run code using the Python profiler
296 prun : run code using the Python profiler
297 (:meth:`~IPython.core.magics.execution.ExecutionMagics.prun`)
297 (:meth:`~IPython.core.magics.execution.ExecutionMagics.prun`)
298 """
298 """
299 warn("%profile is now deprecated. Please use get_ipython().profile instead.")
299 warn("%profile is now deprecated. Please use get_ipython().profile instead.")
300 from IPython.core.application import BaseIPythonApplication
300 from IPython.core.application import BaseIPythonApplication
301 if BaseIPythonApplication.initialized():
301 if BaseIPythonApplication.initialized():
302 print(BaseIPythonApplication.instance().profile)
302 print(BaseIPythonApplication.instance().profile)
303 else:
303 else:
304 error("profile is an application-level value, but you don't appear to be in an IPython application")
304 error("profile is an application-level value, but you don't appear to be in an IPython application")
305
305
306 @line_magic
306 @line_magic
307 def pprint(self, parameter_s=''):
307 def pprint(self, parameter_s=''):
308 """Toggle pretty printing on/off."""
308 """Toggle pretty printing on/off."""
309 ptformatter = self.shell.display_formatter.formatters['text/plain']
309 ptformatter = self.shell.display_formatter.formatters['text/plain']
310 ptformatter.pprint = bool(1 - ptformatter.pprint)
310 ptformatter.pprint = bool(1 - ptformatter.pprint)
311 print('Pretty printing has been turned',
311 print('Pretty printing has been turned',
312 ['OFF','ON'][ptformatter.pprint])
312 ['OFF','ON'][ptformatter.pprint])
313
313
314 @line_magic
314 @line_magic
315 def colors(self, parameter_s=''):
315 def colors(self, parameter_s=''):
316 """Switch color scheme for prompts, info system and exception handlers.
316 """Switch color scheme for prompts, info system and exception handlers.
317
317
318 Currently implemented schemes: NoColor, Linux, LightBG.
318 Currently implemented schemes: NoColor, Linux, LightBG.
319
319
320 Color scheme names are not case-sensitive.
320 Color scheme names are not case-sensitive.
321
321
322 Examples
322 Examples
323 --------
323 --------
324 To get a plain black and white terminal::
324 To get a plain black and white terminal::
325
325
326 %colors nocolor
326 %colors nocolor
327 """
327 """
328 def color_switch_err(name):
328 def color_switch_err(name):
329 warn('Error changing %s color schemes.\n%s' %
329 warn('Error changing %s color schemes.\n%s' %
330 (name, sys.exc_info()[1]))
330 (name, sys.exc_info()[1]))
331
331
332
332
333 new_scheme = parameter_s.strip()
333 new_scheme = parameter_s.strip()
334 if not new_scheme:
334 if not new_scheme:
335 raise UsageError(
335 raise UsageError(
336 "%colors: you must specify a color scheme. See '%colors?'")
336 "%colors: you must specify a color scheme. See '%colors?'")
337 # local shortcut
337 # local shortcut
338 shell = self.shell
338 shell = self.shell
339
339
340 import IPython.utils.rlineimpl as readline
340 import IPython.utils.rlineimpl as readline
341
341
342 if not shell.colors_force and \
342 if not shell.colors_force and \
343 not readline.have_readline and \
343 not readline.have_readline and \
344 (sys.platform == "win32" or sys.platform == "cli"):
344 (sys.platform == "win32" or sys.platform == "cli"):
345 msg = """\
345 msg = """\
346 Proper color support under MS Windows requires the pyreadline library.
346 Proper color support under MS Windows requires the pyreadline library.
347 You can find it at:
347 You can find it at:
348 http://ipython.org/pyreadline.html
348 http://ipython.org/pyreadline.html
349
349
350 Defaulting color scheme to 'NoColor'"""
350 Defaulting color scheme to 'NoColor'"""
351 new_scheme = 'NoColor'
351 new_scheme = 'NoColor'
352 warn(msg)
352 warn(msg)
353
353
354 # readline option is 0
354 # readline option is 0
355 if not shell.colors_force and not shell.has_readline:
355 if not shell.colors_force and not shell.has_readline:
356 new_scheme = 'NoColor'
356 new_scheme = 'NoColor'
357
357
358 # Set prompt colors
358 # Set prompt colors
359 try:
359 try:
360 shell.prompt_manager.color_scheme = new_scheme
360 shell.prompt_manager.color_scheme = new_scheme
361 except:
361 except:
362 color_switch_err('prompt')
362 color_switch_err('prompt')
363 else:
363 else:
364 shell.colors = \
364 shell.colors = \
365 shell.prompt_manager.color_scheme_table.active_scheme_name
365 shell.prompt_manager.color_scheme_table.active_scheme_name
366 # Set exception colors
366 # Set exception colors
367 try:
367 try:
368 shell.InteractiveTB.set_colors(scheme = new_scheme)
368 shell.InteractiveTB.set_colors(scheme = new_scheme)
369 shell.SyntaxTB.set_colors(scheme = new_scheme)
369 shell.SyntaxTB.set_colors(scheme = new_scheme)
370 except:
370 except:
371 color_switch_err('exception')
371 color_switch_err('exception')
372
372
373 # Set info (for 'object?') colors
373 # Set info (for 'object?') colors
374 if shell.color_info:
374 if shell.color_info:
375 try:
375 try:
376 shell.inspector.set_active_scheme(new_scheme)
376 shell.inspector.set_active_scheme(new_scheme)
377 except:
377 except:
378 color_switch_err('object inspector')
378 color_switch_err('object inspector')
379 else:
379 else:
380 shell.inspector.set_active_scheme('NoColor')
380 shell.inspector.set_active_scheme('NoColor')
381
381
382 @line_magic
382 @line_magic
383 def xmode(self, parameter_s=''):
383 def xmode(self, parameter_s=''):
384 """Switch modes for the exception handlers.
384 """Switch modes for the exception handlers.
385
385
386 Valid modes: Plain, Context and Verbose.
386 Valid modes: Plain, Context and Verbose.
387
387
388 If called without arguments, acts as a toggle."""
388 If called without arguments, acts as a toggle."""
389
389
390 def xmode_switch_err(name):
390 def xmode_switch_err(name):
391 warn('Error changing %s exception modes.\n%s' %
391 warn('Error changing %s exception modes.\n%s' %
392 (name,sys.exc_info()[1]))
392 (name,sys.exc_info()[1]))
393
393
394 shell = self.shell
394 shell = self.shell
395 new_mode = parameter_s.strip().capitalize()
395 new_mode = parameter_s.strip().capitalize()
396 try:
396 try:
397 shell.InteractiveTB.set_mode(mode=new_mode)
397 shell.InteractiveTB.set_mode(mode=new_mode)
398 print('Exception reporting mode:',shell.InteractiveTB.mode)
398 print('Exception reporting mode:',shell.InteractiveTB.mode)
399 except:
399 except:
400 xmode_switch_err('user')
400 xmode_switch_err('user')
401
401
402 @line_magic
402 @line_magic
403 def quickref(self,arg):
403 def quickref(self,arg):
404 """ Show a quick reference sheet """
404 """ Show a quick reference sheet """
405 from IPython.core.usage import quick_reference
405 from IPython.core.usage import quick_reference
406 qr = quick_reference + self._magic_docs(brief=True)
406 qr = quick_reference + self._magic_docs(brief=True)
407 page.page(qr)
407 page.page(qr)
408
408
409 @line_magic
409 @line_magic
410 def doctest_mode(self, parameter_s=''):
410 def doctest_mode(self, parameter_s=''):
411 """Toggle doctest mode on and off.
411 """Toggle doctest mode on and off.
412
412
413 This mode is intended to make IPython behave as much as possible like a
413 This mode is intended to make IPython behave as much as possible like a
414 plain Python shell, from the perspective of how its prompts, exceptions
414 plain Python shell, from the perspective of how its prompts, exceptions
415 and output look. This makes it easy to copy and paste parts of a
415 and output look. This makes it easy to copy and paste parts of a
416 session into doctests. It does so by:
416 session into doctests. It does so by:
417
417
418 - Changing the prompts to the classic ``>>>`` ones.
418 - Changing the prompts to the classic ``>>>`` ones.
419 - Changing the exception reporting mode to 'Plain'.
419 - Changing the exception reporting mode to 'Plain'.
420 - Disabling pretty-printing of output.
420 - Disabling pretty-printing of output.
421
421
422 Note that IPython also supports the pasting of code snippets that have
422 Note that IPython also supports the pasting of code snippets that have
423 leading '>>>' and '...' prompts in them. This means that you can paste
423 leading '>>>' and '...' prompts in them. This means that you can paste
424 doctests from files or docstrings (even if they have leading
424 doctests from files or docstrings (even if they have leading
425 whitespace), and the code will execute correctly. You can then use
425 whitespace), and the code will execute correctly. You can then use
426 '%history -t' to see the translated history; this will give you the
426 '%history -t' to see the translated history; this will give you the
427 input after removal of all the leading prompts and whitespace, which
427 input after removal of all the leading prompts and whitespace, which
428 can be pasted back into an editor.
428 can be pasted back into an editor.
429
429
430 With these features, you can switch into this mode easily whenever you
430 With these features, you can switch into this mode easily whenever you
431 need to do testing and changes to doctests, without having to leave
431 need to do testing and changes to doctests, without having to leave
432 your existing IPython session.
432 your existing IPython session.
433 """
433 """
434
434
435 # Shorthands
435 # Shorthands
436 shell = self.shell
436 shell = self.shell
437 pm = shell.prompt_manager
437 pm = shell.prompt_manager
438 meta = shell.meta
438 meta = shell.meta
439 disp_formatter = self.shell.display_formatter
439 disp_formatter = self.shell.display_formatter
440 ptformatter = disp_formatter.formatters['text/plain']
440 ptformatter = disp_formatter.formatters['text/plain']
441 # dstore is a data store kept in the instance metadata bag to track any
441 # dstore is a data store kept in the instance metadata bag to track any
442 # changes we make, so we can undo them later.
442 # changes we make, so we can undo them later.
443 dstore = meta.setdefault('doctest_mode',Struct())
443 dstore = meta.setdefault('doctest_mode',Struct())
444 save_dstore = dstore.setdefault
444 save_dstore = dstore.setdefault
445
445
446 # save a few values we'll need to recover later
446 # save a few values we'll need to recover later
447 mode = save_dstore('mode',False)
447 mode = save_dstore('mode',False)
448 save_dstore('rc_pprint',ptformatter.pprint)
448 save_dstore('rc_pprint',ptformatter.pprint)
449 save_dstore('xmode',shell.InteractiveTB.mode)
449 save_dstore('xmode',shell.InteractiveTB.mode)
450 save_dstore('rc_separate_out',shell.separate_out)
450 save_dstore('rc_separate_out',shell.separate_out)
451 save_dstore('rc_separate_out2',shell.separate_out2)
451 save_dstore('rc_separate_out2',shell.separate_out2)
452 save_dstore('rc_prompts_pad_left',pm.justify)
452 save_dstore('rc_prompts_pad_left',pm.justify)
453 save_dstore('rc_separate_in',shell.separate_in)
453 save_dstore('rc_separate_in',shell.separate_in)
454 save_dstore('rc_active_types',disp_formatter.active_types)
454 save_dstore('rc_active_types',disp_formatter.active_types)
455 save_dstore('prompt_templates',(pm.in_template, pm.in2_template, pm.out_template))
455 save_dstore('prompt_templates',(pm.in_template, pm.in2_template, pm.out_template))
456
456
457 if mode == False:
457 if mode == False:
458 # turn on
458 # turn on
459 pm.in_template = '>>> '
459 pm.in_template = '>>> '
460 pm.in2_template = '... '
460 pm.in2_template = '... '
461 pm.out_template = ''
461 pm.out_template = ''
462
462
463 # Prompt separators like plain python
463 # Prompt separators like plain python
464 shell.separate_in = ''
464 shell.separate_in = ''
465 shell.separate_out = ''
465 shell.separate_out = ''
466 shell.separate_out2 = ''
466 shell.separate_out2 = ''
467
467
468 pm.justify = False
468 pm.justify = False
469
469
470 ptformatter.pprint = False
470 ptformatter.pprint = False
471 disp_formatter.active_types = ['text/plain']
471 disp_formatter.active_types = ['text/plain']
472
472
473 shell.magic('xmode Plain')
473 shell.magic('xmode Plain')
474 else:
474 else:
475 # turn off
475 # turn off
476 pm.in_template, pm.in2_template, pm.out_template = dstore.prompt_templates
476 pm.in_template, pm.in2_template, pm.out_template = dstore.prompt_templates
477
477
478 shell.separate_in = dstore.rc_separate_in
478 shell.separate_in = dstore.rc_separate_in
479
479
480 shell.separate_out = dstore.rc_separate_out
480 shell.separate_out = dstore.rc_separate_out
481 shell.separate_out2 = dstore.rc_separate_out2
481 shell.separate_out2 = dstore.rc_separate_out2
482
482
483 pm.justify = dstore.rc_prompts_pad_left
483 pm.justify = dstore.rc_prompts_pad_left
484
484
485 ptformatter.pprint = dstore.rc_pprint
485 ptformatter.pprint = dstore.rc_pprint
486 disp_formatter.active_types = dstore.rc_active_types
486 disp_formatter.active_types = dstore.rc_active_types
487
487
488 shell.magic('xmode ' + dstore.xmode)
488 shell.magic('xmode ' + dstore.xmode)
489
489
490 # Store new mode and inform
490 # Store new mode and inform
491 dstore.mode = bool(1-int(mode))
491 dstore.mode = bool(1-int(mode))
492 mode_label = ['OFF','ON'][dstore.mode]
492 mode_label = ['OFF','ON'][dstore.mode]
493 print('Doctest mode is:', mode_label)
493 print('Doctest mode is:', mode_label)
494
494
495 @line_magic
495 @line_magic
496 def gui(self, parameter_s=''):
496 def gui(self, parameter_s=''):
497 """Enable or disable IPython GUI event loop integration.
497 """Enable or disable IPython GUI event loop integration.
498
498
499 %gui [GUINAME]
499 %gui [GUINAME]
500
500
501 This magic replaces IPython's threaded shells that were activated
501 This magic replaces IPython's threaded shells that were activated
502 using the (pylab/wthread/etc.) command line flags. GUI toolkits
502 using the (pylab/wthread/etc.) command line flags. GUI toolkits
503 can now be enabled at runtime and keyboard
503 can now be enabled at runtime and keyboard
504 interrupts should work without any problems. The following toolkits
504 interrupts should work without any problems. The following toolkits
505 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
505 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
506
506
507 %gui wx # enable wxPython event loop integration
507 %gui wx # enable wxPython event loop integration
508 %gui qt4|qt # enable PyQt4 event loop integration
508 %gui qt4|qt # enable PyQt4 event loop integration
509 %gui qt5 # enable PyQt5 event loop integration
509 %gui qt5 # enable PyQt5 event loop integration
510 %gui gtk # enable PyGTK event loop integration
510 %gui gtk # enable PyGTK event loop integration
511 %gui gtk3 # enable Gtk3 event loop integration
511 %gui gtk3 # enable Gtk3 event loop integration
512 %gui tk # enable Tk event loop integration
512 %gui tk # enable Tk event loop integration
513 %gui osx # enable Cocoa event loop integration
513 %gui osx # enable Cocoa event loop integration
514 # (requires %matplotlib 1.1)
514 # (requires %matplotlib 1.1)
515 %gui # disable all event loop integration
515 %gui # disable all event loop integration
516
516
517 WARNING: after any of these has been called you can simply create
517 WARNING: after any of these has been called you can simply create
518 an application object, but DO NOT start the event loop yourself, as
518 an application object, but DO NOT start the event loop yourself, as
519 we have already handled that.
519 we have already handled that.
520 """
520 """
521 opts, arg = self.parse_options(parameter_s, '')
521 opts, arg = self.parse_options(parameter_s, '')
522 if arg=='': arg = None
522 if arg=='': arg = None
523 try:
523 try:
524 return self.shell.enable_gui(arg)
524 return self.shell.enable_gui(arg)
525 except Exception as e:
525 except Exception as e:
526 # print simple error message, rather than traceback if we can't
526 # print simple error message, rather than traceback if we can't
527 # hook up the GUI
527 # hook up the GUI
528 error(str(e))
528 error(str(e))
529
529
530 @skip_doctest
530 @skip_doctest
531 @line_magic
531 @line_magic
532 def precision(self, s=''):
532 def precision(self, s=''):
533 """Set floating point precision for pretty printing.
533 """Set floating point precision for pretty printing.
534
534
535 Can set either integer precision or a format string.
535 Can set either integer precision or a format string.
536
536
537 If numpy has been imported and precision is an int,
537 If numpy has been imported and precision is an int,
538 numpy display precision will also be set, via ``numpy.set_printoptions``.
538 numpy display precision will also be set, via ``numpy.set_printoptions``.
539
539
540 If no argument is given, defaults will be restored.
540 If no argument is given, defaults will be restored.
541
541
542 Examples
542 Examples
543 --------
543 --------
544 ::
544 ::
545
545
546 In [1]: from math import pi
546 In [1]: from math import pi
547
547
548 In [2]: %precision 3
548 In [2]: %precision 3
549 Out[2]: u'%.3f'
549 Out[2]: u'%.3f'
550
550
551 In [3]: pi
551 In [3]: pi
552 Out[3]: 3.142
552 Out[3]: 3.142
553
553
554 In [4]: %precision %i
554 In [4]: %precision %i
555 Out[4]: u'%i'
555 Out[4]: u'%i'
556
556
557 In [5]: pi
557 In [5]: pi
558 Out[5]: 3
558 Out[5]: 3
559
559
560 In [6]: %precision %e
560 In [6]: %precision %e
561 Out[6]: u'%e'
561 Out[6]: u'%e'
562
562
563 In [7]: pi**10
563 In [7]: pi**10
564 Out[7]: 9.364805e+04
564 Out[7]: 9.364805e+04
565
565
566 In [8]: %precision
566 In [8]: %precision
567 Out[8]: u'%r'
567 Out[8]: u'%r'
568
568
569 In [9]: pi**10
569 In [9]: pi**10
570 Out[9]: 93648.047476082982
570 Out[9]: 93648.047476082982
571 """
571 """
572 ptformatter = self.shell.display_formatter.formatters['text/plain']
572 ptformatter = self.shell.display_formatter.formatters['text/plain']
573 ptformatter.float_precision = s
573 ptformatter.float_precision = s
574 return ptformatter.float_format
574 return ptformatter.float_format
575
575
576 @magic_arguments.magic_arguments()
576 @magic_arguments.magic_arguments()
577 @magic_arguments.argument(
577 @magic_arguments.argument(
578 '-e', '--export', action='store_true', default=False,
578 '-e', '--export', action='store_true', default=False,
579 help='Export IPython history as a notebook. The filename argument '
579 help='Export IPython history as a notebook. The filename argument '
580 'is used to specify the notebook name and format. For example '
580 'is used to specify the notebook name and format. For example '
581 'a filename of notebook.ipynb will result in a notebook name '
581 'a filename of notebook.ipynb will result in a notebook name '
582 'of "notebook" and a format of "json". Likewise using a ".py" '
582 'of "notebook" and a format of "json". Likewise using a ".py" '
583 'file extension will write the notebook as a Python script'
583 'file extension will write the notebook as a Python script'
584 )
584 )
585 @magic_arguments.argument(
585 @magic_arguments.argument(
586 'filename', type=unicode_type,
586 'filename', type=unicode_type,
587 help='Notebook name or filename'
587 help='Notebook name or filename'
588 )
588 )
589 @line_magic
589 @line_magic
590 def notebook(self, s):
590 def notebook(self, s):
591 """Export and convert IPython notebooks.
591 """Export and convert IPython notebooks.
592
592
593 This function can export the current IPython history to a notebook file.
593 This function can export the current IPython history to a notebook file.
594 For example, to export the history to "foo.ipynb" do "%notebook -e foo.ipynb".
594 For example, to export the history to "foo.ipynb" do "%notebook -e foo.ipynb".
595 To export the history to "foo.py" do "%notebook -e foo.py".
595 To export the history to "foo.py" do "%notebook -e foo.py".
596 """
596 """
597 args = magic_arguments.parse_argstring(self.notebook, s)
597 args = magic_arguments.parse_argstring(self.notebook, s)
598
598
599 from IPython.nbformat import current
599 from IPython.nbformat import write, v4
600 args.filename = unquote_filename(args.filename)
600 args.filename = unquote_filename(args.filename)
601 if args.export:
601 if args.export:
602 cells = []
602 cells = []
603 hist = list(self.shell.history_manager.get_range())
603 hist = list(self.shell.history_manager.get_range())
604 for session, prompt_number, input in hist[:-1]:
604 for session, execution_count, input in hist[:-1]:
605 cells.append(current.new_code_cell(prompt_number=prompt_number,
605 cells.append(v4.new_code_cell(
606 input=input))
606 execution_count=execution_count,
607 nb = current.new_notebook(cells=cells)
607 source=source
608 ))
609 nb = v4.new_notebook(cells=cells)
608 with io.open(args.filename, 'w', encoding='utf-8') as f:
610 with io.open(args.filename, 'w', encoding='utf-8') as f:
609 current.write(nb, f)
611 write(f, nb, version=4)
@@ -1,962 +1,955 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for various magic functions.
2 """Tests for various magic functions.
3
3
4 Needs to be run by nose (to make ipython session available).
4 Needs to be run by nose (to make ipython session available).
5 """
5 """
6 from __future__ import absolute_import
6 from __future__ import absolute_import
7
7
8 #-----------------------------------------------------------------------------
9 # Imports
10 #-----------------------------------------------------------------------------
11
12 import io
8 import io
13 import os
9 import os
14 import sys
10 import sys
15 from unittest import TestCase, skipIf
11 from unittest import TestCase, skipIf
16
12
17 try:
13 try:
18 from importlib import invalidate_caches # Required from Python 3.3
14 from importlib import invalidate_caches # Required from Python 3.3
19 except ImportError:
15 except ImportError:
20 def invalidate_caches():
16 def invalidate_caches():
21 pass
17 pass
22
18
23 import nose.tools as nt
19 import nose.tools as nt
24
20
25 from IPython.core import magic
21 from IPython.core import magic
26 from IPython.core.magic import (Magics, magics_class, line_magic,
22 from IPython.core.magic import (Magics, magics_class, line_magic,
27 cell_magic, line_cell_magic,
23 cell_magic, line_cell_magic,
28 register_line_magic, register_cell_magic,
24 register_line_magic, register_cell_magic,
29 register_line_cell_magic)
25 register_line_cell_magic)
30 from IPython.core.magics import execution, script, code
26 from IPython.core.magics import execution, script, code
31 from IPython.testing import decorators as dec
27 from IPython.testing import decorators as dec
32 from IPython.testing import tools as tt
28 from IPython.testing import tools as tt
33 from IPython.utils import py3compat
29 from IPython.utils import py3compat
34 from IPython.utils.io import capture_output
30 from IPython.utils.io import capture_output
35 from IPython.utils.tempdir import TemporaryDirectory
31 from IPython.utils.tempdir import TemporaryDirectory
36 from IPython.utils.process import find_cmd
32 from IPython.utils.process import find_cmd
37
33
38 if py3compat.PY3:
34 if py3compat.PY3:
39 from io import StringIO
35 from io import StringIO
40 else:
36 else:
41 from StringIO import StringIO
37 from StringIO import StringIO
42
38
43 #-----------------------------------------------------------------------------
44 # Test functions begin
45 #-----------------------------------------------------------------------------
46
39
47 @magic.magics_class
40 @magic.magics_class
48 class DummyMagics(magic.Magics): pass
41 class DummyMagics(magic.Magics): pass
49
42
50 def test_extract_code_ranges():
43 def test_extract_code_ranges():
51 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
44 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
52 expected = [(0, 1),
45 expected = [(0, 1),
53 (2, 3),
46 (2, 3),
54 (4, 6),
47 (4, 6),
55 (6, 9),
48 (6, 9),
56 (9, 14),
49 (9, 14),
57 (16, None),
50 (16, None),
58 (None, 9),
51 (None, 9),
59 (9, None),
52 (9, None),
60 (None, 13),
53 (None, 13),
61 (None, None)]
54 (None, None)]
62 actual = list(code.extract_code_ranges(instr))
55 actual = list(code.extract_code_ranges(instr))
63 nt.assert_equal(actual, expected)
56 nt.assert_equal(actual, expected)
64
57
65 def test_extract_symbols():
58 def test_extract_symbols():
66 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
59 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
67 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
60 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
68 expected = [([], ['a']),
61 expected = [([], ['a']),
69 (["def b():\n return 42\n"], []),
62 (["def b():\n return 42\n"], []),
70 (["class A: pass\n"], []),
63 (["class A: pass\n"], []),
71 (["class A: pass\n", "def b():\n return 42\n"], []),
64 (["class A: pass\n", "def b():\n return 42\n"], []),
72 (["class A: pass\n"], ['a']),
65 (["class A: pass\n"], ['a']),
73 ([], ['z'])]
66 ([], ['z'])]
74 for symbols, exp in zip(symbols_args, expected):
67 for symbols, exp in zip(symbols_args, expected):
75 nt.assert_equal(code.extract_symbols(source, symbols), exp)
68 nt.assert_equal(code.extract_symbols(source, symbols), exp)
76
69
77
70
78 def test_extract_symbols_raises_exception_with_non_python_code():
71 def test_extract_symbols_raises_exception_with_non_python_code():
79 source = ("=begin A Ruby program :)=end\n"
72 source = ("=begin A Ruby program :)=end\n"
80 "def hello\n"
73 "def hello\n"
81 "puts 'Hello world'\n"
74 "puts 'Hello world'\n"
82 "end")
75 "end")
83 with nt.assert_raises(SyntaxError):
76 with nt.assert_raises(SyntaxError):
84 code.extract_symbols(source, "hello")
77 code.extract_symbols(source, "hello")
85
78
86 def test_config():
79 def test_config():
87 """ test that config magic does not raise
80 """ test that config magic does not raise
88 can happen if Configurable init is moved too early into
81 can happen if Configurable init is moved too early into
89 Magics.__init__ as then a Config object will be registerd as a
82 Magics.__init__ as then a Config object will be registerd as a
90 magic.
83 magic.
91 """
84 """
92 ## should not raise.
85 ## should not raise.
93 _ip.magic('config')
86 _ip.magic('config')
94
87
95 def test_rehashx():
88 def test_rehashx():
96 # clear up everything
89 # clear up everything
97 _ip = get_ipython()
90 _ip = get_ipython()
98 _ip.alias_manager.clear_aliases()
91 _ip.alias_manager.clear_aliases()
99 del _ip.db['syscmdlist']
92 del _ip.db['syscmdlist']
100
93
101 _ip.magic('rehashx')
94 _ip.magic('rehashx')
102 # Practically ALL ipython development systems will have more than 10 aliases
95 # Practically ALL ipython development systems will have more than 10 aliases
103
96
104 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
97 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
105 for name, cmd in _ip.alias_manager.aliases:
98 for name, cmd in _ip.alias_manager.aliases:
106 # we must strip dots from alias names
99 # we must strip dots from alias names
107 nt.assert_not_in('.', name)
100 nt.assert_not_in('.', name)
108
101
109 # rehashx must fill up syscmdlist
102 # rehashx must fill up syscmdlist
110 scoms = _ip.db['syscmdlist']
103 scoms = _ip.db['syscmdlist']
111 nt.assert_true(len(scoms) > 10)
104 nt.assert_true(len(scoms) > 10)
112
105
113
106
114 def test_magic_parse_options():
107 def test_magic_parse_options():
115 """Test that we don't mangle paths when parsing magic options."""
108 """Test that we don't mangle paths when parsing magic options."""
116 ip = get_ipython()
109 ip = get_ipython()
117 path = 'c:\\x'
110 path = 'c:\\x'
118 m = DummyMagics(ip)
111 m = DummyMagics(ip)
119 opts = m.parse_options('-f %s' % path,'f:')[0]
112 opts = m.parse_options('-f %s' % path,'f:')[0]
120 # argv splitting is os-dependent
113 # argv splitting is os-dependent
121 if os.name == 'posix':
114 if os.name == 'posix':
122 expected = 'c:x'
115 expected = 'c:x'
123 else:
116 else:
124 expected = path
117 expected = path
125 nt.assert_equal(opts['f'], expected)
118 nt.assert_equal(opts['f'], expected)
126
119
127 def test_magic_parse_long_options():
120 def test_magic_parse_long_options():
128 """Magic.parse_options can handle --foo=bar long options"""
121 """Magic.parse_options can handle --foo=bar long options"""
129 ip = get_ipython()
122 ip = get_ipython()
130 m = DummyMagics(ip)
123 m = DummyMagics(ip)
131 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
124 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
132 nt.assert_in('foo', opts)
125 nt.assert_in('foo', opts)
133 nt.assert_in('bar', opts)
126 nt.assert_in('bar', opts)
134 nt.assert_equal(opts['bar'], "bubble")
127 nt.assert_equal(opts['bar'], "bubble")
135
128
136
129
137 @dec.skip_without('sqlite3')
130 @dec.skip_without('sqlite3')
138 def doctest_hist_f():
131 def doctest_hist_f():
139 """Test %hist -f with temporary filename.
132 """Test %hist -f with temporary filename.
140
133
141 In [9]: import tempfile
134 In [9]: import tempfile
142
135
143 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
136 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
144
137
145 In [11]: %hist -nl -f $tfile 3
138 In [11]: %hist -nl -f $tfile 3
146
139
147 In [13]: import os; os.unlink(tfile)
140 In [13]: import os; os.unlink(tfile)
148 """
141 """
149
142
150
143
151 @dec.skip_without('sqlite3')
144 @dec.skip_without('sqlite3')
152 def doctest_hist_r():
145 def doctest_hist_r():
153 """Test %hist -r
146 """Test %hist -r
154
147
155 XXX - This test is not recording the output correctly. For some reason, in
148 XXX - This test is not recording the output correctly. For some reason, in
156 testing mode the raw history isn't getting populated. No idea why.
149 testing mode the raw history isn't getting populated. No idea why.
157 Disabling the output checking for now, though at least we do run it.
150 Disabling the output checking for now, though at least we do run it.
158
151
159 In [1]: 'hist' in _ip.lsmagic()
152 In [1]: 'hist' in _ip.lsmagic()
160 Out[1]: True
153 Out[1]: True
161
154
162 In [2]: x=1
155 In [2]: x=1
163
156
164 In [3]: %hist -rl 2
157 In [3]: %hist -rl 2
165 x=1 # random
158 x=1 # random
166 %hist -r 2
159 %hist -r 2
167 """
160 """
168
161
169
162
170 @dec.skip_without('sqlite3')
163 @dec.skip_without('sqlite3')
171 def doctest_hist_op():
164 def doctest_hist_op():
172 """Test %hist -op
165 """Test %hist -op
173
166
174 In [1]: class b(float):
167 In [1]: class b(float):
175 ...: pass
168 ...: pass
176 ...:
169 ...:
177
170
178 In [2]: class s(object):
171 In [2]: class s(object):
179 ...: def __str__(self):
172 ...: def __str__(self):
180 ...: return 's'
173 ...: return 's'
181 ...:
174 ...:
182
175
183 In [3]:
176 In [3]:
184
177
185 In [4]: class r(b):
178 In [4]: class r(b):
186 ...: def __repr__(self):
179 ...: def __repr__(self):
187 ...: return 'r'
180 ...: return 'r'
188 ...:
181 ...:
189
182
190 In [5]: class sr(s,r): pass
183 In [5]: class sr(s,r): pass
191 ...:
184 ...:
192
185
193 In [6]:
186 In [6]:
194
187
195 In [7]: bb=b()
188 In [7]: bb=b()
196
189
197 In [8]: ss=s()
190 In [8]: ss=s()
198
191
199 In [9]: rr=r()
192 In [9]: rr=r()
200
193
201 In [10]: ssrr=sr()
194 In [10]: ssrr=sr()
202
195
203 In [11]: 4.5
196 In [11]: 4.5
204 Out[11]: 4.5
197 Out[11]: 4.5
205
198
206 In [12]: str(ss)
199 In [12]: str(ss)
207 Out[12]: 's'
200 Out[12]: 's'
208
201
209 In [13]:
202 In [13]:
210
203
211 In [14]: %hist -op
204 In [14]: %hist -op
212 >>> class b:
205 >>> class b:
213 ... pass
206 ... pass
214 ...
207 ...
215 >>> class s(b):
208 >>> class s(b):
216 ... def __str__(self):
209 ... def __str__(self):
217 ... return 's'
210 ... return 's'
218 ...
211 ...
219 >>>
212 >>>
220 >>> class r(b):
213 >>> class r(b):
221 ... def __repr__(self):
214 ... def __repr__(self):
222 ... return 'r'
215 ... return 'r'
223 ...
216 ...
224 >>> class sr(s,r): pass
217 >>> class sr(s,r): pass
225 >>>
218 >>>
226 >>> bb=b()
219 >>> bb=b()
227 >>> ss=s()
220 >>> ss=s()
228 >>> rr=r()
221 >>> rr=r()
229 >>> ssrr=sr()
222 >>> ssrr=sr()
230 >>> 4.5
223 >>> 4.5
231 4.5
224 4.5
232 >>> str(ss)
225 >>> str(ss)
233 's'
226 's'
234 >>>
227 >>>
235 """
228 """
236
229
237 def test_hist_pof():
230 def test_hist_pof():
238 ip = get_ipython()
231 ip = get_ipython()
239 ip.run_cell(u"1+2", store_history=True)
232 ip.run_cell(u"1+2", store_history=True)
240 #raise Exception(ip.history_manager.session_number)
233 #raise Exception(ip.history_manager.session_number)
241 #raise Exception(list(ip.history_manager._get_range_session()))
234 #raise Exception(list(ip.history_manager._get_range_session()))
242 with TemporaryDirectory() as td:
235 with TemporaryDirectory() as td:
243 tf = os.path.join(td, 'hist.py')
236 tf = os.path.join(td, 'hist.py')
244 ip.run_line_magic('history', '-pof %s' % tf)
237 ip.run_line_magic('history', '-pof %s' % tf)
245 assert os.path.isfile(tf)
238 assert os.path.isfile(tf)
246
239
247
240
248 @dec.skip_without('sqlite3')
241 @dec.skip_without('sqlite3')
249 def test_macro():
242 def test_macro():
250 ip = get_ipython()
243 ip = get_ipython()
251 ip.history_manager.reset() # Clear any existing history.
244 ip.history_manager.reset() # Clear any existing history.
252 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
245 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
253 for i, cmd in enumerate(cmds, start=1):
246 for i, cmd in enumerate(cmds, start=1):
254 ip.history_manager.store_inputs(i, cmd)
247 ip.history_manager.store_inputs(i, cmd)
255 ip.magic("macro test 1-3")
248 ip.magic("macro test 1-3")
256 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
249 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
257
250
258 # List macros
251 # List macros
259 nt.assert_in("test", ip.magic("macro"))
252 nt.assert_in("test", ip.magic("macro"))
260
253
261
254
262 @dec.skip_without('sqlite3')
255 @dec.skip_without('sqlite3')
263 def test_macro_run():
256 def test_macro_run():
264 """Test that we can run a multi-line macro successfully."""
257 """Test that we can run a multi-line macro successfully."""
265 ip = get_ipython()
258 ip = get_ipython()
266 ip.history_manager.reset()
259 ip.history_manager.reset()
267 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
260 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
268 "%macro test 2-3"]
261 "%macro test 2-3"]
269 for cmd in cmds:
262 for cmd in cmds:
270 ip.run_cell(cmd, store_history=True)
263 ip.run_cell(cmd, store_history=True)
271 nt.assert_equal(ip.user_ns["test"].value,
264 nt.assert_equal(ip.user_ns["test"].value,
272 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
265 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
273 with tt.AssertPrints("12"):
266 with tt.AssertPrints("12"):
274 ip.run_cell("test")
267 ip.run_cell("test")
275 with tt.AssertPrints("13"):
268 with tt.AssertPrints("13"):
276 ip.run_cell("test")
269 ip.run_cell("test")
277
270
278
271
279 def test_magic_magic():
272 def test_magic_magic():
280 """Test %magic"""
273 """Test %magic"""
281 ip = get_ipython()
274 ip = get_ipython()
282 with capture_output() as captured:
275 with capture_output() as captured:
283 ip.magic("magic")
276 ip.magic("magic")
284
277
285 stdout = captured.stdout
278 stdout = captured.stdout
286 nt.assert_in('%magic', stdout)
279 nt.assert_in('%magic', stdout)
287 nt.assert_in('IPython', stdout)
280 nt.assert_in('IPython', stdout)
288 nt.assert_in('Available', stdout)
281 nt.assert_in('Available', stdout)
289
282
290
283
291 @dec.skipif_not_numpy
284 @dec.skipif_not_numpy
292 def test_numpy_reset_array_undec():
285 def test_numpy_reset_array_undec():
293 "Test '%reset array' functionality"
286 "Test '%reset array' functionality"
294 _ip.ex('import numpy as np')
287 _ip.ex('import numpy as np')
295 _ip.ex('a = np.empty(2)')
288 _ip.ex('a = np.empty(2)')
296 nt.assert_in('a', _ip.user_ns)
289 nt.assert_in('a', _ip.user_ns)
297 _ip.magic('reset -f array')
290 _ip.magic('reset -f array')
298 nt.assert_not_in('a', _ip.user_ns)
291 nt.assert_not_in('a', _ip.user_ns)
299
292
300 def test_reset_out():
293 def test_reset_out():
301 "Test '%reset out' magic"
294 "Test '%reset out' magic"
302 _ip.run_cell("parrot = 'dead'", store_history=True)
295 _ip.run_cell("parrot = 'dead'", store_history=True)
303 # test '%reset -f out', make an Out prompt
296 # test '%reset -f out', make an Out prompt
304 _ip.run_cell("parrot", store_history=True)
297 _ip.run_cell("parrot", store_history=True)
305 nt.assert_true('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
298 nt.assert_true('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
306 _ip.magic('reset -f out')
299 _ip.magic('reset -f out')
307 nt.assert_false('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
300 nt.assert_false('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
308 nt.assert_equal(len(_ip.user_ns['Out']), 0)
301 nt.assert_equal(len(_ip.user_ns['Out']), 0)
309
302
310 def test_reset_in():
303 def test_reset_in():
311 "Test '%reset in' magic"
304 "Test '%reset in' magic"
312 # test '%reset -f in'
305 # test '%reset -f in'
313 _ip.run_cell("parrot", store_history=True)
306 _ip.run_cell("parrot", store_history=True)
314 nt.assert_true('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
307 nt.assert_true('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
315 _ip.magic('%reset -f in')
308 _ip.magic('%reset -f in')
316 nt.assert_false('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
309 nt.assert_false('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
317 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
310 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
318
311
319 def test_reset_dhist():
312 def test_reset_dhist():
320 "Test '%reset dhist' magic"
313 "Test '%reset dhist' magic"
321 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
314 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
322 _ip.magic('cd ' + os.path.dirname(nt.__file__))
315 _ip.magic('cd ' + os.path.dirname(nt.__file__))
323 _ip.magic('cd -')
316 _ip.magic('cd -')
324 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
317 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
325 _ip.magic('reset -f dhist')
318 _ip.magic('reset -f dhist')
326 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
319 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
327 _ip.run_cell("_dh = [d for d in tmp]") #restore
320 _ip.run_cell("_dh = [d for d in tmp]") #restore
328
321
329 def test_reset_in_length():
322 def test_reset_in_length():
330 "Test that '%reset in' preserves In[] length"
323 "Test that '%reset in' preserves In[] length"
331 _ip.run_cell("print 'foo'")
324 _ip.run_cell("print 'foo'")
332 _ip.run_cell("reset -f in")
325 _ip.run_cell("reset -f in")
333 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
326 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
334
327
335 def test_tb_syntaxerror():
328 def test_tb_syntaxerror():
336 """test %tb after a SyntaxError"""
329 """test %tb after a SyntaxError"""
337 ip = get_ipython()
330 ip = get_ipython()
338 ip.run_cell("for")
331 ip.run_cell("for")
339
332
340 # trap and validate stdout
333 # trap and validate stdout
341 save_stdout = sys.stdout
334 save_stdout = sys.stdout
342 try:
335 try:
343 sys.stdout = StringIO()
336 sys.stdout = StringIO()
344 ip.run_cell("%tb")
337 ip.run_cell("%tb")
345 out = sys.stdout.getvalue()
338 out = sys.stdout.getvalue()
346 finally:
339 finally:
347 sys.stdout = save_stdout
340 sys.stdout = save_stdout
348 # trim output, and only check the last line
341 # trim output, and only check the last line
349 last_line = out.rstrip().splitlines()[-1].strip()
342 last_line = out.rstrip().splitlines()[-1].strip()
350 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
343 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
351
344
352
345
353 def test_time():
346 def test_time():
354 ip = get_ipython()
347 ip = get_ipython()
355
348
356 with tt.AssertPrints("Wall time: "):
349 with tt.AssertPrints("Wall time: "):
357 ip.run_cell("%time None")
350 ip.run_cell("%time None")
358
351
359 ip.run_cell("def f(kmjy):\n"
352 ip.run_cell("def f(kmjy):\n"
360 " %time print (2*kmjy)")
353 " %time print (2*kmjy)")
361
354
362 with tt.AssertPrints("Wall time: "):
355 with tt.AssertPrints("Wall time: "):
363 with tt.AssertPrints("hihi", suppress=False):
356 with tt.AssertPrints("hihi", suppress=False):
364 ip.run_cell("f('hi')")
357 ip.run_cell("f('hi')")
365
358
366
359
367 @dec.skip_win32
360 @dec.skip_win32
368 def test_time2():
361 def test_time2():
369 ip = get_ipython()
362 ip = get_ipython()
370
363
371 with tt.AssertPrints("CPU times: user "):
364 with tt.AssertPrints("CPU times: user "):
372 ip.run_cell("%time None")
365 ip.run_cell("%time None")
373
366
374 def test_time3():
367 def test_time3():
375 """Erroneous magic function calls, issue gh-3334"""
368 """Erroneous magic function calls, issue gh-3334"""
376 ip = get_ipython()
369 ip = get_ipython()
377 ip.user_ns.pop('run', None)
370 ip.user_ns.pop('run', None)
378
371
379 with tt.AssertNotPrints("not found", channel='stderr'):
372 with tt.AssertNotPrints("not found", channel='stderr'):
380 ip.run_cell("%%time\n"
373 ip.run_cell("%%time\n"
381 "run = 0\n"
374 "run = 0\n"
382 "run += 1")
375 "run += 1")
383
376
384 @dec.skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
377 @dec.skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
385 def test_time_futures():
378 def test_time_futures():
386 "Test %time with __future__ environments"
379 "Test %time with __future__ environments"
387 ip = get_ipython()
380 ip = get_ipython()
388 ip.autocall = 0
381 ip.autocall = 0
389 ip.run_cell("from __future__ import division")
382 ip.run_cell("from __future__ import division")
390 with tt.AssertPrints('0.25'):
383 with tt.AssertPrints('0.25'):
391 ip.run_line_magic('time', 'print(1/4)')
384 ip.run_line_magic('time', 'print(1/4)')
392 ip.compile.reset_compiler_flags()
385 ip.compile.reset_compiler_flags()
393 with tt.AssertNotPrints('0.25'):
386 with tt.AssertNotPrints('0.25'):
394 ip.run_line_magic('time', 'print(1/4)')
387 ip.run_line_magic('time', 'print(1/4)')
395
388
396 def test_doctest_mode():
389 def test_doctest_mode():
397 "Toggle doctest_mode twice, it should be a no-op and run without error"
390 "Toggle doctest_mode twice, it should be a no-op and run without error"
398 _ip.magic('doctest_mode')
391 _ip.magic('doctest_mode')
399 _ip.magic('doctest_mode')
392 _ip.magic('doctest_mode')
400
393
401
394
402 def test_parse_options():
395 def test_parse_options():
403 """Tests for basic options parsing in magics."""
396 """Tests for basic options parsing in magics."""
404 # These are only the most minimal of tests, more should be added later. At
397 # These are only the most minimal of tests, more should be added later. At
405 # the very least we check that basic text/unicode calls work OK.
398 # the very least we check that basic text/unicode calls work OK.
406 m = DummyMagics(_ip)
399 m = DummyMagics(_ip)
407 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
400 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
408 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
401 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
409
402
410
403
411 def test_dirops():
404 def test_dirops():
412 """Test various directory handling operations."""
405 """Test various directory handling operations."""
413 # curpath = lambda :os.path.splitdrive(py3compat.getcwd())[1].replace('\\','/')
406 # curpath = lambda :os.path.splitdrive(py3compat.getcwd())[1].replace('\\','/')
414 curpath = py3compat.getcwd
407 curpath = py3compat.getcwd
415 startdir = py3compat.getcwd()
408 startdir = py3compat.getcwd()
416 ipdir = os.path.realpath(_ip.ipython_dir)
409 ipdir = os.path.realpath(_ip.ipython_dir)
417 try:
410 try:
418 _ip.magic('cd "%s"' % ipdir)
411 _ip.magic('cd "%s"' % ipdir)
419 nt.assert_equal(curpath(), ipdir)
412 nt.assert_equal(curpath(), ipdir)
420 _ip.magic('cd -')
413 _ip.magic('cd -')
421 nt.assert_equal(curpath(), startdir)
414 nt.assert_equal(curpath(), startdir)
422 _ip.magic('pushd "%s"' % ipdir)
415 _ip.magic('pushd "%s"' % ipdir)
423 nt.assert_equal(curpath(), ipdir)
416 nt.assert_equal(curpath(), ipdir)
424 _ip.magic('popd')
417 _ip.magic('popd')
425 nt.assert_equal(curpath(), startdir)
418 nt.assert_equal(curpath(), startdir)
426 finally:
419 finally:
427 os.chdir(startdir)
420 os.chdir(startdir)
428
421
429
422
430 def test_xmode():
423 def test_xmode():
431 # Calling xmode three times should be a no-op
424 # Calling xmode three times should be a no-op
432 xmode = _ip.InteractiveTB.mode
425 xmode = _ip.InteractiveTB.mode
433 for i in range(3):
426 for i in range(3):
434 _ip.magic("xmode")
427 _ip.magic("xmode")
435 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
428 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
436
429
437 def test_reset_hard():
430 def test_reset_hard():
438 monitor = []
431 monitor = []
439 class A(object):
432 class A(object):
440 def __del__(self):
433 def __del__(self):
441 monitor.append(1)
434 monitor.append(1)
442 def __repr__(self):
435 def __repr__(self):
443 return "<A instance>"
436 return "<A instance>"
444
437
445 _ip.user_ns["a"] = A()
438 _ip.user_ns["a"] = A()
446 _ip.run_cell("a")
439 _ip.run_cell("a")
447
440
448 nt.assert_equal(monitor, [])
441 nt.assert_equal(monitor, [])
449 _ip.magic("reset -f")
442 _ip.magic("reset -f")
450 nt.assert_equal(monitor, [1])
443 nt.assert_equal(monitor, [1])
451
444
452 class TestXdel(tt.TempFileMixin):
445 class TestXdel(tt.TempFileMixin):
453 def test_xdel(self):
446 def test_xdel(self):
454 """Test that references from %run are cleared by xdel."""
447 """Test that references from %run are cleared by xdel."""
455 src = ("class A(object):\n"
448 src = ("class A(object):\n"
456 " monitor = []\n"
449 " monitor = []\n"
457 " def __del__(self):\n"
450 " def __del__(self):\n"
458 " self.monitor.append(1)\n"
451 " self.monitor.append(1)\n"
459 "a = A()\n")
452 "a = A()\n")
460 self.mktmp(src)
453 self.mktmp(src)
461 # %run creates some hidden references...
454 # %run creates some hidden references...
462 _ip.magic("run %s" % self.fname)
455 _ip.magic("run %s" % self.fname)
463 # ... as does the displayhook.
456 # ... as does the displayhook.
464 _ip.run_cell("a")
457 _ip.run_cell("a")
465
458
466 monitor = _ip.user_ns["A"].monitor
459 monitor = _ip.user_ns["A"].monitor
467 nt.assert_equal(monitor, [])
460 nt.assert_equal(monitor, [])
468
461
469 _ip.magic("xdel a")
462 _ip.magic("xdel a")
470
463
471 # Check that a's __del__ method has been called.
464 # Check that a's __del__ method has been called.
472 nt.assert_equal(monitor, [1])
465 nt.assert_equal(monitor, [1])
473
466
474 def doctest_who():
467 def doctest_who():
475 """doctest for %who
468 """doctest for %who
476
469
477 In [1]: %reset -f
470 In [1]: %reset -f
478
471
479 In [2]: alpha = 123
472 In [2]: alpha = 123
480
473
481 In [3]: beta = 'beta'
474 In [3]: beta = 'beta'
482
475
483 In [4]: %who int
476 In [4]: %who int
484 alpha
477 alpha
485
478
486 In [5]: %who str
479 In [5]: %who str
487 beta
480 beta
488
481
489 In [6]: %whos
482 In [6]: %whos
490 Variable Type Data/Info
483 Variable Type Data/Info
491 ----------------------------
484 ----------------------------
492 alpha int 123
485 alpha int 123
493 beta str beta
486 beta str beta
494
487
495 In [7]: %who_ls
488 In [7]: %who_ls
496 Out[7]: ['alpha', 'beta']
489 Out[7]: ['alpha', 'beta']
497 """
490 """
498
491
499 def test_whos():
492 def test_whos():
500 """Check that whos is protected against objects where repr() fails."""
493 """Check that whos is protected against objects where repr() fails."""
501 class A(object):
494 class A(object):
502 def __repr__(self):
495 def __repr__(self):
503 raise Exception()
496 raise Exception()
504 _ip.user_ns['a'] = A()
497 _ip.user_ns['a'] = A()
505 _ip.magic("whos")
498 _ip.magic("whos")
506
499
507 @py3compat.u_format
500 @py3compat.u_format
508 def doctest_precision():
501 def doctest_precision():
509 """doctest for %precision
502 """doctest for %precision
510
503
511 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
504 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
512
505
513 In [2]: %precision 5
506 In [2]: %precision 5
514 Out[2]: {u}'%.5f'
507 Out[2]: {u}'%.5f'
515
508
516 In [3]: f.float_format
509 In [3]: f.float_format
517 Out[3]: {u}'%.5f'
510 Out[3]: {u}'%.5f'
518
511
519 In [4]: %precision %e
512 In [4]: %precision %e
520 Out[4]: {u}'%e'
513 Out[4]: {u}'%e'
521
514
522 In [5]: f(3.1415927)
515 In [5]: f(3.1415927)
523 Out[5]: {u}'3.141593e+00'
516 Out[5]: {u}'3.141593e+00'
524 """
517 """
525
518
526 def test_psearch():
519 def test_psearch():
527 with tt.AssertPrints("dict.fromkeys"):
520 with tt.AssertPrints("dict.fromkeys"):
528 _ip.run_cell("dict.fr*?")
521 _ip.run_cell("dict.fr*?")
529
522
530 def test_timeit_shlex():
523 def test_timeit_shlex():
531 """test shlex issues with timeit (#1109)"""
524 """test shlex issues with timeit (#1109)"""
532 _ip.ex("def f(*a,**kw): pass")
525 _ip.ex("def f(*a,**kw): pass")
533 _ip.magic('timeit -n1 "this is a bug".count(" ")')
526 _ip.magic('timeit -n1 "this is a bug".count(" ")')
534 _ip.magic('timeit -r1 -n1 f(" ", 1)')
527 _ip.magic('timeit -r1 -n1 f(" ", 1)')
535 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
528 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
536 _ip.magic('timeit -r1 -n1 ("a " + "b")')
529 _ip.magic('timeit -r1 -n1 ("a " + "b")')
537 _ip.magic('timeit -r1 -n1 f("a " + "b")')
530 _ip.magic('timeit -r1 -n1 f("a " + "b")')
538 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
531 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
539
532
540
533
541 def test_timeit_arguments():
534 def test_timeit_arguments():
542 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
535 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
543 _ip.magic("timeit ('#')")
536 _ip.magic("timeit ('#')")
544
537
545
538
546 def test_timeit_special_syntax():
539 def test_timeit_special_syntax():
547 "Test %%timeit with IPython special syntax"
540 "Test %%timeit with IPython special syntax"
548 @register_line_magic
541 @register_line_magic
549 def lmagic(line):
542 def lmagic(line):
550 ip = get_ipython()
543 ip = get_ipython()
551 ip.user_ns['lmagic_out'] = line
544 ip.user_ns['lmagic_out'] = line
552
545
553 # line mode test
546 # line mode test
554 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
547 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
555 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
548 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
556 # cell mode test
549 # cell mode test
557 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
550 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
558 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
551 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
559
552
560 def test_timeit_return():
553 def test_timeit_return():
561 """
554 """
562 test wether timeit -o return object
555 test wether timeit -o return object
563 """
556 """
564
557
565 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
558 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
566 assert(res is not None)
559 assert(res is not None)
567
560
568 def test_timeit_quiet():
561 def test_timeit_quiet():
569 """
562 """
570 test quiet option of timeit magic
563 test quiet option of timeit magic
571 """
564 """
572 with tt.AssertNotPrints("loops"):
565 with tt.AssertNotPrints("loops"):
573 _ip.run_cell("%timeit -n1 -r1 -q 1")
566 _ip.run_cell("%timeit -n1 -r1 -q 1")
574
567
575 @dec.skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
568 @dec.skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
576 def test_timeit_futures():
569 def test_timeit_futures():
577 "Test %timeit with __future__ environments"
570 "Test %timeit with __future__ environments"
578 ip = get_ipython()
571 ip = get_ipython()
579 ip.run_cell("from __future__ import division")
572 ip.run_cell("from __future__ import division")
580 with tt.AssertPrints('0.25'):
573 with tt.AssertPrints('0.25'):
581 ip.run_line_magic('timeit', '-n1 -r1 print(1/4)')
574 ip.run_line_magic('timeit', '-n1 -r1 print(1/4)')
582 ip.compile.reset_compiler_flags()
575 ip.compile.reset_compiler_flags()
583 with tt.AssertNotPrints('0.25'):
576 with tt.AssertNotPrints('0.25'):
584 ip.run_line_magic('timeit', '-n1 -r1 print(1/4)')
577 ip.run_line_magic('timeit', '-n1 -r1 print(1/4)')
585
578
586 @dec.skipif(execution.profile is None)
579 @dec.skipif(execution.profile is None)
587 def test_prun_special_syntax():
580 def test_prun_special_syntax():
588 "Test %%prun with IPython special syntax"
581 "Test %%prun with IPython special syntax"
589 @register_line_magic
582 @register_line_magic
590 def lmagic(line):
583 def lmagic(line):
591 ip = get_ipython()
584 ip = get_ipython()
592 ip.user_ns['lmagic_out'] = line
585 ip.user_ns['lmagic_out'] = line
593
586
594 # line mode test
587 # line mode test
595 _ip.run_line_magic('prun', '-q %lmagic my line')
588 _ip.run_line_magic('prun', '-q %lmagic my line')
596 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
589 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
597 # cell mode test
590 # cell mode test
598 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
591 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
599 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
592 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
600
593
601 @dec.skipif(execution.profile is None)
594 @dec.skipif(execution.profile is None)
602 def test_prun_quotes():
595 def test_prun_quotes():
603 "Test that prun does not clobber string escapes (GH #1302)"
596 "Test that prun does not clobber string escapes (GH #1302)"
604 _ip.magic(r"prun -q x = '\t'")
597 _ip.magic(r"prun -q x = '\t'")
605 nt.assert_equal(_ip.user_ns['x'], '\t')
598 nt.assert_equal(_ip.user_ns['x'], '\t')
606
599
607 def test_extension():
600 def test_extension():
608 tmpdir = TemporaryDirectory()
601 tmpdir = TemporaryDirectory()
609 orig_ipython_dir = _ip.ipython_dir
602 orig_ipython_dir = _ip.ipython_dir
610 try:
603 try:
611 _ip.ipython_dir = tmpdir.name
604 _ip.ipython_dir = tmpdir.name
612 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
605 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
613 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
606 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
614 _ip.magic("install_ext %s" % url)
607 _ip.magic("install_ext %s" % url)
615 _ip.user_ns.pop('arq', None)
608 _ip.user_ns.pop('arq', None)
616 invalidate_caches() # Clear import caches
609 invalidate_caches() # Clear import caches
617 _ip.magic("load_ext daft_extension")
610 _ip.magic("load_ext daft_extension")
618 nt.assert_equal(_ip.user_ns['arq'], 185)
611 nt.assert_equal(_ip.user_ns['arq'], 185)
619 _ip.magic("unload_ext daft_extension")
612 _ip.magic("unload_ext daft_extension")
620 assert 'arq' not in _ip.user_ns
613 assert 'arq' not in _ip.user_ns
621 finally:
614 finally:
622 _ip.ipython_dir = orig_ipython_dir
615 _ip.ipython_dir = orig_ipython_dir
623 tmpdir.cleanup()
616 tmpdir.cleanup()
624
617
625
618
626 # The nose skip decorator doesn't work on classes, so this uses unittest's skipIf
619 # The nose skip decorator doesn't work on classes, so this uses unittest's skipIf
627 @skipIf(dec.module_not_available('IPython.nbformat.current'), 'nbformat not importable')
620 @skipIf(dec.module_not_available('IPython.nbformat'), 'nbformat not importable')
628 class NotebookExportMagicTests(TestCase):
621 class NotebookExportMagicTests(TestCase):
629 def test_notebook_export_json(self):
622 def test_notebook_export_json(self):
630 with TemporaryDirectory() as td:
623 with TemporaryDirectory() as td:
631 outfile = os.path.join(td, "nb.ipynb")
624 outfile = os.path.join(td, "nb.ipynb")
632 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
625 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
633 _ip.magic("notebook -e %s" % outfile)
626 _ip.magic("notebook -e %s" % outfile)
634
627
635
628
636 def test_env():
629 def test_env():
637 env = _ip.magic("env")
630 env = _ip.magic("env")
638 assert isinstance(env, dict), type(env)
631 assert isinstance(env, dict), type(env)
639
632
640
633
641 class CellMagicTestCase(TestCase):
634 class CellMagicTestCase(TestCase):
642
635
643 def check_ident(self, magic):
636 def check_ident(self, magic):
644 # Manually called, we get the result
637 # Manually called, we get the result
645 out = _ip.run_cell_magic(magic, 'a', 'b')
638 out = _ip.run_cell_magic(magic, 'a', 'b')
646 nt.assert_equal(out, ('a','b'))
639 nt.assert_equal(out, ('a','b'))
647 # Via run_cell, it goes into the user's namespace via displayhook
640 # Via run_cell, it goes into the user's namespace via displayhook
648 _ip.run_cell('%%' + magic +' c\nd')
641 _ip.run_cell('%%' + magic +' c\nd')
649 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
642 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
650
643
651 def test_cell_magic_func_deco(self):
644 def test_cell_magic_func_deco(self):
652 "Cell magic using simple decorator"
645 "Cell magic using simple decorator"
653 @register_cell_magic
646 @register_cell_magic
654 def cellm(line, cell):
647 def cellm(line, cell):
655 return line, cell
648 return line, cell
656
649
657 self.check_ident('cellm')
650 self.check_ident('cellm')
658
651
659 def test_cell_magic_reg(self):
652 def test_cell_magic_reg(self):
660 "Cell magic manually registered"
653 "Cell magic manually registered"
661 def cellm(line, cell):
654 def cellm(line, cell):
662 return line, cell
655 return line, cell
663
656
664 _ip.register_magic_function(cellm, 'cell', 'cellm2')
657 _ip.register_magic_function(cellm, 'cell', 'cellm2')
665 self.check_ident('cellm2')
658 self.check_ident('cellm2')
666
659
667 def test_cell_magic_class(self):
660 def test_cell_magic_class(self):
668 "Cell magics declared via a class"
661 "Cell magics declared via a class"
669 @magics_class
662 @magics_class
670 class MyMagics(Magics):
663 class MyMagics(Magics):
671
664
672 @cell_magic
665 @cell_magic
673 def cellm3(self, line, cell):
666 def cellm3(self, line, cell):
674 return line, cell
667 return line, cell
675
668
676 _ip.register_magics(MyMagics)
669 _ip.register_magics(MyMagics)
677 self.check_ident('cellm3')
670 self.check_ident('cellm3')
678
671
679 def test_cell_magic_class2(self):
672 def test_cell_magic_class2(self):
680 "Cell magics declared via a class, #2"
673 "Cell magics declared via a class, #2"
681 @magics_class
674 @magics_class
682 class MyMagics2(Magics):
675 class MyMagics2(Magics):
683
676
684 @cell_magic('cellm4')
677 @cell_magic('cellm4')
685 def cellm33(self, line, cell):
678 def cellm33(self, line, cell):
686 return line, cell
679 return line, cell
687
680
688 _ip.register_magics(MyMagics2)
681 _ip.register_magics(MyMagics2)
689 self.check_ident('cellm4')
682 self.check_ident('cellm4')
690 # Check that nothing is registered as 'cellm33'
683 # Check that nothing is registered as 'cellm33'
691 c33 = _ip.find_cell_magic('cellm33')
684 c33 = _ip.find_cell_magic('cellm33')
692 nt.assert_equal(c33, None)
685 nt.assert_equal(c33, None)
693
686
694 def test_file():
687 def test_file():
695 """Basic %%file"""
688 """Basic %%file"""
696 ip = get_ipython()
689 ip = get_ipython()
697 with TemporaryDirectory() as td:
690 with TemporaryDirectory() as td:
698 fname = os.path.join(td, 'file1')
691 fname = os.path.join(td, 'file1')
699 ip.run_cell_magic("file", fname, u'\n'.join([
692 ip.run_cell_magic("file", fname, u'\n'.join([
700 'line1',
693 'line1',
701 'line2',
694 'line2',
702 ]))
695 ]))
703 with open(fname) as f:
696 with open(fname) as f:
704 s = f.read()
697 s = f.read()
705 nt.assert_in('line1\n', s)
698 nt.assert_in('line1\n', s)
706 nt.assert_in('line2', s)
699 nt.assert_in('line2', s)
707
700
708 def test_file_var_expand():
701 def test_file_var_expand():
709 """%%file $filename"""
702 """%%file $filename"""
710 ip = get_ipython()
703 ip = get_ipython()
711 with TemporaryDirectory() as td:
704 with TemporaryDirectory() as td:
712 fname = os.path.join(td, 'file1')
705 fname = os.path.join(td, 'file1')
713 ip.user_ns['filename'] = fname
706 ip.user_ns['filename'] = fname
714 ip.run_cell_magic("file", '$filename', u'\n'.join([
707 ip.run_cell_magic("file", '$filename', u'\n'.join([
715 'line1',
708 'line1',
716 'line2',
709 'line2',
717 ]))
710 ]))
718 with open(fname) as f:
711 with open(fname) as f:
719 s = f.read()
712 s = f.read()
720 nt.assert_in('line1\n', s)
713 nt.assert_in('line1\n', s)
721 nt.assert_in('line2', s)
714 nt.assert_in('line2', s)
722
715
723 def test_file_unicode():
716 def test_file_unicode():
724 """%%file with unicode cell"""
717 """%%file with unicode cell"""
725 ip = get_ipython()
718 ip = get_ipython()
726 with TemporaryDirectory() as td:
719 with TemporaryDirectory() as td:
727 fname = os.path.join(td, 'file1')
720 fname = os.path.join(td, 'file1')
728 ip.run_cell_magic("file", fname, u'\n'.join([
721 ip.run_cell_magic("file", fname, u'\n'.join([
729 u'liné1',
722 u'liné1',
730 u'liné2',
723 u'liné2',
731 ]))
724 ]))
732 with io.open(fname, encoding='utf-8') as f:
725 with io.open(fname, encoding='utf-8') as f:
733 s = f.read()
726 s = f.read()
734 nt.assert_in(u'liné1\n', s)
727 nt.assert_in(u'liné1\n', s)
735 nt.assert_in(u'liné2', s)
728 nt.assert_in(u'liné2', s)
736
729
737 def test_file_amend():
730 def test_file_amend():
738 """%%file -a amends files"""
731 """%%file -a amends files"""
739 ip = get_ipython()
732 ip = get_ipython()
740 with TemporaryDirectory() as td:
733 with TemporaryDirectory() as td:
741 fname = os.path.join(td, 'file2')
734 fname = os.path.join(td, 'file2')
742 ip.run_cell_magic("file", fname, u'\n'.join([
735 ip.run_cell_magic("file", fname, u'\n'.join([
743 'line1',
736 'line1',
744 'line2',
737 'line2',
745 ]))
738 ]))
746 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
739 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
747 'line3',
740 'line3',
748 'line4',
741 'line4',
749 ]))
742 ]))
750 with open(fname) as f:
743 with open(fname) as f:
751 s = f.read()
744 s = f.read()
752 nt.assert_in('line1\n', s)
745 nt.assert_in('line1\n', s)
753 nt.assert_in('line3\n', s)
746 nt.assert_in('line3\n', s)
754
747
755
748
756 def test_script_config():
749 def test_script_config():
757 ip = get_ipython()
750 ip = get_ipython()
758 ip.config.ScriptMagics.script_magics = ['whoda']
751 ip.config.ScriptMagics.script_magics = ['whoda']
759 sm = script.ScriptMagics(shell=ip)
752 sm = script.ScriptMagics(shell=ip)
760 nt.assert_in('whoda', sm.magics['cell'])
753 nt.assert_in('whoda', sm.magics['cell'])
761
754
762 @dec.skip_win32
755 @dec.skip_win32
763 def test_script_out():
756 def test_script_out():
764 ip = get_ipython()
757 ip = get_ipython()
765 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
758 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
766 nt.assert_equal(ip.user_ns['output'], 'hi\n')
759 nt.assert_equal(ip.user_ns['output'], 'hi\n')
767
760
768 @dec.skip_win32
761 @dec.skip_win32
769 def test_script_err():
762 def test_script_err():
770 ip = get_ipython()
763 ip = get_ipython()
771 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
764 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
772 nt.assert_equal(ip.user_ns['error'], 'hello\n')
765 nt.assert_equal(ip.user_ns['error'], 'hello\n')
773
766
774 @dec.skip_win32
767 @dec.skip_win32
775 def test_script_out_err():
768 def test_script_out_err():
776 ip = get_ipython()
769 ip = get_ipython()
777 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
770 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
778 nt.assert_equal(ip.user_ns['output'], 'hi\n')
771 nt.assert_equal(ip.user_ns['output'], 'hi\n')
779 nt.assert_equal(ip.user_ns['error'], 'hello\n')
772 nt.assert_equal(ip.user_ns['error'], 'hello\n')
780
773
781 @dec.skip_win32
774 @dec.skip_win32
782 def test_script_bg_out():
775 def test_script_bg_out():
783 ip = get_ipython()
776 ip = get_ipython()
784 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
777 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
785 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
778 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
786
779
787 @dec.skip_win32
780 @dec.skip_win32
788 def test_script_bg_err():
781 def test_script_bg_err():
789 ip = get_ipython()
782 ip = get_ipython()
790 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
783 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
791 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
784 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
792
785
793 @dec.skip_win32
786 @dec.skip_win32
794 def test_script_bg_out_err():
787 def test_script_bg_out_err():
795 ip = get_ipython()
788 ip = get_ipython()
796 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
789 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
797 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
790 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
798 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
791 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
799
792
800 def test_script_defaults():
793 def test_script_defaults():
801 ip = get_ipython()
794 ip = get_ipython()
802 for cmd in ['sh', 'bash', 'perl', 'ruby']:
795 for cmd in ['sh', 'bash', 'perl', 'ruby']:
803 try:
796 try:
804 find_cmd(cmd)
797 find_cmd(cmd)
805 except Exception:
798 except Exception:
806 pass
799 pass
807 else:
800 else:
808 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
801 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
809
802
810
803
811 @magics_class
804 @magics_class
812 class FooFoo(Magics):
805 class FooFoo(Magics):
813 """class with both %foo and %%foo magics"""
806 """class with both %foo and %%foo magics"""
814 @line_magic('foo')
807 @line_magic('foo')
815 def line_foo(self, line):
808 def line_foo(self, line):
816 "I am line foo"
809 "I am line foo"
817 pass
810 pass
818
811
819 @cell_magic("foo")
812 @cell_magic("foo")
820 def cell_foo(self, line, cell):
813 def cell_foo(self, line, cell):
821 "I am cell foo, not line foo"
814 "I am cell foo, not line foo"
822 pass
815 pass
823
816
824 def test_line_cell_info():
817 def test_line_cell_info():
825 """%%foo and %foo magics are distinguishable to inspect"""
818 """%%foo and %foo magics are distinguishable to inspect"""
826 ip = get_ipython()
819 ip = get_ipython()
827 ip.magics_manager.register(FooFoo)
820 ip.magics_manager.register(FooFoo)
828 oinfo = ip.object_inspect('foo')
821 oinfo = ip.object_inspect('foo')
829 nt.assert_true(oinfo['found'])
822 nt.assert_true(oinfo['found'])
830 nt.assert_true(oinfo['ismagic'])
823 nt.assert_true(oinfo['ismagic'])
831
824
832 oinfo = ip.object_inspect('%%foo')
825 oinfo = ip.object_inspect('%%foo')
833 nt.assert_true(oinfo['found'])
826 nt.assert_true(oinfo['found'])
834 nt.assert_true(oinfo['ismagic'])
827 nt.assert_true(oinfo['ismagic'])
835 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
828 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
836
829
837 oinfo = ip.object_inspect('%foo')
830 oinfo = ip.object_inspect('%foo')
838 nt.assert_true(oinfo['found'])
831 nt.assert_true(oinfo['found'])
839 nt.assert_true(oinfo['ismagic'])
832 nt.assert_true(oinfo['ismagic'])
840 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
833 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
841
834
842 def test_multiple_magics():
835 def test_multiple_magics():
843 ip = get_ipython()
836 ip = get_ipython()
844 foo1 = FooFoo(ip)
837 foo1 = FooFoo(ip)
845 foo2 = FooFoo(ip)
838 foo2 = FooFoo(ip)
846 mm = ip.magics_manager
839 mm = ip.magics_manager
847 mm.register(foo1)
840 mm.register(foo1)
848 nt.assert_true(mm.magics['line']['foo'].__self__ is foo1)
841 nt.assert_true(mm.magics['line']['foo'].__self__ is foo1)
849 mm.register(foo2)
842 mm.register(foo2)
850 nt.assert_true(mm.magics['line']['foo'].__self__ is foo2)
843 nt.assert_true(mm.magics['line']['foo'].__self__ is foo2)
851
844
852 def test_alias_magic():
845 def test_alias_magic():
853 """Test %alias_magic."""
846 """Test %alias_magic."""
854 ip = get_ipython()
847 ip = get_ipython()
855 mm = ip.magics_manager
848 mm = ip.magics_manager
856
849
857 # Basic operation: both cell and line magics are created, if possible.
850 # Basic operation: both cell and line magics are created, if possible.
858 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
851 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
859 nt.assert_in('timeit_alias', mm.magics['line'])
852 nt.assert_in('timeit_alias', mm.magics['line'])
860 nt.assert_in('timeit_alias', mm.magics['cell'])
853 nt.assert_in('timeit_alias', mm.magics['cell'])
861
854
862 # --cell is specified, line magic not created.
855 # --cell is specified, line magic not created.
863 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
856 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
864 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
857 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
865 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
858 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
866
859
867 # Test that line alias is created successfully.
860 # Test that line alias is created successfully.
868 ip.run_line_magic('alias_magic', '--line env_alias env')
861 ip.run_line_magic('alias_magic', '--line env_alias env')
869 nt.assert_equal(ip.run_line_magic('env', ''),
862 nt.assert_equal(ip.run_line_magic('env', ''),
870 ip.run_line_magic('env_alias', ''))
863 ip.run_line_magic('env_alias', ''))
871
864
872 def test_save():
865 def test_save():
873 """Test %save."""
866 """Test %save."""
874 ip = get_ipython()
867 ip = get_ipython()
875 ip.history_manager.reset() # Clear any existing history.
868 ip.history_manager.reset() # Clear any existing history.
876 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
869 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
877 for i, cmd in enumerate(cmds, start=1):
870 for i, cmd in enumerate(cmds, start=1):
878 ip.history_manager.store_inputs(i, cmd)
871 ip.history_manager.store_inputs(i, cmd)
879 with TemporaryDirectory() as tmpdir:
872 with TemporaryDirectory() as tmpdir:
880 file = os.path.join(tmpdir, "testsave.py")
873 file = os.path.join(tmpdir, "testsave.py")
881 ip.run_line_magic("save", "%s 1-10" % file)
874 ip.run_line_magic("save", "%s 1-10" % file)
882 with open(file) as f:
875 with open(file) as f:
883 content = f.read()
876 content = f.read()
884 nt.assert_equal(content.count(cmds[0]), 1)
877 nt.assert_equal(content.count(cmds[0]), 1)
885 nt.assert_in('coding: utf-8', content)
878 nt.assert_in('coding: utf-8', content)
886 ip.run_line_magic("save", "-a %s 1-10" % file)
879 ip.run_line_magic("save", "-a %s 1-10" % file)
887 with open(file) as f:
880 with open(file) as f:
888 content = f.read()
881 content = f.read()
889 nt.assert_equal(content.count(cmds[0]), 2)
882 nt.assert_equal(content.count(cmds[0]), 2)
890 nt.assert_in('coding: utf-8', content)
883 nt.assert_in('coding: utf-8', content)
891
884
892
885
893 def test_store():
886 def test_store():
894 """Test %store."""
887 """Test %store."""
895 ip = get_ipython()
888 ip = get_ipython()
896 ip.run_line_magic('load_ext', 'storemagic')
889 ip.run_line_magic('load_ext', 'storemagic')
897
890
898 # make sure the storage is empty
891 # make sure the storage is empty
899 ip.run_line_magic('store', '-z')
892 ip.run_line_magic('store', '-z')
900 ip.user_ns['var'] = 42
893 ip.user_ns['var'] = 42
901 ip.run_line_magic('store', 'var')
894 ip.run_line_magic('store', 'var')
902 ip.user_ns['var'] = 39
895 ip.user_ns['var'] = 39
903 ip.run_line_magic('store', '-r')
896 ip.run_line_magic('store', '-r')
904 nt.assert_equal(ip.user_ns['var'], 42)
897 nt.assert_equal(ip.user_ns['var'], 42)
905
898
906 ip.run_line_magic('store', '-d var')
899 ip.run_line_magic('store', '-d var')
907 ip.user_ns['var'] = 39
900 ip.user_ns['var'] = 39
908 ip.run_line_magic('store' , '-r')
901 ip.run_line_magic('store' , '-r')
909 nt.assert_equal(ip.user_ns['var'], 39)
902 nt.assert_equal(ip.user_ns['var'], 39)
910
903
911
904
912 def _run_edit_test(arg_s, exp_filename=None,
905 def _run_edit_test(arg_s, exp_filename=None,
913 exp_lineno=-1,
906 exp_lineno=-1,
914 exp_contents=None,
907 exp_contents=None,
915 exp_is_temp=None):
908 exp_is_temp=None):
916 ip = get_ipython()
909 ip = get_ipython()
917 M = code.CodeMagics(ip)
910 M = code.CodeMagics(ip)
918 last_call = ['','']
911 last_call = ['','']
919 opts,args = M.parse_options(arg_s,'prxn:')
912 opts,args = M.parse_options(arg_s,'prxn:')
920 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
913 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
921
914
922 if exp_filename is not None:
915 if exp_filename is not None:
923 nt.assert_equal(exp_filename, filename)
916 nt.assert_equal(exp_filename, filename)
924 if exp_contents is not None:
917 if exp_contents is not None:
925 with io.open(filename, 'r', encoding='utf-8') as f:
918 with io.open(filename, 'r', encoding='utf-8') as f:
926 contents = f.read()
919 contents = f.read()
927 nt.assert_equal(exp_contents, contents)
920 nt.assert_equal(exp_contents, contents)
928 if exp_lineno != -1:
921 if exp_lineno != -1:
929 nt.assert_equal(exp_lineno, lineno)
922 nt.assert_equal(exp_lineno, lineno)
930 if exp_is_temp is not None:
923 if exp_is_temp is not None:
931 nt.assert_equal(exp_is_temp, is_temp)
924 nt.assert_equal(exp_is_temp, is_temp)
932
925
933
926
934 def test_edit_interactive():
927 def test_edit_interactive():
935 """%edit on interactively defined objects"""
928 """%edit on interactively defined objects"""
936 ip = get_ipython()
929 ip = get_ipython()
937 n = ip.execution_count
930 n = ip.execution_count
938 ip.run_cell(u"def foo(): return 1", store_history=True)
931 ip.run_cell(u"def foo(): return 1", store_history=True)
939
932
940 try:
933 try:
941 _run_edit_test("foo")
934 _run_edit_test("foo")
942 except code.InteractivelyDefined as e:
935 except code.InteractivelyDefined as e:
943 nt.assert_equal(e.index, n)
936 nt.assert_equal(e.index, n)
944 else:
937 else:
945 raise AssertionError("Should have raised InteractivelyDefined")
938 raise AssertionError("Should have raised InteractivelyDefined")
946
939
947
940
948 def test_edit_cell():
941 def test_edit_cell():
949 """%edit [cell id]"""
942 """%edit [cell id]"""
950 ip = get_ipython()
943 ip = get_ipython()
951
944
952 ip.run_cell(u"def foo(): return 1", store_history=True)
945 ip.run_cell(u"def foo(): return 1", store_history=True)
953
946
954 # test
947 # test
955 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
948 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
956
949
957 def test_bookmark():
950 def test_bookmark():
958 ip = get_ipython()
951 ip = get_ipython()
959 ip.run_line_magic('bookmark', 'bmname')
952 ip.run_line_magic('bookmark', 'bmname')
960 with tt.AssertPrints('bmname'):
953 with tt.AssertPrints('bmname'):
961 ip.run_line_magic('bookmark', '-l')
954 ip.run_line_magic('bookmark', '-l')
962 ip.run_line_magic('bookmark', '-d bmname')
955 ip.run_line_magic('bookmark', '-d bmname')
@@ -1,514 +1,512 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for code execution (%run and related), which is particularly tricky.
2 """Tests for code execution (%run and related), which is particularly tricky.
3
3
4 Because of how %run manages namespaces, and the fact that we are trying here to
4 Because of how %run manages namespaces, and the fact that we are trying here to
5 verify subtle object deletion and reference counting issues, the %run tests
5 verify subtle object deletion and reference counting issues, the %run tests
6 will be kept in this separate file. This makes it easier to aggregate in one
6 will be kept in this separate file. This makes it easier to aggregate in one
7 place the tricks needed to handle it; most other magics are much easier to test
7 place the tricks needed to handle it; most other magics are much easier to test
8 and we do so in a common test_magic file.
8 and we do so in a common test_magic file.
9 """
9 """
10
11 # Copyright (c) IPython Development Team.
12 # Distributed under the terms of the Modified BSD License.
13
10 from __future__ import absolute_import
14 from __future__ import absolute_import
11
15
12 #-----------------------------------------------------------------------------
13 # Imports
14 #-----------------------------------------------------------------------------
15
16
16 import functools
17 import functools
17 import os
18 import os
18 from os.path import join as pjoin
19 from os.path import join as pjoin
19 import random
20 import random
20 import sys
21 import sys
21 import tempfile
22 import tempfile
22 import textwrap
23 import textwrap
23 import unittest
24 import unittest
24
25
25 import nose.tools as nt
26 import nose.tools as nt
26 from nose import SkipTest
27 from nose import SkipTest
27
28
28 from IPython.testing import decorators as dec
29 from IPython.testing import decorators as dec
29 from IPython.testing import tools as tt
30 from IPython.testing import tools as tt
30 from IPython.utils import py3compat
31 from IPython.utils import py3compat
31 from IPython.utils.io import capture_output
32 from IPython.utils.io import capture_output
32 from IPython.utils.tempdir import TemporaryDirectory
33 from IPython.utils.tempdir import TemporaryDirectory
33 from IPython.core import debugger
34 from IPython.core import debugger
34
35
35 #-----------------------------------------------------------------------------
36 # Test functions begin
37 #-----------------------------------------------------------------------------
38
36
39 def doctest_refbug():
37 def doctest_refbug():
40 """Very nasty problem with references held by multiple runs of a script.
38 """Very nasty problem with references held by multiple runs of a script.
41 See: https://github.com/ipython/ipython/issues/141
39 See: https://github.com/ipython/ipython/issues/141
42
40
43 In [1]: _ip.clear_main_mod_cache()
41 In [1]: _ip.clear_main_mod_cache()
44 # random
42 # random
45
43
46 In [2]: %run refbug
44 In [2]: %run refbug
47
45
48 In [3]: call_f()
46 In [3]: call_f()
49 lowercased: hello
47 lowercased: hello
50
48
51 In [4]: %run refbug
49 In [4]: %run refbug
52
50
53 In [5]: call_f()
51 In [5]: call_f()
54 lowercased: hello
52 lowercased: hello
55 lowercased: hello
53 lowercased: hello
56 """
54 """
57
55
58
56
59 def doctest_run_builtins():
57 def doctest_run_builtins():
60 r"""Check that %run doesn't damage __builtins__.
58 r"""Check that %run doesn't damage __builtins__.
61
59
62 In [1]: import tempfile
60 In [1]: import tempfile
63
61
64 In [2]: bid1 = id(__builtins__)
62 In [2]: bid1 = id(__builtins__)
65
63
66 In [3]: fname = tempfile.mkstemp('.py')[1]
64 In [3]: fname = tempfile.mkstemp('.py')[1]
67
65
68 In [3]: f = open(fname,'w')
66 In [3]: f = open(fname,'w')
69
67
70 In [4]: dummy= f.write('pass\n')
68 In [4]: dummy= f.write('pass\n')
71
69
72 In [5]: f.flush()
70 In [5]: f.flush()
73
71
74 In [6]: t1 = type(__builtins__)
72 In [6]: t1 = type(__builtins__)
75
73
76 In [7]: %run $fname
74 In [7]: %run $fname
77
75
78 In [7]: f.close()
76 In [7]: f.close()
79
77
80 In [8]: bid2 = id(__builtins__)
78 In [8]: bid2 = id(__builtins__)
81
79
82 In [9]: t2 = type(__builtins__)
80 In [9]: t2 = type(__builtins__)
83
81
84 In [10]: t1 == t2
82 In [10]: t1 == t2
85 Out[10]: True
83 Out[10]: True
86
84
87 In [10]: bid1 == bid2
85 In [10]: bid1 == bid2
88 Out[10]: True
86 Out[10]: True
89
87
90 In [12]: try:
88 In [12]: try:
91 ....: os.unlink(fname)
89 ....: os.unlink(fname)
92 ....: except:
90 ....: except:
93 ....: pass
91 ....: pass
94 ....:
92 ....:
95 """
93 """
96
94
97
95
98 def doctest_run_option_parser():
96 def doctest_run_option_parser():
99 r"""Test option parser in %run.
97 r"""Test option parser in %run.
100
98
101 In [1]: %run print_argv.py
99 In [1]: %run print_argv.py
102 []
100 []
103
101
104 In [2]: %run print_argv.py print*.py
102 In [2]: %run print_argv.py print*.py
105 ['print_argv.py']
103 ['print_argv.py']
106
104
107 In [3]: %run -G print_argv.py print*.py
105 In [3]: %run -G print_argv.py print*.py
108 ['print*.py']
106 ['print*.py']
109
107
110 """
108 """
111
109
112
110
113 @dec.skip_win32
111 @dec.skip_win32
114 def doctest_run_option_parser_for_posix():
112 def doctest_run_option_parser_for_posix():
115 r"""Test option parser in %run (Linux/OSX specific).
113 r"""Test option parser in %run (Linux/OSX specific).
116
114
117 You need double quote to escape glob in POSIX systems:
115 You need double quote to escape glob in POSIX systems:
118
116
119 In [1]: %run print_argv.py print\\*.py
117 In [1]: %run print_argv.py print\\*.py
120 ['print*.py']
118 ['print*.py']
121
119
122 You can't use quote to escape glob in POSIX systems:
120 You can't use quote to escape glob in POSIX systems:
123
121
124 In [2]: %run print_argv.py 'print*.py'
122 In [2]: %run print_argv.py 'print*.py'
125 ['print_argv.py']
123 ['print_argv.py']
126
124
127 """
125 """
128
126
129
127
130 @dec.skip_if_not_win32
128 @dec.skip_if_not_win32
131 def doctest_run_option_parser_for_windows():
129 def doctest_run_option_parser_for_windows():
132 r"""Test option parser in %run (Windows specific).
130 r"""Test option parser in %run (Windows specific).
133
131
134 In Windows, you can't escape ``*` `by backslash:
132 In Windows, you can't escape ``*` `by backslash:
135
133
136 In [1]: %run print_argv.py print\\*.py
134 In [1]: %run print_argv.py print\\*.py
137 ['print\\*.py']
135 ['print\\*.py']
138
136
139 You can use quote to escape glob:
137 You can use quote to escape glob:
140
138
141 In [2]: %run print_argv.py 'print*.py'
139 In [2]: %run print_argv.py 'print*.py'
142 ['print*.py']
140 ['print*.py']
143
141
144 """
142 """
145
143
146
144
147 @py3compat.doctest_refactor_print
145 @py3compat.doctest_refactor_print
148 def doctest_reset_del():
146 def doctest_reset_del():
149 """Test that resetting doesn't cause errors in __del__ methods.
147 """Test that resetting doesn't cause errors in __del__ methods.
150
148
151 In [2]: class A(object):
149 In [2]: class A(object):
152 ...: def __del__(self):
150 ...: def __del__(self):
153 ...: print str("Hi")
151 ...: print str("Hi")
154 ...:
152 ...:
155
153
156 In [3]: a = A()
154 In [3]: a = A()
157
155
158 In [4]: get_ipython().reset()
156 In [4]: get_ipython().reset()
159 Hi
157 Hi
160
158
161 In [5]: 1+1
159 In [5]: 1+1
162 Out[5]: 2
160 Out[5]: 2
163 """
161 """
164
162
165 # For some tests, it will be handy to organize them in a class with a common
163 # For some tests, it will be handy to organize them in a class with a common
166 # setup that makes a temp file
164 # setup that makes a temp file
167
165
168 class TestMagicRunPass(tt.TempFileMixin):
166 class TestMagicRunPass(tt.TempFileMixin):
169
167
170 def setup(self):
168 def setup(self):
171 """Make a valid python temp file."""
169 """Make a valid python temp file."""
172 self.mktmp('pass\n')
170 self.mktmp('pass\n')
173
171
174 def run_tmpfile(self):
172 def run_tmpfile(self):
175 _ip = get_ipython()
173 _ip = get_ipython()
176 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
174 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
177 # See below and ticket https://bugs.launchpad.net/bugs/366353
175 # See below and ticket https://bugs.launchpad.net/bugs/366353
178 _ip.magic('run %s' % self.fname)
176 _ip.magic('run %s' % self.fname)
179
177
180 def run_tmpfile_p(self):
178 def run_tmpfile_p(self):
181 _ip = get_ipython()
179 _ip = get_ipython()
182 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
180 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
183 # See below and ticket https://bugs.launchpad.net/bugs/366353
181 # See below and ticket https://bugs.launchpad.net/bugs/366353
184 _ip.magic('run -p %s' % self.fname)
182 _ip.magic('run -p %s' % self.fname)
185
183
186 def test_builtins_id(self):
184 def test_builtins_id(self):
187 """Check that %run doesn't damage __builtins__ """
185 """Check that %run doesn't damage __builtins__ """
188 _ip = get_ipython()
186 _ip = get_ipython()
189 # Test that the id of __builtins__ is not modified by %run
187 # Test that the id of __builtins__ is not modified by %run
190 bid1 = id(_ip.user_ns['__builtins__'])
188 bid1 = id(_ip.user_ns['__builtins__'])
191 self.run_tmpfile()
189 self.run_tmpfile()
192 bid2 = id(_ip.user_ns['__builtins__'])
190 bid2 = id(_ip.user_ns['__builtins__'])
193 nt.assert_equal(bid1, bid2)
191 nt.assert_equal(bid1, bid2)
194
192
195 def test_builtins_type(self):
193 def test_builtins_type(self):
196 """Check that the type of __builtins__ doesn't change with %run.
194 """Check that the type of __builtins__ doesn't change with %run.
197
195
198 However, the above could pass if __builtins__ was already modified to
196 However, the above could pass if __builtins__ was already modified to
199 be a dict (it should be a module) by a previous use of %run. So we
197 be a dict (it should be a module) by a previous use of %run. So we
200 also check explicitly that it really is a module:
198 also check explicitly that it really is a module:
201 """
199 """
202 _ip = get_ipython()
200 _ip = get_ipython()
203 self.run_tmpfile()
201 self.run_tmpfile()
204 nt.assert_equal(type(_ip.user_ns['__builtins__']),type(sys))
202 nt.assert_equal(type(_ip.user_ns['__builtins__']),type(sys))
205
203
206 def test_prompts(self):
204 def test_prompts(self):
207 """Test that prompts correctly generate after %run"""
205 """Test that prompts correctly generate after %run"""
208 self.run_tmpfile()
206 self.run_tmpfile()
209 _ip = get_ipython()
207 _ip = get_ipython()
210 p2 = _ip.prompt_manager.render('in2').strip()
208 p2 = _ip.prompt_manager.render('in2').strip()
211 nt.assert_equal(p2[:3], '...')
209 nt.assert_equal(p2[:3], '...')
212
210
213 def test_run_profile( self ):
211 def test_run_profile( self ):
214 """Test that the option -p, which invokes the profiler, do not
212 """Test that the option -p, which invokes the profiler, do not
215 crash by invoking execfile"""
213 crash by invoking execfile"""
216 _ip = get_ipython()
214 _ip = get_ipython()
217 self.run_tmpfile_p()
215 self.run_tmpfile_p()
218
216
219
217
220 class TestMagicRunSimple(tt.TempFileMixin):
218 class TestMagicRunSimple(tt.TempFileMixin):
221
219
222 def test_simpledef(self):
220 def test_simpledef(self):
223 """Test that simple class definitions work."""
221 """Test that simple class definitions work."""
224 src = ("class foo: pass\n"
222 src = ("class foo: pass\n"
225 "def f(): return foo()")
223 "def f(): return foo()")
226 self.mktmp(src)
224 self.mktmp(src)
227 _ip.magic('run %s' % self.fname)
225 _ip.magic('run %s' % self.fname)
228 _ip.run_cell('t = isinstance(f(), foo)')
226 _ip.run_cell('t = isinstance(f(), foo)')
229 nt.assert_true(_ip.user_ns['t'])
227 nt.assert_true(_ip.user_ns['t'])
230
228
231 def test_obj_del(self):
229 def test_obj_del(self):
232 """Test that object's __del__ methods are called on exit."""
230 """Test that object's __del__ methods are called on exit."""
233 if sys.platform == 'win32':
231 if sys.platform == 'win32':
234 try:
232 try:
235 import win32api
233 import win32api
236 except ImportError:
234 except ImportError:
237 raise SkipTest("Test requires pywin32")
235 raise SkipTest("Test requires pywin32")
238 src = ("class A(object):\n"
236 src = ("class A(object):\n"
239 " def __del__(self):\n"
237 " def __del__(self):\n"
240 " print 'object A deleted'\n"
238 " print 'object A deleted'\n"
241 "a = A()\n")
239 "a = A()\n")
242 self.mktmp(py3compat.doctest_refactor_print(src))
240 self.mktmp(py3compat.doctest_refactor_print(src))
243 if dec.module_not_available('sqlite3'):
241 if dec.module_not_available('sqlite3'):
244 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
242 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
245 else:
243 else:
246 err = None
244 err = None
247 tt.ipexec_validate(self.fname, 'object A deleted', err)
245 tt.ipexec_validate(self.fname, 'object A deleted', err)
248
246
249 def test_aggressive_namespace_cleanup(self):
247 def test_aggressive_namespace_cleanup(self):
250 """Test that namespace cleanup is not too aggressive GH-238
248 """Test that namespace cleanup is not too aggressive GH-238
251
249
252 Returning from another run magic deletes the namespace"""
250 Returning from another run magic deletes the namespace"""
253 # see ticket https://github.com/ipython/ipython/issues/238
251 # see ticket https://github.com/ipython/ipython/issues/238
254 class secondtmp(tt.TempFileMixin): pass
252 class secondtmp(tt.TempFileMixin): pass
255 empty = secondtmp()
253 empty = secondtmp()
256 empty.mktmp('')
254 empty.mktmp('')
257 # On Windows, the filename will have \users in it, so we need to use the
255 # On Windows, the filename will have \users in it, so we need to use the
258 # repr so that the \u becomes \\u.
256 # repr so that the \u becomes \\u.
259 src = ("ip = get_ipython()\n"
257 src = ("ip = get_ipython()\n"
260 "for i in range(5):\n"
258 "for i in range(5):\n"
261 " try:\n"
259 " try:\n"
262 " ip.magic(%r)\n"
260 " ip.magic(%r)\n"
263 " except NameError as e:\n"
261 " except NameError as e:\n"
264 " print(i)\n"
262 " print(i)\n"
265 " break\n" % ('run ' + empty.fname))
263 " break\n" % ('run ' + empty.fname))
266 self.mktmp(src)
264 self.mktmp(src)
267 _ip.magic('run %s' % self.fname)
265 _ip.magic('run %s' % self.fname)
268 _ip.run_cell('ip == get_ipython()')
266 _ip.run_cell('ip == get_ipython()')
269 nt.assert_equal(_ip.user_ns['i'], 4)
267 nt.assert_equal(_ip.user_ns['i'], 4)
270
268
271 def test_run_second(self):
269 def test_run_second(self):
272 """Test that running a second file doesn't clobber the first, gh-3547
270 """Test that running a second file doesn't clobber the first, gh-3547
273 """
271 """
274 self.mktmp("avar = 1\n"
272 self.mktmp("avar = 1\n"
275 "def afunc():\n"
273 "def afunc():\n"
276 " return avar\n")
274 " return avar\n")
277
275
278 empty = tt.TempFileMixin()
276 empty = tt.TempFileMixin()
279 empty.mktmp("")
277 empty.mktmp("")
280
278
281 _ip.magic('run %s' % self.fname)
279 _ip.magic('run %s' % self.fname)
282 _ip.magic('run %s' % empty.fname)
280 _ip.magic('run %s' % empty.fname)
283 nt.assert_equal(_ip.user_ns['afunc'](), 1)
281 nt.assert_equal(_ip.user_ns['afunc'](), 1)
284
282
285 @dec.skip_win32
283 @dec.skip_win32
286 def test_tclass(self):
284 def test_tclass(self):
287 mydir = os.path.dirname(__file__)
285 mydir = os.path.dirname(__file__)
288 tc = os.path.join(mydir, 'tclass')
286 tc = os.path.join(mydir, 'tclass')
289 src = ("%%run '%s' C-first\n"
287 src = ("%%run '%s' C-first\n"
290 "%%run '%s' C-second\n"
288 "%%run '%s' C-second\n"
291 "%%run '%s' C-third\n") % (tc, tc, tc)
289 "%%run '%s' C-third\n") % (tc, tc, tc)
292 self.mktmp(src, '.ipy')
290 self.mktmp(src, '.ipy')
293 out = """\
291 out = """\
294 ARGV 1-: ['C-first']
292 ARGV 1-: ['C-first']
295 ARGV 1-: ['C-second']
293 ARGV 1-: ['C-second']
296 tclass.py: deleting object: C-first
294 tclass.py: deleting object: C-first
297 ARGV 1-: ['C-third']
295 ARGV 1-: ['C-third']
298 tclass.py: deleting object: C-second
296 tclass.py: deleting object: C-second
299 tclass.py: deleting object: C-third
297 tclass.py: deleting object: C-third
300 """
298 """
301 if dec.module_not_available('sqlite3'):
299 if dec.module_not_available('sqlite3'):
302 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
300 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
303 else:
301 else:
304 err = None
302 err = None
305 tt.ipexec_validate(self.fname, out, err)
303 tt.ipexec_validate(self.fname, out, err)
306
304
307 def test_run_i_after_reset(self):
305 def test_run_i_after_reset(self):
308 """Check that %run -i still works after %reset (gh-693)"""
306 """Check that %run -i still works after %reset (gh-693)"""
309 src = "yy = zz\n"
307 src = "yy = zz\n"
310 self.mktmp(src)
308 self.mktmp(src)
311 _ip.run_cell("zz = 23")
309 _ip.run_cell("zz = 23")
312 _ip.magic('run -i %s' % self.fname)
310 _ip.magic('run -i %s' % self.fname)
313 nt.assert_equal(_ip.user_ns['yy'], 23)
311 nt.assert_equal(_ip.user_ns['yy'], 23)
314 _ip.magic('reset -f')
312 _ip.magic('reset -f')
315 _ip.run_cell("zz = 23")
313 _ip.run_cell("zz = 23")
316 _ip.magic('run -i %s' % self.fname)
314 _ip.magic('run -i %s' % self.fname)
317 nt.assert_equal(_ip.user_ns['yy'], 23)
315 nt.assert_equal(_ip.user_ns['yy'], 23)
318
316
319 def test_unicode(self):
317 def test_unicode(self):
320 """Check that files in odd encodings are accepted."""
318 """Check that files in odd encodings are accepted."""
321 mydir = os.path.dirname(__file__)
319 mydir = os.path.dirname(__file__)
322 na = os.path.join(mydir, 'nonascii.py')
320 na = os.path.join(mydir, 'nonascii.py')
323 _ip.magic('run "%s"' % na)
321 _ip.magic('run "%s"' % na)
324 nt.assert_equal(_ip.user_ns['u'], u'Ўт№Ф')
322 nt.assert_equal(_ip.user_ns['u'], u'Ўт№Ф')
325
323
326 def test_run_py_file_attribute(self):
324 def test_run_py_file_attribute(self):
327 """Test handling of `__file__` attribute in `%run <file>.py`."""
325 """Test handling of `__file__` attribute in `%run <file>.py`."""
328 src = "t = __file__\n"
326 src = "t = __file__\n"
329 self.mktmp(src)
327 self.mktmp(src)
330 _missing = object()
328 _missing = object()
331 file1 = _ip.user_ns.get('__file__', _missing)
329 file1 = _ip.user_ns.get('__file__', _missing)
332 _ip.magic('run %s' % self.fname)
330 _ip.magic('run %s' % self.fname)
333 file2 = _ip.user_ns.get('__file__', _missing)
331 file2 = _ip.user_ns.get('__file__', _missing)
334
332
335 # Check that __file__ was equal to the filename in the script's
333 # Check that __file__ was equal to the filename in the script's
336 # namespace.
334 # namespace.
337 nt.assert_equal(_ip.user_ns['t'], self.fname)
335 nt.assert_equal(_ip.user_ns['t'], self.fname)
338
336
339 # Check that __file__ was not leaked back into user_ns.
337 # Check that __file__ was not leaked back into user_ns.
340 nt.assert_equal(file1, file2)
338 nt.assert_equal(file1, file2)
341
339
342 def test_run_ipy_file_attribute(self):
340 def test_run_ipy_file_attribute(self):
343 """Test handling of `__file__` attribute in `%run <file.ipy>`."""
341 """Test handling of `__file__` attribute in `%run <file.ipy>`."""
344 src = "t = __file__\n"
342 src = "t = __file__\n"
345 self.mktmp(src, ext='.ipy')
343 self.mktmp(src, ext='.ipy')
346 _missing = object()
344 _missing = object()
347 file1 = _ip.user_ns.get('__file__', _missing)
345 file1 = _ip.user_ns.get('__file__', _missing)
348 _ip.magic('run %s' % self.fname)
346 _ip.magic('run %s' % self.fname)
349 file2 = _ip.user_ns.get('__file__', _missing)
347 file2 = _ip.user_ns.get('__file__', _missing)
350
348
351 # Check that __file__ was equal to the filename in the script's
349 # Check that __file__ was equal to the filename in the script's
352 # namespace.
350 # namespace.
353 nt.assert_equal(_ip.user_ns['t'], self.fname)
351 nt.assert_equal(_ip.user_ns['t'], self.fname)
354
352
355 # Check that __file__ was not leaked back into user_ns.
353 # Check that __file__ was not leaked back into user_ns.
356 nt.assert_equal(file1, file2)
354 nt.assert_equal(file1, file2)
357
355
358 def test_run_formatting(self):
356 def test_run_formatting(self):
359 """ Test that %run -t -N<N> does not raise a TypeError for N > 1."""
357 """ Test that %run -t -N<N> does not raise a TypeError for N > 1."""
360 src = "pass"
358 src = "pass"
361 self.mktmp(src)
359 self.mktmp(src)
362 _ip.magic('run -t -N 1 %s' % self.fname)
360 _ip.magic('run -t -N 1 %s' % self.fname)
363 _ip.magic('run -t -N 10 %s' % self.fname)
361 _ip.magic('run -t -N 10 %s' % self.fname)
364
362
365 def test_ignore_sys_exit(self):
363 def test_ignore_sys_exit(self):
366 """Test the -e option to ignore sys.exit()"""
364 """Test the -e option to ignore sys.exit()"""
367 src = "import sys; sys.exit(1)"
365 src = "import sys; sys.exit(1)"
368 self.mktmp(src)
366 self.mktmp(src)
369 with tt.AssertPrints('SystemExit'):
367 with tt.AssertPrints('SystemExit'):
370 _ip.magic('run %s' % self.fname)
368 _ip.magic('run %s' % self.fname)
371
369
372 with tt.AssertNotPrints('SystemExit'):
370 with tt.AssertNotPrints('SystemExit'):
373 _ip.magic('run -e %s' % self.fname)
371 _ip.magic('run -e %s' % self.fname)
374
372
375 @dec.skip_without('IPython.nbformat.current') # Requires jsonschema
373 @dec.skip_without('IPython.nbformat') # Requires jsonschema
376 def test_run_nb(self):
374 def test_run_nb(self):
377 """Test %run notebook.ipynb"""
375 """Test %run notebook.ipynb"""
378 from IPython.nbformat import current
376 from IPython.nbformat import v4, writes
379 nb = current.new_notebook(
377 nb = v4.new_notebook(
380 cells=[
378 cells=[
381 current.new_markdown_cell("The Ultimate Question of Everything"),
379 v4.new_markdown_cell("The Ultimate Question of Everything"),
382 current.new_code_cell("answer=42")
380 v4.new_code_cell("answer=42")
383 ]
381 ]
384 )
382 )
385 src = current.writes(nb)
383 src = writes(nb, version=4)
386 self.mktmp(src, ext='.ipynb')
384 self.mktmp(src, ext='.ipynb')
387
385
388 _ip.magic("run %s" % self.fname)
386 _ip.magic("run %s" % self.fname)
389
387
390 nt.assert_equal(_ip.user_ns['answer'], 42)
388 nt.assert_equal(_ip.user_ns['answer'], 42)
391
389
392
390
393
391
394 class TestMagicRunWithPackage(unittest.TestCase):
392 class TestMagicRunWithPackage(unittest.TestCase):
395
393
396 def writefile(self, name, content):
394 def writefile(self, name, content):
397 path = os.path.join(self.tempdir.name, name)
395 path = os.path.join(self.tempdir.name, name)
398 d = os.path.dirname(path)
396 d = os.path.dirname(path)
399 if not os.path.isdir(d):
397 if not os.path.isdir(d):
400 os.makedirs(d)
398 os.makedirs(d)
401 with open(path, 'w') as f:
399 with open(path, 'w') as f:
402 f.write(textwrap.dedent(content))
400 f.write(textwrap.dedent(content))
403
401
404 def setUp(self):
402 def setUp(self):
405 self.package = package = 'tmp{0}'.format(repr(random.random())[2:])
403 self.package = package = 'tmp{0}'.format(repr(random.random())[2:])
406 """Temporary valid python package name."""
404 """Temporary valid python package name."""
407
405
408 self.value = int(random.random() * 10000)
406 self.value = int(random.random() * 10000)
409
407
410 self.tempdir = TemporaryDirectory()
408 self.tempdir = TemporaryDirectory()
411 self.__orig_cwd = py3compat.getcwd()
409 self.__orig_cwd = py3compat.getcwd()
412 sys.path.insert(0, self.tempdir.name)
410 sys.path.insert(0, self.tempdir.name)
413
411
414 self.writefile(os.path.join(package, '__init__.py'), '')
412 self.writefile(os.path.join(package, '__init__.py'), '')
415 self.writefile(os.path.join(package, 'sub.py'), """
413 self.writefile(os.path.join(package, 'sub.py'), """
416 x = {0!r}
414 x = {0!r}
417 """.format(self.value))
415 """.format(self.value))
418 self.writefile(os.path.join(package, 'relative.py'), """
416 self.writefile(os.path.join(package, 'relative.py'), """
419 from .sub import x
417 from .sub import x
420 """)
418 """)
421 self.writefile(os.path.join(package, 'absolute.py'), """
419 self.writefile(os.path.join(package, 'absolute.py'), """
422 from {0}.sub import x
420 from {0}.sub import x
423 """.format(package))
421 """.format(package))
424
422
425 def tearDown(self):
423 def tearDown(self):
426 os.chdir(self.__orig_cwd)
424 os.chdir(self.__orig_cwd)
427 sys.path[:] = [p for p in sys.path if p != self.tempdir.name]
425 sys.path[:] = [p for p in sys.path if p != self.tempdir.name]
428 self.tempdir.cleanup()
426 self.tempdir.cleanup()
429
427
430 def check_run_submodule(self, submodule, opts=''):
428 def check_run_submodule(self, submodule, opts=''):
431 _ip.user_ns.pop('x', None)
429 _ip.user_ns.pop('x', None)
432 _ip.magic('run {2} -m {0}.{1}'.format(self.package, submodule, opts))
430 _ip.magic('run {2} -m {0}.{1}'.format(self.package, submodule, opts))
433 self.assertEqual(_ip.user_ns['x'], self.value,
431 self.assertEqual(_ip.user_ns['x'], self.value,
434 'Variable `x` is not loaded from module `{0}`.'
432 'Variable `x` is not loaded from module `{0}`.'
435 .format(submodule))
433 .format(submodule))
436
434
437 def test_run_submodule_with_absolute_import(self):
435 def test_run_submodule_with_absolute_import(self):
438 self.check_run_submodule('absolute')
436 self.check_run_submodule('absolute')
439
437
440 def test_run_submodule_with_relative_import(self):
438 def test_run_submodule_with_relative_import(self):
441 """Run submodule that has a relative import statement (#2727)."""
439 """Run submodule that has a relative import statement (#2727)."""
442 self.check_run_submodule('relative')
440 self.check_run_submodule('relative')
443
441
444 def test_prun_submodule_with_absolute_import(self):
442 def test_prun_submodule_with_absolute_import(self):
445 self.check_run_submodule('absolute', '-p')
443 self.check_run_submodule('absolute', '-p')
446
444
447 def test_prun_submodule_with_relative_import(self):
445 def test_prun_submodule_with_relative_import(self):
448 self.check_run_submodule('relative', '-p')
446 self.check_run_submodule('relative', '-p')
449
447
450 def with_fake_debugger(func):
448 def with_fake_debugger(func):
451 @functools.wraps(func)
449 @functools.wraps(func)
452 def wrapper(*args, **kwds):
450 def wrapper(*args, **kwds):
453 with tt.monkeypatch(debugger.Pdb, 'run', staticmethod(eval)):
451 with tt.monkeypatch(debugger.Pdb, 'run', staticmethod(eval)):
454 return func(*args, **kwds)
452 return func(*args, **kwds)
455 return wrapper
453 return wrapper
456
454
457 @with_fake_debugger
455 @with_fake_debugger
458 def test_debug_run_submodule_with_absolute_import(self):
456 def test_debug_run_submodule_with_absolute_import(self):
459 self.check_run_submodule('absolute', '-d')
457 self.check_run_submodule('absolute', '-d')
460
458
461 @with_fake_debugger
459 @with_fake_debugger
462 def test_debug_run_submodule_with_relative_import(self):
460 def test_debug_run_submodule_with_relative_import(self):
463 self.check_run_submodule('relative', '-d')
461 self.check_run_submodule('relative', '-d')
464
462
465 def test_run__name__():
463 def test_run__name__():
466 with TemporaryDirectory() as td:
464 with TemporaryDirectory() as td:
467 path = pjoin(td, 'foo.py')
465 path = pjoin(td, 'foo.py')
468 with open(path, 'w') as f:
466 with open(path, 'w') as f:
469 f.write("q = __name__")
467 f.write("q = __name__")
470
468
471 _ip.user_ns.pop('q', None)
469 _ip.user_ns.pop('q', None)
472 _ip.magic('run {}'.format(path))
470 _ip.magic('run {}'.format(path))
473 nt.assert_equal(_ip.user_ns.pop('q'), '__main__')
471 nt.assert_equal(_ip.user_ns.pop('q'), '__main__')
474
472
475 _ip.magic('run -n {}'.format(path))
473 _ip.magic('run -n {}'.format(path))
476 nt.assert_equal(_ip.user_ns.pop('q'), 'foo')
474 nt.assert_equal(_ip.user_ns.pop('q'), 'foo')
477
475
478 def test_run_tb():
476 def test_run_tb():
479 """Test traceback offset in %run"""
477 """Test traceback offset in %run"""
480 with TemporaryDirectory() as td:
478 with TemporaryDirectory() as td:
481 path = pjoin(td, 'foo.py')
479 path = pjoin(td, 'foo.py')
482 with open(path, 'w') as f:
480 with open(path, 'w') as f:
483 f.write('\n'.join([
481 f.write('\n'.join([
484 "def foo():",
482 "def foo():",
485 " return bar()",
483 " return bar()",
486 "def bar():",
484 "def bar():",
487 " raise RuntimeError('hello!')",
485 " raise RuntimeError('hello!')",
488 "foo()",
486 "foo()",
489 ]))
487 ]))
490 with capture_output() as io:
488 with capture_output() as io:
491 _ip.magic('run {}'.format(path))
489 _ip.magic('run {}'.format(path))
492 out = io.stdout
490 out = io.stdout
493 nt.assert_not_in("execfile", out)
491 nt.assert_not_in("execfile", out)
494 nt.assert_in("RuntimeError", out)
492 nt.assert_in("RuntimeError", out)
495 nt.assert_equal(out.count("---->"), 3)
493 nt.assert_equal(out.count("---->"), 3)
496
494
497 @dec.knownfailureif(sys.platform == 'win32', "writes to io.stdout aren't captured on Windows")
495 @dec.knownfailureif(sys.platform == 'win32', "writes to io.stdout aren't captured on Windows")
498 def test_script_tb():
496 def test_script_tb():
499 """Test traceback offset in `ipython script.py`"""
497 """Test traceback offset in `ipython script.py`"""
500 with TemporaryDirectory() as td:
498 with TemporaryDirectory() as td:
501 path = pjoin(td, 'foo.py')
499 path = pjoin(td, 'foo.py')
502 with open(path, 'w') as f:
500 with open(path, 'w') as f:
503 f.write('\n'.join([
501 f.write('\n'.join([
504 "def foo():",
502 "def foo():",
505 " return bar()",
503 " return bar()",
506 "def bar():",
504 "def bar():",
507 " raise RuntimeError('hello!')",
505 " raise RuntimeError('hello!')",
508 "foo()",
506 "foo()",
509 ]))
507 ]))
510 out, err = tt.ipexec(path)
508 out, err = tt.ipexec(path)
511 nt.assert_not_in("execfile", out)
509 nt.assert_not_in("execfile", out)
512 nt.assert_in("RuntimeError", out)
510 nt.assert_in("RuntimeError", out)
513 nt.assert_equal(out.count("---->"), 3)
511 nt.assert_equal(out.count("---->"), 3)
514
512
@@ -1,42 +1,30 b''
1 """Test help output of various IPython entry points"""
1 """Test help output of various IPython entry points"""
2
2
3 #-----------------------------------------------------------------------------
3 # Copyright (c) IPython Development Team.
4 # Copyright (C) 2013 The IPython Development Team
4 # Distributed under the terms of the Modified BSD License.
5 #
6 # Distributed under the terms of the BSD License. The full license is in
7 # the file COPYING, distributed as part of this software.
8 #-----------------------------------------------------------------------------
9
10 #-----------------------------------------------------------------------------
11 # Imports
12 #-----------------------------------------------------------------------------
13
5
14 import IPython.testing.tools as tt
6 import IPython.testing.tools as tt
15 from IPython.testing.decorators import skip_without
7 from IPython.testing.decorators import skip_without
16
8
17 #-----------------------------------------------------------------------------
18 # Tests
19 #-----------------------------------------------------------------------------
20
21
9
22 def test_ipython_help():
10 def test_ipython_help():
23 tt.help_all_output_test()
11 tt.help_all_output_test()
24
12
25 def test_profile_help():
13 def test_profile_help():
26 tt.help_all_output_test("profile")
14 tt.help_all_output_test("profile")
27
15
28 def test_profile_list_help():
16 def test_profile_list_help():
29 tt.help_all_output_test("profile list")
17 tt.help_all_output_test("profile list")
30
18
31 def test_profile_create_help():
19 def test_profile_create_help():
32 tt.help_all_output_test("profile create")
20 tt.help_all_output_test("profile create")
33
21
34 def test_locate_help():
22 def test_locate_help():
35 tt.help_all_output_test("locate")
23 tt.help_all_output_test("locate")
36
24
37 def test_locate_profile_help():
25 def test_locate_profile_help():
38 tt.help_all_output_test("locate profile")
26 tt.help_all_output_test("locate profile")
39
27
40 @skip_without('IPython.nbformat.current') # Requires jsonschema to be installed
28 @skip_without('IPython.nbformat') # Requires jsonschema to be installed
41 def test_trust_help():
29 def test_trust_help():
42 tt.help_all_output_test("trust")
30 tt.help_all_output_test("trust")
General Comments 0
You need to be logged in to leave comments. Login now