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