##// END OF EJS Templates
adds the optional parameter -s to the magic %load that loads specific function or classes from the python source given. forcing the patch ignoring whitespace changes
Martín Gaitán -
Show More
@@ -1,614 +1,653 b''
1 """Implementation of code management magic functions.
1 """Implementation of code management magic functions.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2012 The IPython Development Team.
4 # Copyright (c) 2012 The IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 # Stdlib
15 # Stdlib
16 import inspect
16 import inspect
17 import io
17 import io
18 import os
18 import os
19 import re
19 import re
20 import sys
20 import sys
21 import ast
21 from itertools import chain
22 from itertools import chain
22
23
23 # Our own packages
24 # Our own packages
24 from IPython.core.error import TryNext, StdinNotImplementedError, UsageError
25 from IPython.core.error import TryNext, StdinNotImplementedError, UsageError
25 from IPython.core.macro import Macro
26 from IPython.core.macro import Macro
26 from IPython.core.magic import Magics, magics_class, line_magic
27 from IPython.core.magic import Magics, magics_class, line_magic
27 from IPython.core.oinspect import find_file, find_source_lines
28 from IPython.core.oinspect import find_file, find_source_lines
28 from IPython.testing.skipdoctest import skip_doctest
29 from IPython.testing.skipdoctest import skip_doctest
29 from IPython.utils import py3compat
30 from IPython.utils import py3compat
30 from IPython.utils.contexts import preserve_keys
31 from IPython.utils.contexts import preserve_keys
31 from IPython.utils.path import get_py_filename, unquote_filename
32 from IPython.utils.path import get_py_filename, unquote_filename
32 from IPython.utils.warn import warn
33 from IPython.utils.warn import warn
33
34
34 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
35 # Magic implementation classes
36 # Magic implementation classes
36 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
37
38
38 # Used for exception handling in magic_edit
39 # Used for exception handling in magic_edit
39 class MacroToEdit(ValueError): pass
40 class MacroToEdit(ValueError): pass
40
41
41 ipython_input_pat = re.compile(r"<ipython\-input\-(\d+)-[a-z\d]+>$")
42 ipython_input_pat = re.compile(r"<ipython\-input\-(\d+)-[a-z\d]+>$")
42
43
43 # To match, e.g. 8-10 1:5 :10 3-
44 # To match, e.g. 8-10 1:5 :10 3-
44 range_re = re.compile(r"""
45 range_re = re.compile(r"""
45 (?P<start>\d+)?
46 (?P<start>\d+)?
46 ((?P<sep>[\-:])
47 ((?P<sep>[\-:])
47 (?P<end>\d+)?)?
48 (?P<end>\d+)?)?
48 $""", re.VERBOSE)
49 $""", re.VERBOSE)
49
50
50
51 def extract_code_ranges(ranges_str):
51 def extract_code_ranges(ranges_str):
52 """Turn a string of range for %%load into 2-tuples of (start, stop)
52 """Turn a string of range for %%load into 2-tuples of (start, stop)
53 ready to use as a slice of the content splitted by lines.
53 ready to use as a slice of the content splitted by lines.
54
54
55 Examples
55 Examples
56 --------
56 --------
57 list(extract_input_ranges("5-10 2"))
57 list(extract_input_ranges("5-10 2"))
58 [(4, 10), (1, 2)]
58 [(4, 10), (1, 2)]
59 """
59 """
60 for range_str in ranges_str.split():
60 for range_str in ranges_str.split():
61 rmatch = range_re.match(range_str)
61 rmatch = range_re.match(range_str)
62 if not rmatch:
62 if not rmatch:
63 continue
63 continue
64 sep = rmatch.group("sep")
64 sep = rmatch.group("sep")
65 start = rmatch.group("start")
65 start = rmatch.group("start")
66 end = rmatch.group("end")
66 end = rmatch.group("end")
67
67
68 if sep == '-':
68 if sep == '-':
69 start = int(start) - 1 if start else None
69 start = int(start) - 1 if start else None
70 end = int(end) if end else None
70 end = int(end) if end else None
71 elif sep == ':':
71 elif sep == ':':
72 start = int(start) - 1 if start else None
72 start = int(start) - 1 if start else None
73 end = int(end) - 1 if end else None
73 end = int(end) - 1 if end else None
74 else:
74 else:
75 end = int(start)
75 end = int(start)
76 start = int(start) - 1
76 start = int(start) - 1
77 yield (start, end)
77 yield (start, end)
78
78
79 def extract_symbols(code, symbols):
80 """
81 Return a list of code fragments for each symbol parsed from code
82 For example, suppose code is::
83
84 a = 10
85
86 def b(): return 42
87
88 class A: pass
89
90 >>> extract_symbols(code, 'A,b'):
91 class A: pass
92
93 def b(): return 42
94 """
95 try:
96 py_code = ast.parse(code)
97 except SyntaxError:
98 return []
99 marks = [(getattr(s, 'name', None), s.lineno) for s in py_code.body]
100 end = None
101 symbols_lines = {}
102 for name, start in reversed(marks):
103 if name:
104 symbols_lines[name] = (start - 1, end)
105 end = start - 1
106 blocks = []
107 code = code.split('\n')
108 for symbol in symbols.split(','):
109 if symbol in symbols_lines:
110 blocks.append('\n'.join(code[slice(*symbols_lines[symbol])]))
111 return blocks
112
79
113
80 class InteractivelyDefined(Exception):
114 class InteractivelyDefined(Exception):
81 """Exception for interactively defined variable in magic_edit"""
115 """Exception for interactively defined variable in magic_edit"""
82 def __init__(self, index):
116 def __init__(self, index):
83 self.index = index
117 self.index = index
84
118
85
119
86 @magics_class
120 @magics_class
87 class CodeMagics(Magics):
121 class CodeMagics(Magics):
88 """Magics related to code management (loading, saving, editing, ...)."""
122 """Magics related to code management (loading, saving, editing, ...)."""
89
123
90 @line_magic
124 @line_magic
91 def save(self, parameter_s=''):
125 def save(self, parameter_s=''):
92 """Save a set of lines or a macro to a given filename.
126 """Save a set of lines or a macro to a given filename.
93
127
94 Usage:\\
128 Usage:\\
95 %save [options] filename n1-n2 n3-n4 ... n5 .. n6 ...
129 %save [options] filename n1-n2 n3-n4 ... n5 .. n6 ...
96
130
97 Options:
131 Options:
98
132
99 -r: use 'raw' input. By default, the 'processed' history is used,
133 -r: use 'raw' input. By default, the 'processed' history is used,
100 so that magics are loaded in their transformed version to valid
134 so that magics are loaded in their transformed version to valid
101 Python. If this option is given, the raw input as typed as the
135 Python. If this option is given, the raw input as typed as the
102 command line is used instead.
136 command line is used instead.
103
137
104 -f: force overwrite. If file exists, %save will prompt for overwrite
138 -f: force overwrite. If file exists, %save will prompt for overwrite
105 unless -f is given.
139 unless -f is given.
106
140
107 -a: append to the file instead of overwriting it.
141 -a: append to the file instead of overwriting it.
108
142
109 This function uses the same syntax as %history for input ranges,
143 This function uses the same syntax as %history for input ranges,
110 then saves the lines to the filename you specify.
144 then saves the lines to the filename you specify.
111
145
112 It adds a '.py' extension to the file if you don't do so yourself, and
146 It adds a '.py' extension to the file if you don't do so yourself, and
113 it asks for confirmation before overwriting existing files.
147 it asks for confirmation before overwriting existing files.
114
148
115 If `-r` option is used, the default extension is `.ipy`.
149 If `-r` option is used, the default extension is `.ipy`.
116 """
150 """
117
151
118 opts,args = self.parse_options(parameter_s,'fra',mode='list')
152 opts,args = self.parse_options(parameter_s,'fra',mode='list')
119 if not args:
153 if not args:
120 raise UsageError('Missing filename.')
154 raise UsageError('Missing filename.')
121 raw = 'r' in opts
155 raw = 'r' in opts
122 force = 'f' in opts
156 force = 'f' in opts
123 append = 'a' in opts
157 append = 'a' in opts
124 mode = 'a' if append else 'w'
158 mode = 'a' if append else 'w'
125 ext = u'.ipy' if raw else u'.py'
159 ext = u'.ipy' if raw else u'.py'
126 fname, codefrom = unquote_filename(args[0]), " ".join(args[1:])
160 fname, codefrom = unquote_filename(args[0]), " ".join(args[1:])
127 if not fname.endswith((u'.py',u'.ipy')):
161 if not fname.endswith((u'.py',u'.ipy')):
128 fname += ext
162 fname += ext
129 file_exists = os.path.isfile(fname)
163 file_exists = os.path.isfile(fname)
130 if file_exists and not force and not append:
164 if file_exists and not force and not append:
131 try:
165 try:
132 overwrite = self.shell.ask_yes_no('File `%s` exists. Overwrite (y/[N])? ' % fname, default='n')
166 overwrite = self.shell.ask_yes_no('File `%s` exists. Overwrite (y/[N])? ' % fname, default='n')
133 except StdinNotImplementedError:
167 except StdinNotImplementedError:
134 print "File `%s` exists. Use `%%save -f %s` to force overwrite" % (fname, parameter_s)
168 print "File `%s` exists. Use `%%save -f %s` to force overwrite" % (fname, parameter_s)
135 return
169 return
136 if not overwrite :
170 if not overwrite :
137 print 'Operation cancelled.'
171 print 'Operation cancelled.'
138 return
172 return
139 try:
173 try:
140 cmds = self.shell.find_user_code(codefrom,raw)
174 cmds = self.shell.find_user_code(codefrom,raw)
141 except (TypeError, ValueError) as e:
175 except (TypeError, ValueError) as e:
142 print e.args[0]
176 print e.args[0]
143 return
177 return
144 out = py3compat.cast_unicode(cmds)
178 out = py3compat.cast_unicode(cmds)
145 with io.open(fname, mode, encoding="utf-8") as f:
179 with io.open(fname, mode, encoding="utf-8") as f:
146 if not file_exists or not append:
180 if not file_exists or not append:
147 f.write(u"# coding: utf-8\n")
181 f.write(u"# coding: utf-8\n")
148 f.write(out)
182 f.write(out)
149 # make sure we end on a newline
183 # make sure we end on a newline
150 if not out.endswith(u'\n'):
184 if not out.endswith(u'\n'):
151 f.write(u'\n')
185 f.write(u'\n')
152 print 'The following commands were written to file `%s`:' % fname
186 print 'The following commands were written to file `%s`:' % fname
153 print cmds
187 print cmds
154
188
155 @line_magic
189 @line_magic
156 def pastebin(self, parameter_s=''):
190 def pastebin(self, parameter_s=''):
157 """Upload code to Github's Gist paste bin, returning the URL.
191 """Upload code to Github's Gist paste bin, returning the URL.
158
192
159 Usage:\\
193 Usage:\\
160 %pastebin [-d "Custom description"] 1-7
194 %pastebin [-d "Custom description"] 1-7
161
195
162 The argument can be an input history range, a filename, or the name of a
196 The argument can be an input history range, a filename, or the name of a
163 string or macro.
197 string or macro.
164
198
165 Options:
199 Options:
166
200
167 -d: Pass a custom description for the gist. The default will say
201 -d: Pass a custom description for the gist. The default will say
168 "Pasted from IPython".
202 "Pasted from IPython".
169 """
203 """
170 opts, args = self.parse_options(parameter_s, 'd:')
204 opts, args = self.parse_options(parameter_s, 'd:')
171
205
172 try:
206 try:
173 code = self.shell.find_user_code(args)
207 code = self.shell.find_user_code(args)
174 except (ValueError, TypeError) as e:
208 except (ValueError, TypeError) as e:
175 print e.args[0]
209 print e.args[0]
176 return
210 return
177
211
178 from urllib2 import urlopen # Deferred import
212 from urllib2 import urlopen # Deferred import
179 import json
213 import json
180 post_data = json.dumps({
214 post_data = json.dumps({
181 "description": opts.get('d', "Pasted from IPython"),
215 "description": opts.get('d', "Pasted from IPython"),
182 "public": True,
216 "public": True,
183 "files": {
217 "files": {
184 "file1.py": {
218 "file1.py": {
185 "content": code
219 "content": code
186 }
220 }
187 }
221 }
188 }).encode('utf-8')
222 }).encode('utf-8')
189
223
190 response = urlopen("https://api.github.com/gists", post_data)
224 response = urlopen("https://api.github.com/gists", post_data)
191 response_data = json.loads(response.read().decode('utf-8'))
225 response_data = json.loads(response.read().decode('utf-8'))
192 return response_data['html_url']
226 return response_data['html_url']
193
227
194 @line_magic
228 @line_magic
195 def loadpy(self, arg_s):
229 def loadpy(self, arg_s):
196 """Alias of `%load`
230 """Alias of `%load`
197
231
198 `%loadpy` has gained some flexibility and dropped the requirement of a `.py`
232 `%loadpy` has gained some flexibility and dropped the requirement of a `.py`
199 extension. So it has been renamed simply into %load. You can look at
233 extension. So it has been renamed simply into %load. You can look at
200 `%load`'s docstring for more info.
234 `%load`'s docstring for more info.
201 """
235 """
202 self.load(arg_s)
236 self.load(arg_s)
203
237
204 @line_magic
238 @line_magic
205 def load(self, arg_s):
239 def load(self, arg_s):
206 """Load code into the current frontend.
240 """Load code into the current frontend.
207
241
208 Usage:\\
242 Usage:\\
209 %load [options] source
243 %load [options] source
210
244
211 where source can be a filename, URL, input history range or macro
245 where source can be a filename, URL, input history range or macro
212
246
213 Options:
247 Options:
214 --------
248 --------
215 -r <lines>: Specify lines or ranges of lines to load from the source.
249 -r <lines>: Specify lines or ranges of lines to load from the source.
216 Ranges could be specified as x-y (x..y) or in python-style x:y
250 Ranges could be specified as x-y (x..y) or in python-style x:y
217 (x..(y-1)). Both limits x and y can be left blank (meaning the
251 (x..(y-1)). Both limits x and y can be left blank (meaning the
218 beginning and end of the file, respectively).
252 beginning and end of the file, respectively).
219
253
254 -s <symbols>: Specify function or classes to load from python source. Could be
255
220 -y : Don't ask confirmation for loading source above 200 000 characters.
256 -y : Don't ask confirmation for loading source above 200 000 characters.
221
257
222 This magic command can either take a local filename, a URL, an history
258 This magic command can either take a local filename, a URL, an history
223 range (see %history) or a macro as argument, it will prompt for
259 range (see %history) or a macro as argument, it will prompt for
224 confirmation before loading source with more than 200 000 characters, unless
260 confirmation before loading source with more than 200 000 characters, unless
225 -y flag is passed or if the frontend does not support raw_input::
261 -y flag is passed or if the frontend does not support raw_input::
226
262
227 %load myscript.py
263 %load myscript.py
228 %load 7-27
264 %load 7-27
229 %load myMacro
265 %load myMacro
230 %load http://www.example.com/myscript.py
266 %load http://www.example.com/myscript.py
231 %load -r 5-10 myscript.py
267 %load -r 5-10 myscript.py
232 %load -r 10-20,30,40: foo.py
268 %load -r 10-20,30,40: foo.py
269 %load -s MyClass,wonder_function myscript.py
233 """
270 """
234 opts,args = self.parse_options(arg_s,'yr:')
271 opts,args = self.parse_options(arg_s,'ys:r:')
235
272
236 if not args:
273 if not args:
237 raise UsageError('Missing filename, URL, input history range, '
274 raise UsageError('Missing filename, URL, input history range, '
238 'or macro.')
275 'or macro.')
239
276
240 contents = self.shell.find_user_code(args)
277 contents = self.shell.find_user_code(args)
241
278
279 if 's' in opts:
280 contents = '\n'.join(extract_symbols(contents, opts['s']))
281
242 if 'r' in opts:
282 if 'r' in opts:
243 ranges = opts['r'].replace(',', ' ')
283 ranges = opts['r'].replace(',', ' ')
244 lines = contents.split('\n')
284 lines = contents.split('\n')
245 slices = extract_code_ranges(ranges)
285 slices = extract_code_ranges(ranges)
246 contents = [lines[slice(*slc)] for slc in slices]
286 contents = [lines[slice(*slc)] for slc in slices]
247 contents = '\n'.join(chain.from_iterable(contents))
287 contents = '\n'.join(chain.from_iterable(contents))
248
288
249 l = len(contents)
289 l = len(contents)
250
290
251
252 # 200 000 is ~ 2500 full 80 caracter lines
291 # 200 000 is ~ 2500 full 80 caracter lines
253 # so in average, more than 5000 lines
292 # so in average, more than 5000 lines
254 if l > 200000 and 'y' not in opts:
293 if l > 200000 and 'y' not in opts:
255 try:
294 try:
256 ans = self.shell.ask_yes_no(("The text you're trying to load seems pretty big"\
295 ans = self.shell.ask_yes_no(("The text you're trying to load seems pretty big"\
257 " (%d characters). Continue (y/[N]) ?" % l), default='n' )
296 " (%d characters). Continue (y/[N]) ?" % l), default='n' )
258 except StdinNotImplementedError:
297 except StdinNotImplementedError:
259 #asume yes if raw input not implemented
298 #asume yes if raw input not implemented
260 ans = True
299 ans = True
261
300
262 if ans is False :
301 if ans is False :
263 print 'Operation cancelled.'
302 print 'Operation cancelled.'
264 return
303 return
265
304
266 self.shell.set_next_input(contents)
305 self.shell.set_next_input(contents)
267
306
268 @staticmethod
307 @staticmethod
269 def _find_edit_target(shell, args, opts, last_call):
308 def _find_edit_target(shell, args, opts, last_call):
270 """Utility method used by magic_edit to find what to edit."""
309 """Utility method used by magic_edit to find what to edit."""
271
310
272 def make_filename(arg):
311 def make_filename(arg):
273 "Make a filename from the given args"
312 "Make a filename from the given args"
274 arg = unquote_filename(arg)
313 arg = unquote_filename(arg)
275 try:
314 try:
276 filename = get_py_filename(arg)
315 filename = get_py_filename(arg)
277 except IOError:
316 except IOError:
278 # If it ends with .py but doesn't already exist, assume we want
317 # If it ends with .py but doesn't already exist, assume we want
279 # a new file.
318 # a new file.
280 if arg.endswith('.py'):
319 if arg.endswith('.py'):
281 filename = arg
320 filename = arg
282 else:
321 else:
283 filename = None
322 filename = None
284 return filename
323 return filename
285
324
286 # Set a few locals from the options for convenience:
325 # Set a few locals from the options for convenience:
287 opts_prev = 'p' in opts
326 opts_prev = 'p' in opts
288 opts_raw = 'r' in opts
327 opts_raw = 'r' in opts
289
328
290 # custom exceptions
329 # custom exceptions
291 class DataIsObject(Exception): pass
330 class DataIsObject(Exception): pass
292
331
293 # Default line number value
332 # Default line number value
294 lineno = opts.get('n',None)
333 lineno = opts.get('n',None)
295
334
296 if opts_prev:
335 if opts_prev:
297 args = '_%s' % last_call[0]
336 args = '_%s' % last_call[0]
298 if args not in shell.user_ns:
337 if args not in shell.user_ns:
299 args = last_call[1]
338 args = last_call[1]
300
339
301 # by default this is done with temp files, except when the given
340 # by default this is done with temp files, except when the given
302 # arg is a filename
341 # arg is a filename
303 use_temp = True
342 use_temp = True
304
343
305 data = ''
344 data = ''
306
345
307 # First, see if the arguments should be a filename.
346 # First, see if the arguments should be a filename.
308 filename = make_filename(args)
347 filename = make_filename(args)
309 if filename:
348 if filename:
310 use_temp = False
349 use_temp = False
311 elif args:
350 elif args:
312 # Mode where user specifies ranges of lines, like in %macro.
351 # Mode where user specifies ranges of lines, like in %macro.
313 data = shell.extract_input_lines(args, opts_raw)
352 data = shell.extract_input_lines(args, opts_raw)
314 if not data:
353 if not data:
315 try:
354 try:
316 # Load the parameter given as a variable. If not a string,
355 # Load the parameter given as a variable. If not a string,
317 # process it as an object instead (below)
356 # process it as an object instead (below)
318
357
319 #print '*** args',args,'type',type(args) # dbg
358 #print '*** args',args,'type',type(args) # dbg
320 data = eval(args, shell.user_ns)
359 data = eval(args, shell.user_ns)
321 if not isinstance(data, basestring):
360 if not isinstance(data, basestring):
322 raise DataIsObject
361 raise DataIsObject
323
362
324 except (NameError,SyntaxError):
363 except (NameError,SyntaxError):
325 # given argument is not a variable, try as a filename
364 # given argument is not a variable, try as a filename
326 filename = make_filename(args)
365 filename = make_filename(args)
327 if filename is None:
366 if filename is None:
328 warn("Argument given (%s) can't be found as a variable "
367 warn("Argument given (%s) can't be found as a variable "
329 "or as a filename." % args)
368 "or as a filename." % args)
330 return (None, None, None)
369 return (None, None, None)
331 use_temp = False
370 use_temp = False
332
371
333 except DataIsObject:
372 except DataIsObject:
334 # macros have a special edit function
373 # macros have a special edit function
335 if isinstance(data, Macro):
374 if isinstance(data, Macro):
336 raise MacroToEdit(data)
375 raise MacroToEdit(data)
337
376
338 # For objects, try to edit the file where they are defined
377 # For objects, try to edit the file where they are defined
339 filename = find_file(data)
378 filename = find_file(data)
340 if filename:
379 if filename:
341 if 'fakemodule' in filename.lower() and \
380 if 'fakemodule' in filename.lower() and \
342 inspect.isclass(data):
381 inspect.isclass(data):
343 # class created by %edit? Try to find source
382 # class created by %edit? Try to find source
344 # by looking for method definitions instead, the
383 # by looking for method definitions instead, the
345 # __module__ in those classes is FakeModule.
384 # __module__ in those classes is FakeModule.
346 attrs = [getattr(data, aname) for aname in dir(data)]
385 attrs = [getattr(data, aname) for aname in dir(data)]
347 for attr in attrs:
386 for attr in attrs:
348 if not inspect.ismethod(attr):
387 if not inspect.ismethod(attr):
349 continue
388 continue
350 filename = find_file(attr)
389 filename = find_file(attr)
351 if filename and \
390 if filename and \
352 'fakemodule' not in filename.lower():
391 'fakemodule' not in filename.lower():
353 # change the attribute to be the edit
392 # change the attribute to be the edit
354 # target instead
393 # target instead
355 data = attr
394 data = attr
356 break
395 break
357
396
358 m = ipython_input_pat.match(os.path.basename(filename))
397 m = ipython_input_pat.match(os.path.basename(filename))
359 if m:
398 if m:
360 raise InteractivelyDefined(int(m.groups()[0]))
399 raise InteractivelyDefined(int(m.groups()[0]))
361
400
362 datafile = 1
401 datafile = 1
363 if filename is None:
402 if filename is None:
364 filename = make_filename(args)
403 filename = make_filename(args)
365 datafile = 1
404 datafile = 1
366 if filename is not None:
405 if filename is not None:
367 # only warn about this if we get a real name
406 # only warn about this if we get a real name
368 warn('Could not find file where `%s` is defined.\n'
407 warn('Could not find file where `%s` is defined.\n'
369 'Opening a file named `%s`' % (args, filename))
408 'Opening a file named `%s`' % (args, filename))
370 # Now, make sure we can actually read the source (if it was
409 # Now, make sure we can actually read the source (if it was
371 # in a temp file it's gone by now).
410 # in a temp file it's gone by now).
372 if datafile:
411 if datafile:
373 if lineno is None:
412 if lineno is None:
374 lineno = find_source_lines(data)
413 lineno = find_source_lines(data)
375 if lineno is None:
414 if lineno is None:
376 filename = make_filename(args)
415 filename = make_filename(args)
377 if filename is None:
416 if filename is None:
378 warn('The file where `%s` was defined '
417 warn('The file where `%s` was defined '
379 'cannot be read or found.' % data)
418 'cannot be read or found.' % data)
380 return (None, None, None)
419 return (None, None, None)
381 use_temp = False
420 use_temp = False
382
421
383 if use_temp:
422 if use_temp:
384 filename = shell.mktempfile(data)
423 filename = shell.mktempfile(data)
385 print 'IPython will make a temporary file named:',filename
424 print 'IPython will make a temporary file named:',filename
386
425
387 # use last_call to remember the state of the previous call, but don't
426 # use last_call to remember the state of the previous call, but don't
388 # let it be clobbered by successive '-p' calls.
427 # let it be clobbered by successive '-p' calls.
389 try:
428 try:
390 last_call[0] = shell.displayhook.prompt_count
429 last_call[0] = shell.displayhook.prompt_count
391 if not opts_prev:
430 if not opts_prev:
392 last_call[1] = args
431 last_call[1] = args
393 except:
432 except:
394 pass
433 pass
395
434
396
435
397 return filename, lineno, use_temp
436 return filename, lineno, use_temp
398
437
399 def _edit_macro(self,mname,macro):
438 def _edit_macro(self,mname,macro):
400 """open an editor with the macro data in a file"""
439 """open an editor with the macro data in a file"""
401 filename = self.shell.mktempfile(macro.value)
440 filename = self.shell.mktempfile(macro.value)
402 self.shell.hooks.editor(filename)
441 self.shell.hooks.editor(filename)
403
442
404 # and make a new macro object, to replace the old one
443 # and make a new macro object, to replace the old one
405 mfile = open(filename)
444 mfile = open(filename)
406 mvalue = mfile.read()
445 mvalue = mfile.read()
407 mfile.close()
446 mfile.close()
408 self.shell.user_ns[mname] = Macro(mvalue)
447 self.shell.user_ns[mname] = Macro(mvalue)
409
448
410 @skip_doctest
449 @skip_doctest
411 @line_magic
450 @line_magic
412 def edit(self, parameter_s='',last_call=['','']):
451 def edit(self, parameter_s='',last_call=['','']):
413 """Bring up an editor and execute the resulting code.
452 """Bring up an editor and execute the resulting code.
414
453
415 Usage:
454 Usage:
416 %edit [options] [args]
455 %edit [options] [args]
417
456
418 %edit runs IPython's editor hook. The default version of this hook is
457 %edit runs IPython's editor hook. The default version of this hook is
419 set to call the editor specified by your $EDITOR environment variable.
458 set to call the editor specified by your $EDITOR environment variable.
420 If this isn't found, it will default to vi under Linux/Unix and to
459 If this isn't found, it will default to vi under Linux/Unix and to
421 notepad under Windows. See the end of this docstring for how to change
460 notepad under Windows. See the end of this docstring for how to change
422 the editor hook.
461 the editor hook.
423
462
424 You can also set the value of this editor via the
463 You can also set the value of this editor via the
425 ``TerminalInteractiveShell.editor`` option in your configuration file.
464 ``TerminalInteractiveShell.editor`` option in your configuration file.
426 This is useful if you wish to use a different editor from your typical
465 This is useful if you wish to use a different editor from your typical
427 default with IPython (and for Windows users who typically don't set
466 default with IPython (and for Windows users who typically don't set
428 environment variables).
467 environment variables).
429
468
430 This command allows you to conveniently edit multi-line code right in
469 This command allows you to conveniently edit multi-line code right in
431 your IPython session.
470 your IPython session.
432
471
433 If called without arguments, %edit opens up an empty editor with a
472 If called without arguments, %edit opens up an empty editor with a
434 temporary file and will execute the contents of this file when you
473 temporary file and will execute the contents of this file when you
435 close it (don't forget to save it!).
474 close it (don't forget to save it!).
436
475
437
476
438 Options:
477 Options:
439
478
440 -n <number>: open the editor at a specified line number. By default,
479 -n <number>: open the editor at a specified line number. By default,
441 the IPython editor hook uses the unix syntax 'editor +N filename', but
480 the IPython editor hook uses the unix syntax 'editor +N filename', but
442 you can configure this by providing your own modified hook if your
481 you can configure this by providing your own modified hook if your
443 favorite editor supports line-number specifications with a different
482 favorite editor supports line-number specifications with a different
444 syntax.
483 syntax.
445
484
446 -p: this will call the editor with the same data as the previous time
485 -p: this will call the editor with the same data as the previous time
447 it was used, regardless of how long ago (in your current session) it
486 it was used, regardless of how long ago (in your current session) it
448 was.
487 was.
449
488
450 -r: use 'raw' input. This option only applies to input taken from the
489 -r: use 'raw' input. This option only applies to input taken from the
451 user's history. By default, the 'processed' history is used, so that
490 user's history. By default, the 'processed' history is used, so that
452 magics are loaded in their transformed version to valid Python. If
491 magics are loaded in their transformed version to valid Python. If
453 this option is given, the raw input as typed as the command line is
492 this option is given, the raw input as typed as the command line is
454 used instead. When you exit the editor, it will be executed by
493 used instead. When you exit the editor, it will be executed by
455 IPython's own processor.
494 IPython's own processor.
456
495
457 -x: do not execute the edited code immediately upon exit. This is
496 -x: do not execute the edited code immediately upon exit. This is
458 mainly useful if you are editing programs which need to be called with
497 mainly useful if you are editing programs which need to be called with
459 command line arguments, which you can then do using %run.
498 command line arguments, which you can then do using %run.
460
499
461
500
462 Arguments:
501 Arguments:
463
502
464 If arguments are given, the following possibilities exist:
503 If arguments are given, the following possibilities exist:
465
504
466 - If the argument is a filename, IPython will load that into the
505 - If the argument is a filename, IPython will load that into the
467 editor. It will execute its contents with execfile() when you exit,
506 editor. It will execute its contents with execfile() when you exit,
468 loading any code in the file into your interactive namespace.
507 loading any code in the file into your interactive namespace.
469
508
470 - The arguments are ranges of input history, e.g. "7 ~1/4-6".
509 - The arguments are ranges of input history, e.g. "7 ~1/4-6".
471 The syntax is the same as in the %history magic.
510 The syntax is the same as in the %history magic.
472
511
473 - If the argument is a string variable, its contents are loaded
512 - If the argument is a string variable, its contents are loaded
474 into the editor. You can thus edit any string which contains
513 into the editor. You can thus edit any string which contains
475 python code (including the result of previous edits).
514 python code (including the result of previous edits).
476
515
477 - If the argument is the name of an object (other than a string),
516 - If the argument is the name of an object (other than a string),
478 IPython will try to locate the file where it was defined and open the
517 IPython will try to locate the file where it was defined and open the
479 editor at the point where it is defined. You can use `%edit function`
518 editor at the point where it is defined. You can use `%edit function`
480 to load an editor exactly at the point where 'function' is defined,
519 to load an editor exactly at the point where 'function' is defined,
481 edit it and have the file be executed automatically.
520 edit it and have the file be executed automatically.
482
521
483 - If the object is a macro (see %macro for details), this opens up your
522 - If the object is a macro (see %macro for details), this opens up your
484 specified editor with a temporary file containing the macro's data.
523 specified editor with a temporary file containing the macro's data.
485 Upon exit, the macro is reloaded with the contents of the file.
524 Upon exit, the macro is reloaded with the contents of the file.
486
525
487 Note: opening at an exact line is only supported under Unix, and some
526 Note: opening at an exact line is only supported under Unix, and some
488 editors (like kedit and gedit up to Gnome 2.8) do not understand the
527 editors (like kedit and gedit up to Gnome 2.8) do not understand the
489 '+NUMBER' parameter necessary for this feature. Good editors like
528 '+NUMBER' parameter necessary for this feature. Good editors like
490 (X)Emacs, vi, jed, pico and joe all do.
529 (X)Emacs, vi, jed, pico and joe all do.
491
530
492 After executing your code, %edit will return as output the code you
531 After executing your code, %edit will return as output the code you
493 typed in the editor (except when it was an existing file). This way
532 typed in the editor (except when it was an existing file). This way
494 you can reload the code in further invocations of %edit as a variable,
533 you can reload the code in further invocations of %edit as a variable,
495 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
534 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
496 the output.
535 the output.
497
536
498 Note that %edit is also available through the alias %ed.
537 Note that %edit is also available through the alias %ed.
499
538
500 This is an example of creating a simple function inside the editor and
539 This is an example of creating a simple function inside the editor and
501 then modifying it. First, start up the editor::
540 then modifying it. First, start up the editor::
502
541
503 In [1]: edit
542 In [1]: edit
504 Editing... done. Executing edited code...
543 Editing... done. Executing edited code...
505 Out[1]: 'def foo():\\n print "foo() was defined in an editing
544 Out[1]: 'def foo():\\n print "foo() was defined in an editing
506 session"\\n'
545 session"\\n'
507
546
508 We can then call the function foo()::
547 We can then call the function foo()::
509
548
510 In [2]: foo()
549 In [2]: foo()
511 foo() was defined in an editing session
550 foo() was defined in an editing session
512
551
513 Now we edit foo. IPython automatically loads the editor with the
552 Now we edit foo. IPython automatically loads the editor with the
514 (temporary) file where foo() was previously defined::
553 (temporary) file where foo() was previously defined::
515
554
516 In [3]: edit foo
555 In [3]: edit foo
517 Editing... done. Executing edited code...
556 Editing... done. Executing edited code...
518
557
519 And if we call foo() again we get the modified version::
558 And if we call foo() again we get the modified version::
520
559
521 In [4]: foo()
560 In [4]: foo()
522 foo() has now been changed!
561 foo() has now been changed!
523
562
524 Here is an example of how to edit a code snippet successive
563 Here is an example of how to edit a code snippet successive
525 times. First we call the editor::
564 times. First we call the editor::
526
565
527 In [5]: edit
566 In [5]: edit
528 Editing... done. Executing edited code...
567 Editing... done. Executing edited code...
529 hello
568 hello
530 Out[5]: "print 'hello'\\n"
569 Out[5]: "print 'hello'\\n"
531
570
532 Now we call it again with the previous output (stored in _)::
571 Now we call it again with the previous output (stored in _)::
533
572
534 In [6]: edit _
573 In [6]: edit _
535 Editing... done. Executing edited code...
574 Editing... done. Executing edited code...
536 hello world
575 hello world
537 Out[6]: "print 'hello world'\\n"
576 Out[6]: "print 'hello world'\\n"
538
577
539 Now we call it with the output #8 (stored in _8, also as Out[8])::
578 Now we call it with the output #8 (stored in _8, also as Out[8])::
540
579
541 In [7]: edit _8
580 In [7]: edit _8
542 Editing... done. Executing edited code...
581 Editing... done. Executing edited code...
543 hello again
582 hello again
544 Out[7]: "print 'hello again'\\n"
583 Out[7]: "print 'hello again'\\n"
545
584
546
585
547 Changing the default editor hook:
586 Changing the default editor hook:
548
587
549 If you wish to write your own editor hook, you can put it in a
588 If you wish to write your own editor hook, you can put it in a
550 configuration file which you load at startup time. The default hook
589 configuration file which you load at startup time. The default hook
551 is defined in the IPython.core.hooks module, and you can use that as a
590 is defined in the IPython.core.hooks module, and you can use that as a
552 starting example for further modifications. That file also has
591 starting example for further modifications. That file also has
553 general instructions on how to set a new hook for use once you've
592 general instructions on how to set a new hook for use once you've
554 defined it."""
593 defined it."""
555 opts,args = self.parse_options(parameter_s,'prxn:')
594 opts,args = self.parse_options(parameter_s,'prxn:')
556
595
557 try:
596 try:
558 filename, lineno, is_temp = self._find_edit_target(self.shell,
597 filename, lineno, is_temp = self._find_edit_target(self.shell,
559 args, opts, last_call)
598 args, opts, last_call)
560 except MacroToEdit as e:
599 except MacroToEdit as e:
561 self._edit_macro(args, e.args[0])
600 self._edit_macro(args, e.args[0])
562 return
601 return
563 except InteractivelyDefined as e:
602 except InteractivelyDefined as e:
564 print "Editing In[%i]" % e.index
603 print "Editing In[%i]" % e.index
565 args = str(e.index)
604 args = str(e.index)
566 filename, lineno, is_temp = self._find_edit_target(self.shell,
605 filename, lineno, is_temp = self._find_edit_target(self.shell,
567 args, opts, last_call)
606 args, opts, last_call)
568 if filename is None:
607 if filename is None:
569 # nothing was found, warnings have already been issued,
608 # nothing was found, warnings have already been issued,
570 # just give up.
609 # just give up.
571 return
610 return
572
611
573 # do actual editing here
612 # do actual editing here
574 print 'Editing...',
613 print 'Editing...',
575 sys.stdout.flush()
614 sys.stdout.flush()
576 try:
615 try:
577 # Quote filenames that may have spaces in them
616 # Quote filenames that may have spaces in them
578 if ' ' in filename:
617 if ' ' in filename:
579 filename = "'%s'" % filename
618 filename = "'%s'" % filename
580 self.shell.hooks.editor(filename,lineno)
619 self.shell.hooks.editor(filename,lineno)
581 except TryNext:
620 except TryNext:
582 warn('Could not open editor')
621 warn('Could not open editor')
583 return
622 return
584
623
585 # XXX TODO: should this be generalized for all string vars?
624 # XXX TODO: should this be generalized for all string vars?
586 # For now, this is special-cased to blocks created by cpaste
625 # For now, this is special-cased to blocks created by cpaste
587 if args.strip() == 'pasted_block':
626 if args.strip() == 'pasted_block':
588 with open(filename, 'r') as f:
627 with open(filename, 'r') as f:
589 self.shell.user_ns['pasted_block'] = f.read()
628 self.shell.user_ns['pasted_block'] = f.read()
590
629
591 if 'x' in opts: # -x prevents actual execution
630 if 'x' in opts: # -x prevents actual execution
592 print
631 print
593 else:
632 else:
594 print 'done. Executing edited code...'
633 print 'done. Executing edited code...'
595 with preserve_keys(self.shell.user_ns, '__file__'):
634 with preserve_keys(self.shell.user_ns, '__file__'):
596 if not is_temp:
635 if not is_temp:
597 self.shell.user_ns['__file__'] = filename
636 self.shell.user_ns['__file__'] = filename
598 if 'r' in opts: # Untranslated IPython code
637 if 'r' in opts: # Untranslated IPython code
599 with open(filename, 'r') as f:
638 with open(filename, 'r') as f:
600 source = f.read()
639 source = f.read()
601 self.shell.run_cell(source, store_history=False)
640 self.shell.run_cell(source, store_history=False)
602 else:
641 else:
603 self.shell.safe_execfile(filename, self.shell.user_ns,
642 self.shell.safe_execfile(filename, self.shell.user_ns,
604 self.shell.user_ns)
643 self.shell.user_ns)
605
644
606 if is_temp:
645 if is_temp:
607 try:
646 try:
608 return open(filename).read()
647 return open(filename).read()
609 except IOError as msg:
648 except IOError as msg:
610 if msg.filename == filename:
649 if msg.filename == filename:
611 warn('File not found. Did you forget to save?')
650 warn('File not found. Did you forget to save?')
612 return
651 return
613 else:
652 else:
614 self.shell.showtraceback()
653 self.shell.showtraceback()
@@ -1,910 +1,932 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 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9 # Imports
9 # Imports
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11
11
12 import io
12 import io
13 import os
13 import os
14 import sys
14 import sys
15 from StringIO import StringIO
15 from StringIO import StringIO
16 from unittest import TestCase
16 from unittest import TestCase
17
17
18 try:
18 try:
19 from importlib import invalidate_caches # Required from Python 3.3
19 from importlib import invalidate_caches # Required from Python 3.3
20 except ImportError:
20 except ImportError:
21 def invalidate_caches():
21 def invalidate_caches():
22 pass
22 pass
23
23
24 import nose.tools as nt
24 import nose.tools as nt
25
25
26 from IPython.core import magic
26 from IPython.core import magic
27 from IPython.core.magic import (Magics, magics_class, line_magic,
27 from IPython.core.magic import (Magics, magics_class, line_magic,
28 cell_magic, line_cell_magic,
28 cell_magic, line_cell_magic,
29 register_line_magic, register_cell_magic,
29 register_line_magic, register_cell_magic,
30 register_line_cell_magic)
30 register_line_cell_magic)
31 from IPython.core.magics import execution, script, code
31 from IPython.core.magics import execution, script, code
32 from IPython.nbformat.v3.tests.nbexamples import nb0
32 from IPython.nbformat.v3.tests.nbexamples import nb0
33 from IPython.nbformat import current
33 from IPython.nbformat import current
34 from IPython.testing import decorators as dec
34 from IPython.testing import decorators as dec
35 from IPython.testing import tools as tt
35 from IPython.testing import tools as tt
36 from IPython.utils import py3compat
36 from IPython.utils import py3compat
37 from IPython.utils.io import capture_output
37 from IPython.utils.io import capture_output
38 from IPython.utils.tempdir import TemporaryDirectory
38 from IPython.utils.tempdir import TemporaryDirectory
39 from IPython.utils.process import find_cmd
39 from IPython.utils.process import find_cmd
40
40
41 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
42 # Test functions begin
42 # Test functions begin
43 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
44
44
45 @magic.magics_class
45 @magic.magics_class
46 class DummyMagics(magic.Magics): pass
46 class DummyMagics(magic.Magics): pass
47
47
48 def test_extract_code_ranges():
48 def test_extract_code_ranges():
49 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
49 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
50 expected = [(0, 1),
50 expected = [(0, 1),
51 (2, 3),
51 (2, 3),
52 (4, 6),
52 (4, 6),
53 (6, 9),
53 (6, 9),
54 (9, 14),
54 (9, 14),
55 (16, None),
55 (16, None),
56 (None, 9),
56 (None, 9),
57 (9, None),
57 (9, None),
58 (None, 13),
58 (None, 13),
59 (None, None)]
59 (None, None)]
60 actual = list(code.extract_code_ranges(instr))
60 actual = list(code.extract_code_ranges(instr))
61 nt.assert_equal(actual, expected)
61 nt.assert_equal(actual, expected)
62
62
63
64 def test_extract_symbols():
65 source = """import foo\na = 10\ndef b():\n return 42\nclass A: pass\n"""
66 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
67 expected = [[],
68 ["def b():\n return 42"],
69 ["class A: pass\n"],
70 ["class A: pass\n", "def b():\n return 42"],
71 ["class A: pass\n"],
72 []]
73 for symbols, exp in zip(symbols_args, expected):
74 nt.assert_equal(code.extract_symbols(source, symbols), exp)
75
76
77 def test_extract_symbols_ignores_non_python_code():
78 source = ("=begin A Ruby program :)=end\n"
79 "def hello\n"
80 "puts 'Hello world'\n"
81 "end")
82 nt.assert_equal(code.extract_symbols(source, "hello"), [])
83
84
63 def test_rehashx():
85 def test_rehashx():
64 # clear up everything
86 # clear up everything
65 _ip = get_ipython()
87 _ip = get_ipython()
66 _ip.alias_manager.clear_aliases()
88 _ip.alias_manager.clear_aliases()
67 del _ip.db['syscmdlist']
89 del _ip.db['syscmdlist']
68
90
69 _ip.magic('rehashx')
91 _ip.magic('rehashx')
70 # Practically ALL ipython development systems will have more than 10 aliases
92 # Practically ALL ipython development systems will have more than 10 aliases
71
93
72 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
94 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
73 for name, cmd in _ip.alias_manager.aliases:
95 for name, cmd in _ip.alias_manager.aliases:
74 # we must strip dots from alias names
96 # we must strip dots from alias names
75 nt.assert_not_in('.', name)
97 nt.assert_not_in('.', name)
76
98
77 # rehashx must fill up syscmdlist
99 # rehashx must fill up syscmdlist
78 scoms = _ip.db['syscmdlist']
100 scoms = _ip.db['syscmdlist']
79 nt.assert_true(len(scoms) > 10)
101 nt.assert_true(len(scoms) > 10)
80
102
81
103
82 def test_magic_parse_options():
104 def test_magic_parse_options():
83 """Test that we don't mangle paths when parsing magic options."""
105 """Test that we don't mangle paths when parsing magic options."""
84 ip = get_ipython()
106 ip = get_ipython()
85 path = 'c:\\x'
107 path = 'c:\\x'
86 m = DummyMagics(ip)
108 m = DummyMagics(ip)
87 opts = m.parse_options('-f %s' % path,'f:')[0]
109 opts = m.parse_options('-f %s' % path,'f:')[0]
88 # argv splitting is os-dependent
110 # argv splitting is os-dependent
89 if os.name == 'posix':
111 if os.name == 'posix':
90 expected = 'c:x'
112 expected = 'c:x'
91 else:
113 else:
92 expected = path
114 expected = path
93 nt.assert_equal(opts['f'], expected)
115 nt.assert_equal(opts['f'], expected)
94
116
95 def test_magic_parse_long_options():
117 def test_magic_parse_long_options():
96 """Magic.parse_options can handle --foo=bar long options"""
118 """Magic.parse_options can handle --foo=bar long options"""
97 ip = get_ipython()
119 ip = get_ipython()
98 m = DummyMagics(ip)
120 m = DummyMagics(ip)
99 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
121 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
100 nt.assert_in('foo', opts)
122 nt.assert_in('foo', opts)
101 nt.assert_in('bar', opts)
123 nt.assert_in('bar', opts)
102 nt.assert_equal(opts['bar'], "bubble")
124 nt.assert_equal(opts['bar'], "bubble")
103
125
104
126
105 @dec.skip_without('sqlite3')
127 @dec.skip_without('sqlite3')
106 def doctest_hist_f():
128 def doctest_hist_f():
107 """Test %hist -f with temporary filename.
129 """Test %hist -f with temporary filename.
108
130
109 In [9]: import tempfile
131 In [9]: import tempfile
110
132
111 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
133 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
112
134
113 In [11]: %hist -nl -f $tfile 3
135 In [11]: %hist -nl -f $tfile 3
114
136
115 In [13]: import os; os.unlink(tfile)
137 In [13]: import os; os.unlink(tfile)
116 """
138 """
117
139
118
140
119 @dec.skip_without('sqlite3')
141 @dec.skip_without('sqlite3')
120 def doctest_hist_r():
142 def doctest_hist_r():
121 """Test %hist -r
143 """Test %hist -r
122
144
123 XXX - This test is not recording the output correctly. For some reason, in
145 XXX - This test is not recording the output correctly. For some reason, in
124 testing mode the raw history isn't getting populated. No idea why.
146 testing mode the raw history isn't getting populated. No idea why.
125 Disabling the output checking for now, though at least we do run it.
147 Disabling the output checking for now, though at least we do run it.
126
148
127 In [1]: 'hist' in _ip.lsmagic()
149 In [1]: 'hist' in _ip.lsmagic()
128 Out[1]: True
150 Out[1]: True
129
151
130 In [2]: x=1
152 In [2]: x=1
131
153
132 In [3]: %hist -rl 2
154 In [3]: %hist -rl 2
133 x=1 # random
155 x=1 # random
134 %hist -r 2
156 %hist -r 2
135 """
157 """
136
158
137
159
138 @dec.skip_without('sqlite3')
160 @dec.skip_without('sqlite3')
139 def doctest_hist_op():
161 def doctest_hist_op():
140 """Test %hist -op
162 """Test %hist -op
141
163
142 In [1]: class b(float):
164 In [1]: class b(float):
143 ...: pass
165 ...: pass
144 ...:
166 ...:
145
167
146 In [2]: class s(object):
168 In [2]: class s(object):
147 ...: def __str__(self):
169 ...: def __str__(self):
148 ...: return 's'
170 ...: return 's'
149 ...:
171 ...:
150
172
151 In [3]:
173 In [3]:
152
174
153 In [4]: class r(b):
175 In [4]: class r(b):
154 ...: def __repr__(self):
176 ...: def __repr__(self):
155 ...: return 'r'
177 ...: return 'r'
156 ...:
178 ...:
157
179
158 In [5]: class sr(s,r): pass
180 In [5]: class sr(s,r): pass
159 ...:
181 ...:
160
182
161 In [6]:
183 In [6]:
162
184
163 In [7]: bb=b()
185 In [7]: bb=b()
164
186
165 In [8]: ss=s()
187 In [8]: ss=s()
166
188
167 In [9]: rr=r()
189 In [9]: rr=r()
168
190
169 In [10]: ssrr=sr()
191 In [10]: ssrr=sr()
170
192
171 In [11]: 4.5
193 In [11]: 4.5
172 Out[11]: 4.5
194 Out[11]: 4.5
173
195
174 In [12]: str(ss)
196 In [12]: str(ss)
175 Out[12]: 's'
197 Out[12]: 's'
176
198
177 In [13]:
199 In [13]:
178
200
179 In [14]: %hist -op
201 In [14]: %hist -op
180 >>> class b:
202 >>> class b:
181 ... pass
203 ... pass
182 ...
204 ...
183 >>> class s(b):
205 >>> class s(b):
184 ... def __str__(self):
206 ... def __str__(self):
185 ... return 's'
207 ... return 's'
186 ...
208 ...
187 >>>
209 >>>
188 >>> class r(b):
210 >>> class r(b):
189 ... def __repr__(self):
211 ... def __repr__(self):
190 ... return 'r'
212 ... return 'r'
191 ...
213 ...
192 >>> class sr(s,r): pass
214 >>> class sr(s,r): pass
193 >>>
215 >>>
194 >>> bb=b()
216 >>> bb=b()
195 >>> ss=s()
217 >>> ss=s()
196 >>> rr=r()
218 >>> rr=r()
197 >>> ssrr=sr()
219 >>> ssrr=sr()
198 >>> 4.5
220 >>> 4.5
199 4.5
221 4.5
200 >>> str(ss)
222 >>> str(ss)
201 's'
223 's'
202 >>>
224 >>>
203 """
225 """
204
226
205
227
206 @dec.skip_without('sqlite3')
228 @dec.skip_without('sqlite3')
207 def test_macro():
229 def test_macro():
208 ip = get_ipython()
230 ip = get_ipython()
209 ip.history_manager.reset() # Clear any existing history.
231 ip.history_manager.reset() # Clear any existing history.
210 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
232 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
211 for i, cmd in enumerate(cmds, start=1):
233 for i, cmd in enumerate(cmds, start=1):
212 ip.history_manager.store_inputs(i, cmd)
234 ip.history_manager.store_inputs(i, cmd)
213 ip.magic("macro test 1-3")
235 ip.magic("macro test 1-3")
214 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
236 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
215
237
216 # List macros
238 # List macros
217 nt.assert_in("test", ip.magic("macro"))
239 nt.assert_in("test", ip.magic("macro"))
218
240
219
241
220 @dec.skip_without('sqlite3')
242 @dec.skip_without('sqlite3')
221 def test_macro_run():
243 def test_macro_run():
222 """Test that we can run a multi-line macro successfully."""
244 """Test that we can run a multi-line macro successfully."""
223 ip = get_ipython()
245 ip = get_ipython()
224 ip.history_manager.reset()
246 ip.history_manager.reset()
225 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
247 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
226 "%macro test 2-3"]
248 "%macro test 2-3"]
227 for cmd in cmds:
249 for cmd in cmds:
228 ip.run_cell(cmd, store_history=True)
250 ip.run_cell(cmd, store_history=True)
229 nt.assert_equal(ip.user_ns["test"].value,
251 nt.assert_equal(ip.user_ns["test"].value,
230 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
252 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
231 with tt.AssertPrints("12"):
253 with tt.AssertPrints("12"):
232 ip.run_cell("test")
254 ip.run_cell("test")
233 with tt.AssertPrints("13"):
255 with tt.AssertPrints("13"):
234 ip.run_cell("test")
256 ip.run_cell("test")
235
257
236
258
237 def test_magic_magic():
259 def test_magic_magic():
238 """Test %magic"""
260 """Test %magic"""
239 ip = get_ipython()
261 ip = get_ipython()
240 with capture_output() as captured:
262 with capture_output() as captured:
241 ip.magic("magic")
263 ip.magic("magic")
242
264
243 stdout = captured.stdout
265 stdout = captured.stdout
244 nt.assert_in('%magic', stdout)
266 nt.assert_in('%magic', stdout)
245 nt.assert_in('IPython', stdout)
267 nt.assert_in('IPython', stdout)
246 nt.assert_in('Available', stdout)
268 nt.assert_in('Available', stdout)
247
269
248
270
249 @dec.skipif_not_numpy
271 @dec.skipif_not_numpy
250 def test_numpy_reset_array_undec():
272 def test_numpy_reset_array_undec():
251 "Test '%reset array' functionality"
273 "Test '%reset array' functionality"
252 _ip.ex('import numpy as np')
274 _ip.ex('import numpy as np')
253 _ip.ex('a = np.empty(2)')
275 _ip.ex('a = np.empty(2)')
254 nt.assert_in('a', _ip.user_ns)
276 nt.assert_in('a', _ip.user_ns)
255 _ip.magic('reset -f array')
277 _ip.magic('reset -f array')
256 nt.assert_not_in('a', _ip.user_ns)
278 nt.assert_not_in('a', _ip.user_ns)
257
279
258 def test_reset_out():
280 def test_reset_out():
259 "Test '%reset out' magic"
281 "Test '%reset out' magic"
260 _ip.run_cell("parrot = 'dead'", store_history=True)
282 _ip.run_cell("parrot = 'dead'", store_history=True)
261 # test '%reset -f out', make an Out prompt
283 # test '%reset -f out', make an Out prompt
262 _ip.run_cell("parrot", store_history=True)
284 _ip.run_cell("parrot", store_history=True)
263 nt.assert_true('dead' in [_ip.user_ns[x] for x in '_','__','___'])
285 nt.assert_true('dead' in [_ip.user_ns[x] for x in '_','__','___'])
264 _ip.magic('reset -f out')
286 _ip.magic('reset -f out')
265 nt.assert_false('dead' in [_ip.user_ns[x] for x in '_','__','___'])
287 nt.assert_false('dead' in [_ip.user_ns[x] for x in '_','__','___'])
266 nt.assert_equal(len(_ip.user_ns['Out']), 0)
288 nt.assert_equal(len(_ip.user_ns['Out']), 0)
267
289
268 def test_reset_in():
290 def test_reset_in():
269 "Test '%reset in' magic"
291 "Test '%reset in' magic"
270 # test '%reset -f in'
292 # test '%reset -f in'
271 _ip.run_cell("parrot", store_history=True)
293 _ip.run_cell("parrot", store_history=True)
272 nt.assert_true('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
294 nt.assert_true('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
273 _ip.magic('%reset -f in')
295 _ip.magic('%reset -f in')
274 nt.assert_false('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
296 nt.assert_false('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
275 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
297 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
276
298
277 def test_reset_dhist():
299 def test_reset_dhist():
278 "Test '%reset dhist' magic"
300 "Test '%reset dhist' magic"
279 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
301 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
280 _ip.magic('cd ' + os.path.dirname(nt.__file__))
302 _ip.magic('cd ' + os.path.dirname(nt.__file__))
281 _ip.magic('cd -')
303 _ip.magic('cd -')
282 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
304 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
283 _ip.magic('reset -f dhist')
305 _ip.magic('reset -f dhist')
284 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
306 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
285 _ip.run_cell("_dh = [d for d in tmp]") #restore
307 _ip.run_cell("_dh = [d for d in tmp]") #restore
286
308
287 def test_reset_in_length():
309 def test_reset_in_length():
288 "Test that '%reset in' preserves In[] length"
310 "Test that '%reset in' preserves In[] length"
289 _ip.run_cell("print 'foo'")
311 _ip.run_cell("print 'foo'")
290 _ip.run_cell("reset -f in")
312 _ip.run_cell("reset -f in")
291 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
313 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
292
314
293 def test_tb_syntaxerror():
315 def test_tb_syntaxerror():
294 """test %tb after a SyntaxError"""
316 """test %tb after a SyntaxError"""
295 ip = get_ipython()
317 ip = get_ipython()
296 ip.run_cell("for")
318 ip.run_cell("for")
297
319
298 # trap and validate stdout
320 # trap and validate stdout
299 save_stdout = sys.stdout
321 save_stdout = sys.stdout
300 try:
322 try:
301 sys.stdout = StringIO()
323 sys.stdout = StringIO()
302 ip.run_cell("%tb")
324 ip.run_cell("%tb")
303 out = sys.stdout.getvalue()
325 out = sys.stdout.getvalue()
304 finally:
326 finally:
305 sys.stdout = save_stdout
327 sys.stdout = save_stdout
306 # trim output, and only check the last line
328 # trim output, and only check the last line
307 last_line = out.rstrip().splitlines()[-1].strip()
329 last_line = out.rstrip().splitlines()[-1].strip()
308 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
330 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
309
331
310
332
311 def test_time():
333 def test_time():
312 ip = get_ipython()
334 ip = get_ipython()
313
335
314 with tt.AssertPrints("Wall time: "):
336 with tt.AssertPrints("Wall time: "):
315 ip.run_cell("%time None")
337 ip.run_cell("%time None")
316
338
317 ip.run_cell("def f(kmjy):\n"
339 ip.run_cell("def f(kmjy):\n"
318 " %time print (2*kmjy)")
340 " %time print (2*kmjy)")
319
341
320 with tt.AssertPrints("Wall time: "):
342 with tt.AssertPrints("Wall time: "):
321 with tt.AssertPrints("hihi", suppress=False):
343 with tt.AssertPrints("hihi", suppress=False):
322 ip.run_cell("f('hi')")
344 ip.run_cell("f('hi')")
323
345
324
346
325 @dec.skip_win32
347 @dec.skip_win32
326 def test_time2():
348 def test_time2():
327 ip = get_ipython()
349 ip = get_ipython()
328
350
329 with tt.AssertPrints("CPU times: user "):
351 with tt.AssertPrints("CPU times: user "):
330 ip.run_cell("%time None")
352 ip.run_cell("%time None")
331
353
332 def test_time3():
354 def test_time3():
333 """Erroneous magic function calls, issue gh-3334"""
355 """Erroneous magic function calls, issue gh-3334"""
334 ip = get_ipython()
356 ip = get_ipython()
335 ip.user_ns.pop('run', None)
357 ip.user_ns.pop('run', None)
336
358
337 with tt.AssertNotPrints("not found", channel='stderr'):
359 with tt.AssertNotPrints("not found", channel='stderr'):
338 ip.run_cell("%%time\n"
360 ip.run_cell("%%time\n"
339 "run = 0\n"
361 "run = 0\n"
340 "run += 1")
362 "run += 1")
341
363
342 def test_doctest_mode():
364 def test_doctest_mode():
343 "Toggle doctest_mode twice, it should be a no-op and run without error"
365 "Toggle doctest_mode twice, it should be a no-op and run without error"
344 _ip.magic('doctest_mode')
366 _ip.magic('doctest_mode')
345 _ip.magic('doctest_mode')
367 _ip.magic('doctest_mode')
346
368
347
369
348 def test_parse_options():
370 def test_parse_options():
349 """Tests for basic options parsing in magics."""
371 """Tests for basic options parsing in magics."""
350 # These are only the most minimal of tests, more should be added later. At
372 # These are only the most minimal of tests, more should be added later. At
351 # the very least we check that basic text/unicode calls work OK.
373 # the very least we check that basic text/unicode calls work OK.
352 m = DummyMagics(_ip)
374 m = DummyMagics(_ip)
353 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
375 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
354 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
376 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
355
377
356
378
357 def test_dirops():
379 def test_dirops():
358 """Test various directory handling operations."""
380 """Test various directory handling operations."""
359 # curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/')
381 # curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/')
360 curpath = os.getcwdu
382 curpath = os.getcwdu
361 startdir = os.getcwdu()
383 startdir = os.getcwdu()
362 ipdir = os.path.realpath(_ip.ipython_dir)
384 ipdir = os.path.realpath(_ip.ipython_dir)
363 try:
385 try:
364 _ip.magic('cd "%s"' % ipdir)
386 _ip.magic('cd "%s"' % ipdir)
365 nt.assert_equal(curpath(), ipdir)
387 nt.assert_equal(curpath(), ipdir)
366 _ip.magic('cd -')
388 _ip.magic('cd -')
367 nt.assert_equal(curpath(), startdir)
389 nt.assert_equal(curpath(), startdir)
368 _ip.magic('pushd "%s"' % ipdir)
390 _ip.magic('pushd "%s"' % ipdir)
369 nt.assert_equal(curpath(), ipdir)
391 nt.assert_equal(curpath(), ipdir)
370 _ip.magic('popd')
392 _ip.magic('popd')
371 nt.assert_equal(curpath(), startdir)
393 nt.assert_equal(curpath(), startdir)
372 finally:
394 finally:
373 os.chdir(startdir)
395 os.chdir(startdir)
374
396
375
397
376 def test_xmode():
398 def test_xmode():
377 # Calling xmode three times should be a no-op
399 # Calling xmode three times should be a no-op
378 xmode = _ip.InteractiveTB.mode
400 xmode = _ip.InteractiveTB.mode
379 for i in range(3):
401 for i in range(3):
380 _ip.magic("xmode")
402 _ip.magic("xmode")
381 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
403 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
382
404
383 def test_reset_hard():
405 def test_reset_hard():
384 monitor = []
406 monitor = []
385 class A(object):
407 class A(object):
386 def __del__(self):
408 def __del__(self):
387 monitor.append(1)
409 monitor.append(1)
388 def __repr__(self):
410 def __repr__(self):
389 return "<A instance>"
411 return "<A instance>"
390
412
391 _ip.user_ns["a"] = A()
413 _ip.user_ns["a"] = A()
392 _ip.run_cell("a")
414 _ip.run_cell("a")
393
415
394 nt.assert_equal(monitor, [])
416 nt.assert_equal(monitor, [])
395 _ip.magic("reset -f")
417 _ip.magic("reset -f")
396 nt.assert_equal(monitor, [1])
418 nt.assert_equal(monitor, [1])
397
419
398 class TestXdel(tt.TempFileMixin):
420 class TestXdel(tt.TempFileMixin):
399 def test_xdel(self):
421 def test_xdel(self):
400 """Test that references from %run are cleared by xdel."""
422 """Test that references from %run are cleared by xdel."""
401 src = ("class A(object):\n"
423 src = ("class A(object):\n"
402 " monitor = []\n"
424 " monitor = []\n"
403 " def __del__(self):\n"
425 " def __del__(self):\n"
404 " self.monitor.append(1)\n"
426 " self.monitor.append(1)\n"
405 "a = A()\n")
427 "a = A()\n")
406 self.mktmp(src)
428 self.mktmp(src)
407 # %run creates some hidden references...
429 # %run creates some hidden references...
408 _ip.magic("run %s" % self.fname)
430 _ip.magic("run %s" % self.fname)
409 # ... as does the displayhook.
431 # ... as does the displayhook.
410 _ip.run_cell("a")
432 _ip.run_cell("a")
411
433
412 monitor = _ip.user_ns["A"].monitor
434 monitor = _ip.user_ns["A"].monitor
413 nt.assert_equal(monitor, [])
435 nt.assert_equal(monitor, [])
414
436
415 _ip.magic("xdel a")
437 _ip.magic("xdel a")
416
438
417 # Check that a's __del__ method has been called.
439 # Check that a's __del__ method has been called.
418 nt.assert_equal(monitor, [1])
440 nt.assert_equal(monitor, [1])
419
441
420 def doctest_who():
442 def doctest_who():
421 """doctest for %who
443 """doctest for %who
422
444
423 In [1]: %reset -f
445 In [1]: %reset -f
424
446
425 In [2]: alpha = 123
447 In [2]: alpha = 123
426
448
427 In [3]: beta = 'beta'
449 In [3]: beta = 'beta'
428
450
429 In [4]: %who int
451 In [4]: %who int
430 alpha
452 alpha
431
453
432 In [5]: %who str
454 In [5]: %who str
433 beta
455 beta
434
456
435 In [6]: %whos
457 In [6]: %whos
436 Variable Type Data/Info
458 Variable Type Data/Info
437 ----------------------------
459 ----------------------------
438 alpha int 123
460 alpha int 123
439 beta str beta
461 beta str beta
440
462
441 In [7]: %who_ls
463 In [7]: %who_ls
442 Out[7]: ['alpha', 'beta']
464 Out[7]: ['alpha', 'beta']
443 """
465 """
444
466
445 def test_whos():
467 def test_whos():
446 """Check that whos is protected against objects where repr() fails."""
468 """Check that whos is protected against objects where repr() fails."""
447 class A(object):
469 class A(object):
448 def __repr__(self):
470 def __repr__(self):
449 raise Exception()
471 raise Exception()
450 _ip.user_ns['a'] = A()
472 _ip.user_ns['a'] = A()
451 _ip.magic("whos")
473 _ip.magic("whos")
452
474
453 @py3compat.u_format
475 @py3compat.u_format
454 def doctest_precision():
476 def doctest_precision():
455 """doctest for %precision
477 """doctest for %precision
456
478
457 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
479 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
458
480
459 In [2]: %precision 5
481 In [2]: %precision 5
460 Out[2]: {u}'%.5f'
482 Out[2]: {u}'%.5f'
461
483
462 In [3]: f.float_format
484 In [3]: f.float_format
463 Out[3]: {u}'%.5f'
485 Out[3]: {u}'%.5f'
464
486
465 In [4]: %precision %e
487 In [4]: %precision %e
466 Out[4]: {u}'%e'
488 Out[4]: {u}'%e'
467
489
468 In [5]: f(3.1415927)
490 In [5]: f(3.1415927)
469 Out[5]: {u}'3.141593e+00'
491 Out[5]: {u}'3.141593e+00'
470 """
492 """
471
493
472 def test_psearch():
494 def test_psearch():
473 with tt.AssertPrints("dict.fromkeys"):
495 with tt.AssertPrints("dict.fromkeys"):
474 _ip.run_cell("dict.fr*?")
496 _ip.run_cell("dict.fr*?")
475
497
476 def test_timeit_shlex():
498 def test_timeit_shlex():
477 """test shlex issues with timeit (#1109)"""
499 """test shlex issues with timeit (#1109)"""
478 _ip.ex("def f(*a,**kw): pass")
500 _ip.ex("def f(*a,**kw): pass")
479 _ip.magic('timeit -n1 "this is a bug".count(" ")')
501 _ip.magic('timeit -n1 "this is a bug".count(" ")')
480 _ip.magic('timeit -r1 -n1 f(" ", 1)')
502 _ip.magic('timeit -r1 -n1 f(" ", 1)')
481 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
503 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
482 _ip.magic('timeit -r1 -n1 ("a " + "b")')
504 _ip.magic('timeit -r1 -n1 ("a " + "b")')
483 _ip.magic('timeit -r1 -n1 f("a " + "b")')
505 _ip.magic('timeit -r1 -n1 f("a " + "b")')
484 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
506 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
485
507
486
508
487 def test_timeit_arguments():
509 def test_timeit_arguments():
488 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
510 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
489 _ip.magic("timeit ('#')")
511 _ip.magic("timeit ('#')")
490
512
491
513
492 def test_timeit_special_syntax():
514 def test_timeit_special_syntax():
493 "Test %%timeit with IPython special syntax"
515 "Test %%timeit with IPython special syntax"
494 @register_line_magic
516 @register_line_magic
495 def lmagic(line):
517 def lmagic(line):
496 ip = get_ipython()
518 ip = get_ipython()
497 ip.user_ns['lmagic_out'] = line
519 ip.user_ns['lmagic_out'] = line
498
520
499 # line mode test
521 # line mode test
500 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
522 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
501 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
523 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
502 # cell mode test
524 # cell mode test
503 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
525 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
504 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
526 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
505
527
506 def test_timeit_return():
528 def test_timeit_return():
507 """
529 """
508 test wether timeit -o return object
530 test wether timeit -o return object
509 """
531 """
510
532
511 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
533 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
512 assert(res is not None)
534 assert(res is not None)
513
535
514 def test_timeit_quiet():
536 def test_timeit_quiet():
515 """
537 """
516 test quiet option of timeit magic
538 test quiet option of timeit magic
517 """
539 """
518 with tt.AssertNotPrints("loops"):
540 with tt.AssertNotPrints("loops"):
519 _ip.run_cell("%timeit -n1 -r1 -q 1")
541 _ip.run_cell("%timeit -n1 -r1 -q 1")
520
542
521 @dec.skipif(execution.profile is None)
543 @dec.skipif(execution.profile is None)
522 def test_prun_special_syntax():
544 def test_prun_special_syntax():
523 "Test %%prun with IPython special syntax"
545 "Test %%prun with IPython special syntax"
524 @register_line_magic
546 @register_line_magic
525 def lmagic(line):
547 def lmagic(line):
526 ip = get_ipython()
548 ip = get_ipython()
527 ip.user_ns['lmagic_out'] = line
549 ip.user_ns['lmagic_out'] = line
528
550
529 # line mode test
551 # line mode test
530 _ip.run_line_magic('prun', '-q %lmagic my line')
552 _ip.run_line_magic('prun', '-q %lmagic my line')
531 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
553 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
532 # cell mode test
554 # cell mode test
533 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
555 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
534 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
556 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
535
557
536 @dec.skipif(execution.profile is None)
558 @dec.skipif(execution.profile is None)
537 def test_prun_quotes():
559 def test_prun_quotes():
538 "Test that prun does not clobber string escapes (GH #1302)"
560 "Test that prun does not clobber string escapes (GH #1302)"
539 _ip.magic(r"prun -q x = '\t'")
561 _ip.magic(r"prun -q x = '\t'")
540 nt.assert_equal(_ip.user_ns['x'], '\t')
562 nt.assert_equal(_ip.user_ns['x'], '\t')
541
563
542 def test_extension():
564 def test_extension():
543 tmpdir = TemporaryDirectory()
565 tmpdir = TemporaryDirectory()
544 orig_ipython_dir = _ip.ipython_dir
566 orig_ipython_dir = _ip.ipython_dir
545 try:
567 try:
546 _ip.ipython_dir = tmpdir.name
568 _ip.ipython_dir = tmpdir.name
547 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
569 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
548 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
570 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
549 _ip.magic("install_ext %s" % url)
571 _ip.magic("install_ext %s" % url)
550 _ip.user_ns.pop('arq', None)
572 _ip.user_ns.pop('arq', None)
551 invalidate_caches() # Clear import caches
573 invalidate_caches() # Clear import caches
552 _ip.magic("load_ext daft_extension")
574 _ip.magic("load_ext daft_extension")
553 nt.assert_equal(_ip.user_ns['arq'], 185)
575 nt.assert_equal(_ip.user_ns['arq'], 185)
554 _ip.magic("unload_ext daft_extension")
576 _ip.magic("unload_ext daft_extension")
555 assert 'arq' not in _ip.user_ns
577 assert 'arq' not in _ip.user_ns
556 finally:
578 finally:
557 _ip.ipython_dir = orig_ipython_dir
579 _ip.ipython_dir = orig_ipython_dir
558 tmpdir.cleanup()
580 tmpdir.cleanup()
559
581
560 def test_notebook_export_json():
582 def test_notebook_export_json():
561 with TemporaryDirectory() as td:
583 with TemporaryDirectory() as td:
562 outfile = os.path.join(td, "nb.ipynb")
584 outfile = os.path.join(td, "nb.ipynb")
563 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
585 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
564 _ip.magic("notebook -e %s" % outfile)
586 _ip.magic("notebook -e %s" % outfile)
565
587
566 def test_notebook_export_py():
588 def test_notebook_export_py():
567 with TemporaryDirectory() as td:
589 with TemporaryDirectory() as td:
568 outfile = os.path.join(td, "nb.py")
590 outfile = os.path.join(td, "nb.py")
569 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
591 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
570 _ip.magic("notebook -e %s" % outfile)
592 _ip.magic("notebook -e %s" % outfile)
571
593
572 def test_notebook_reformat_py():
594 def test_notebook_reformat_py():
573 with TemporaryDirectory() as td:
595 with TemporaryDirectory() as td:
574 infile = os.path.join(td, "nb.ipynb")
596 infile = os.path.join(td, "nb.ipynb")
575 with io.open(infile, 'w', encoding='utf-8') as f:
597 with io.open(infile, 'w', encoding='utf-8') as f:
576 current.write(nb0, f, 'json')
598 current.write(nb0, f, 'json')
577
599
578 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
600 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
579 _ip.magic("notebook -f py %s" % infile)
601 _ip.magic("notebook -f py %s" % infile)
580
602
581 def test_notebook_reformat_json():
603 def test_notebook_reformat_json():
582 with TemporaryDirectory() as td:
604 with TemporaryDirectory() as td:
583 infile = os.path.join(td, "nb.py")
605 infile = os.path.join(td, "nb.py")
584 with io.open(infile, 'w', encoding='utf-8') as f:
606 with io.open(infile, 'w', encoding='utf-8') as f:
585 current.write(nb0, f, 'py')
607 current.write(nb0, f, 'py')
586
608
587 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
609 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
588 _ip.magic("notebook -f ipynb %s" % infile)
610 _ip.magic("notebook -f ipynb %s" % infile)
589 _ip.magic("notebook -f json %s" % infile)
611 _ip.magic("notebook -f json %s" % infile)
590
612
591 def test_env():
613 def test_env():
592 env = _ip.magic("env")
614 env = _ip.magic("env")
593 assert isinstance(env, dict), type(env)
615 assert isinstance(env, dict), type(env)
594
616
595
617
596 class CellMagicTestCase(TestCase):
618 class CellMagicTestCase(TestCase):
597
619
598 def check_ident(self, magic):
620 def check_ident(self, magic):
599 # Manually called, we get the result
621 # Manually called, we get the result
600 out = _ip.run_cell_magic(magic, 'a', 'b')
622 out = _ip.run_cell_magic(magic, 'a', 'b')
601 nt.assert_equal(out, ('a','b'))
623 nt.assert_equal(out, ('a','b'))
602 # Via run_cell, it goes into the user's namespace via displayhook
624 # Via run_cell, it goes into the user's namespace via displayhook
603 _ip.run_cell('%%' + magic +' c\nd')
625 _ip.run_cell('%%' + magic +' c\nd')
604 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
626 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
605
627
606 def test_cell_magic_func_deco(self):
628 def test_cell_magic_func_deco(self):
607 "Cell magic using simple decorator"
629 "Cell magic using simple decorator"
608 @register_cell_magic
630 @register_cell_magic
609 def cellm(line, cell):
631 def cellm(line, cell):
610 return line, cell
632 return line, cell
611
633
612 self.check_ident('cellm')
634 self.check_ident('cellm')
613
635
614 def test_cell_magic_reg(self):
636 def test_cell_magic_reg(self):
615 "Cell magic manually registered"
637 "Cell magic manually registered"
616 def cellm(line, cell):
638 def cellm(line, cell):
617 return line, cell
639 return line, cell
618
640
619 _ip.register_magic_function(cellm, 'cell', 'cellm2')
641 _ip.register_magic_function(cellm, 'cell', 'cellm2')
620 self.check_ident('cellm2')
642 self.check_ident('cellm2')
621
643
622 def test_cell_magic_class(self):
644 def test_cell_magic_class(self):
623 "Cell magics declared via a class"
645 "Cell magics declared via a class"
624 @magics_class
646 @magics_class
625 class MyMagics(Magics):
647 class MyMagics(Magics):
626
648
627 @cell_magic
649 @cell_magic
628 def cellm3(self, line, cell):
650 def cellm3(self, line, cell):
629 return line, cell
651 return line, cell
630
652
631 _ip.register_magics(MyMagics)
653 _ip.register_magics(MyMagics)
632 self.check_ident('cellm3')
654 self.check_ident('cellm3')
633
655
634 def test_cell_magic_class2(self):
656 def test_cell_magic_class2(self):
635 "Cell magics declared via a class, #2"
657 "Cell magics declared via a class, #2"
636 @magics_class
658 @magics_class
637 class MyMagics2(Magics):
659 class MyMagics2(Magics):
638
660
639 @cell_magic('cellm4')
661 @cell_magic('cellm4')
640 def cellm33(self, line, cell):
662 def cellm33(self, line, cell):
641 return line, cell
663 return line, cell
642
664
643 _ip.register_magics(MyMagics2)
665 _ip.register_magics(MyMagics2)
644 self.check_ident('cellm4')
666 self.check_ident('cellm4')
645 # Check that nothing is registered as 'cellm33'
667 # Check that nothing is registered as 'cellm33'
646 c33 = _ip.find_cell_magic('cellm33')
668 c33 = _ip.find_cell_magic('cellm33')
647 nt.assert_equal(c33, None)
669 nt.assert_equal(c33, None)
648
670
649 def test_file():
671 def test_file():
650 """Basic %%file"""
672 """Basic %%file"""
651 ip = get_ipython()
673 ip = get_ipython()
652 with TemporaryDirectory() as td:
674 with TemporaryDirectory() as td:
653 fname = os.path.join(td, 'file1')
675 fname = os.path.join(td, 'file1')
654 ip.run_cell_magic("file", fname, u'\n'.join([
676 ip.run_cell_magic("file", fname, u'\n'.join([
655 'line1',
677 'line1',
656 'line2',
678 'line2',
657 ]))
679 ]))
658 with open(fname) as f:
680 with open(fname) as f:
659 s = f.read()
681 s = f.read()
660 nt.assert_in('line1\n', s)
682 nt.assert_in('line1\n', s)
661 nt.assert_in('line2', s)
683 nt.assert_in('line2', s)
662
684
663 def test_file_var_expand():
685 def test_file_var_expand():
664 """%%file $filename"""
686 """%%file $filename"""
665 ip = get_ipython()
687 ip = get_ipython()
666 with TemporaryDirectory() as td:
688 with TemporaryDirectory() as td:
667 fname = os.path.join(td, 'file1')
689 fname = os.path.join(td, 'file1')
668 ip.user_ns['filename'] = fname
690 ip.user_ns['filename'] = fname
669 ip.run_cell_magic("file", '$filename', u'\n'.join([
691 ip.run_cell_magic("file", '$filename', u'\n'.join([
670 'line1',
692 'line1',
671 'line2',
693 'line2',
672 ]))
694 ]))
673 with open(fname) as f:
695 with open(fname) as f:
674 s = f.read()
696 s = f.read()
675 nt.assert_in('line1\n', s)
697 nt.assert_in('line1\n', s)
676 nt.assert_in('line2', s)
698 nt.assert_in('line2', s)
677
699
678 def test_file_unicode():
700 def test_file_unicode():
679 """%%file with unicode cell"""
701 """%%file with unicode cell"""
680 ip = get_ipython()
702 ip = get_ipython()
681 with TemporaryDirectory() as td:
703 with TemporaryDirectory() as td:
682 fname = os.path.join(td, 'file1')
704 fname = os.path.join(td, 'file1')
683 ip.run_cell_magic("file", fname, u'\n'.join([
705 ip.run_cell_magic("file", fname, u'\n'.join([
684 u'liné1',
706 u'liné1',
685 u'liné2',
707 u'liné2',
686 ]))
708 ]))
687 with io.open(fname, encoding='utf-8') as f:
709 with io.open(fname, encoding='utf-8') as f:
688 s = f.read()
710 s = f.read()
689 nt.assert_in(u'liné1\n', s)
711 nt.assert_in(u'liné1\n', s)
690 nt.assert_in(u'liné2', s)
712 nt.assert_in(u'liné2', s)
691
713
692 def test_file_amend():
714 def test_file_amend():
693 """%%file -a amends files"""
715 """%%file -a amends files"""
694 ip = get_ipython()
716 ip = get_ipython()
695 with TemporaryDirectory() as td:
717 with TemporaryDirectory() as td:
696 fname = os.path.join(td, 'file2')
718 fname = os.path.join(td, 'file2')
697 ip.run_cell_magic("file", fname, u'\n'.join([
719 ip.run_cell_magic("file", fname, u'\n'.join([
698 'line1',
720 'line1',
699 'line2',
721 'line2',
700 ]))
722 ]))
701 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
723 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
702 'line3',
724 'line3',
703 'line4',
725 'line4',
704 ]))
726 ]))
705 with open(fname) as f:
727 with open(fname) as f:
706 s = f.read()
728 s = f.read()
707 nt.assert_in('line1\n', s)
729 nt.assert_in('line1\n', s)
708 nt.assert_in('line3\n', s)
730 nt.assert_in('line3\n', s)
709
731
710
732
711 def test_script_config():
733 def test_script_config():
712 ip = get_ipython()
734 ip = get_ipython()
713 ip.config.ScriptMagics.script_magics = ['whoda']
735 ip.config.ScriptMagics.script_magics = ['whoda']
714 sm = script.ScriptMagics(shell=ip)
736 sm = script.ScriptMagics(shell=ip)
715 nt.assert_in('whoda', sm.magics['cell'])
737 nt.assert_in('whoda', sm.magics['cell'])
716
738
717 @dec.skip_win32
739 @dec.skip_win32
718 def test_script_out():
740 def test_script_out():
719 ip = get_ipython()
741 ip = get_ipython()
720 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
742 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
721 nt.assert_equal(ip.user_ns['output'], 'hi\n')
743 nt.assert_equal(ip.user_ns['output'], 'hi\n')
722
744
723 @dec.skip_win32
745 @dec.skip_win32
724 def test_script_err():
746 def test_script_err():
725 ip = get_ipython()
747 ip = get_ipython()
726 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
748 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
727 nt.assert_equal(ip.user_ns['error'], 'hello\n')
749 nt.assert_equal(ip.user_ns['error'], 'hello\n')
728
750
729 @dec.skip_win32
751 @dec.skip_win32
730 def test_script_out_err():
752 def test_script_out_err():
731 ip = get_ipython()
753 ip = get_ipython()
732 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
754 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
733 nt.assert_equal(ip.user_ns['output'], 'hi\n')
755 nt.assert_equal(ip.user_ns['output'], 'hi\n')
734 nt.assert_equal(ip.user_ns['error'], 'hello\n')
756 nt.assert_equal(ip.user_ns['error'], 'hello\n')
735
757
736 @dec.skip_win32
758 @dec.skip_win32
737 def test_script_bg_out():
759 def test_script_bg_out():
738 ip = get_ipython()
760 ip = get_ipython()
739 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
761 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
740 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
762 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
741
763
742 @dec.skip_win32
764 @dec.skip_win32
743 def test_script_bg_err():
765 def test_script_bg_err():
744 ip = get_ipython()
766 ip = get_ipython()
745 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
767 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
746 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
768 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
747
769
748 @dec.skip_win32
770 @dec.skip_win32
749 def test_script_bg_out_err():
771 def test_script_bg_out_err():
750 ip = get_ipython()
772 ip = get_ipython()
751 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
773 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
752 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
774 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
753 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
775 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
754
776
755 def test_script_defaults():
777 def test_script_defaults():
756 ip = get_ipython()
778 ip = get_ipython()
757 for cmd in ['sh', 'bash', 'perl', 'ruby']:
779 for cmd in ['sh', 'bash', 'perl', 'ruby']:
758 try:
780 try:
759 find_cmd(cmd)
781 find_cmd(cmd)
760 except Exception:
782 except Exception:
761 pass
783 pass
762 else:
784 else:
763 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
785 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
764
786
765
787
766 @magics_class
788 @magics_class
767 class FooFoo(Magics):
789 class FooFoo(Magics):
768 """class with both %foo and %%foo magics"""
790 """class with both %foo and %%foo magics"""
769 @line_magic('foo')
791 @line_magic('foo')
770 def line_foo(self, line):
792 def line_foo(self, line):
771 "I am line foo"
793 "I am line foo"
772 pass
794 pass
773
795
774 @cell_magic("foo")
796 @cell_magic("foo")
775 def cell_foo(self, line, cell):
797 def cell_foo(self, line, cell):
776 "I am cell foo, not line foo"
798 "I am cell foo, not line foo"
777 pass
799 pass
778
800
779 def test_line_cell_info():
801 def test_line_cell_info():
780 """%%foo and %foo magics are distinguishable to inspect"""
802 """%%foo and %foo magics are distinguishable to inspect"""
781 ip = get_ipython()
803 ip = get_ipython()
782 ip.magics_manager.register(FooFoo)
804 ip.magics_manager.register(FooFoo)
783 oinfo = ip.object_inspect('foo')
805 oinfo = ip.object_inspect('foo')
784 nt.assert_true(oinfo['found'])
806 nt.assert_true(oinfo['found'])
785 nt.assert_true(oinfo['ismagic'])
807 nt.assert_true(oinfo['ismagic'])
786
808
787 oinfo = ip.object_inspect('%%foo')
809 oinfo = ip.object_inspect('%%foo')
788 nt.assert_true(oinfo['found'])
810 nt.assert_true(oinfo['found'])
789 nt.assert_true(oinfo['ismagic'])
811 nt.assert_true(oinfo['ismagic'])
790 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
812 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
791
813
792 oinfo = ip.object_inspect('%foo')
814 oinfo = ip.object_inspect('%foo')
793 nt.assert_true(oinfo['found'])
815 nt.assert_true(oinfo['found'])
794 nt.assert_true(oinfo['ismagic'])
816 nt.assert_true(oinfo['ismagic'])
795 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
817 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
796
818
797 def test_multiple_magics():
819 def test_multiple_magics():
798 ip = get_ipython()
820 ip = get_ipython()
799 foo1 = FooFoo(ip)
821 foo1 = FooFoo(ip)
800 foo2 = FooFoo(ip)
822 foo2 = FooFoo(ip)
801 mm = ip.magics_manager
823 mm = ip.magics_manager
802 mm.register(foo1)
824 mm.register(foo1)
803 nt.assert_true(mm.magics['line']['foo'].im_self is foo1)
825 nt.assert_true(mm.magics['line']['foo'].im_self is foo1)
804 mm.register(foo2)
826 mm.register(foo2)
805 nt.assert_true(mm.magics['line']['foo'].im_self is foo2)
827 nt.assert_true(mm.magics['line']['foo'].im_self is foo2)
806
828
807 def test_alias_magic():
829 def test_alias_magic():
808 """Test %alias_magic."""
830 """Test %alias_magic."""
809 ip = get_ipython()
831 ip = get_ipython()
810 mm = ip.magics_manager
832 mm = ip.magics_manager
811
833
812 # Basic operation: both cell and line magics are created, if possible.
834 # Basic operation: both cell and line magics are created, if possible.
813 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
835 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
814 nt.assert_in('timeit_alias', mm.magics['line'])
836 nt.assert_in('timeit_alias', mm.magics['line'])
815 nt.assert_in('timeit_alias', mm.magics['cell'])
837 nt.assert_in('timeit_alias', mm.magics['cell'])
816
838
817 # --cell is specified, line magic not created.
839 # --cell is specified, line magic not created.
818 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
840 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
819 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
841 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
820 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
842 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
821
843
822 # Test that line alias is created successfully.
844 # Test that line alias is created successfully.
823 ip.run_line_magic('alias_magic', '--line env_alias env')
845 ip.run_line_magic('alias_magic', '--line env_alias env')
824 nt.assert_equal(ip.run_line_magic('env', ''),
846 nt.assert_equal(ip.run_line_magic('env', ''),
825 ip.run_line_magic('env_alias', ''))
847 ip.run_line_magic('env_alias', ''))
826
848
827 def test_save():
849 def test_save():
828 """Test %save."""
850 """Test %save."""
829 ip = get_ipython()
851 ip = get_ipython()
830 ip.history_manager.reset() # Clear any existing history.
852 ip.history_manager.reset() # Clear any existing history.
831 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
853 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
832 for i, cmd in enumerate(cmds, start=1):
854 for i, cmd in enumerate(cmds, start=1):
833 ip.history_manager.store_inputs(i, cmd)
855 ip.history_manager.store_inputs(i, cmd)
834 with TemporaryDirectory() as tmpdir:
856 with TemporaryDirectory() as tmpdir:
835 file = os.path.join(tmpdir, "testsave.py")
857 file = os.path.join(tmpdir, "testsave.py")
836 ip.run_line_magic("save", "%s 1-10" % file)
858 ip.run_line_magic("save", "%s 1-10" % file)
837 with open(file) as f:
859 with open(file) as f:
838 content = f.read()
860 content = f.read()
839 nt.assert_equal(content.count(cmds[0]), 1)
861 nt.assert_equal(content.count(cmds[0]), 1)
840 nt.assert_in('coding: utf-8', content)
862 nt.assert_in('coding: utf-8', content)
841 ip.run_line_magic("save", "-a %s 1-10" % file)
863 ip.run_line_magic("save", "-a %s 1-10" % file)
842 with open(file) as f:
864 with open(file) as f:
843 content = f.read()
865 content = f.read()
844 nt.assert_equal(content.count(cmds[0]), 2)
866 nt.assert_equal(content.count(cmds[0]), 2)
845 nt.assert_in('coding: utf-8', content)
867 nt.assert_in('coding: utf-8', content)
846
868
847
869
848 def test_store():
870 def test_store():
849 """Test %store."""
871 """Test %store."""
850 ip = get_ipython()
872 ip = get_ipython()
851 ip.run_line_magic('load_ext', 'storemagic')
873 ip.run_line_magic('load_ext', 'storemagic')
852
874
853 # make sure the storage is empty
875 # make sure the storage is empty
854 ip.run_line_magic('store', '-z')
876 ip.run_line_magic('store', '-z')
855 ip.user_ns['var'] = 42
877 ip.user_ns['var'] = 42
856 ip.run_line_magic('store', 'var')
878 ip.run_line_magic('store', 'var')
857 ip.user_ns['var'] = 39
879 ip.user_ns['var'] = 39
858 ip.run_line_magic('store', '-r')
880 ip.run_line_magic('store', '-r')
859 nt.assert_equal(ip.user_ns['var'], 42)
881 nt.assert_equal(ip.user_ns['var'], 42)
860
882
861 ip.run_line_magic('store', '-d var')
883 ip.run_line_magic('store', '-d var')
862 ip.user_ns['var'] = 39
884 ip.user_ns['var'] = 39
863 ip.run_line_magic('store' , '-r')
885 ip.run_line_magic('store' , '-r')
864 nt.assert_equal(ip.user_ns['var'], 39)
886 nt.assert_equal(ip.user_ns['var'], 39)
865
887
866
888
867 def _run_edit_test(arg_s, exp_filename=None,
889 def _run_edit_test(arg_s, exp_filename=None,
868 exp_lineno=-1,
890 exp_lineno=-1,
869 exp_contents=None,
891 exp_contents=None,
870 exp_is_temp=None):
892 exp_is_temp=None):
871 ip = get_ipython()
893 ip = get_ipython()
872 M = code.CodeMagics(ip)
894 M = code.CodeMagics(ip)
873 last_call = ['','']
895 last_call = ['','']
874 opts,args = M.parse_options(arg_s,'prxn:')
896 opts,args = M.parse_options(arg_s,'prxn:')
875 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
897 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
876
898
877 if exp_filename is not None:
899 if exp_filename is not None:
878 nt.assert_equal(exp_filename, filename)
900 nt.assert_equal(exp_filename, filename)
879 if exp_contents is not None:
901 if exp_contents is not None:
880 with io.open(filename, 'r') as f:
902 with io.open(filename, 'r') as f:
881 contents = f.read()
903 contents = f.read()
882 nt.assert_equal(exp_contents, contents)
904 nt.assert_equal(exp_contents, contents)
883 if exp_lineno != -1:
905 if exp_lineno != -1:
884 nt.assert_equal(exp_lineno, lineno)
906 nt.assert_equal(exp_lineno, lineno)
885 if exp_is_temp is not None:
907 if exp_is_temp is not None:
886 nt.assert_equal(exp_is_temp, is_temp)
908 nt.assert_equal(exp_is_temp, is_temp)
887
909
888
910
889 def test_edit_interactive():
911 def test_edit_interactive():
890 """%edit on interactively defined objects"""
912 """%edit on interactively defined objects"""
891 ip = get_ipython()
913 ip = get_ipython()
892 n = ip.execution_count
914 n = ip.execution_count
893 ip.run_cell(u"def foo(): return 1", store_history=True)
915 ip.run_cell(u"def foo(): return 1", store_history=True)
894
916
895 try:
917 try:
896 _run_edit_test("foo")
918 _run_edit_test("foo")
897 except code.InteractivelyDefined as e:
919 except code.InteractivelyDefined as e:
898 nt.assert_equal(e.index, n)
920 nt.assert_equal(e.index, n)
899 else:
921 else:
900 raise AssertionError("Should have raised InteractivelyDefined")
922 raise AssertionError("Should have raised InteractivelyDefined")
901
923
902
924
903 def test_edit_cell():
925 def test_edit_cell():
904 """%edit [cell id]"""
926 """%edit [cell id]"""
905 ip = get_ipython()
927 ip = get_ipython()
906
928
907 ip.run_cell(u"def foo(): return 1", store_history=True)
929 ip.run_cell(u"def foo(): return 1", store_history=True)
908
930
909 # test
931 # test
910 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
932 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
General Comments 0
You need to be logged in to leave comments. Login now