##// END OF EJS Templates
Merge pull request #11330 from hongshaoyang/patch-1...
Matthias Bussonnier -
r24696:2f25f7dd merge
parent child Browse files
Show More
@@ -1,831 +1,834 b''
1 """Implementation of magic functions for interaction with the OS.
1 """Implementation of magic functions for interaction with the OS.
2
2
3 Note: this module is named 'osm' instead of 'os' to avoid a collision with the
3 Note: this module is named 'osm' instead of 'os' to avoid a collision with the
4 builtin.
4 builtin.
5 """
5 """
6 # Copyright (c) IPython Development Team.
6 # Copyright (c) IPython Development Team.
7 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
8
8
9 import io
9 import io
10 import os
10 import os
11 import re
11 import re
12 import sys
12 import sys
13 from pprint import pformat
13 from pprint import pformat
14
14
15 from IPython.core import magic_arguments
15 from IPython.core import magic_arguments
16 from IPython.core import oinspect
16 from IPython.core import oinspect
17 from IPython.core import page
17 from IPython.core import page
18 from IPython.core.alias import AliasError, Alias
18 from IPython.core.alias import AliasError, Alias
19 from IPython.core.error import UsageError
19 from IPython.core.error import UsageError
20 from IPython.core.magic import (
20 from IPython.core.magic import (
21 Magics, compress_dhist, magics_class, line_magic, cell_magic, line_cell_magic
21 Magics, compress_dhist, magics_class, line_magic, cell_magic, line_cell_magic
22 )
22 )
23 from IPython.testing.skipdoctest import skip_doctest
23 from IPython.testing.skipdoctest import skip_doctest
24 from IPython.utils.openpy import source_to_unicode
24 from IPython.utils.openpy import source_to_unicode
25 from IPython.utils.process import abbrev_cwd
25 from IPython.utils.process import abbrev_cwd
26 from IPython.utils.terminal import set_term_title
26 from IPython.utils.terminal import set_term_title
27
27
28
28
29 @magics_class
29 @magics_class
30 class OSMagics(Magics):
30 class OSMagics(Magics):
31 """Magics to interact with the underlying OS (shell-type functionality).
31 """Magics to interact with the underlying OS (shell-type functionality).
32 """
32 """
33
33
34 def __init__(self, shell=None, **kwargs):
34 def __init__(self, shell=None, **kwargs):
35
35
36 # Now define isexec in a cross platform manner.
36 # Now define isexec in a cross platform manner.
37 self.is_posix = False
37 self.is_posix = False
38 self.execre = None
38 self.execre = None
39 if os.name == 'posix':
39 if os.name == 'posix':
40 self.is_posix = True
40 self.is_posix = True
41 else:
41 else:
42 try:
42 try:
43 winext = os.environ['pathext'].replace(';','|').replace('.','')
43 winext = os.environ['pathext'].replace(';','|').replace('.','')
44 except KeyError:
44 except KeyError:
45 winext = 'exe|com|bat|py'
45 winext = 'exe|com|bat|py'
46
46
47 self.execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE)
47 self.execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE)
48
48
49 # call up the chain
49 # call up the chain
50 super().__init__(shell=shell, **kwargs)
50 super().__init__(shell=shell, **kwargs)
51
51
52
52
53 @skip_doctest
53 @skip_doctest
54 def _isexec_POSIX(self, file):
54 def _isexec_POSIX(self, file):
55 """
55 """
56 Test for executible on a POSIX system
56 Test for executible on a POSIX system
57 """
57 """
58 return file.is_file() and os.access(file.path, os.X_OK)
58 return file.is_file() and os.access(file.path, os.X_OK)
59
59
60
60
61 @skip_doctest
61 @skip_doctest
62 def _isexec_WIN(self, file):
62 def _isexec_WIN(self, file):
63 """
63 """
64 Test for executible file on non POSIX system
64 Test for executible file on non POSIX system
65 """
65 """
66 return file.is_file() and self.execre.match(file.name) is not None
66 return file.is_file() and self.execre.match(file.name) is not None
67
67
68 @skip_doctest
68 @skip_doctest
69 def isexec(self, file):
69 def isexec(self, file):
70 """
70 """
71 Test for executible file on non POSIX system
71 Test for executible file on non POSIX system
72 """
72 """
73 if self.is_posix:
73 if self.is_posix:
74 return self._isexec_POSIX(file)
74 return self._isexec_POSIX(file)
75 else:
75 else:
76 return self._isexec_WIN(file)
76 return self._isexec_WIN(file)
77
77
78
78
79 @skip_doctest
79 @skip_doctest
80 @line_magic
80 @line_magic
81 def alias(self, parameter_s=''):
81 def alias(self, parameter_s=''):
82 """Define an alias for a system command.
82 """Define an alias for a system command.
83
83
84 '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd'
84 '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd'
85
85
86 Then, typing 'alias_name params' will execute the system command 'cmd
86 Then, typing 'alias_name params' will execute the system command 'cmd
87 params' (from your underlying operating system).
87 params' (from your underlying operating system).
88
88
89 Aliases have lower precedence than magic functions and Python normal
89 Aliases have lower precedence than magic functions and Python normal
90 variables, so if 'foo' is both a Python variable and an alias, the
90 variables, so if 'foo' is both a Python variable and an alias, the
91 alias can not be executed until 'del foo' removes the Python variable.
91 alias can not be executed until 'del foo' removes the Python variable.
92
92
93 You can use the %l specifier in an alias definition to represent the
93 You can use the %l specifier in an alias definition to represent the
94 whole line when the alias is called. For example::
94 whole line when the alias is called. For example::
95
95
96 In [2]: alias bracket echo "Input in brackets: <%l>"
96 In [2]: alias bracket echo "Input in brackets: <%l>"
97 In [3]: bracket hello world
97 In [3]: bracket hello world
98 Input in brackets: <hello world>
98 Input in brackets: <hello world>
99
99
100 You can also define aliases with parameters using %s specifiers (one
100 You can also define aliases with parameters using %s specifiers (one
101 per parameter)::
101 per parameter)::
102
102
103 In [1]: alias parts echo first %s second %s
103 In [1]: alias parts echo first %s second %s
104 In [2]: %parts A B
104 In [2]: %parts A B
105 first A second B
105 first A second B
106 In [3]: %parts A
106 In [3]: %parts A
107 Incorrect number of arguments: 2 expected.
107 Incorrect number of arguments: 2 expected.
108 parts is an alias to: 'echo first %s second %s'
108 parts is an alias to: 'echo first %s second %s'
109
109
110 Note that %l and %s are mutually exclusive. You can only use one or
110 Note that %l and %s are mutually exclusive. You can only use one or
111 the other in your aliases.
111 the other in your aliases.
112
112
113 Aliases expand Python variables just like system calls using ! or !!
113 Aliases expand Python variables just like system calls using ! or !!
114 do: all expressions prefixed with '$' get expanded. For details of
114 do: all expressions prefixed with '$' get expanded. For details of
115 the semantic rules, see PEP-215:
115 the semantic rules, see PEP-215:
116 http://www.python.org/peps/pep-0215.html. This is the library used by
116 http://www.python.org/peps/pep-0215.html. This is the library used by
117 IPython for variable expansion. If you want to access a true shell
117 IPython for variable expansion. If you want to access a true shell
118 variable, an extra $ is necessary to prevent its expansion by
118 variable, an extra $ is necessary to prevent its expansion by
119 IPython::
119 IPython::
120
120
121 In [6]: alias show echo
121 In [6]: alias show echo
122 In [7]: PATH='A Python string'
122 In [7]: PATH='A Python string'
123 In [8]: show $PATH
123 In [8]: show $PATH
124 A Python string
124 A Python string
125 In [9]: show $$PATH
125 In [9]: show $$PATH
126 /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:...
126 /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:...
127
127
128 You can use the alias facility to access all of $PATH. See the %rehashx
128 You can use the alias facility to access all of $PATH. See the %rehashx
129 function, which automatically creates aliases for the contents of your
129 function, which automatically creates aliases for the contents of your
130 $PATH.
130 $PATH.
131
131
132 If called with no parameters, %alias prints the current alias table
132 If called with no parameters, %alias prints the current alias table
133 for your system. For posix systems, the default aliases are 'cat',
133 for your system. For posix systems, the default aliases are 'cat',
134 'cp', 'mv', 'rm', 'rmdir', and 'mkdir', and other platform-specific
134 'cp', 'mv', 'rm', 'rmdir', and 'mkdir', and other platform-specific
135 aliases are added. For windows-based systems, the default aliases are
135 aliases are added. For windows-based systems, the default aliases are
136 'copy', 'ddir', 'echo', 'ls', 'ldir', 'mkdir', 'ren', and 'rmdir'.
136 'copy', 'ddir', 'echo', 'ls', 'ldir', 'mkdir', 'ren', and 'rmdir'.
137
137
138 You can see the definition of alias by adding a question mark in the
138 You can see the definition of alias by adding a question mark in the
139 end::
139 end::
140
140
141 In [1]: cat?
141 In [1]: cat?
142 Repr: <alias cat for 'cat'>"""
142 Repr: <alias cat for 'cat'>"""
143
143
144 par = parameter_s.strip()
144 par = parameter_s.strip()
145 if not par:
145 if not par:
146 aliases = sorted(self.shell.alias_manager.aliases)
146 aliases = sorted(self.shell.alias_manager.aliases)
147 # stored = self.shell.db.get('stored_aliases', {} )
147 # stored = self.shell.db.get('stored_aliases', {} )
148 # for k, v in stored:
148 # for k, v in stored:
149 # atab.append(k, v[0])
149 # atab.append(k, v[0])
150
150
151 print("Total number of aliases:", len(aliases))
151 print("Total number of aliases:", len(aliases))
152 sys.stdout.flush()
152 sys.stdout.flush()
153 return aliases
153 return aliases
154
154
155 # Now try to define a new one
155 # Now try to define a new one
156 try:
156 try:
157 alias,cmd = par.split(None, 1)
157 alias,cmd = par.split(None, 1)
158 except TypeError:
158 except TypeError:
159 print(oinspect.getdoc(self.alias))
159 print(oinspect.getdoc(self.alias))
160 return
160 return
161
161
162 try:
162 try:
163 self.shell.alias_manager.define_alias(alias, cmd)
163 self.shell.alias_manager.define_alias(alias, cmd)
164 except AliasError as e:
164 except AliasError as e:
165 print(e)
165 print(e)
166 # end magic_alias
166 # end magic_alias
167
167
168 @line_magic
168 @line_magic
169 def unalias(self, parameter_s=''):
169 def unalias(self, parameter_s=''):
170 """Remove an alias"""
170 """Remove an alias"""
171
171
172 aname = parameter_s.strip()
172 aname = parameter_s.strip()
173 try:
173 try:
174 self.shell.alias_manager.undefine_alias(aname)
174 self.shell.alias_manager.undefine_alias(aname)
175 except ValueError as e:
175 except ValueError as e:
176 print(e)
176 print(e)
177 return
177 return
178
178
179 stored = self.shell.db.get('stored_aliases', {} )
179 stored = self.shell.db.get('stored_aliases', {} )
180 if aname in stored:
180 if aname in stored:
181 print("Removing %stored alias",aname)
181 print("Removing %stored alias",aname)
182 del stored[aname]
182 del stored[aname]
183 self.shell.db['stored_aliases'] = stored
183 self.shell.db['stored_aliases'] = stored
184
184
185 @line_magic
185 @line_magic
186 def rehashx(self, parameter_s=''):
186 def rehashx(self, parameter_s=''):
187 """Update the alias table with all executable files in $PATH.
187 """Update the alias table with all executable files in $PATH.
188
188
189 rehashx explicitly checks that every entry in $PATH is a file
189 rehashx explicitly checks that every entry in $PATH is a file
190 with execute access (os.X_OK).
190 with execute access (os.X_OK).
191
191
192 Under Windows, it checks executability as a match against a
192 Under Windows, it checks executability as a match against a
193 '|'-separated string of extensions, stored in the IPython config
193 '|'-separated string of extensions, stored in the IPython config
194 variable win_exec_ext. This defaults to 'exe|com|bat'.
194 variable win_exec_ext. This defaults to 'exe|com|bat'.
195
195
196 This function also resets the root module cache of module completer,
196 This function also resets the root module cache of module completer,
197 used on slow filesystems.
197 used on slow filesystems.
198 """
198 """
199 from IPython.core.alias import InvalidAliasError
199 from IPython.core.alias import InvalidAliasError
200
200
201 # for the benefit of module completer in ipy_completers.py
201 # for the benefit of module completer in ipy_completers.py
202 del self.shell.db['rootmodules_cache']
202 del self.shell.db['rootmodules_cache']
203
203
204 path = [os.path.abspath(os.path.expanduser(p)) for p in
204 path = [os.path.abspath(os.path.expanduser(p)) for p in
205 os.environ.get('PATH','').split(os.pathsep)]
205 os.environ.get('PATH','').split(os.pathsep)]
206
206
207 syscmdlist = []
207 syscmdlist = []
208 savedir = os.getcwd()
208 savedir = os.getcwd()
209
209
210 # Now walk the paths looking for executables to alias.
210 # Now walk the paths looking for executables to alias.
211 try:
211 try:
212 # write the whole loop for posix/Windows so we don't have an if in
212 # write the whole loop for posix/Windows so we don't have an if in
213 # the innermost part
213 # the innermost part
214 if self.is_posix:
214 if self.is_posix:
215 for pdir in path:
215 for pdir in path:
216 try:
216 try:
217 os.chdir(pdir)
217 os.chdir(pdir)
218 except OSError:
218 except OSError:
219 continue
219 continue
220
220
221 # for python 3.6+ rewrite to: with os.scandir(pdir) as dirlist:
221 # for python 3.6+ rewrite to: with os.scandir(pdir) as dirlist:
222 dirlist = os.scandir(path=pdir)
222 dirlist = os.scandir(path=pdir)
223 for ff in dirlist:
223 for ff in dirlist:
224 if self.isexec(ff):
224 if self.isexec(ff):
225 fname = ff.name
225 fname = ff.name
226 try:
226 try:
227 # Removes dots from the name since ipython
227 # Removes dots from the name since ipython
228 # will assume names with dots to be python.
228 # will assume names with dots to be python.
229 if not self.shell.alias_manager.is_alias(fname):
229 if not self.shell.alias_manager.is_alias(fname):
230 self.shell.alias_manager.define_alias(
230 self.shell.alias_manager.define_alias(
231 fname.replace('.',''), fname)
231 fname.replace('.',''), fname)
232 except InvalidAliasError:
232 except InvalidAliasError:
233 pass
233 pass
234 else:
234 else:
235 syscmdlist.append(fname)
235 syscmdlist.append(fname)
236 else:
236 else:
237 no_alias = Alias.blacklist
237 no_alias = Alias.blacklist
238 for pdir in path:
238 for pdir in path:
239 try:
239 try:
240 os.chdir(pdir)
240 os.chdir(pdir)
241 except OSError:
241 except OSError:
242 continue
242 continue
243
243
244 # for python 3.6+ rewrite to: with os.scandir(pdir) as dirlist:
244 # for python 3.6+ rewrite to: with os.scandir(pdir) as dirlist:
245 dirlist = os.scandir(pdir)
245 dirlist = os.scandir(pdir)
246 for ff in dirlist:
246 for ff in dirlist:
247 fname = ff.name
247 fname = ff.name
248 base, ext = os.path.splitext(fname)
248 base, ext = os.path.splitext(fname)
249 if self.isexec(ff) and base.lower() not in no_alias:
249 if self.isexec(ff) and base.lower() not in no_alias:
250 if ext.lower() == '.exe':
250 if ext.lower() == '.exe':
251 fname = base
251 fname = base
252 try:
252 try:
253 # Removes dots from the name since ipython
253 # Removes dots from the name since ipython
254 # will assume names with dots to be python.
254 # will assume names with dots to be python.
255 self.shell.alias_manager.define_alias(
255 self.shell.alias_manager.define_alias(
256 base.lower().replace('.',''), fname)
256 base.lower().replace('.',''), fname)
257 except InvalidAliasError:
257 except InvalidAliasError:
258 pass
258 pass
259 syscmdlist.append(fname)
259 syscmdlist.append(fname)
260
260
261 self.shell.db['syscmdlist'] = syscmdlist
261 self.shell.db['syscmdlist'] = syscmdlist
262 finally:
262 finally:
263 os.chdir(savedir)
263 os.chdir(savedir)
264
264
265 @skip_doctest
265 @skip_doctest
266 @line_magic
266 @line_magic
267 def pwd(self, parameter_s=''):
267 def pwd(self, parameter_s=''):
268 """Return the current working directory path.
268 """Return the current working directory path.
269
269
270 Examples
270 Examples
271 --------
271 --------
272 ::
272 ::
273
273
274 In [9]: pwd
274 In [9]: pwd
275 Out[9]: '/home/tsuser/sprint/ipython'
275 Out[9]: '/home/tsuser/sprint/ipython'
276 """
276 """
277 try:
277 try:
278 return os.getcwd()
278 return os.getcwd()
279 except FileNotFoundError:
279 except FileNotFoundError:
280 raise UsageError("CWD no longer exists - please use %cd to change directory.")
280 raise UsageError("CWD no longer exists - please use %cd to change directory.")
281
281
282 @skip_doctest
282 @skip_doctest
283 @line_magic
283 @line_magic
284 def cd(self, parameter_s=''):
284 def cd(self, parameter_s=''):
285 """Change the current working directory.
285 """Change the current working directory.
286
286
287 This command automatically maintains an internal list of directories
287 This command automatically maintains an internal list of directories
288 you visit during your IPython session, in the variable _dh. The
288 you visit during your IPython session, in the variable _dh. The
289 command %dhist shows this history nicely formatted. You can also
289 command %dhist shows this history nicely formatted. You can also
290 do 'cd -<tab>' to see directory history conveniently.
290 do 'cd -<tab>' to see directory history conveniently.
291
291
292 Usage:
292 Usage:
293
293
294 cd 'dir': changes to directory 'dir'.
294 cd 'dir': changes to directory 'dir'.
295
295
296 cd -: changes to the last visited directory.
296 cd -: changes to the last visited directory.
297
297
298 cd -<n>: changes to the n-th directory in the directory history.
298 cd -<n>: changes to the n-th directory in the directory history.
299
299
300 cd --foo: change to directory that matches 'foo' in history
300 cd --foo: change to directory that matches 'foo' in history
301
301
302 cd -b <bookmark_name>: jump to a bookmark set by %bookmark
302 cd -b <bookmark_name>: jump to a bookmark set by %bookmark
303 (note: cd <bookmark_name> is enough if there is no
303 (note: cd <bookmark_name> is enough if there is no
304 directory <bookmark_name>, but a bookmark with the name exists.)
304 directory <bookmark_name>, but a bookmark with the name exists.)
305 'cd -b <tab>' allows you to tab-complete bookmark names.
305 'cd -b <tab>' allows you to tab-complete bookmark names.
306
306
307 Options:
307 Options:
308
308
309 -q: quiet. Do not print the working directory after the cd command is
309 -q: quiet. Do not print the working directory after the cd command is
310 executed. By default IPython's cd command does print this directory,
310 executed. By default IPython's cd command does print this directory,
311 since the default prompts do not display path information.
311 since the default prompts do not display path information.
312
312
313 Note that !cd doesn't work for this purpose because the shell where
313 Note that !cd doesn't work for this purpose because the shell where
314 !command runs is immediately discarded after executing 'command'.
314 !command runs is immediately discarded after executing 'command'.
315
315
316 Examples
316 Examples
317 --------
317 --------
318 ::
318 ::
319
319
320 In [10]: cd parent/child
320 In [10]: cd parent/child
321 /home/tsuser/parent/child
321 /home/tsuser/parent/child
322 """
322 """
323
323
324 try:
324 try:
325 oldcwd = os.getcwd()
325 oldcwd = os.getcwd()
326 except FileNotFoundError:
326 except FileNotFoundError:
327 # Happens if the CWD has been deleted.
327 # Happens if the CWD has been deleted.
328 oldcwd = None
328 oldcwd = None
329
329
330 numcd = re.match(r'(-)(\d+)$',parameter_s)
330 numcd = re.match(r'(-)(\d+)$',parameter_s)
331 # jump in directory history by number
331 # jump in directory history by number
332 if numcd:
332 if numcd:
333 nn = int(numcd.group(2))
333 nn = int(numcd.group(2))
334 try:
334 try:
335 ps = self.shell.user_ns['_dh'][nn]
335 ps = self.shell.user_ns['_dh'][nn]
336 except IndexError:
336 except IndexError:
337 print('The requested directory does not exist in history.')
337 print('The requested directory does not exist in history.')
338 return
338 return
339 else:
339 else:
340 opts = {}
340 opts = {}
341 elif parameter_s.startswith('--'):
341 elif parameter_s.startswith('--'):
342 ps = None
342 ps = None
343 fallback = None
343 fallback = None
344 pat = parameter_s[2:]
344 pat = parameter_s[2:]
345 dh = self.shell.user_ns['_dh']
345 dh = self.shell.user_ns['_dh']
346 # first search only by basename (last component)
346 # first search only by basename (last component)
347 for ent in reversed(dh):
347 for ent in reversed(dh):
348 if pat in os.path.basename(ent) and os.path.isdir(ent):
348 if pat in os.path.basename(ent) and os.path.isdir(ent):
349 ps = ent
349 ps = ent
350 break
350 break
351
351
352 if fallback is None and pat in ent and os.path.isdir(ent):
352 if fallback is None and pat in ent and os.path.isdir(ent):
353 fallback = ent
353 fallback = ent
354
354
355 # if we have no last part match, pick the first full path match
355 # if we have no last part match, pick the first full path match
356 if ps is None:
356 if ps is None:
357 ps = fallback
357 ps = fallback
358
358
359 if ps is None:
359 if ps is None:
360 print("No matching entry in directory history")
360 print("No matching entry in directory history")
361 return
361 return
362 else:
362 else:
363 opts = {}
363 opts = {}
364
364
365
365
366 else:
366 else:
367 opts, ps = self.parse_options(parameter_s, 'qb', mode='string')
367 opts, ps = self.parse_options(parameter_s, 'qb', mode='string')
368 # jump to previous
368 # jump to previous
369 if ps == '-':
369 if ps == '-':
370 try:
370 try:
371 ps = self.shell.user_ns['_dh'][-2]
371 ps = self.shell.user_ns['_dh'][-2]
372 except IndexError:
372 except IndexError:
373 raise UsageError('%cd -: No previous directory to change to.')
373 raise UsageError('%cd -: No previous directory to change to.')
374 # jump to bookmark if needed
374 # jump to bookmark if needed
375 else:
375 else:
376 if not os.path.isdir(ps) or 'b' in opts:
376 if not os.path.isdir(ps) or 'b' in opts:
377 bkms = self.shell.db.get('bookmarks', {})
377 bkms = self.shell.db.get('bookmarks', {})
378
378
379 if ps in bkms:
379 if ps in bkms:
380 target = bkms[ps]
380 target = bkms[ps]
381 print('(bookmark:%s) -> %s' % (ps, target))
381 print('(bookmark:%s) -> %s' % (ps, target))
382 ps = target
382 ps = target
383 else:
383 else:
384 if 'b' in opts:
384 if 'b' in opts:
385 raise UsageError("Bookmark '%s' not found. "
385 raise UsageError("Bookmark '%s' not found. "
386 "Use '%%bookmark -l' to see your bookmarks." % ps)
386 "Use '%%bookmark -l' to see your bookmarks." % ps)
387
387
388 # at this point ps should point to the target dir
388 # at this point ps should point to the target dir
389 if ps:
389 if ps:
390 try:
390 try:
391 os.chdir(os.path.expanduser(ps))
391 os.chdir(os.path.expanduser(ps))
392 if hasattr(self.shell, 'term_title') and self.shell.term_title:
392 if hasattr(self.shell, 'term_title') and self.shell.term_title:
393 set_term_title(self.shell.term_title_format.format(cwd=abbrev_cwd()))
393 set_term_title(self.shell.term_title_format.format(cwd=abbrev_cwd()))
394 except OSError:
394 except OSError:
395 print(sys.exc_info()[1])
395 print(sys.exc_info()[1])
396 else:
396 else:
397 cwd = os.getcwd()
397 cwd = os.getcwd()
398 dhist = self.shell.user_ns['_dh']
398 dhist = self.shell.user_ns['_dh']
399 if oldcwd != cwd:
399 if oldcwd != cwd:
400 dhist.append(cwd)
400 dhist.append(cwd)
401 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
401 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
402
402
403 else:
403 else:
404 os.chdir(self.shell.home_dir)
404 os.chdir(self.shell.home_dir)
405 if hasattr(self.shell, 'term_title') and self.shell.term_title:
405 if hasattr(self.shell, 'term_title') and self.shell.term_title:
406 set_term_title(self.shell.term_title_format.format(cwd="~"))
406 set_term_title(self.shell.term_title_format.format(cwd="~"))
407 cwd = os.getcwd()
407 cwd = os.getcwd()
408 dhist = self.shell.user_ns['_dh']
408 dhist = self.shell.user_ns['_dh']
409
409
410 if oldcwd != cwd:
410 if oldcwd != cwd:
411 dhist.append(cwd)
411 dhist.append(cwd)
412 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
412 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
413 if not 'q' in opts and self.shell.user_ns['_dh']:
413 if not 'q' in opts and self.shell.user_ns['_dh']:
414 print(self.shell.user_ns['_dh'][-1])
414 print(self.shell.user_ns['_dh'][-1])
415
415
416 @line_magic
416 @line_magic
417 def env(self, parameter_s=''):
417 def env(self, parameter_s=''):
418 """Get, set, or list environment variables.
418 """Get, set, or list environment variables.
419
419
420 Usage:\\
420 Usage:\\
421
421
422 %env: lists all environment variables/values
422 %env: lists all environment variables/values
423 %env var: get value for var
423 %env var: get value for var
424 %env var val: set value for var
424 %env var val: set value for var
425 %env var=val: set value for var
425 %env var=val: set value for var
426 %env var=$val: set value for var, using python expansion if possible
426 %env var=$val: set value for var, using python expansion if possible
427 """
427 """
428 if parameter_s.strip():
428 if parameter_s.strip():
429 split = '=' if '=' in parameter_s else ' '
429 split = '=' if '=' in parameter_s else ' '
430 bits = parameter_s.split(split)
430 bits = parameter_s.split(split)
431 if len(bits) == 1:
431 if len(bits) == 1:
432 key = parameter_s.strip()
432 key = parameter_s.strip()
433 if key in os.environ:
433 if key in os.environ:
434 return os.environ[key]
434 return os.environ[key]
435 else:
435 else:
436 err = "Environment does not have key: {0}".format(key)
436 err = "Environment does not have key: {0}".format(key)
437 raise UsageError(err)
437 raise UsageError(err)
438 if len(bits) > 1:
438 if len(bits) > 1:
439 return self.set_env(parameter_s)
439 return self.set_env(parameter_s)
440 return dict(os.environ)
440 return dict(os.environ)
441
441
442 @line_magic
442 @line_magic
443 def set_env(self, parameter_s):
443 def set_env(self, parameter_s):
444 """Set environment variables. Assumptions are that either "val" is a
444 """Set environment variables. Assumptions are that either "val" is a
445 name in the user namespace, or val is something that evaluates to a
445 name in the user namespace, or val is something that evaluates to a
446 string.
446 string.
447
447
448 Usage:\\
448 Usage:\\
449 %set_env var val: set value for var
449 %set_env var val: set value for var
450 %set_env var=val: set value for var
450 %set_env var=val: set value for var
451 %set_env var=$val: set value for var, using python expansion if possible
451 %set_env var=$val: set value for var, using python expansion if possible
452 """
452 """
453 split = '=' if '=' in parameter_s else ' '
453 split = '=' if '=' in parameter_s else ' '
454 bits = parameter_s.split(split, 1)
454 bits = parameter_s.split(split, 1)
455 if not parameter_s.strip() or len(bits)<2:
455 if not parameter_s.strip() or len(bits)<2:
456 raise UsageError("usage is 'set_env var=val'")
456 raise UsageError("usage is 'set_env var=val'")
457 var = bits[0].strip()
457 var = bits[0].strip()
458 val = bits[1].strip()
458 val = bits[1].strip()
459 if re.match(r'.*\s.*', var):
459 if re.match(r'.*\s.*', var):
460 # an environment variable with whitespace is almost certainly
460 # an environment variable with whitespace is almost certainly
461 # not what the user intended. what's more likely is the wrong
461 # not what the user intended. what's more likely is the wrong
462 # split was chosen, ie for "set_env cmd_args A=B", we chose
462 # split was chosen, ie for "set_env cmd_args A=B", we chose
463 # '=' for the split and should have chosen ' '. to get around
463 # '=' for the split and should have chosen ' '. to get around
464 # this, users should just assign directly to os.environ or use
464 # this, users should just assign directly to os.environ or use
465 # standard magic {var} expansion.
465 # standard magic {var} expansion.
466 err = "refusing to set env var with whitespace: '{0}'"
466 err = "refusing to set env var with whitespace: '{0}'"
467 err = err.format(val)
467 err = err.format(val)
468 raise UsageError(err)
468 raise UsageError(err)
469 os.environ[var] = val
469 os.environ[var] = val
470 print('env: {0}={1}'.format(var,val))
470 print('env: {0}={1}'.format(var,val))
471
471
472 @line_magic
472 @line_magic
473 def pushd(self, parameter_s=''):
473 def pushd(self, parameter_s=''):
474 """Place the current dir on stack and change directory.
474 """Place the current dir on stack and change directory.
475
475
476 Usage:\\
476 Usage:\\
477 %pushd ['dirname']
477 %pushd ['dirname']
478 """
478 """
479
479
480 dir_s = self.shell.dir_stack
480 dir_s = self.shell.dir_stack
481 tgt = os.path.expanduser(parameter_s)
481 tgt = os.path.expanduser(parameter_s)
482 cwd = os.getcwd().replace(self.shell.home_dir,'~')
482 cwd = os.getcwd().replace(self.shell.home_dir,'~')
483 if tgt:
483 if tgt:
484 self.cd(parameter_s)
484 self.cd(parameter_s)
485 dir_s.insert(0,cwd)
485 dir_s.insert(0,cwd)
486 return self.shell.magic('dirs')
486 return self.shell.magic('dirs')
487
487
488 @line_magic
488 @line_magic
489 def popd(self, parameter_s=''):
489 def popd(self, parameter_s=''):
490 """Change to directory popped off the top of the stack.
490 """Change to directory popped off the top of the stack.
491 """
491 """
492 if not self.shell.dir_stack:
492 if not self.shell.dir_stack:
493 raise UsageError("%popd on empty stack")
493 raise UsageError("%popd on empty stack")
494 top = self.shell.dir_stack.pop(0)
494 top = self.shell.dir_stack.pop(0)
495 self.cd(top)
495 self.cd(top)
496 print("popd ->",top)
496 print("popd ->",top)
497
497
498 @line_magic
498 @line_magic
499 def dirs(self, parameter_s=''):
499 def dirs(self, parameter_s=''):
500 """Return the current directory stack."""
500 """Return the current directory stack."""
501
501
502 return self.shell.dir_stack
502 return self.shell.dir_stack
503
503
504 @line_magic
504 @line_magic
505 def dhist(self, parameter_s=''):
505 def dhist(self, parameter_s=''):
506 """Print your history of visited directories.
506 """Print your history of visited directories.
507
507
508 %dhist -> print full history\\
508 %dhist -> print full history\\
509 %dhist n -> print last n entries only\\
509 %dhist n -> print last n entries only\\
510 %dhist n1 n2 -> print entries between n1 and n2 (n2 not included)\\
510 %dhist n1 n2 -> print entries between n1 and n2 (n2 not included)\\
511
511
512 This history is automatically maintained by the %cd command, and
512 This history is automatically maintained by the %cd command, and
513 always available as the global list variable _dh. You can use %cd -<n>
513 always available as the global list variable _dh. You can use %cd -<n>
514 to go to directory number <n>.
514 to go to directory number <n>.
515
515
516 Note that most of time, you should view directory history by entering
516 Note that most of time, you should view directory history by entering
517 cd -<TAB>.
517 cd -<TAB>.
518
518
519 """
519 """
520
520
521 dh = self.shell.user_ns['_dh']
521 dh = self.shell.user_ns['_dh']
522 if parameter_s:
522 if parameter_s:
523 try:
523 try:
524 args = map(int,parameter_s.split())
524 args = map(int,parameter_s.split())
525 except:
525 except:
526 self.arg_err(self.dhist)
526 self.arg_err(self.dhist)
527 return
527 return
528 if len(args) == 1:
528 if len(args) == 1:
529 ini,fin = max(len(dh)-(args[0]),0),len(dh)
529 ini,fin = max(len(dh)-(args[0]),0),len(dh)
530 elif len(args) == 2:
530 elif len(args) == 2:
531 ini,fin = args
531 ini,fin = args
532 fin = min(fin, len(dh))
532 fin = min(fin, len(dh))
533 else:
533 else:
534 self.arg_err(self.dhist)
534 self.arg_err(self.dhist)
535 return
535 return
536 else:
536 else:
537 ini,fin = 0,len(dh)
537 ini,fin = 0,len(dh)
538 print('Directory history (kept in _dh)')
538 print('Directory history (kept in _dh)')
539 for i in range(ini, fin):
539 for i in range(ini, fin):
540 print("%d: %s" % (i, dh[i]))
540 print("%d: %s" % (i, dh[i]))
541
541
542 @skip_doctest
542 @skip_doctest
543 @line_magic
543 @line_magic
544 def sc(self, parameter_s=''):
544 def sc(self, parameter_s=''):
545 """Shell capture - run shell command and capture output (DEPRECATED use !).
545 """Shell capture - run shell command and capture output (DEPRECATED use !).
546
546
547 DEPRECATED. Suboptimal, retained for backwards compatibility.
547 DEPRECATED. Suboptimal, retained for backwards compatibility.
548
548
549 You should use the form 'var = !command' instead. Example:
549 You should use the form 'var = !command' instead. Example:
550
550
551 "%sc -l myfiles = ls ~" should now be written as
551 "%sc -l myfiles = ls ~" should now be written as
552
552
553 "myfiles = !ls ~"
553 "myfiles = !ls ~"
554
554
555 myfiles.s, myfiles.l and myfiles.n still apply as documented
555 myfiles.s, myfiles.l and myfiles.n still apply as documented
556 below.
556 below.
557
557
558 --
558 --
559 %sc [options] varname=command
559 %sc [options] varname=command
560
560
561 IPython will run the given command using commands.getoutput(), and
561 IPython will run the given command using commands.getoutput(), and
562 will then update the user's interactive namespace with a variable
562 will then update the user's interactive namespace with a variable
563 called varname, containing the value of the call. Your command can
563 called varname, containing the value of the call. Your command can
564 contain shell wildcards, pipes, etc.
564 contain shell wildcards, pipes, etc.
565
565
566 The '=' sign in the syntax is mandatory, and the variable name you
566 The '=' sign in the syntax is mandatory, and the variable name you
567 supply must follow Python's standard conventions for valid names.
567 supply must follow Python's standard conventions for valid names.
568
568
569 (A special format without variable name exists for internal use)
569 (A special format without variable name exists for internal use)
570
570
571 Options:
571 Options:
572
572
573 -l: list output. Split the output on newlines into a list before
573 -l: list output. Split the output on newlines into a list before
574 assigning it to the given variable. By default the output is stored
574 assigning it to the given variable. By default the output is stored
575 as a single string.
575 as a single string.
576
576
577 -v: verbose. Print the contents of the variable.
577 -v: verbose. Print the contents of the variable.
578
578
579 In most cases you should not need to split as a list, because the
579 In most cases you should not need to split as a list, because the
580 returned value is a special type of string which can automatically
580 returned value is a special type of string which can automatically
581 provide its contents either as a list (split on newlines) or as a
581 provide its contents either as a list (split on newlines) or as a
582 space-separated string. These are convenient, respectively, either
582 space-separated string. These are convenient, respectively, either
583 for sequential processing or to be passed to a shell command.
583 for sequential processing or to be passed to a shell command.
584
584
585 For example::
585 For example::
586
586
587 # Capture into variable a
587 # Capture into variable a
588 In [1]: sc a=ls *py
588 In [1]: sc a=ls *py
589
589
590 # a is a string with embedded newlines
590 # a is a string with embedded newlines
591 In [2]: a
591 In [2]: a
592 Out[2]: 'setup.py\\nwin32_manual_post_install.py'
592 Out[2]: 'setup.py\\nwin32_manual_post_install.py'
593
593
594 # which can be seen as a list:
594 # which can be seen as a list:
595 In [3]: a.l
595 In [3]: a.l
596 Out[3]: ['setup.py', 'win32_manual_post_install.py']
596 Out[3]: ['setup.py', 'win32_manual_post_install.py']
597
597
598 # or as a whitespace-separated string:
598 # or as a whitespace-separated string:
599 In [4]: a.s
599 In [4]: a.s
600 Out[4]: 'setup.py win32_manual_post_install.py'
600 Out[4]: 'setup.py win32_manual_post_install.py'
601
601
602 # a.s is useful to pass as a single command line:
602 # a.s is useful to pass as a single command line:
603 In [5]: !wc -l $a.s
603 In [5]: !wc -l $a.s
604 146 setup.py
604 146 setup.py
605 130 win32_manual_post_install.py
605 130 win32_manual_post_install.py
606 276 total
606 276 total
607
607
608 # while the list form is useful to loop over:
608 # while the list form is useful to loop over:
609 In [6]: for f in a.l:
609 In [6]: for f in a.l:
610 ...: !wc -l $f
610 ...: !wc -l $f
611 ...:
611 ...:
612 146 setup.py
612 146 setup.py
613 130 win32_manual_post_install.py
613 130 win32_manual_post_install.py
614
614
615 Similarly, the lists returned by the -l option are also special, in
615 Similarly, the lists returned by the -l option are also special, in
616 the sense that you can equally invoke the .s attribute on them to
616 the sense that you can equally invoke the .s attribute on them to
617 automatically get a whitespace-separated string from their contents::
617 automatically get a whitespace-separated string from their contents::
618
618
619 In [7]: sc -l b=ls *py
619 In [7]: sc -l b=ls *py
620
620
621 In [8]: b
621 In [8]: b
622 Out[8]: ['setup.py', 'win32_manual_post_install.py']
622 Out[8]: ['setup.py', 'win32_manual_post_install.py']
623
623
624 In [9]: b.s
624 In [9]: b.s
625 Out[9]: 'setup.py win32_manual_post_install.py'
625 Out[9]: 'setup.py win32_manual_post_install.py'
626
626
627 In summary, both the lists and strings used for output capture have
627 In summary, both the lists and strings used for output capture have
628 the following special attributes::
628 the following special attributes::
629
629
630 .l (or .list) : value as list.
630 .l (or .list) : value as list.
631 .n (or .nlstr): value as newline-separated string.
631 .n (or .nlstr): value as newline-separated string.
632 .s (or .spstr): value as space-separated string.
632 .s (or .spstr): value as space-separated string.
633 """
633 """
634
634
635 opts,args = self.parse_options(parameter_s, 'lv')
635 opts,args = self.parse_options(parameter_s, 'lv')
636 # Try to get a variable name and command to run
636 # Try to get a variable name and command to run
637 try:
637 try:
638 # the variable name must be obtained from the parse_options
638 # the variable name must be obtained from the parse_options
639 # output, which uses shlex.split to strip options out.
639 # output, which uses shlex.split to strip options out.
640 var,_ = args.split('=', 1)
640 var,_ = args.split('=', 1)
641 var = var.strip()
641 var = var.strip()
642 # But the command has to be extracted from the original input
642 # But the command has to be extracted from the original input
643 # parameter_s, not on what parse_options returns, to avoid the
643 # parameter_s, not on what parse_options returns, to avoid the
644 # quote stripping which shlex.split performs on it.
644 # quote stripping which shlex.split performs on it.
645 _,cmd = parameter_s.split('=', 1)
645 _,cmd = parameter_s.split('=', 1)
646 except ValueError:
646 except ValueError:
647 var,cmd = '',''
647 var,cmd = '',''
648 # If all looks ok, proceed
648 # If all looks ok, proceed
649 split = 'l' in opts
649 split = 'l' in opts
650 out = self.shell.getoutput(cmd, split=split)
650 out = self.shell.getoutput(cmd, split=split)
651 if 'v' in opts:
651 if 'v' in opts:
652 print('%s ==\n%s' % (var, pformat(out)))
652 print('%s ==\n%s' % (var, pformat(out)))
653 if var:
653 if var:
654 self.shell.user_ns.update({var:out})
654 self.shell.user_ns.update({var:out})
655 else:
655 else:
656 return out
656 return out
657
657
658 @line_cell_magic
658 @line_cell_magic
659 def sx(self, line='', cell=None):
659 def sx(self, line='', cell=None):
660 """Shell execute - run shell command and capture output (!! is short-hand).
660 """Shell execute - run shell command and capture output (!! is short-hand).
661
661
662 %sx command
662 %sx command
663
663
664 IPython will run the given command using commands.getoutput(), and
664 IPython will run the given command using commands.getoutput(), and
665 return the result formatted as a list (split on '\\n'). Since the
665 return the result formatted as a list (split on '\\n'). Since the
666 output is _returned_, it will be stored in ipython's regular output
666 output is _returned_, it will be stored in ipython's regular output
667 cache Out[N] and in the '_N' automatic variables.
667 cache Out[N] and in the '_N' automatic variables.
668
668
669 Notes:
669 Notes:
670
670
671 1) If an input line begins with '!!', then %sx is automatically
671 1) If an input line begins with '!!', then %sx is automatically
672 invoked. That is, while::
672 invoked. That is, while::
673
673
674 !ls
674 !ls
675
675
676 causes ipython to simply issue system('ls'), typing::
676 causes ipython to simply issue system('ls'), typing::
677
677
678 !!ls
678 !!ls
679
679
680 is a shorthand equivalent to::
680 is a shorthand equivalent to::
681
681
682 %sx ls
682 %sx ls
683
683
684 2) %sx differs from %sc in that %sx automatically splits into a list,
684 2) %sx differs from %sc in that %sx automatically splits into a list,
685 like '%sc -l'. The reason for this is to make it as easy as possible
685 like '%sc -l'. The reason for this is to make it as easy as possible
686 to process line-oriented shell output via further python commands.
686 to process line-oriented shell output via further python commands.
687 %sc is meant to provide much finer control, but requires more
687 %sc is meant to provide much finer control, but requires more
688 typing.
688 typing.
689
689
690 3) Just like %sc -l, this is a list with special attributes:
690 3) Just like %sc -l, this is a list with special attributes:
691 ::
691 ::
692
692
693 .l (or .list) : value as list.
693 .l (or .list) : value as list.
694 .n (or .nlstr): value as newline-separated string.
694 .n (or .nlstr): value as newline-separated string.
695 .s (or .spstr): value as whitespace-separated string.
695 .s (or .spstr): value as whitespace-separated string.
696
696
697 This is very useful when trying to use such lists as arguments to
697 This is very useful when trying to use such lists as arguments to
698 system commands."""
698 system commands."""
699
699
700 if cell is None:
700 if cell is None:
701 # line magic
701 # line magic
702 return self.shell.getoutput(line)
702 return self.shell.getoutput(line)
703 else:
703 else:
704 opts,args = self.parse_options(line, '', 'out=')
704 opts,args = self.parse_options(line, '', 'out=')
705 output = self.shell.getoutput(cell)
705 output = self.shell.getoutput(cell)
706 out_name = opts.get('out', opts.get('o'))
706 out_name = opts.get('out', opts.get('o'))
707 if out_name:
707 if out_name:
708 self.shell.user_ns[out_name] = output
708 self.shell.user_ns[out_name] = output
709 else:
709 else:
710 return output
710 return output
711
711
712 system = line_cell_magic('system')(sx)
712 system = line_cell_magic('system')(sx)
713 bang = cell_magic('!')(sx)
713 bang = cell_magic('!')(sx)
714
714
715 @line_magic
715 @line_magic
716 def bookmark(self, parameter_s=''):
716 def bookmark(self, parameter_s=''):
717 """Manage IPython's bookmark system.
717 """Manage IPython's bookmark system.
718
718
719 %bookmark <name> - set bookmark to current dir
719 %bookmark <name> - set bookmark to current dir
720 %bookmark <name> <dir> - set bookmark to <dir>
720 %bookmark <name> <dir> - set bookmark to <dir>
721 %bookmark -l - list all bookmarks
721 %bookmark -l - list all bookmarks
722 %bookmark -d <name> - remove bookmark
722 %bookmark -d <name> - remove bookmark
723 %bookmark -r - remove all bookmarks
723 %bookmark -r - remove all bookmarks
724
724
725 You can later on access a bookmarked folder with::
725 You can later on access a bookmarked folder with::
726
726
727 %cd -b <name>
727 %cd -b <name>
728
728
729 or simply '%cd <name>' if there is no directory called <name> AND
729 or simply '%cd <name>' if there is no directory called <name> AND
730 there is such a bookmark defined.
730 there is such a bookmark defined.
731
731
732 Your bookmarks persist through IPython sessions, but they are
732 Your bookmarks persist through IPython sessions, but they are
733 associated with each profile."""
733 associated with each profile."""
734
734
735 opts,args = self.parse_options(parameter_s,'drl',mode='list')
735 opts,args = self.parse_options(parameter_s,'drl',mode='list')
736 if len(args) > 2:
736 if len(args) > 2:
737 raise UsageError("%bookmark: too many arguments")
737 raise UsageError("%bookmark: too many arguments")
738
738
739 bkms = self.shell.db.get('bookmarks',{})
739 bkms = self.shell.db.get('bookmarks',{})
740
740
741 if 'd' in opts:
741 if 'd' in opts:
742 try:
742 try:
743 todel = args[0]
743 todel = args[0]
744 except IndexError:
744 except IndexError:
745 raise UsageError(
745 raise UsageError(
746 "%bookmark -d: must provide a bookmark to delete")
746 "%bookmark -d: must provide a bookmark to delete")
747 else:
747 else:
748 try:
748 try:
749 del bkms[todel]
749 del bkms[todel]
750 except KeyError:
750 except KeyError:
751 raise UsageError(
751 raise UsageError(
752 "%%bookmark -d: Can't delete bookmark '%s'" % todel)
752 "%%bookmark -d: Can't delete bookmark '%s'" % todel)
753
753
754 elif 'r' in opts:
754 elif 'r' in opts:
755 bkms = {}
755 bkms = {}
756 elif 'l' in opts:
756 elif 'l' in opts:
757 bks = sorted(bkms)
757 bks = sorted(bkms)
758 if bks:
758 if bks:
759 size = max(map(len, bks))
759 size = max(map(len, bks))
760 else:
760 else:
761 size = 0
761 size = 0
762 fmt = '%-'+str(size)+'s -> %s'
762 fmt = '%-'+str(size)+'s -> %s'
763 print('Current bookmarks:')
763 print('Current bookmarks:')
764 for bk in bks:
764 for bk in bks:
765 print(fmt % (bk, bkms[bk]))
765 print(fmt % (bk, bkms[bk]))
766 else:
766 else:
767 if not args:
767 if not args:
768 raise UsageError("%bookmark: You must specify the bookmark name")
768 raise UsageError("%bookmark: You must specify the bookmark name")
769 elif len(args)==1:
769 elif len(args)==1:
770 bkms[args[0]] = os.getcwd()
770 bkms[args[0]] = os.getcwd()
771 elif len(args)==2:
771 elif len(args)==2:
772 bkms[args[0]] = args[1]
772 bkms[args[0]] = args[1]
773 self.shell.db['bookmarks'] = bkms
773 self.shell.db['bookmarks'] = bkms
774
774
775 @line_magic
775 @line_magic
776 def pycat(self, parameter_s=''):
776 def pycat(self, parameter_s=''):
777 """Show a syntax-highlighted file through a pager.
777 """Show a syntax-highlighted file through a pager.
778
778
779 This magic is similar to the cat utility, but it will assume the file
779 This magic is similar to the cat utility, but it will assume the file
780 to be Python source and will show it with syntax highlighting.
780 to be Python source and will show it with syntax highlighting.
781
781
782 This magic command can either take a local filename, an url,
782 This magic command can either take a local filename, an url,
783 an history range (see %history) or a macro as argument ::
783 an history range (see %history) or a macro as argument ::
784
784
785 %pycat myscript.py
785 %pycat myscript.py
786 %pycat 7-27
786 %pycat 7-27
787 %pycat myMacro
787 %pycat myMacro
788 %pycat http://www.example.com/myscript.py
788 %pycat http://www.example.com/myscript.py
789 """
789 """
790 if not parameter_s:
790 if not parameter_s:
791 raise UsageError('Missing filename, URL, input history range, '
791 raise UsageError('Missing filename, URL, input history range, '
792 'or macro.')
792 'or macro.')
793
793
794 try :
794 try :
795 cont = self.shell.find_user_code(parameter_s, skip_encoding_cookie=False)
795 cont = self.shell.find_user_code(parameter_s, skip_encoding_cookie=False)
796 except (ValueError, IOError):
796 except (ValueError, IOError):
797 print("Error: no such file, variable, URL, history range or macro")
797 print("Error: no such file, variable, URL, history range or macro")
798 return
798 return
799
799
800 page.page(self.shell.pycolorize(source_to_unicode(cont)))
800 page.page(self.shell.pycolorize(source_to_unicode(cont)))
801
801
802 @magic_arguments.magic_arguments()
802 @magic_arguments.magic_arguments()
803 @magic_arguments.argument(
803 @magic_arguments.argument(
804 '-a', '--append', action='store_true', default=False,
804 '-a', '--append', action='store_true', default=False,
805 help='Append contents of the cell to an existing file. '
805 help='Append contents of the cell to an existing file. '
806 'The file will be created if it does not exist.'
806 'The file will be created if it does not exist.'
807 )
807 )
808 @magic_arguments.argument(
808 @magic_arguments.argument(
809 'filename', type=str,
809 'filename', type=str,
810 help='file to write'
810 help='file to write'
811 )
811 )
812 @cell_magic
812 @cell_magic
813 def writefile(self, line, cell):
813 def writefile(self, line, cell):
814 """Write the contents of the cell to a file.
814 """Write the contents of the cell to a file.
815
815
816 The file will be overwritten unless the -a (--append) flag is specified.
816 The file will be overwritten unless the -a (--append) flag is specified.
817 """
817 """
818 args = magic_arguments.parse_argstring(self.writefile, line)
818 args = magic_arguments.parse_argstring(self.writefile, line)
819 filename = os.path.expanduser(args.filename)
819 if re.match(r'[\'*\']|["*"]', args.filename):
820
820 filename = os.path.expanduser(args.filename[1:-1])
821 else:
822 filename = os.path.expanduser(args.filename)
823
821 if os.path.exists(filename):
824 if os.path.exists(filename):
822 if args.append:
825 if args.append:
823 print("Appending to %s" % filename)
826 print("Appending to %s" % filename)
824 else:
827 else:
825 print("Overwriting %s" % filename)
828 print("Overwriting %s" % filename)
826 else:
829 else:
827 print("Writing %s" % filename)
830 print("Writing %s" % filename)
828
831
829 mode = 'a' if args.append else 'w'
832 mode = 'a' if args.append else 'w'
830 with io.open(filename, mode, encoding='utf-8') as f:
833 with io.open(filename, mode, encoding='utf-8') as f:
831 f.write(cell)
834 f.write(cell)
@@ -1,1080 +1,1094 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
6
7 import io
7 import io
8 import os
8 import os
9 import re
9 import re
10 import sys
10 import sys
11 import warnings
11 import warnings
12 from unittest import TestCase
12 from unittest import TestCase
13 from importlib import invalidate_caches
13 from importlib import invalidate_caches
14 from io import StringIO
14 from io import StringIO
15
15
16 import nose.tools as nt
16 import nose.tools as nt
17
17
18 import shlex
18 import shlex
19
19
20 from IPython import get_ipython
20 from IPython import get_ipython
21 from IPython.core import magic
21 from IPython.core import magic
22 from IPython.core.error import UsageError
22 from IPython.core.error import UsageError
23 from IPython.core.magic import (Magics, magics_class, line_magic,
23 from IPython.core.magic import (Magics, magics_class, line_magic,
24 cell_magic,
24 cell_magic,
25 register_line_magic, register_cell_magic)
25 register_line_magic, register_cell_magic)
26 from IPython.core.magics import execution, script, code, logging
26 from IPython.core.magics import execution, script, code, logging
27 from IPython.testing import decorators as dec
27 from IPython.testing import decorators as dec
28 from IPython.testing import tools as tt
28 from IPython.testing import tools as tt
29 from IPython.utils.io import capture_output
29 from IPython.utils.io import capture_output
30 from IPython.utils.tempdir import TemporaryDirectory
30 from IPython.utils.tempdir import (TemporaryDirectory,
31 TemporaryWorkingDirectory)
31 from IPython.utils.process import find_cmd
32 from IPython.utils.process import find_cmd
32
33
33
34
34
35
35 _ip = get_ipython()
36 _ip = get_ipython()
36
37
37 @magic.magics_class
38 @magic.magics_class
38 class DummyMagics(magic.Magics): pass
39 class DummyMagics(magic.Magics): pass
39
40
40 def test_extract_code_ranges():
41 def test_extract_code_ranges():
41 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
42 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
42 expected = [(0, 1),
43 expected = [(0, 1),
43 (2, 3),
44 (2, 3),
44 (4, 6),
45 (4, 6),
45 (6, 9),
46 (6, 9),
46 (9, 14),
47 (9, 14),
47 (16, None),
48 (16, None),
48 (None, 9),
49 (None, 9),
49 (9, None),
50 (9, None),
50 (None, 13),
51 (None, 13),
51 (None, None)]
52 (None, None)]
52 actual = list(code.extract_code_ranges(instr))
53 actual = list(code.extract_code_ranges(instr))
53 nt.assert_equal(actual, expected)
54 nt.assert_equal(actual, expected)
54
55
55 def test_extract_symbols():
56 def test_extract_symbols():
56 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
57 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
57 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
58 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
58 expected = [([], ['a']),
59 expected = [([], ['a']),
59 (["def b():\n return 42\n"], []),
60 (["def b():\n return 42\n"], []),
60 (["class A: pass\n"], []),
61 (["class A: pass\n"], []),
61 (["class A: pass\n", "def b():\n return 42\n"], []),
62 (["class A: pass\n", "def b():\n return 42\n"], []),
62 (["class A: pass\n"], ['a']),
63 (["class A: pass\n"], ['a']),
63 ([], ['z'])]
64 ([], ['z'])]
64 for symbols, exp in zip(symbols_args, expected):
65 for symbols, exp in zip(symbols_args, expected):
65 nt.assert_equal(code.extract_symbols(source, symbols), exp)
66 nt.assert_equal(code.extract_symbols(source, symbols), exp)
66
67
67
68
68 def test_extract_symbols_raises_exception_with_non_python_code():
69 def test_extract_symbols_raises_exception_with_non_python_code():
69 source = ("=begin A Ruby program :)=end\n"
70 source = ("=begin A Ruby program :)=end\n"
70 "def hello\n"
71 "def hello\n"
71 "puts 'Hello world'\n"
72 "puts 'Hello world'\n"
72 "end")
73 "end")
73 with nt.assert_raises(SyntaxError):
74 with nt.assert_raises(SyntaxError):
74 code.extract_symbols(source, "hello")
75 code.extract_symbols(source, "hello")
75
76
76
77
77 def test_magic_not_found():
78 def test_magic_not_found():
78 # magic not found raises UsageError
79 # magic not found raises UsageError
79 with nt.assert_raises(UsageError):
80 with nt.assert_raises(UsageError):
80 _ip.magic('doesntexist')
81 _ip.magic('doesntexist')
81
82
82 # ensure result isn't success when a magic isn't found
83 # ensure result isn't success when a magic isn't found
83 result = _ip.run_cell('%doesntexist')
84 result = _ip.run_cell('%doesntexist')
84 assert isinstance(result.error_in_exec, UsageError)
85 assert isinstance(result.error_in_exec, UsageError)
85
86
86
87
87 def test_cell_magic_not_found():
88 def test_cell_magic_not_found():
88 # magic not found raises UsageError
89 # magic not found raises UsageError
89 with nt.assert_raises(UsageError):
90 with nt.assert_raises(UsageError):
90 _ip.run_cell_magic('doesntexist', 'line', 'cell')
91 _ip.run_cell_magic('doesntexist', 'line', 'cell')
91
92
92 # ensure result isn't success when a magic isn't found
93 # ensure result isn't success when a magic isn't found
93 result = _ip.run_cell('%%doesntexist')
94 result = _ip.run_cell('%%doesntexist')
94 assert isinstance(result.error_in_exec, UsageError)
95 assert isinstance(result.error_in_exec, UsageError)
95
96
96
97
97 def test_magic_error_status():
98 def test_magic_error_status():
98 def fail(shell):
99 def fail(shell):
99 1/0
100 1/0
100 _ip.register_magic_function(fail)
101 _ip.register_magic_function(fail)
101 result = _ip.run_cell('%fail')
102 result = _ip.run_cell('%fail')
102 assert isinstance(result.error_in_exec, ZeroDivisionError)
103 assert isinstance(result.error_in_exec, ZeroDivisionError)
103
104
104
105
105 def test_config():
106 def test_config():
106 """ test that config magic does not raise
107 """ test that config magic does not raise
107 can happen if Configurable init is moved too early into
108 can happen if Configurable init is moved too early into
108 Magics.__init__ as then a Config object will be registered as a
109 Magics.__init__ as then a Config object will be registered as a
109 magic.
110 magic.
110 """
111 """
111 ## should not raise.
112 ## should not raise.
112 _ip.magic('config')
113 _ip.magic('config')
113
114
114 def test_config_available_configs():
115 def test_config_available_configs():
115 """ test that config magic prints available configs in unique and
116 """ test that config magic prints available configs in unique and
116 sorted order. """
117 sorted order. """
117 with capture_output() as captured:
118 with capture_output() as captured:
118 _ip.magic('config')
119 _ip.magic('config')
119
120
120 stdout = captured.stdout
121 stdout = captured.stdout
121 config_classes = stdout.strip().split('\n')[1:]
122 config_classes = stdout.strip().split('\n')[1:]
122 nt.assert_list_equal(config_classes, sorted(set(config_classes)))
123 nt.assert_list_equal(config_classes, sorted(set(config_classes)))
123
124
124 def test_config_print_class():
125 def test_config_print_class():
125 """ test that config with a classname prints the class's options. """
126 """ test that config with a classname prints the class's options. """
126 with capture_output() as captured:
127 with capture_output() as captured:
127 _ip.magic('config TerminalInteractiveShell')
128 _ip.magic('config TerminalInteractiveShell')
128
129
129 stdout = captured.stdout
130 stdout = captured.stdout
130 if not re.match("TerminalInteractiveShell.* options", stdout.splitlines()[0]):
131 if not re.match("TerminalInteractiveShell.* options", stdout.splitlines()[0]):
131 print(stdout)
132 print(stdout)
132 raise AssertionError("1st line of stdout not like "
133 raise AssertionError("1st line of stdout not like "
133 "'TerminalInteractiveShell.* options'")
134 "'TerminalInteractiveShell.* options'")
134
135
135 def test_rehashx():
136 def test_rehashx():
136 # clear up everything
137 # clear up everything
137 _ip.alias_manager.clear_aliases()
138 _ip.alias_manager.clear_aliases()
138 del _ip.db['syscmdlist']
139 del _ip.db['syscmdlist']
139
140
140 _ip.magic('rehashx')
141 _ip.magic('rehashx')
141 # Practically ALL ipython development systems will have more than 10 aliases
142 # Practically ALL ipython development systems will have more than 10 aliases
142
143
143 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
144 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
144 for name, cmd in _ip.alias_manager.aliases:
145 for name, cmd in _ip.alias_manager.aliases:
145 # we must strip dots from alias names
146 # we must strip dots from alias names
146 nt.assert_not_in('.', name)
147 nt.assert_not_in('.', name)
147
148
148 # rehashx must fill up syscmdlist
149 # rehashx must fill up syscmdlist
149 scoms = _ip.db['syscmdlist']
150 scoms = _ip.db['syscmdlist']
150 nt.assert_true(len(scoms) > 10)
151 nt.assert_true(len(scoms) > 10)
151
152
152
153
153 def test_magic_parse_options():
154 def test_magic_parse_options():
154 """Test that we don't mangle paths when parsing magic options."""
155 """Test that we don't mangle paths when parsing magic options."""
155 ip = get_ipython()
156 ip = get_ipython()
156 path = 'c:\\x'
157 path = 'c:\\x'
157 m = DummyMagics(ip)
158 m = DummyMagics(ip)
158 opts = m.parse_options('-f %s' % path,'f:')[0]
159 opts = m.parse_options('-f %s' % path,'f:')[0]
159 # argv splitting is os-dependent
160 # argv splitting is os-dependent
160 if os.name == 'posix':
161 if os.name == 'posix':
161 expected = 'c:x'
162 expected = 'c:x'
162 else:
163 else:
163 expected = path
164 expected = path
164 nt.assert_equal(opts['f'], expected)
165 nt.assert_equal(opts['f'], expected)
165
166
166 def test_magic_parse_long_options():
167 def test_magic_parse_long_options():
167 """Magic.parse_options can handle --foo=bar long options"""
168 """Magic.parse_options can handle --foo=bar long options"""
168 ip = get_ipython()
169 ip = get_ipython()
169 m = DummyMagics(ip)
170 m = DummyMagics(ip)
170 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
171 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
171 nt.assert_in('foo', opts)
172 nt.assert_in('foo', opts)
172 nt.assert_in('bar', opts)
173 nt.assert_in('bar', opts)
173 nt.assert_equal(opts['bar'], "bubble")
174 nt.assert_equal(opts['bar'], "bubble")
174
175
175
176
176 @dec.skip_without('sqlite3')
177 @dec.skip_without('sqlite3')
177 def doctest_hist_f():
178 def doctest_hist_f():
178 """Test %hist -f with temporary filename.
179 """Test %hist -f with temporary filename.
179
180
180 In [9]: import tempfile
181 In [9]: import tempfile
181
182
182 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
183 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
183
184
184 In [11]: %hist -nl -f $tfile 3
185 In [11]: %hist -nl -f $tfile 3
185
186
186 In [13]: import os; os.unlink(tfile)
187 In [13]: import os; os.unlink(tfile)
187 """
188 """
188
189
189
190
190 @dec.skip_without('sqlite3')
191 @dec.skip_without('sqlite3')
191 def doctest_hist_r():
192 def doctest_hist_r():
192 """Test %hist -r
193 """Test %hist -r
193
194
194 XXX - This test is not recording the output correctly. For some reason, in
195 XXX - This test is not recording the output correctly. For some reason, in
195 testing mode the raw history isn't getting populated. No idea why.
196 testing mode the raw history isn't getting populated. No idea why.
196 Disabling the output checking for now, though at least we do run it.
197 Disabling the output checking for now, though at least we do run it.
197
198
198 In [1]: 'hist' in _ip.lsmagic()
199 In [1]: 'hist' in _ip.lsmagic()
199 Out[1]: True
200 Out[1]: True
200
201
201 In [2]: x=1
202 In [2]: x=1
202
203
203 In [3]: %hist -rl 2
204 In [3]: %hist -rl 2
204 x=1 # random
205 x=1 # random
205 %hist -r 2
206 %hist -r 2
206 """
207 """
207
208
208
209
209 @dec.skip_without('sqlite3')
210 @dec.skip_without('sqlite3')
210 def doctest_hist_op():
211 def doctest_hist_op():
211 """Test %hist -op
212 """Test %hist -op
212
213
213 In [1]: class b(float):
214 In [1]: class b(float):
214 ...: pass
215 ...: pass
215 ...:
216 ...:
216
217
217 In [2]: class s(object):
218 In [2]: class s(object):
218 ...: def __str__(self):
219 ...: def __str__(self):
219 ...: return 's'
220 ...: return 's'
220 ...:
221 ...:
221
222
222 In [3]:
223 In [3]:
223
224
224 In [4]: class r(b):
225 In [4]: class r(b):
225 ...: def __repr__(self):
226 ...: def __repr__(self):
226 ...: return 'r'
227 ...: return 'r'
227 ...:
228 ...:
228
229
229 In [5]: class sr(s,r): pass
230 In [5]: class sr(s,r): pass
230 ...:
231 ...:
231
232
232 In [6]:
233 In [6]:
233
234
234 In [7]: bb=b()
235 In [7]: bb=b()
235
236
236 In [8]: ss=s()
237 In [8]: ss=s()
237
238
238 In [9]: rr=r()
239 In [9]: rr=r()
239
240
240 In [10]: ssrr=sr()
241 In [10]: ssrr=sr()
241
242
242 In [11]: 4.5
243 In [11]: 4.5
243 Out[11]: 4.5
244 Out[11]: 4.5
244
245
245 In [12]: str(ss)
246 In [12]: str(ss)
246 Out[12]: 's'
247 Out[12]: 's'
247
248
248 In [13]:
249 In [13]:
249
250
250 In [14]: %hist -op
251 In [14]: %hist -op
251 >>> class b:
252 >>> class b:
252 ... pass
253 ... pass
253 ...
254 ...
254 >>> class s(b):
255 >>> class s(b):
255 ... def __str__(self):
256 ... def __str__(self):
256 ... return 's'
257 ... return 's'
257 ...
258 ...
258 >>>
259 >>>
259 >>> class r(b):
260 >>> class r(b):
260 ... def __repr__(self):
261 ... def __repr__(self):
261 ... return 'r'
262 ... return 'r'
262 ...
263 ...
263 >>> class sr(s,r): pass
264 >>> class sr(s,r): pass
264 >>>
265 >>>
265 >>> bb=b()
266 >>> bb=b()
266 >>> ss=s()
267 >>> ss=s()
267 >>> rr=r()
268 >>> rr=r()
268 >>> ssrr=sr()
269 >>> ssrr=sr()
269 >>> 4.5
270 >>> 4.5
270 4.5
271 4.5
271 >>> str(ss)
272 >>> str(ss)
272 's'
273 's'
273 >>>
274 >>>
274 """
275 """
275
276
276 def test_hist_pof():
277 def test_hist_pof():
277 ip = get_ipython()
278 ip = get_ipython()
278 ip.run_cell(u"1+2", store_history=True)
279 ip.run_cell(u"1+2", store_history=True)
279 #raise Exception(ip.history_manager.session_number)
280 #raise Exception(ip.history_manager.session_number)
280 #raise Exception(list(ip.history_manager._get_range_session()))
281 #raise Exception(list(ip.history_manager._get_range_session()))
281 with TemporaryDirectory() as td:
282 with TemporaryDirectory() as td:
282 tf = os.path.join(td, 'hist.py')
283 tf = os.path.join(td, 'hist.py')
283 ip.run_line_magic('history', '-pof %s' % tf)
284 ip.run_line_magic('history', '-pof %s' % tf)
284 assert os.path.isfile(tf)
285 assert os.path.isfile(tf)
285
286
286
287
287 @dec.skip_without('sqlite3')
288 @dec.skip_without('sqlite3')
288 def test_macro():
289 def test_macro():
289 ip = get_ipython()
290 ip = get_ipython()
290 ip.history_manager.reset() # Clear any existing history.
291 ip.history_manager.reset() # Clear any existing history.
291 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
292 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
292 for i, cmd in enumerate(cmds, start=1):
293 for i, cmd in enumerate(cmds, start=1):
293 ip.history_manager.store_inputs(i, cmd)
294 ip.history_manager.store_inputs(i, cmd)
294 ip.magic("macro test 1-3")
295 ip.magic("macro test 1-3")
295 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
296 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
296
297
297 # List macros
298 # List macros
298 nt.assert_in("test", ip.magic("macro"))
299 nt.assert_in("test", ip.magic("macro"))
299
300
300
301
301 @dec.skip_without('sqlite3')
302 @dec.skip_without('sqlite3')
302 def test_macro_run():
303 def test_macro_run():
303 """Test that we can run a multi-line macro successfully."""
304 """Test that we can run a multi-line macro successfully."""
304 ip = get_ipython()
305 ip = get_ipython()
305 ip.history_manager.reset()
306 ip.history_manager.reset()
306 cmds = ["a=10", "a+=1", "print(a)", "%macro test 2-3"]
307 cmds = ["a=10", "a+=1", "print(a)", "%macro test 2-3"]
307 for cmd in cmds:
308 for cmd in cmds:
308 ip.run_cell(cmd, store_history=True)
309 ip.run_cell(cmd, store_history=True)
309 nt.assert_equal(ip.user_ns["test"].value, "a+=1\nprint(a)\n")
310 nt.assert_equal(ip.user_ns["test"].value, "a+=1\nprint(a)\n")
310 with tt.AssertPrints("12"):
311 with tt.AssertPrints("12"):
311 ip.run_cell("test")
312 ip.run_cell("test")
312 with tt.AssertPrints("13"):
313 with tt.AssertPrints("13"):
313 ip.run_cell("test")
314 ip.run_cell("test")
314
315
315
316
316 def test_magic_magic():
317 def test_magic_magic():
317 """Test %magic"""
318 """Test %magic"""
318 ip = get_ipython()
319 ip = get_ipython()
319 with capture_output() as captured:
320 with capture_output() as captured:
320 ip.magic("magic")
321 ip.magic("magic")
321
322
322 stdout = captured.stdout
323 stdout = captured.stdout
323 nt.assert_in('%magic', stdout)
324 nt.assert_in('%magic', stdout)
324 nt.assert_in('IPython', stdout)
325 nt.assert_in('IPython', stdout)
325 nt.assert_in('Available', stdout)
326 nt.assert_in('Available', stdout)
326
327
327
328
328 @dec.skipif_not_numpy
329 @dec.skipif_not_numpy
329 def test_numpy_reset_array_undec():
330 def test_numpy_reset_array_undec():
330 "Test '%reset array' functionality"
331 "Test '%reset array' functionality"
331 _ip.ex('import numpy as np')
332 _ip.ex('import numpy as np')
332 _ip.ex('a = np.empty(2)')
333 _ip.ex('a = np.empty(2)')
333 nt.assert_in('a', _ip.user_ns)
334 nt.assert_in('a', _ip.user_ns)
334 _ip.magic('reset -f array')
335 _ip.magic('reset -f array')
335 nt.assert_not_in('a', _ip.user_ns)
336 nt.assert_not_in('a', _ip.user_ns)
336
337
337 def test_reset_out():
338 def test_reset_out():
338 "Test '%reset out' magic"
339 "Test '%reset out' magic"
339 _ip.run_cell("parrot = 'dead'", store_history=True)
340 _ip.run_cell("parrot = 'dead'", store_history=True)
340 # test '%reset -f out', make an Out prompt
341 # test '%reset -f out', make an Out prompt
341 _ip.run_cell("parrot", store_history=True)
342 _ip.run_cell("parrot", store_history=True)
342 nt.assert_true('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
343 nt.assert_true('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
343 _ip.magic('reset -f out')
344 _ip.magic('reset -f out')
344 nt.assert_false('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
345 nt.assert_false('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
345 nt.assert_equal(len(_ip.user_ns['Out']), 0)
346 nt.assert_equal(len(_ip.user_ns['Out']), 0)
346
347
347 def test_reset_in():
348 def test_reset_in():
348 "Test '%reset in' magic"
349 "Test '%reset in' magic"
349 # test '%reset -f in'
350 # test '%reset -f in'
350 _ip.run_cell("parrot", store_history=True)
351 _ip.run_cell("parrot", store_history=True)
351 nt.assert_true('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
352 nt.assert_true('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
352 _ip.magic('%reset -f in')
353 _ip.magic('%reset -f in')
353 nt.assert_false('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
354 nt.assert_false('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
354 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
355 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
355
356
356 def test_reset_dhist():
357 def test_reset_dhist():
357 "Test '%reset dhist' magic"
358 "Test '%reset dhist' magic"
358 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
359 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
359 _ip.magic('cd ' + os.path.dirname(nt.__file__))
360 _ip.magic('cd ' + os.path.dirname(nt.__file__))
360 _ip.magic('cd -')
361 _ip.magic('cd -')
361 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
362 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
362 _ip.magic('reset -f dhist')
363 _ip.magic('reset -f dhist')
363 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
364 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
364 _ip.run_cell("_dh = [d for d in tmp]") #restore
365 _ip.run_cell("_dh = [d for d in tmp]") #restore
365
366
366 def test_reset_in_length():
367 def test_reset_in_length():
367 "Test that '%reset in' preserves In[] length"
368 "Test that '%reset in' preserves In[] length"
368 _ip.run_cell("print 'foo'")
369 _ip.run_cell("print 'foo'")
369 _ip.run_cell("reset -f in")
370 _ip.run_cell("reset -f in")
370 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
371 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
371
372
372 def test_tb_syntaxerror():
373 def test_tb_syntaxerror():
373 """test %tb after a SyntaxError"""
374 """test %tb after a SyntaxError"""
374 ip = get_ipython()
375 ip = get_ipython()
375 ip.run_cell("for")
376 ip.run_cell("for")
376
377
377 # trap and validate stdout
378 # trap and validate stdout
378 save_stdout = sys.stdout
379 save_stdout = sys.stdout
379 try:
380 try:
380 sys.stdout = StringIO()
381 sys.stdout = StringIO()
381 ip.run_cell("%tb")
382 ip.run_cell("%tb")
382 out = sys.stdout.getvalue()
383 out = sys.stdout.getvalue()
383 finally:
384 finally:
384 sys.stdout = save_stdout
385 sys.stdout = save_stdout
385 # trim output, and only check the last line
386 # trim output, and only check the last line
386 last_line = out.rstrip().splitlines()[-1].strip()
387 last_line = out.rstrip().splitlines()[-1].strip()
387 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
388 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
388
389
389
390
390 def test_time():
391 def test_time():
391 ip = get_ipython()
392 ip = get_ipython()
392
393
393 with tt.AssertPrints("Wall time: "):
394 with tt.AssertPrints("Wall time: "):
394 ip.run_cell("%time None")
395 ip.run_cell("%time None")
395
396
396 ip.run_cell("def f(kmjy):\n"
397 ip.run_cell("def f(kmjy):\n"
397 " %time print (2*kmjy)")
398 " %time print (2*kmjy)")
398
399
399 with tt.AssertPrints("Wall time: "):
400 with tt.AssertPrints("Wall time: "):
400 with tt.AssertPrints("hihi", suppress=False):
401 with tt.AssertPrints("hihi", suppress=False):
401 ip.run_cell("f('hi')")
402 ip.run_cell("f('hi')")
402
403
403
404
404 @dec.skip_win32
405 @dec.skip_win32
405 def test_time2():
406 def test_time2():
406 ip = get_ipython()
407 ip = get_ipython()
407
408
408 with tt.AssertPrints("CPU times: user "):
409 with tt.AssertPrints("CPU times: user "):
409 ip.run_cell("%time None")
410 ip.run_cell("%time None")
410
411
411 def test_time3():
412 def test_time3():
412 """Erroneous magic function calls, issue gh-3334"""
413 """Erroneous magic function calls, issue gh-3334"""
413 ip = get_ipython()
414 ip = get_ipython()
414 ip.user_ns.pop('run', None)
415 ip.user_ns.pop('run', None)
415
416
416 with tt.AssertNotPrints("not found", channel='stderr'):
417 with tt.AssertNotPrints("not found", channel='stderr'):
417 ip.run_cell("%%time\n"
418 ip.run_cell("%%time\n"
418 "run = 0\n"
419 "run = 0\n"
419 "run += 1")
420 "run += 1")
420
421
421 def test_doctest_mode():
422 def test_doctest_mode():
422 "Toggle doctest_mode twice, it should be a no-op and run without error"
423 "Toggle doctest_mode twice, it should be a no-op and run without error"
423 _ip.magic('doctest_mode')
424 _ip.magic('doctest_mode')
424 _ip.magic('doctest_mode')
425 _ip.magic('doctest_mode')
425
426
426
427
427 def test_parse_options():
428 def test_parse_options():
428 """Tests for basic options parsing in magics."""
429 """Tests for basic options parsing in magics."""
429 # These are only the most minimal of tests, more should be added later. At
430 # These are only the most minimal of tests, more should be added later. At
430 # the very least we check that basic text/unicode calls work OK.
431 # the very least we check that basic text/unicode calls work OK.
431 m = DummyMagics(_ip)
432 m = DummyMagics(_ip)
432 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
433 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
433 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
434 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
434
435
435
436
436 def test_dirops():
437 def test_dirops():
437 """Test various directory handling operations."""
438 """Test various directory handling operations."""
438 # curpath = lambda :os.path.splitdrive(os.getcwd())[1].replace('\\','/')
439 # curpath = lambda :os.path.splitdrive(os.getcwd())[1].replace('\\','/')
439 curpath = os.getcwd
440 curpath = os.getcwd
440 startdir = os.getcwd()
441 startdir = os.getcwd()
441 ipdir = os.path.realpath(_ip.ipython_dir)
442 ipdir = os.path.realpath(_ip.ipython_dir)
442 try:
443 try:
443 _ip.magic('cd "%s"' % ipdir)
444 _ip.magic('cd "%s"' % ipdir)
444 nt.assert_equal(curpath(), ipdir)
445 nt.assert_equal(curpath(), ipdir)
445 _ip.magic('cd -')
446 _ip.magic('cd -')
446 nt.assert_equal(curpath(), startdir)
447 nt.assert_equal(curpath(), startdir)
447 _ip.magic('pushd "%s"' % ipdir)
448 _ip.magic('pushd "%s"' % ipdir)
448 nt.assert_equal(curpath(), ipdir)
449 nt.assert_equal(curpath(), ipdir)
449 _ip.magic('popd')
450 _ip.magic('popd')
450 nt.assert_equal(curpath(), startdir)
451 nt.assert_equal(curpath(), startdir)
451 finally:
452 finally:
452 os.chdir(startdir)
453 os.chdir(startdir)
453
454
454
455
455 def test_xmode():
456 def test_xmode():
456 # Calling xmode three times should be a no-op
457 # Calling xmode three times should be a no-op
457 xmode = _ip.InteractiveTB.mode
458 xmode = _ip.InteractiveTB.mode
458 for i in range(3):
459 for i in range(3):
459 _ip.magic("xmode")
460 _ip.magic("xmode")
460 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
461 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
461
462
462 def test_reset_hard():
463 def test_reset_hard():
463 monitor = []
464 monitor = []
464 class A(object):
465 class A(object):
465 def __del__(self):
466 def __del__(self):
466 monitor.append(1)
467 monitor.append(1)
467 def __repr__(self):
468 def __repr__(self):
468 return "<A instance>"
469 return "<A instance>"
469
470
470 _ip.user_ns["a"] = A()
471 _ip.user_ns["a"] = A()
471 _ip.run_cell("a")
472 _ip.run_cell("a")
472
473
473 nt.assert_equal(monitor, [])
474 nt.assert_equal(monitor, [])
474 _ip.magic("reset -f")
475 _ip.magic("reset -f")
475 nt.assert_equal(monitor, [1])
476 nt.assert_equal(monitor, [1])
476
477
477 class TestXdel(tt.TempFileMixin):
478 class TestXdel(tt.TempFileMixin):
478 def test_xdel(self):
479 def test_xdel(self):
479 """Test that references from %run are cleared by xdel."""
480 """Test that references from %run are cleared by xdel."""
480 src = ("class A(object):\n"
481 src = ("class A(object):\n"
481 " monitor = []\n"
482 " monitor = []\n"
482 " def __del__(self):\n"
483 " def __del__(self):\n"
483 " self.monitor.append(1)\n"
484 " self.monitor.append(1)\n"
484 "a = A()\n")
485 "a = A()\n")
485 self.mktmp(src)
486 self.mktmp(src)
486 # %run creates some hidden references...
487 # %run creates some hidden references...
487 _ip.magic("run %s" % self.fname)
488 _ip.magic("run %s" % self.fname)
488 # ... as does the displayhook.
489 # ... as does the displayhook.
489 _ip.run_cell("a")
490 _ip.run_cell("a")
490
491
491 monitor = _ip.user_ns["A"].monitor
492 monitor = _ip.user_ns["A"].monitor
492 nt.assert_equal(monitor, [])
493 nt.assert_equal(monitor, [])
493
494
494 _ip.magic("xdel a")
495 _ip.magic("xdel a")
495
496
496 # Check that a's __del__ method has been called.
497 # Check that a's __del__ method has been called.
497 nt.assert_equal(monitor, [1])
498 nt.assert_equal(monitor, [1])
498
499
499 def doctest_who():
500 def doctest_who():
500 """doctest for %who
501 """doctest for %who
501
502
502 In [1]: %reset -f
503 In [1]: %reset -f
503
504
504 In [2]: alpha = 123
505 In [2]: alpha = 123
505
506
506 In [3]: beta = 'beta'
507 In [3]: beta = 'beta'
507
508
508 In [4]: %who int
509 In [4]: %who int
509 alpha
510 alpha
510
511
511 In [5]: %who str
512 In [5]: %who str
512 beta
513 beta
513
514
514 In [6]: %whos
515 In [6]: %whos
515 Variable Type Data/Info
516 Variable Type Data/Info
516 ----------------------------
517 ----------------------------
517 alpha int 123
518 alpha int 123
518 beta str beta
519 beta str beta
519
520
520 In [7]: %who_ls
521 In [7]: %who_ls
521 Out[7]: ['alpha', 'beta']
522 Out[7]: ['alpha', 'beta']
522 """
523 """
523
524
524 def test_whos():
525 def test_whos():
525 """Check that whos is protected against objects where repr() fails."""
526 """Check that whos is protected against objects where repr() fails."""
526 class A(object):
527 class A(object):
527 def __repr__(self):
528 def __repr__(self):
528 raise Exception()
529 raise Exception()
529 _ip.user_ns['a'] = A()
530 _ip.user_ns['a'] = A()
530 _ip.magic("whos")
531 _ip.magic("whos")
531
532
532 def doctest_precision():
533 def doctest_precision():
533 """doctest for %precision
534 """doctest for %precision
534
535
535 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
536 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
536
537
537 In [2]: %precision 5
538 In [2]: %precision 5
538 Out[2]: '%.5f'
539 Out[2]: '%.5f'
539
540
540 In [3]: f.float_format
541 In [3]: f.float_format
541 Out[3]: '%.5f'
542 Out[3]: '%.5f'
542
543
543 In [4]: %precision %e
544 In [4]: %precision %e
544 Out[4]: '%e'
545 Out[4]: '%e'
545
546
546 In [5]: f(3.1415927)
547 In [5]: f(3.1415927)
547 Out[5]: '3.141593e+00'
548 Out[5]: '3.141593e+00'
548 """
549 """
549
550
550 def test_psearch():
551 def test_psearch():
551 with tt.AssertPrints("dict.fromkeys"):
552 with tt.AssertPrints("dict.fromkeys"):
552 _ip.run_cell("dict.fr*?")
553 _ip.run_cell("dict.fr*?")
553
554
554 def test_timeit_shlex():
555 def test_timeit_shlex():
555 """test shlex issues with timeit (#1109)"""
556 """test shlex issues with timeit (#1109)"""
556 _ip.ex("def f(*a,**kw): pass")
557 _ip.ex("def f(*a,**kw): pass")
557 _ip.magic('timeit -n1 "this is a bug".count(" ")')
558 _ip.magic('timeit -n1 "this is a bug".count(" ")')
558 _ip.magic('timeit -r1 -n1 f(" ", 1)')
559 _ip.magic('timeit -r1 -n1 f(" ", 1)')
559 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
560 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
560 _ip.magic('timeit -r1 -n1 ("a " + "b")')
561 _ip.magic('timeit -r1 -n1 ("a " + "b")')
561 _ip.magic('timeit -r1 -n1 f("a " + "b")')
562 _ip.magic('timeit -r1 -n1 f("a " + "b")')
562 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
563 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
563
564
564
565
565 def test_timeit_special_syntax():
566 def test_timeit_special_syntax():
566 "Test %%timeit with IPython special syntax"
567 "Test %%timeit with IPython special syntax"
567 @register_line_magic
568 @register_line_magic
568 def lmagic(line):
569 def lmagic(line):
569 ip = get_ipython()
570 ip = get_ipython()
570 ip.user_ns['lmagic_out'] = line
571 ip.user_ns['lmagic_out'] = line
571
572
572 # line mode test
573 # line mode test
573 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
574 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
574 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
575 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
575 # cell mode test
576 # cell mode test
576 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
577 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
577 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
578 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
578
579
579 def test_timeit_return():
580 def test_timeit_return():
580 """
581 """
581 test whether timeit -o return object
582 test whether timeit -o return object
582 """
583 """
583
584
584 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
585 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
585 assert(res is not None)
586 assert(res is not None)
586
587
587 def test_timeit_quiet():
588 def test_timeit_quiet():
588 """
589 """
589 test quiet option of timeit magic
590 test quiet option of timeit magic
590 """
591 """
591 with tt.AssertNotPrints("loops"):
592 with tt.AssertNotPrints("loops"):
592 _ip.run_cell("%timeit -n1 -r1 -q 1")
593 _ip.run_cell("%timeit -n1 -r1 -q 1")
593
594
594 def test_timeit_return_quiet():
595 def test_timeit_return_quiet():
595 with tt.AssertNotPrints("loops"):
596 with tt.AssertNotPrints("loops"):
596 res = _ip.run_line_magic('timeit', '-n1 -r1 -q -o 1')
597 res = _ip.run_line_magic('timeit', '-n1 -r1 -q -o 1')
597 assert (res is not None)
598 assert (res is not None)
598
599
599 def test_timeit_invalid_return():
600 def test_timeit_invalid_return():
600 with nt.assert_raises_regex(SyntaxError, "outside function"):
601 with nt.assert_raises_regex(SyntaxError, "outside function"):
601 _ip.run_line_magic('timeit', 'return')
602 _ip.run_line_magic('timeit', 'return')
602
603
603 @dec.skipif(execution.profile is None)
604 @dec.skipif(execution.profile is None)
604 def test_prun_special_syntax():
605 def test_prun_special_syntax():
605 "Test %%prun with IPython special syntax"
606 "Test %%prun with IPython special syntax"
606 @register_line_magic
607 @register_line_magic
607 def lmagic(line):
608 def lmagic(line):
608 ip = get_ipython()
609 ip = get_ipython()
609 ip.user_ns['lmagic_out'] = line
610 ip.user_ns['lmagic_out'] = line
610
611
611 # line mode test
612 # line mode test
612 _ip.run_line_magic('prun', '-q %lmagic my line')
613 _ip.run_line_magic('prun', '-q %lmagic my line')
613 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
614 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
614 # cell mode test
615 # cell mode test
615 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
616 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
616 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
617 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
617
618
618 @dec.skipif(execution.profile is None)
619 @dec.skipif(execution.profile is None)
619 def test_prun_quotes():
620 def test_prun_quotes():
620 "Test that prun does not clobber string escapes (GH #1302)"
621 "Test that prun does not clobber string escapes (GH #1302)"
621 _ip.magic(r"prun -q x = '\t'")
622 _ip.magic(r"prun -q x = '\t'")
622 nt.assert_equal(_ip.user_ns['x'], '\t')
623 nt.assert_equal(_ip.user_ns['x'], '\t')
623
624
624 def test_extension():
625 def test_extension():
625 # Debugging information for failures of this test
626 # Debugging information for failures of this test
626 print('sys.path:')
627 print('sys.path:')
627 for p in sys.path:
628 for p in sys.path:
628 print(' ', p)
629 print(' ', p)
629 print('CWD', os.getcwd())
630 print('CWD', os.getcwd())
630
631
631 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
632 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
632 daft_path = os.path.join(os.path.dirname(__file__), "daft_extension")
633 daft_path = os.path.join(os.path.dirname(__file__), "daft_extension")
633 sys.path.insert(0, daft_path)
634 sys.path.insert(0, daft_path)
634 try:
635 try:
635 _ip.user_ns.pop('arq', None)
636 _ip.user_ns.pop('arq', None)
636 invalidate_caches() # Clear import caches
637 invalidate_caches() # Clear import caches
637 _ip.magic("load_ext daft_extension")
638 _ip.magic("load_ext daft_extension")
638 nt.assert_equal(_ip.user_ns['arq'], 185)
639 nt.assert_equal(_ip.user_ns['arq'], 185)
639 _ip.magic("unload_ext daft_extension")
640 _ip.magic("unload_ext daft_extension")
640 assert 'arq' not in _ip.user_ns
641 assert 'arq' not in _ip.user_ns
641 finally:
642 finally:
642 sys.path.remove(daft_path)
643 sys.path.remove(daft_path)
643
644
644
645
645 def test_notebook_export_json():
646 def test_notebook_export_json():
646 _ip = get_ipython()
647 _ip = get_ipython()
647 _ip.history_manager.reset() # Clear any existing history.
648 _ip.history_manager.reset() # Clear any existing history.
648 cmds = [u"a=1", u"def b():\n return a**2", u"print('noΓ«l, Γ©tΓ©', b())"]
649 cmds = [u"a=1", u"def b():\n return a**2", u"print('noΓ«l, Γ©tΓ©', b())"]
649 for i, cmd in enumerate(cmds, start=1):
650 for i, cmd in enumerate(cmds, start=1):
650 _ip.history_manager.store_inputs(i, cmd)
651 _ip.history_manager.store_inputs(i, cmd)
651 with TemporaryDirectory() as td:
652 with TemporaryDirectory() as td:
652 outfile = os.path.join(td, "nb.ipynb")
653 outfile = os.path.join(td, "nb.ipynb")
653 _ip.magic("notebook -e %s" % outfile)
654 _ip.magic("notebook -e %s" % outfile)
654
655
655
656
656 class TestEnv(TestCase):
657 class TestEnv(TestCase):
657
658
658 def test_env(self):
659 def test_env(self):
659 env = _ip.magic("env")
660 env = _ip.magic("env")
660 self.assertTrue(isinstance(env, dict))
661 self.assertTrue(isinstance(env, dict))
661
662
662 def test_env_get_set_simple(self):
663 def test_env_get_set_simple(self):
663 env = _ip.magic("env var val1")
664 env = _ip.magic("env var val1")
664 self.assertEqual(env, None)
665 self.assertEqual(env, None)
665 self.assertEqual(os.environ['var'], 'val1')
666 self.assertEqual(os.environ['var'], 'val1')
666 self.assertEqual(_ip.magic("env var"), 'val1')
667 self.assertEqual(_ip.magic("env var"), 'val1')
667 env = _ip.magic("env var=val2")
668 env = _ip.magic("env var=val2")
668 self.assertEqual(env, None)
669 self.assertEqual(env, None)
669 self.assertEqual(os.environ['var'], 'val2')
670 self.assertEqual(os.environ['var'], 'val2')
670
671
671 def test_env_get_set_complex(self):
672 def test_env_get_set_complex(self):
672 env = _ip.magic("env var 'val1 '' 'val2")
673 env = _ip.magic("env var 'val1 '' 'val2")
673 self.assertEqual(env, None)
674 self.assertEqual(env, None)
674 self.assertEqual(os.environ['var'], "'val1 '' 'val2")
675 self.assertEqual(os.environ['var'], "'val1 '' 'val2")
675 self.assertEqual(_ip.magic("env var"), "'val1 '' 'val2")
676 self.assertEqual(_ip.magic("env var"), "'val1 '' 'val2")
676 env = _ip.magic('env var=val2 val3="val4')
677 env = _ip.magic('env var=val2 val3="val4')
677 self.assertEqual(env, None)
678 self.assertEqual(env, None)
678 self.assertEqual(os.environ['var'], 'val2 val3="val4')
679 self.assertEqual(os.environ['var'], 'val2 val3="val4')
679
680
680 def test_env_set_bad_input(self):
681 def test_env_set_bad_input(self):
681 self.assertRaises(UsageError, lambda: _ip.magic("set_env var"))
682 self.assertRaises(UsageError, lambda: _ip.magic("set_env var"))
682
683
683 def test_env_set_whitespace(self):
684 def test_env_set_whitespace(self):
684 self.assertRaises(UsageError, lambda: _ip.magic("env var A=B"))
685 self.assertRaises(UsageError, lambda: _ip.magic("env var A=B"))
685
686
686
687
687 class CellMagicTestCase(TestCase):
688 class CellMagicTestCase(TestCase):
688
689
689 def check_ident(self, magic):
690 def check_ident(self, magic):
690 # Manually called, we get the result
691 # Manually called, we get the result
691 out = _ip.run_cell_magic(magic, 'a', 'b')
692 out = _ip.run_cell_magic(magic, 'a', 'b')
692 nt.assert_equal(out, ('a','b'))
693 nt.assert_equal(out, ('a','b'))
693 # Via run_cell, it goes into the user's namespace via displayhook
694 # Via run_cell, it goes into the user's namespace via displayhook
694 _ip.run_cell('%%' + magic +' c\nd\n')
695 _ip.run_cell('%%' + magic +' c\nd\n')
695 nt.assert_equal(_ip.user_ns['_'], ('c','d\n'))
696 nt.assert_equal(_ip.user_ns['_'], ('c','d\n'))
696
697
697 def test_cell_magic_func_deco(self):
698 def test_cell_magic_func_deco(self):
698 "Cell magic using simple decorator"
699 "Cell magic using simple decorator"
699 @register_cell_magic
700 @register_cell_magic
700 def cellm(line, cell):
701 def cellm(line, cell):
701 return line, cell
702 return line, cell
702
703
703 self.check_ident('cellm')
704 self.check_ident('cellm')
704
705
705 def test_cell_magic_reg(self):
706 def test_cell_magic_reg(self):
706 "Cell magic manually registered"
707 "Cell magic manually registered"
707 def cellm(line, cell):
708 def cellm(line, cell):
708 return line, cell
709 return line, cell
709
710
710 _ip.register_magic_function(cellm, 'cell', 'cellm2')
711 _ip.register_magic_function(cellm, 'cell', 'cellm2')
711 self.check_ident('cellm2')
712 self.check_ident('cellm2')
712
713
713 def test_cell_magic_class(self):
714 def test_cell_magic_class(self):
714 "Cell magics declared via a class"
715 "Cell magics declared via a class"
715 @magics_class
716 @magics_class
716 class MyMagics(Magics):
717 class MyMagics(Magics):
717
718
718 @cell_magic
719 @cell_magic
719 def cellm3(self, line, cell):
720 def cellm3(self, line, cell):
720 return line, cell
721 return line, cell
721
722
722 _ip.register_magics(MyMagics)
723 _ip.register_magics(MyMagics)
723 self.check_ident('cellm3')
724 self.check_ident('cellm3')
724
725
725 def test_cell_magic_class2(self):
726 def test_cell_magic_class2(self):
726 "Cell magics declared via a class, #2"
727 "Cell magics declared via a class, #2"
727 @magics_class
728 @magics_class
728 class MyMagics2(Magics):
729 class MyMagics2(Magics):
729
730
730 @cell_magic('cellm4')
731 @cell_magic('cellm4')
731 def cellm33(self, line, cell):
732 def cellm33(self, line, cell):
732 return line, cell
733 return line, cell
733
734
734 _ip.register_magics(MyMagics2)
735 _ip.register_magics(MyMagics2)
735 self.check_ident('cellm4')
736 self.check_ident('cellm4')
736 # Check that nothing is registered as 'cellm33'
737 # Check that nothing is registered as 'cellm33'
737 c33 = _ip.find_cell_magic('cellm33')
738 c33 = _ip.find_cell_magic('cellm33')
738 nt.assert_equal(c33, None)
739 nt.assert_equal(c33, None)
739
740
740 def test_file():
741 def test_file():
741 """Basic %%writefile"""
742 """Basic %%writefile"""
742 ip = get_ipython()
743 ip = get_ipython()
743 with TemporaryDirectory() as td:
744 with TemporaryDirectory() as td:
744 fname = os.path.join(td, 'file1')
745 fname = os.path.join(td, 'file1')
745 ip.run_cell_magic("writefile", fname, u'\n'.join([
746 ip.run_cell_magic("writefile", fname, u'\n'.join([
746 'line1',
747 'line1',
747 'line2',
748 'line2',
748 ]))
749 ]))
749 with open(fname) as f:
750 with open(fname) as f:
750 s = f.read()
751 s = f.read()
751 nt.assert_in('line1\n', s)
752 nt.assert_in('line1\n', s)
752 nt.assert_in('line2', s)
753 nt.assert_in('line2', s)
753
754
754 def test_file_var_expand():
755 def test_file_var_expand():
755 """%%writefile $filename"""
756 """%%writefile $filename"""
756 ip = get_ipython()
757 ip = get_ipython()
757 with TemporaryDirectory() as td:
758 with TemporaryDirectory() as td:
758 fname = os.path.join(td, 'file1')
759 fname = os.path.join(td, 'file1')
759 ip.user_ns['filename'] = fname
760 ip.user_ns['filename'] = fname
760 ip.run_cell_magic("writefile", '$filename', u'\n'.join([
761 ip.run_cell_magic("writefile", '$filename', u'\n'.join([
761 'line1',
762 'line1',
762 'line2',
763 'line2',
763 ]))
764 ]))
764 with open(fname) as f:
765 with open(fname) as f:
765 s = f.read()
766 s = f.read()
766 nt.assert_in('line1\n', s)
767 nt.assert_in('line1\n', s)
767 nt.assert_in('line2', s)
768 nt.assert_in('line2', s)
768
769
769 def test_file_unicode():
770 def test_file_unicode():
770 """%%writefile with unicode cell"""
771 """%%writefile with unicode cell"""
771 ip = get_ipython()
772 ip = get_ipython()
772 with TemporaryDirectory() as td:
773 with TemporaryDirectory() as td:
773 fname = os.path.join(td, 'file1')
774 fname = os.path.join(td, 'file1')
774 ip.run_cell_magic("writefile", fname, u'\n'.join([
775 ip.run_cell_magic("writefile", fname, u'\n'.join([
775 u'linΓ©1',
776 u'linΓ©1',
776 u'linΓ©2',
777 u'linΓ©2',
777 ]))
778 ]))
778 with io.open(fname, encoding='utf-8') as f:
779 with io.open(fname, encoding='utf-8') as f:
779 s = f.read()
780 s = f.read()
780 nt.assert_in(u'linΓ©1\n', s)
781 nt.assert_in(u'linΓ©1\n', s)
781 nt.assert_in(u'linΓ©2', s)
782 nt.assert_in(u'linΓ©2', s)
782
783
783 def test_file_amend():
784 def test_file_amend():
784 """%%writefile -a amends files"""
785 """%%writefile -a amends files"""
785 ip = get_ipython()
786 ip = get_ipython()
786 with TemporaryDirectory() as td:
787 with TemporaryDirectory() as td:
787 fname = os.path.join(td, 'file2')
788 fname = os.path.join(td, 'file2')
788 ip.run_cell_magic("writefile", fname, u'\n'.join([
789 ip.run_cell_magic("writefile", fname, u'\n'.join([
789 'line1',
790 'line1',
790 'line2',
791 'line2',
791 ]))
792 ]))
792 ip.run_cell_magic("writefile", "-a %s" % fname, u'\n'.join([
793 ip.run_cell_magic("writefile", "-a %s" % fname, u'\n'.join([
793 'line3',
794 'line3',
794 'line4',
795 'line4',
795 ]))
796 ]))
796 with open(fname) as f:
797 with open(fname) as f:
797 s = f.read()
798 s = f.read()
798 nt.assert_in('line1\n', s)
799 nt.assert_in('line1\n', s)
799 nt.assert_in('line3\n', s)
800 nt.assert_in('line3\n', s)
800
801
802 def test_file_spaces():
803 """%%file with spaces in filename"""
804 ip = get_ipython()
805 with TemporaryWorkingDirectory() as td:
806 fname = "file name"
807 ip.run_cell_magic("file", '"%s"'%fname, u'\n'.join([
808 'line1',
809 'line2',
810 ]))
811 with open(fname) as f:
812 s = f.read()
813 nt.assert_in('line1\n', s)
814 nt.assert_in('line2', s)
801
815
802 def test_script_config():
816 def test_script_config():
803 ip = get_ipython()
817 ip = get_ipython()
804 ip.config.ScriptMagics.script_magics = ['whoda']
818 ip.config.ScriptMagics.script_magics = ['whoda']
805 sm = script.ScriptMagics(shell=ip)
819 sm = script.ScriptMagics(shell=ip)
806 nt.assert_in('whoda', sm.magics['cell'])
820 nt.assert_in('whoda', sm.magics['cell'])
807
821
808 @dec.skip_win32
822 @dec.skip_win32
809 def test_script_out():
823 def test_script_out():
810 ip = get_ipython()
824 ip = get_ipython()
811 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
825 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
812 nt.assert_equal(ip.user_ns['output'], 'hi\n')
826 nt.assert_equal(ip.user_ns['output'], 'hi\n')
813
827
814 @dec.skip_win32
828 @dec.skip_win32
815 def test_script_err():
829 def test_script_err():
816 ip = get_ipython()
830 ip = get_ipython()
817 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
831 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
818 nt.assert_equal(ip.user_ns['error'], 'hello\n')
832 nt.assert_equal(ip.user_ns['error'], 'hello\n')
819
833
820 @dec.skip_win32
834 @dec.skip_win32
821 def test_script_out_err():
835 def test_script_out_err():
822 ip = get_ipython()
836 ip = get_ipython()
823 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
837 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
824 nt.assert_equal(ip.user_ns['output'], 'hi\n')
838 nt.assert_equal(ip.user_ns['output'], 'hi\n')
825 nt.assert_equal(ip.user_ns['error'], 'hello\n')
839 nt.assert_equal(ip.user_ns['error'], 'hello\n')
826
840
827 @dec.skip_win32
841 @dec.skip_win32
828 def test_script_bg_out():
842 def test_script_bg_out():
829 ip = get_ipython()
843 ip = get_ipython()
830 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
844 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
831
845
832 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
846 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
833 ip.user_ns['output'].close()
847 ip.user_ns['output'].close()
834
848
835 @dec.skip_win32
849 @dec.skip_win32
836 def test_script_bg_err():
850 def test_script_bg_err():
837 ip = get_ipython()
851 ip = get_ipython()
838 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
852 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
839 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
853 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
840 ip.user_ns['error'].close()
854 ip.user_ns['error'].close()
841
855
842 @dec.skip_win32
856 @dec.skip_win32
843 def test_script_bg_out_err():
857 def test_script_bg_out_err():
844 ip = get_ipython()
858 ip = get_ipython()
845 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
859 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
846 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
860 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
847 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
861 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
848 ip.user_ns['output'].close()
862 ip.user_ns['output'].close()
849 ip.user_ns['error'].close()
863 ip.user_ns['error'].close()
850
864
851 def test_script_defaults():
865 def test_script_defaults():
852 ip = get_ipython()
866 ip = get_ipython()
853 for cmd in ['sh', 'bash', 'perl', 'ruby']:
867 for cmd in ['sh', 'bash', 'perl', 'ruby']:
854 try:
868 try:
855 find_cmd(cmd)
869 find_cmd(cmd)
856 except Exception:
870 except Exception:
857 pass
871 pass
858 else:
872 else:
859 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
873 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
860
874
861
875
862 @magics_class
876 @magics_class
863 class FooFoo(Magics):
877 class FooFoo(Magics):
864 """class with both %foo and %%foo magics"""
878 """class with both %foo and %%foo magics"""
865 @line_magic('foo')
879 @line_magic('foo')
866 def line_foo(self, line):
880 def line_foo(self, line):
867 "I am line foo"
881 "I am line foo"
868 pass
882 pass
869
883
870 @cell_magic("foo")
884 @cell_magic("foo")
871 def cell_foo(self, line, cell):
885 def cell_foo(self, line, cell):
872 "I am cell foo, not line foo"
886 "I am cell foo, not line foo"
873 pass
887 pass
874
888
875 def test_line_cell_info():
889 def test_line_cell_info():
876 """%%foo and %foo magics are distinguishable to inspect"""
890 """%%foo and %foo magics are distinguishable to inspect"""
877 ip = get_ipython()
891 ip = get_ipython()
878 ip.magics_manager.register(FooFoo)
892 ip.magics_manager.register(FooFoo)
879 oinfo = ip.object_inspect('foo')
893 oinfo = ip.object_inspect('foo')
880 nt.assert_true(oinfo['found'])
894 nt.assert_true(oinfo['found'])
881 nt.assert_true(oinfo['ismagic'])
895 nt.assert_true(oinfo['ismagic'])
882
896
883 oinfo = ip.object_inspect('%%foo')
897 oinfo = ip.object_inspect('%%foo')
884 nt.assert_true(oinfo['found'])
898 nt.assert_true(oinfo['found'])
885 nt.assert_true(oinfo['ismagic'])
899 nt.assert_true(oinfo['ismagic'])
886 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
900 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
887
901
888 oinfo = ip.object_inspect('%foo')
902 oinfo = ip.object_inspect('%foo')
889 nt.assert_true(oinfo['found'])
903 nt.assert_true(oinfo['found'])
890 nt.assert_true(oinfo['ismagic'])
904 nt.assert_true(oinfo['ismagic'])
891 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
905 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
892
906
893 def test_multiple_magics():
907 def test_multiple_magics():
894 ip = get_ipython()
908 ip = get_ipython()
895 foo1 = FooFoo(ip)
909 foo1 = FooFoo(ip)
896 foo2 = FooFoo(ip)
910 foo2 = FooFoo(ip)
897 mm = ip.magics_manager
911 mm = ip.magics_manager
898 mm.register(foo1)
912 mm.register(foo1)
899 nt.assert_true(mm.magics['line']['foo'].__self__ is foo1)
913 nt.assert_true(mm.magics['line']['foo'].__self__ is foo1)
900 mm.register(foo2)
914 mm.register(foo2)
901 nt.assert_true(mm.magics['line']['foo'].__self__ is foo2)
915 nt.assert_true(mm.magics['line']['foo'].__self__ is foo2)
902
916
903 def test_alias_magic():
917 def test_alias_magic():
904 """Test %alias_magic."""
918 """Test %alias_magic."""
905 ip = get_ipython()
919 ip = get_ipython()
906 mm = ip.magics_manager
920 mm = ip.magics_manager
907
921
908 # Basic operation: both cell and line magics are created, if possible.
922 # Basic operation: both cell and line magics are created, if possible.
909 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
923 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
910 nt.assert_in('timeit_alias', mm.magics['line'])
924 nt.assert_in('timeit_alias', mm.magics['line'])
911 nt.assert_in('timeit_alias', mm.magics['cell'])
925 nt.assert_in('timeit_alias', mm.magics['cell'])
912
926
913 # --cell is specified, line magic not created.
927 # --cell is specified, line magic not created.
914 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
928 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
915 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
929 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
916 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
930 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
917
931
918 # Test that line alias is created successfully.
932 # Test that line alias is created successfully.
919 ip.run_line_magic('alias_magic', '--line env_alias env')
933 ip.run_line_magic('alias_magic', '--line env_alias env')
920 nt.assert_equal(ip.run_line_magic('env', ''),
934 nt.assert_equal(ip.run_line_magic('env', ''),
921 ip.run_line_magic('env_alias', ''))
935 ip.run_line_magic('env_alias', ''))
922
936
923 # Test that line alias with parameters passed in is created successfully.
937 # Test that line alias with parameters passed in is created successfully.
924 ip.run_line_magic('alias_magic', '--line history_alias history --params ' + shlex.quote('3'))
938 ip.run_line_magic('alias_magic', '--line history_alias history --params ' + shlex.quote('3'))
925 nt.assert_in('history_alias', mm.magics['line'])
939 nt.assert_in('history_alias', mm.magics['line'])
926
940
927
941
928 def test_save():
942 def test_save():
929 """Test %save."""
943 """Test %save."""
930 ip = get_ipython()
944 ip = get_ipython()
931 ip.history_manager.reset() # Clear any existing history.
945 ip.history_manager.reset() # Clear any existing history.
932 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
946 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
933 for i, cmd in enumerate(cmds, start=1):
947 for i, cmd in enumerate(cmds, start=1):
934 ip.history_manager.store_inputs(i, cmd)
948 ip.history_manager.store_inputs(i, cmd)
935 with TemporaryDirectory() as tmpdir:
949 with TemporaryDirectory() as tmpdir:
936 file = os.path.join(tmpdir, "testsave.py")
950 file = os.path.join(tmpdir, "testsave.py")
937 ip.run_line_magic("save", "%s 1-10" % file)
951 ip.run_line_magic("save", "%s 1-10" % file)
938 with open(file) as f:
952 with open(file) as f:
939 content = f.read()
953 content = f.read()
940 nt.assert_equal(content.count(cmds[0]), 1)
954 nt.assert_equal(content.count(cmds[0]), 1)
941 nt.assert_in('coding: utf-8', content)
955 nt.assert_in('coding: utf-8', content)
942 ip.run_line_magic("save", "-a %s 1-10" % file)
956 ip.run_line_magic("save", "-a %s 1-10" % file)
943 with open(file) as f:
957 with open(file) as f:
944 content = f.read()
958 content = f.read()
945 nt.assert_equal(content.count(cmds[0]), 2)
959 nt.assert_equal(content.count(cmds[0]), 2)
946 nt.assert_in('coding: utf-8', content)
960 nt.assert_in('coding: utf-8', content)
947
961
948
962
949 def test_store():
963 def test_store():
950 """Test %store."""
964 """Test %store."""
951 ip = get_ipython()
965 ip = get_ipython()
952 ip.run_line_magic('load_ext', 'storemagic')
966 ip.run_line_magic('load_ext', 'storemagic')
953
967
954 # make sure the storage is empty
968 # make sure the storage is empty
955 ip.run_line_magic('store', '-z')
969 ip.run_line_magic('store', '-z')
956 ip.user_ns['var'] = 42
970 ip.user_ns['var'] = 42
957 ip.run_line_magic('store', 'var')
971 ip.run_line_magic('store', 'var')
958 ip.user_ns['var'] = 39
972 ip.user_ns['var'] = 39
959 ip.run_line_magic('store', '-r')
973 ip.run_line_magic('store', '-r')
960 nt.assert_equal(ip.user_ns['var'], 42)
974 nt.assert_equal(ip.user_ns['var'], 42)
961
975
962 ip.run_line_magic('store', '-d var')
976 ip.run_line_magic('store', '-d var')
963 ip.user_ns['var'] = 39
977 ip.user_ns['var'] = 39
964 ip.run_line_magic('store' , '-r')
978 ip.run_line_magic('store' , '-r')
965 nt.assert_equal(ip.user_ns['var'], 39)
979 nt.assert_equal(ip.user_ns['var'], 39)
966
980
967
981
968 def _run_edit_test(arg_s, exp_filename=None,
982 def _run_edit_test(arg_s, exp_filename=None,
969 exp_lineno=-1,
983 exp_lineno=-1,
970 exp_contents=None,
984 exp_contents=None,
971 exp_is_temp=None):
985 exp_is_temp=None):
972 ip = get_ipython()
986 ip = get_ipython()
973 M = code.CodeMagics(ip)
987 M = code.CodeMagics(ip)
974 last_call = ['','']
988 last_call = ['','']
975 opts,args = M.parse_options(arg_s,'prxn:')
989 opts,args = M.parse_options(arg_s,'prxn:')
976 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
990 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
977
991
978 if exp_filename is not None:
992 if exp_filename is not None:
979 nt.assert_equal(exp_filename, filename)
993 nt.assert_equal(exp_filename, filename)
980 if exp_contents is not None:
994 if exp_contents is not None:
981 with io.open(filename, 'r', encoding='utf-8') as f:
995 with io.open(filename, 'r', encoding='utf-8') as f:
982 contents = f.read()
996 contents = f.read()
983 nt.assert_equal(exp_contents, contents)
997 nt.assert_equal(exp_contents, contents)
984 if exp_lineno != -1:
998 if exp_lineno != -1:
985 nt.assert_equal(exp_lineno, lineno)
999 nt.assert_equal(exp_lineno, lineno)
986 if exp_is_temp is not None:
1000 if exp_is_temp is not None:
987 nt.assert_equal(exp_is_temp, is_temp)
1001 nt.assert_equal(exp_is_temp, is_temp)
988
1002
989
1003
990 def test_edit_interactive():
1004 def test_edit_interactive():
991 """%edit on interactively defined objects"""
1005 """%edit on interactively defined objects"""
992 ip = get_ipython()
1006 ip = get_ipython()
993 n = ip.execution_count
1007 n = ip.execution_count
994 ip.run_cell(u"def foo(): return 1", store_history=True)
1008 ip.run_cell(u"def foo(): return 1", store_history=True)
995
1009
996 try:
1010 try:
997 _run_edit_test("foo")
1011 _run_edit_test("foo")
998 except code.InteractivelyDefined as e:
1012 except code.InteractivelyDefined as e:
999 nt.assert_equal(e.index, n)
1013 nt.assert_equal(e.index, n)
1000 else:
1014 else:
1001 raise AssertionError("Should have raised InteractivelyDefined")
1015 raise AssertionError("Should have raised InteractivelyDefined")
1002
1016
1003
1017
1004 def test_edit_cell():
1018 def test_edit_cell():
1005 """%edit [cell id]"""
1019 """%edit [cell id]"""
1006 ip = get_ipython()
1020 ip = get_ipython()
1007
1021
1008 ip.run_cell(u"def foo(): return 1", store_history=True)
1022 ip.run_cell(u"def foo(): return 1", store_history=True)
1009
1023
1010 # test
1024 # test
1011 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
1025 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
1012
1026
1013 def test_bookmark():
1027 def test_bookmark():
1014 ip = get_ipython()
1028 ip = get_ipython()
1015 ip.run_line_magic('bookmark', 'bmname')
1029 ip.run_line_magic('bookmark', 'bmname')
1016 with tt.AssertPrints('bmname'):
1030 with tt.AssertPrints('bmname'):
1017 ip.run_line_magic('bookmark', '-l')
1031 ip.run_line_magic('bookmark', '-l')
1018 ip.run_line_magic('bookmark', '-d bmname')
1032 ip.run_line_magic('bookmark', '-d bmname')
1019
1033
1020 def test_ls_magic():
1034 def test_ls_magic():
1021 ip = get_ipython()
1035 ip = get_ipython()
1022 json_formatter = ip.display_formatter.formatters['application/json']
1036 json_formatter = ip.display_formatter.formatters['application/json']
1023 json_formatter.enabled = True
1037 json_formatter.enabled = True
1024 lsmagic = ip.magic('lsmagic')
1038 lsmagic = ip.magic('lsmagic')
1025 with warnings.catch_warnings(record=True) as w:
1039 with warnings.catch_warnings(record=True) as w:
1026 j = json_formatter(lsmagic)
1040 j = json_formatter(lsmagic)
1027 nt.assert_equal(sorted(j), ['cell', 'line'])
1041 nt.assert_equal(sorted(j), ['cell', 'line'])
1028 nt.assert_equal(w, []) # no warnings
1042 nt.assert_equal(w, []) # no warnings
1029
1043
1030 def test_strip_initial_indent():
1044 def test_strip_initial_indent():
1031 def sii(s):
1045 def sii(s):
1032 lines = s.splitlines()
1046 lines = s.splitlines()
1033 return '\n'.join(code.strip_initial_indent(lines))
1047 return '\n'.join(code.strip_initial_indent(lines))
1034
1048
1035 nt.assert_equal(sii(" a = 1\nb = 2"), "a = 1\nb = 2")
1049 nt.assert_equal(sii(" a = 1\nb = 2"), "a = 1\nb = 2")
1036 nt.assert_equal(sii(" a\n b\nc"), "a\n b\nc")
1050 nt.assert_equal(sii(" a\n b\nc"), "a\n b\nc")
1037 nt.assert_equal(sii("a\n b"), "a\n b")
1051 nt.assert_equal(sii("a\n b"), "a\n b")
1038
1052
1039 def test_logging_magic_quiet_from_arg():
1053 def test_logging_magic_quiet_from_arg():
1040 _ip.config.LoggingMagics.quiet = False
1054 _ip.config.LoggingMagics.quiet = False
1041 lm = logging.LoggingMagics(shell=_ip)
1055 lm = logging.LoggingMagics(shell=_ip)
1042 with TemporaryDirectory() as td:
1056 with TemporaryDirectory() as td:
1043 try:
1057 try:
1044 with tt.AssertNotPrints(re.compile("Activating.*")):
1058 with tt.AssertNotPrints(re.compile("Activating.*")):
1045 lm.logstart('-q {}'.format(
1059 lm.logstart('-q {}'.format(
1046 os.path.join(td, "quiet_from_arg.log")))
1060 os.path.join(td, "quiet_from_arg.log")))
1047 finally:
1061 finally:
1048 _ip.logger.logstop()
1062 _ip.logger.logstop()
1049
1063
1050 def test_logging_magic_quiet_from_config():
1064 def test_logging_magic_quiet_from_config():
1051 _ip.config.LoggingMagics.quiet = True
1065 _ip.config.LoggingMagics.quiet = True
1052 lm = logging.LoggingMagics(shell=_ip)
1066 lm = logging.LoggingMagics(shell=_ip)
1053 with TemporaryDirectory() as td:
1067 with TemporaryDirectory() as td:
1054 try:
1068 try:
1055 with tt.AssertNotPrints(re.compile("Activating.*")):
1069 with tt.AssertNotPrints(re.compile("Activating.*")):
1056 lm.logstart(os.path.join(td, "quiet_from_config.log"))
1070 lm.logstart(os.path.join(td, "quiet_from_config.log"))
1057 finally:
1071 finally:
1058 _ip.logger.logstop()
1072 _ip.logger.logstop()
1059
1073
1060 def test_logging_magic_not_quiet():
1074 def test_logging_magic_not_quiet():
1061 _ip.config.LoggingMagics.quiet = False
1075 _ip.config.LoggingMagics.quiet = False
1062 lm = logging.LoggingMagics(shell=_ip)
1076 lm = logging.LoggingMagics(shell=_ip)
1063 with TemporaryDirectory() as td:
1077 with TemporaryDirectory() as td:
1064 try:
1078 try:
1065 with tt.AssertPrints(re.compile("Activating.*")):
1079 with tt.AssertPrints(re.compile("Activating.*")):
1066 lm.logstart(os.path.join(td, "not_quiet.log"))
1080 lm.logstart(os.path.join(td, "not_quiet.log"))
1067 finally:
1081 finally:
1068 _ip.logger.logstop()
1082 _ip.logger.logstop()
1069
1083
1070 ##
1084 ##
1071 # this is slow, put at the end for local testing.
1085 # this is slow, put at the end for local testing.
1072 ##
1086 ##
1073 def test_timeit_arguments():
1087 def test_timeit_arguments():
1074 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
1088 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
1075 if sys.version_info < (3,7):
1089 if sys.version_info < (3,7):
1076 _ip.magic("timeit ('#')")
1090 _ip.magic("timeit ('#')")
1077 else:
1091 else:
1078 # 3.7 optimize no-op statement like above out, and complain there is
1092 # 3.7 optimize no-op statement like above out, and complain there is
1079 # nothing in the for loop.
1093 # nothing in the for loop.
1080 _ip.magic("timeit a=('#')")
1094 _ip.magic("timeit a=('#')")
General Comments 0
You need to be logged in to leave comments. Login now