##// END OF EJS Templates
Change to `Creates` as function is now singular.
Matthias Bussonnier -
Show More
@@ -1,796 +1,796 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 from __future__ import print_function
6 from __future__ import print_function
7 #-----------------------------------------------------------------------------
7 #-----------------------------------------------------------------------------
8 # Copyright (c) 2012 The IPython Development Team.
8 # Copyright (c) 2012 The IPython Development Team.
9 #
9 #
10 # Distributed under the terms of the Modified BSD License.
10 # Distributed under the terms of the Modified BSD License.
11 #
11 #
12 # The full license is in the file COPYING.txt, distributed with this software.
12 # The full license is in the file COPYING.txt, distributed with this software.
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Imports
16 # Imports
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 # Stdlib
19 # Stdlib
20 import io
20 import io
21 import os
21 import os
22 import re
22 import re
23 import sys
23 import sys
24 from pprint import pformat
24 from pprint import pformat
25
25
26 # Our own packages
26 # Our own packages
27 from IPython.core import magic_arguments
27 from IPython.core import magic_arguments
28 from IPython.core import oinspect
28 from IPython.core import oinspect
29 from IPython.core import page
29 from IPython.core import page
30 from IPython.core.alias import AliasError, Alias
30 from IPython.core.alias import AliasError, Alias
31 from IPython.core.error import UsageError
31 from IPython.core.error import UsageError
32 from IPython.core.magic import (
32 from IPython.core.magic import (
33 Magics, compress_dhist, magics_class, line_magic, cell_magic, line_cell_magic
33 Magics, compress_dhist, magics_class, line_magic, cell_magic, line_cell_magic
34 )
34 )
35 from IPython.testing.skipdoctest import skip_doctest
35 from IPython.testing.skipdoctest import skip_doctest
36 from IPython.utils.openpy import source_to_unicode
36 from IPython.utils.openpy import source_to_unicode
37 from IPython.utils.path import unquote_filename
37 from IPython.utils.path import unquote_filename
38 from IPython.utils.process import abbrev_cwd
38 from IPython.utils.process import abbrev_cwd
39 from IPython.utils import py3compat
39 from IPython.utils import py3compat
40 from IPython.utils.py3compat import unicode_type
40 from IPython.utils.py3compat import unicode_type
41 from IPython.utils.terminal import set_term_title
41 from IPython.utils.terminal import set_term_title
42
42
43 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
44 # Magic implementation classes
44 # Magic implementation classes
45 #-----------------------------------------------------------------------------
45 #-----------------------------------------------------------------------------
46 @magics_class
46 @magics_class
47 class OSMagics(Magics):
47 class OSMagics(Magics):
48 """Magics to interact with the underlying OS (shell-type functionality).
48 """Magics to interact with the underlying OS (shell-type functionality).
49 """
49 """
50
50
51 @skip_doctest
51 @skip_doctest
52 @line_magic
52 @line_magic
53 def alias(self, parameter_s=''):
53 def alias(self, parameter_s=''):
54 """Define an alias for a system command.
54 """Define an alias for a system command.
55
55
56 '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd'
56 '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd'
57
57
58 Then, typing 'alias_name params' will execute the system command 'cmd
58 Then, typing 'alias_name params' will execute the system command 'cmd
59 params' (from your underlying operating system).
59 params' (from your underlying operating system).
60
60
61 Aliases have lower precedence than magic functions and Python normal
61 Aliases have lower precedence than magic functions and Python normal
62 variables, so if 'foo' is both a Python variable and an alias, the
62 variables, so if 'foo' is both a Python variable and an alias, the
63 alias can not be executed until 'del foo' removes the Python variable.
63 alias can not be executed until 'del foo' removes the Python variable.
64
64
65 You can use the %l specifier in an alias definition to represent the
65 You can use the %l specifier in an alias definition to represent the
66 whole line when the alias is called. For example::
66 whole line when the alias is called. For example::
67
67
68 In [2]: alias bracket echo "Input in brackets: <%l>"
68 In [2]: alias bracket echo "Input in brackets: <%l>"
69 In [3]: bracket hello world
69 In [3]: bracket hello world
70 Input in brackets: <hello world>
70 Input in brackets: <hello world>
71
71
72 You can also define aliases with parameters using %s specifiers (one
72 You can also define aliases with parameters using %s specifiers (one
73 per parameter)::
73 per parameter)::
74
74
75 In [1]: alias parts echo first %s second %s
75 In [1]: alias parts echo first %s second %s
76 In [2]: %parts A B
76 In [2]: %parts A B
77 first A second B
77 first A second B
78 In [3]: %parts A
78 In [3]: %parts A
79 Incorrect number of arguments: 2 expected.
79 Incorrect number of arguments: 2 expected.
80 parts is an alias to: 'echo first %s second %s'
80 parts is an alias to: 'echo first %s second %s'
81
81
82 Note that %l and %s are mutually exclusive. You can only use one or
82 Note that %l and %s are mutually exclusive. You can only use one or
83 the other in your aliases.
83 the other in your aliases.
84
84
85 Aliases expand Python variables just like system calls using ! or !!
85 Aliases expand Python variables just like system calls using ! or !!
86 do: all expressions prefixed with '$' get expanded. For details of
86 do: all expressions prefixed with '$' get expanded. For details of
87 the semantic rules, see PEP-215:
87 the semantic rules, see PEP-215:
88 http://www.python.org/peps/pep-0215.html. This is the library used by
88 http://www.python.org/peps/pep-0215.html. This is the library used by
89 IPython for variable expansion. If you want to access a true shell
89 IPython for variable expansion. If you want to access a true shell
90 variable, an extra $ is necessary to prevent its expansion by
90 variable, an extra $ is necessary to prevent its expansion by
91 IPython::
91 IPython::
92
92
93 In [6]: alias show echo
93 In [6]: alias show echo
94 In [7]: PATH='A Python string'
94 In [7]: PATH='A Python string'
95 In [8]: show $PATH
95 In [8]: show $PATH
96 A Python string
96 A Python string
97 In [9]: show $$PATH
97 In [9]: show $$PATH
98 /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:...
98 /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:...
99
99
100 You can use the alias facility to acess all of $PATH. See the %rehashx
100 You can use the alias facility to acess all of $PATH. See the %rehashx
101 function, which automatically create aliases for the contents of your
101 function, which automatically creates aliases for the contents of your
102 $PATH.
102 $PATH.
103
103
104 If called with no parameters, %alias prints the current alias table."""
104 If called with no parameters, %alias prints the current alias table."""
105
105
106 par = parameter_s.strip()
106 par = parameter_s.strip()
107 if not par:
107 if not par:
108 aliases = sorted(self.shell.alias_manager.aliases)
108 aliases = sorted(self.shell.alias_manager.aliases)
109 # stored = self.shell.db.get('stored_aliases', {} )
109 # stored = self.shell.db.get('stored_aliases', {} )
110 # for k, v in stored:
110 # for k, v in stored:
111 # atab.append(k, v[0])
111 # atab.append(k, v[0])
112
112
113 print("Total number of aliases:", len(aliases))
113 print("Total number of aliases:", len(aliases))
114 sys.stdout.flush()
114 sys.stdout.flush()
115 return aliases
115 return aliases
116
116
117 # Now try to define a new one
117 # Now try to define a new one
118 try:
118 try:
119 alias,cmd = par.split(None, 1)
119 alias,cmd = par.split(None, 1)
120 except TypeError:
120 except TypeError:
121 print(oinspect.getdoc(self.alias))
121 print(oinspect.getdoc(self.alias))
122 return
122 return
123
123
124 try:
124 try:
125 self.shell.alias_manager.define_alias(alias, cmd)
125 self.shell.alias_manager.define_alias(alias, cmd)
126 except AliasError as e:
126 except AliasError as e:
127 print(e)
127 print(e)
128 # end magic_alias
128 # end magic_alias
129
129
130 @line_magic
130 @line_magic
131 def unalias(self, parameter_s=''):
131 def unalias(self, parameter_s=''):
132 """Remove an alias"""
132 """Remove an alias"""
133
133
134 aname = parameter_s.strip()
134 aname = parameter_s.strip()
135 try:
135 try:
136 self.shell.alias_manager.undefine_alias(aname)
136 self.shell.alias_manager.undefine_alias(aname)
137 except ValueError as e:
137 except ValueError as e:
138 print(e)
138 print(e)
139 return
139 return
140
140
141 stored = self.shell.db.get('stored_aliases', {} )
141 stored = self.shell.db.get('stored_aliases', {} )
142 if aname in stored:
142 if aname in stored:
143 print("Removing %stored alias",aname)
143 print("Removing %stored alias",aname)
144 del stored[aname]
144 del stored[aname]
145 self.shell.db['stored_aliases'] = stored
145 self.shell.db['stored_aliases'] = stored
146
146
147 @line_magic
147 @line_magic
148 def rehashx(self, parameter_s=''):
148 def rehashx(self, parameter_s=''):
149 """Update the alias table with all executable files in $PATH.
149 """Update the alias table with all executable files in $PATH.
150
150
151 rehashx explicitly checks that every entry in $PATH is a file
151 rehashx explicitly checks that every entry in $PATH is a file
152 with execute access (os.X_OK).
152 with execute access (os.X_OK).
153
153
154 Under Windows, it checks executability as a match against a
154 Under Windows, it checks executability as a match against a
155 '|'-separated string of extensions, stored in the IPython config
155 '|'-separated string of extensions, stored in the IPython config
156 variable win_exec_ext. This defaults to 'exe|com|bat'.
156 variable win_exec_ext. This defaults to 'exe|com|bat'.
157
157
158 This function also resets the root module cache of module completer,
158 This function also resets the root module cache of module completer,
159 used on slow filesystems.
159 used on slow filesystems.
160 """
160 """
161 from IPython.core.alias import InvalidAliasError
161 from IPython.core.alias import InvalidAliasError
162
162
163 # for the benefit of module completer in ipy_completers.py
163 # for the benefit of module completer in ipy_completers.py
164 del self.shell.db['rootmodules_cache']
164 del self.shell.db['rootmodules_cache']
165
165
166 path = [os.path.abspath(os.path.expanduser(p)) for p in
166 path = [os.path.abspath(os.path.expanduser(p)) for p in
167 os.environ.get('PATH','').split(os.pathsep)]
167 os.environ.get('PATH','').split(os.pathsep)]
168
168
169 syscmdlist = []
169 syscmdlist = []
170 # Now define isexec in a cross platform manner.
170 # Now define isexec in a cross platform manner.
171 if os.name == 'posix':
171 if os.name == 'posix':
172 isexec = lambda fname:os.path.isfile(fname) and \
172 isexec = lambda fname:os.path.isfile(fname) and \
173 os.access(fname,os.X_OK)
173 os.access(fname,os.X_OK)
174 else:
174 else:
175 try:
175 try:
176 winext = os.environ['pathext'].replace(';','|').replace('.','')
176 winext = os.environ['pathext'].replace(';','|').replace('.','')
177 except KeyError:
177 except KeyError:
178 winext = 'exe|com|bat|py'
178 winext = 'exe|com|bat|py'
179 if 'py' not in winext:
179 if 'py' not in winext:
180 winext += '|py'
180 winext += '|py'
181 execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE)
181 execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE)
182 isexec = lambda fname:os.path.isfile(fname) and execre.match(fname)
182 isexec = lambda fname:os.path.isfile(fname) and execre.match(fname)
183 savedir = py3compat.getcwd()
183 savedir = py3compat.getcwd()
184
184
185 # Now walk the paths looking for executables to alias.
185 # Now walk the paths looking for executables to alias.
186 try:
186 try:
187 # write the whole loop for posix/Windows so we don't have an if in
187 # write the whole loop for posix/Windows so we don't have an if in
188 # the innermost part
188 # the innermost part
189 if os.name == 'posix':
189 if os.name == 'posix':
190 for pdir in path:
190 for pdir in path:
191 try:
191 try:
192 os.chdir(pdir)
192 os.chdir(pdir)
193 dirlist = os.listdir(pdir)
193 dirlist = os.listdir(pdir)
194 except OSError:
194 except OSError:
195 continue
195 continue
196 for ff in dirlist:
196 for ff in dirlist:
197 if isexec(ff):
197 if isexec(ff):
198 try:
198 try:
199 # Removes dots from the name since ipython
199 # Removes dots from the name since ipython
200 # will assume names with dots to be python.
200 # will assume names with dots to be python.
201 if not self.shell.alias_manager.is_alias(ff):
201 if not self.shell.alias_manager.is_alias(ff):
202 self.shell.alias_manager.define_alias(
202 self.shell.alias_manager.define_alias(
203 ff.replace('.',''), ff)
203 ff.replace('.',''), ff)
204 except InvalidAliasError:
204 except InvalidAliasError:
205 pass
205 pass
206 else:
206 else:
207 syscmdlist.append(ff)
207 syscmdlist.append(ff)
208 else:
208 else:
209 no_alias = Alias.blacklist
209 no_alias = Alias.blacklist
210 for pdir in path:
210 for pdir in path:
211 try:
211 try:
212 os.chdir(pdir)
212 os.chdir(pdir)
213 dirlist = os.listdir(pdir)
213 dirlist = os.listdir(pdir)
214 except OSError:
214 except OSError:
215 continue
215 continue
216 for ff in dirlist:
216 for ff in dirlist:
217 base, ext = os.path.splitext(ff)
217 base, ext = os.path.splitext(ff)
218 if isexec(ff) and base.lower() not in no_alias:
218 if isexec(ff) and base.lower() not in no_alias:
219 if ext.lower() == '.exe':
219 if ext.lower() == '.exe':
220 ff = base
220 ff = base
221 try:
221 try:
222 # Removes dots from the name since ipython
222 # Removes dots from the name since ipython
223 # will assume names with dots to be python.
223 # will assume names with dots to be python.
224 self.shell.alias_manager.define_alias(
224 self.shell.alias_manager.define_alias(
225 base.lower().replace('.',''), ff)
225 base.lower().replace('.',''), ff)
226 except InvalidAliasError:
226 except InvalidAliasError:
227 pass
227 pass
228 syscmdlist.append(ff)
228 syscmdlist.append(ff)
229 self.shell.db['syscmdlist'] = syscmdlist
229 self.shell.db['syscmdlist'] = syscmdlist
230 finally:
230 finally:
231 os.chdir(savedir)
231 os.chdir(savedir)
232
232
233 @skip_doctest
233 @skip_doctest
234 @line_magic
234 @line_magic
235 def pwd(self, parameter_s=''):
235 def pwd(self, parameter_s=''):
236 """Return the current working directory path.
236 """Return the current working directory path.
237
237
238 Examples
238 Examples
239 --------
239 --------
240 ::
240 ::
241
241
242 In [9]: pwd
242 In [9]: pwd
243 Out[9]: '/home/tsuser/sprint/ipython'
243 Out[9]: '/home/tsuser/sprint/ipython'
244 """
244 """
245 return py3compat.getcwd()
245 return py3compat.getcwd()
246
246
247 @skip_doctest
247 @skip_doctest
248 @line_magic
248 @line_magic
249 def cd(self, parameter_s=''):
249 def cd(self, parameter_s=''):
250 """Change the current working directory.
250 """Change the current working directory.
251
251
252 This command automatically maintains an internal list of directories
252 This command automatically maintains an internal list of directories
253 you visit during your IPython session, in the variable _dh. The
253 you visit during your IPython session, in the variable _dh. The
254 command %dhist shows this history nicely formatted. You can also
254 command %dhist shows this history nicely formatted. You can also
255 do 'cd -<tab>' to see directory history conveniently.
255 do 'cd -<tab>' to see directory history conveniently.
256
256
257 Usage:
257 Usage:
258
258
259 cd 'dir': changes to directory 'dir'.
259 cd 'dir': changes to directory 'dir'.
260
260
261 cd -: changes to the last visited directory.
261 cd -: changes to the last visited directory.
262
262
263 cd -<n>: changes to the n-th directory in the directory history.
263 cd -<n>: changes to the n-th directory in the directory history.
264
264
265 cd --foo: change to directory that matches 'foo' in history
265 cd --foo: change to directory that matches 'foo' in history
266
266
267 cd -b <bookmark_name>: jump to a bookmark set by %bookmark
267 cd -b <bookmark_name>: jump to a bookmark set by %bookmark
268 (note: cd <bookmark_name> is enough if there is no
268 (note: cd <bookmark_name> is enough if there is no
269 directory <bookmark_name>, but a bookmark with the name exists.)
269 directory <bookmark_name>, but a bookmark with the name exists.)
270 'cd -b <tab>' allows you to tab-complete bookmark names.
270 'cd -b <tab>' allows you to tab-complete bookmark names.
271
271
272 Options:
272 Options:
273
273
274 -q: quiet. Do not print the working directory after the cd command is
274 -q: quiet. Do not print the working directory after the cd command is
275 executed. By default IPython's cd command does print this directory,
275 executed. By default IPython's cd command does print this directory,
276 since the default prompts do not display path information.
276 since the default prompts do not display path information.
277
277
278 Note that !cd doesn't work for this purpose because the shell where
278 Note that !cd doesn't work for this purpose because the shell where
279 !command runs is immediately discarded after executing 'command'.
279 !command runs is immediately discarded after executing 'command'.
280
280
281 Examples
281 Examples
282 --------
282 --------
283 ::
283 ::
284
284
285 In [10]: cd parent/child
285 In [10]: cd parent/child
286 /home/tsuser/parent/child
286 /home/tsuser/parent/child
287 """
287 """
288
288
289 oldcwd = py3compat.getcwd()
289 oldcwd = py3compat.getcwd()
290 numcd = re.match(r'(-)(\d+)$',parameter_s)
290 numcd = re.match(r'(-)(\d+)$',parameter_s)
291 # jump in directory history by number
291 # jump in directory history by number
292 if numcd:
292 if numcd:
293 nn = int(numcd.group(2))
293 nn = int(numcd.group(2))
294 try:
294 try:
295 ps = self.shell.user_ns['_dh'][nn]
295 ps = self.shell.user_ns['_dh'][nn]
296 except IndexError:
296 except IndexError:
297 print('The requested directory does not exist in history.')
297 print('The requested directory does not exist in history.')
298 return
298 return
299 else:
299 else:
300 opts = {}
300 opts = {}
301 elif parameter_s.startswith('--'):
301 elif parameter_s.startswith('--'):
302 ps = None
302 ps = None
303 fallback = None
303 fallback = None
304 pat = parameter_s[2:]
304 pat = parameter_s[2:]
305 dh = self.shell.user_ns['_dh']
305 dh = self.shell.user_ns['_dh']
306 # first search only by basename (last component)
306 # first search only by basename (last component)
307 for ent in reversed(dh):
307 for ent in reversed(dh):
308 if pat in os.path.basename(ent) and os.path.isdir(ent):
308 if pat in os.path.basename(ent) and os.path.isdir(ent):
309 ps = ent
309 ps = ent
310 break
310 break
311
311
312 if fallback is None and pat in ent and os.path.isdir(ent):
312 if fallback is None and pat in ent and os.path.isdir(ent):
313 fallback = ent
313 fallback = ent
314
314
315 # if we have no last part match, pick the first full path match
315 # if we have no last part match, pick the first full path match
316 if ps is None:
316 if ps is None:
317 ps = fallback
317 ps = fallback
318
318
319 if ps is None:
319 if ps is None:
320 print("No matching entry in directory history")
320 print("No matching entry in directory history")
321 return
321 return
322 else:
322 else:
323 opts = {}
323 opts = {}
324
324
325
325
326 else:
326 else:
327 #turn all non-space-escaping backslashes to slashes,
327 #turn all non-space-escaping backslashes to slashes,
328 # for c:\windows\directory\names\
328 # for c:\windows\directory\names\
329 parameter_s = re.sub(r'\\(?! )','/', parameter_s)
329 parameter_s = re.sub(r'\\(?! )','/', parameter_s)
330 opts,ps = self.parse_options(parameter_s,'qb',mode='string')
330 opts,ps = self.parse_options(parameter_s,'qb',mode='string')
331 # jump to previous
331 # jump to previous
332 if ps == '-':
332 if ps == '-':
333 try:
333 try:
334 ps = self.shell.user_ns['_dh'][-2]
334 ps = self.shell.user_ns['_dh'][-2]
335 except IndexError:
335 except IndexError:
336 raise UsageError('%cd -: No previous directory to change to.')
336 raise UsageError('%cd -: No previous directory to change to.')
337 # jump to bookmark if needed
337 # jump to bookmark if needed
338 else:
338 else:
339 if not os.path.isdir(ps) or 'b' in opts:
339 if not os.path.isdir(ps) or 'b' in opts:
340 bkms = self.shell.db.get('bookmarks', {})
340 bkms = self.shell.db.get('bookmarks', {})
341
341
342 if ps in bkms:
342 if ps in bkms:
343 target = bkms[ps]
343 target = bkms[ps]
344 print('(bookmark:%s) -> %s' % (ps, target))
344 print('(bookmark:%s) -> %s' % (ps, target))
345 ps = target
345 ps = target
346 else:
346 else:
347 if 'b' in opts:
347 if 'b' in opts:
348 raise UsageError("Bookmark '%s' not found. "
348 raise UsageError("Bookmark '%s' not found. "
349 "Use '%%bookmark -l' to see your bookmarks." % ps)
349 "Use '%%bookmark -l' to see your bookmarks." % ps)
350
350
351 # strip extra quotes on Windows, because os.chdir doesn't like them
351 # strip extra quotes on Windows, because os.chdir doesn't like them
352 ps = unquote_filename(ps)
352 ps = unquote_filename(ps)
353 # at this point ps should point to the target dir
353 # at this point ps should point to the target dir
354 if ps:
354 if ps:
355 try:
355 try:
356 os.chdir(os.path.expanduser(ps))
356 os.chdir(os.path.expanduser(ps))
357 if hasattr(self.shell, 'term_title') and self.shell.term_title:
357 if hasattr(self.shell, 'term_title') and self.shell.term_title:
358 set_term_title('IPython: ' + abbrev_cwd())
358 set_term_title('IPython: ' + abbrev_cwd())
359 except OSError:
359 except OSError:
360 print(sys.exc_info()[1])
360 print(sys.exc_info()[1])
361 else:
361 else:
362 cwd = py3compat.getcwd()
362 cwd = py3compat.getcwd()
363 dhist = self.shell.user_ns['_dh']
363 dhist = self.shell.user_ns['_dh']
364 if oldcwd != cwd:
364 if oldcwd != cwd:
365 dhist.append(cwd)
365 dhist.append(cwd)
366 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
366 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
367
367
368 else:
368 else:
369 os.chdir(self.shell.home_dir)
369 os.chdir(self.shell.home_dir)
370 if hasattr(self.shell, 'term_title') and self.shell.term_title:
370 if hasattr(self.shell, 'term_title') and self.shell.term_title:
371 set_term_title('IPython: ' + '~')
371 set_term_title('IPython: ' + '~')
372 cwd = py3compat.getcwd()
372 cwd = py3compat.getcwd()
373 dhist = self.shell.user_ns['_dh']
373 dhist = self.shell.user_ns['_dh']
374
374
375 if oldcwd != cwd:
375 if oldcwd != cwd:
376 dhist.append(cwd)
376 dhist.append(cwd)
377 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
377 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
378 if not 'q' in opts and self.shell.user_ns['_dh']:
378 if not 'q' in opts and self.shell.user_ns['_dh']:
379 print(self.shell.user_ns['_dh'][-1])
379 print(self.shell.user_ns['_dh'][-1])
380
380
381 @line_magic
381 @line_magic
382 def env(self, parameter_s=''):
382 def env(self, parameter_s=''):
383 """Get, set, or list environment variables.
383 """Get, set, or list environment variables.
384
384
385 Usage:\\
385 Usage:\\
386
386
387 %env: lists all environment variables/values
387 %env: lists all environment variables/values
388 %env var: get value for var
388 %env var: get value for var
389 %env var val: set value for var
389 %env var val: set value for var
390 %env var=val: set value for var
390 %env var=val: set value for var
391 %env var=$val: set value for var, using python expansion if possible
391 %env var=$val: set value for var, using python expansion if possible
392 """
392 """
393 if parameter_s.strip():
393 if parameter_s.strip():
394 split = '=' if '=' in parameter_s else ' '
394 split = '=' if '=' in parameter_s else ' '
395 bits = parameter_s.split(split)
395 bits = parameter_s.split(split)
396 if len(bits) == 1:
396 if len(bits) == 1:
397 key = parameter_s.strip()
397 key = parameter_s.strip()
398 if key in os.environ:
398 if key in os.environ:
399 return os.environ[key]
399 return os.environ[key]
400 else:
400 else:
401 err = "Environment does not have key: {0}".format(key)
401 err = "Environment does not have key: {0}".format(key)
402 raise UsageError(err)
402 raise UsageError(err)
403 if len(bits) > 1:
403 if len(bits) > 1:
404 return self.set_env(parameter_s)
404 return self.set_env(parameter_s)
405 return dict(os.environ)
405 return dict(os.environ)
406
406
407 @line_magic
407 @line_magic
408 def set_env(self, parameter_s):
408 def set_env(self, parameter_s):
409 """Set environment variables. Assumptions are that either "val" is a
409 """Set environment variables. Assumptions are that either "val" is a
410 name in the user namespace, or val is something that evaluates to a
410 name in the user namespace, or val is something that evaluates to a
411 string.
411 string.
412
412
413 Usage:\\
413 Usage:\\
414 %set_env var val: set value for var
414 %set_env var val: set value for var
415 %set_env var=val: set value for var
415 %set_env var=val: set value for var
416 %set_env var=$val: set value for var, using python expansion if possible
416 %set_env var=$val: set value for var, using python expansion if possible
417 """
417 """
418 split = '=' if '=' in parameter_s else ' '
418 split = '=' if '=' in parameter_s else ' '
419 bits = parameter_s.split(split, 1)
419 bits = parameter_s.split(split, 1)
420 if not parameter_s.strip() or len(bits)<2:
420 if not parameter_s.strip() or len(bits)<2:
421 raise UsageError("usage is 'set_env var=val'")
421 raise UsageError("usage is 'set_env var=val'")
422 var = bits[0].strip()
422 var = bits[0].strip()
423 val = bits[1].strip()
423 val = bits[1].strip()
424 if re.match(r'.*\s.*', var):
424 if re.match(r'.*\s.*', var):
425 # an environment variable with whitespace is almost certainly
425 # an environment variable with whitespace is almost certainly
426 # not what the user intended. what's more likely is the wrong
426 # not what the user intended. what's more likely is the wrong
427 # split was chosen, ie for "set_env cmd_args A=B", we chose
427 # split was chosen, ie for "set_env cmd_args A=B", we chose
428 # '=' for the split and should have chosen ' '. to get around
428 # '=' for the split and should have chosen ' '. to get around
429 # this, users should just assign directly to os.environ or use
429 # this, users should just assign directly to os.environ or use
430 # standard magic {var} expansion.
430 # standard magic {var} expansion.
431 err = "refusing to set env var with whitespace: '{0}'"
431 err = "refusing to set env var with whitespace: '{0}'"
432 err = err.format(val)
432 err = err.format(val)
433 raise UsageError(err)
433 raise UsageError(err)
434 os.environ[py3compat.cast_bytes_py2(var)] = py3compat.cast_bytes_py2(val)
434 os.environ[py3compat.cast_bytes_py2(var)] = py3compat.cast_bytes_py2(val)
435 print('env: {0}={1}'.format(var,val))
435 print('env: {0}={1}'.format(var,val))
436
436
437 @line_magic
437 @line_magic
438 def pushd(self, parameter_s=''):
438 def pushd(self, parameter_s=''):
439 """Place the current dir on stack and change directory.
439 """Place the current dir on stack and change directory.
440
440
441 Usage:\\
441 Usage:\\
442 %pushd ['dirname']
442 %pushd ['dirname']
443 """
443 """
444
444
445 dir_s = self.shell.dir_stack
445 dir_s = self.shell.dir_stack
446 tgt = os.path.expanduser(unquote_filename(parameter_s))
446 tgt = os.path.expanduser(unquote_filename(parameter_s))
447 cwd = py3compat.getcwd().replace(self.shell.home_dir,'~')
447 cwd = py3compat.getcwd().replace(self.shell.home_dir,'~')
448 if tgt:
448 if tgt:
449 self.cd(parameter_s)
449 self.cd(parameter_s)
450 dir_s.insert(0,cwd)
450 dir_s.insert(0,cwd)
451 return self.shell.magic('dirs')
451 return self.shell.magic('dirs')
452
452
453 @line_magic
453 @line_magic
454 def popd(self, parameter_s=''):
454 def popd(self, parameter_s=''):
455 """Change to directory popped off the top of the stack.
455 """Change to directory popped off the top of the stack.
456 """
456 """
457 if not self.shell.dir_stack:
457 if not self.shell.dir_stack:
458 raise UsageError("%popd on empty stack")
458 raise UsageError("%popd on empty stack")
459 top = self.shell.dir_stack.pop(0)
459 top = self.shell.dir_stack.pop(0)
460 self.cd(top)
460 self.cd(top)
461 print("popd ->",top)
461 print("popd ->",top)
462
462
463 @line_magic
463 @line_magic
464 def dirs(self, parameter_s=''):
464 def dirs(self, parameter_s=''):
465 """Return the current directory stack."""
465 """Return the current directory stack."""
466
466
467 return self.shell.dir_stack
467 return self.shell.dir_stack
468
468
469 @line_magic
469 @line_magic
470 def dhist(self, parameter_s=''):
470 def dhist(self, parameter_s=''):
471 """Print your history of visited directories.
471 """Print your history of visited directories.
472
472
473 %dhist -> print full history\\
473 %dhist -> print full history\\
474 %dhist n -> print last n entries only\\
474 %dhist n -> print last n entries only\\
475 %dhist n1 n2 -> print entries between n1 and n2 (n2 not included)\\
475 %dhist n1 n2 -> print entries between n1 and n2 (n2 not included)\\
476
476
477 This history is automatically maintained by the %cd command, and
477 This history is automatically maintained by the %cd command, and
478 always available as the global list variable _dh. You can use %cd -<n>
478 always available as the global list variable _dh. You can use %cd -<n>
479 to go to directory number <n>.
479 to go to directory number <n>.
480
480
481 Note that most of time, you should view directory history by entering
481 Note that most of time, you should view directory history by entering
482 cd -<TAB>.
482 cd -<TAB>.
483
483
484 """
484 """
485
485
486 dh = self.shell.user_ns['_dh']
486 dh = self.shell.user_ns['_dh']
487 if parameter_s:
487 if parameter_s:
488 try:
488 try:
489 args = map(int,parameter_s.split())
489 args = map(int,parameter_s.split())
490 except:
490 except:
491 self.arg_err(self.dhist)
491 self.arg_err(self.dhist)
492 return
492 return
493 if len(args) == 1:
493 if len(args) == 1:
494 ini,fin = max(len(dh)-(args[0]),0),len(dh)
494 ini,fin = max(len(dh)-(args[0]),0),len(dh)
495 elif len(args) == 2:
495 elif len(args) == 2:
496 ini,fin = args
496 ini,fin = args
497 fin = min(fin, len(dh))
497 fin = min(fin, len(dh))
498 else:
498 else:
499 self.arg_err(self.dhist)
499 self.arg_err(self.dhist)
500 return
500 return
501 else:
501 else:
502 ini,fin = 0,len(dh)
502 ini,fin = 0,len(dh)
503 print('Directory history (kept in _dh)')
503 print('Directory history (kept in _dh)')
504 for i in range(ini, fin):
504 for i in range(ini, fin):
505 print("%d: %s" % (i, dh[i]))
505 print("%d: %s" % (i, dh[i]))
506
506
507 @skip_doctest
507 @skip_doctest
508 @line_magic
508 @line_magic
509 def sc(self, parameter_s=''):
509 def sc(self, parameter_s=''):
510 """Shell capture - run shell command and capture output (DEPRECATED use !).
510 """Shell capture - run shell command and capture output (DEPRECATED use !).
511
511
512 DEPRECATED. Suboptimal, retained for backwards compatibility.
512 DEPRECATED. Suboptimal, retained for backwards compatibility.
513
513
514 You should use the form 'var = !command' instead. Example:
514 You should use the form 'var = !command' instead. Example:
515
515
516 "%sc -l myfiles = ls ~" should now be written as
516 "%sc -l myfiles = ls ~" should now be written as
517
517
518 "myfiles = !ls ~"
518 "myfiles = !ls ~"
519
519
520 myfiles.s, myfiles.l and myfiles.n still apply as documented
520 myfiles.s, myfiles.l and myfiles.n still apply as documented
521 below.
521 below.
522
522
523 --
523 --
524 %sc [options] varname=command
524 %sc [options] varname=command
525
525
526 IPython will run the given command using commands.getoutput(), and
526 IPython will run the given command using commands.getoutput(), and
527 will then update the user's interactive namespace with a variable
527 will then update the user's interactive namespace with a variable
528 called varname, containing the value of the call. Your command can
528 called varname, containing the value of the call. Your command can
529 contain shell wildcards, pipes, etc.
529 contain shell wildcards, pipes, etc.
530
530
531 The '=' sign in the syntax is mandatory, and the variable name you
531 The '=' sign in the syntax is mandatory, and the variable name you
532 supply must follow Python's standard conventions for valid names.
532 supply must follow Python's standard conventions for valid names.
533
533
534 (A special format without variable name exists for internal use)
534 (A special format without variable name exists for internal use)
535
535
536 Options:
536 Options:
537
537
538 -l: list output. Split the output on newlines into a list before
538 -l: list output. Split the output on newlines into a list before
539 assigning it to the given variable. By default the output is stored
539 assigning it to the given variable. By default the output is stored
540 as a single string.
540 as a single string.
541
541
542 -v: verbose. Print the contents of the variable.
542 -v: verbose. Print the contents of the variable.
543
543
544 In most cases you should not need to split as a list, because the
544 In most cases you should not need to split as a list, because the
545 returned value is a special type of string which can automatically
545 returned value is a special type of string which can automatically
546 provide its contents either as a list (split on newlines) or as a
546 provide its contents either as a list (split on newlines) or as a
547 space-separated string. These are convenient, respectively, either
547 space-separated string. These are convenient, respectively, either
548 for sequential processing or to be passed to a shell command.
548 for sequential processing or to be passed to a shell command.
549
549
550 For example::
550 For example::
551
551
552 # Capture into variable a
552 # Capture into variable a
553 In [1]: sc a=ls *py
553 In [1]: sc a=ls *py
554
554
555 # a is a string with embedded newlines
555 # a is a string with embedded newlines
556 In [2]: a
556 In [2]: a
557 Out[2]: 'setup.py\\nwin32_manual_post_install.py'
557 Out[2]: 'setup.py\\nwin32_manual_post_install.py'
558
558
559 # which can be seen as a list:
559 # which can be seen as a list:
560 In [3]: a.l
560 In [3]: a.l
561 Out[3]: ['setup.py', 'win32_manual_post_install.py']
561 Out[3]: ['setup.py', 'win32_manual_post_install.py']
562
562
563 # or as a whitespace-separated string:
563 # or as a whitespace-separated string:
564 In [4]: a.s
564 In [4]: a.s
565 Out[4]: 'setup.py win32_manual_post_install.py'
565 Out[4]: 'setup.py win32_manual_post_install.py'
566
566
567 # a.s is useful to pass as a single command line:
567 # a.s is useful to pass as a single command line:
568 In [5]: !wc -l $a.s
568 In [5]: !wc -l $a.s
569 146 setup.py
569 146 setup.py
570 130 win32_manual_post_install.py
570 130 win32_manual_post_install.py
571 276 total
571 276 total
572
572
573 # while the list form is useful to loop over:
573 # while the list form is useful to loop over:
574 In [6]: for f in a.l:
574 In [6]: for f in a.l:
575 ...: !wc -l $f
575 ...: !wc -l $f
576 ...:
576 ...:
577 146 setup.py
577 146 setup.py
578 130 win32_manual_post_install.py
578 130 win32_manual_post_install.py
579
579
580 Similarly, the lists returned by the -l option are also special, in
580 Similarly, the lists returned by the -l option are also special, in
581 the sense that you can equally invoke the .s attribute on them to
581 the sense that you can equally invoke the .s attribute on them to
582 automatically get a whitespace-separated string from their contents::
582 automatically get a whitespace-separated string from their contents::
583
583
584 In [7]: sc -l b=ls *py
584 In [7]: sc -l b=ls *py
585
585
586 In [8]: b
586 In [8]: b
587 Out[8]: ['setup.py', 'win32_manual_post_install.py']
587 Out[8]: ['setup.py', 'win32_manual_post_install.py']
588
588
589 In [9]: b.s
589 In [9]: b.s
590 Out[9]: 'setup.py win32_manual_post_install.py'
590 Out[9]: 'setup.py win32_manual_post_install.py'
591
591
592 In summary, both the lists and strings used for output capture have
592 In summary, both the lists and strings used for output capture have
593 the following special attributes::
593 the following special attributes::
594
594
595 .l (or .list) : value as list.
595 .l (or .list) : value as list.
596 .n (or .nlstr): value as newline-separated string.
596 .n (or .nlstr): value as newline-separated string.
597 .s (or .spstr): value as space-separated string.
597 .s (or .spstr): value as space-separated string.
598 """
598 """
599
599
600 opts,args = self.parse_options(parameter_s, 'lv')
600 opts,args = self.parse_options(parameter_s, 'lv')
601 # Try to get a variable name and command to run
601 # Try to get a variable name and command to run
602 try:
602 try:
603 # the variable name must be obtained from the parse_options
603 # the variable name must be obtained from the parse_options
604 # output, which uses shlex.split to strip options out.
604 # output, which uses shlex.split to strip options out.
605 var,_ = args.split('=', 1)
605 var,_ = args.split('=', 1)
606 var = var.strip()
606 var = var.strip()
607 # But the command has to be extracted from the original input
607 # But the command has to be extracted from the original input
608 # parameter_s, not on what parse_options returns, to avoid the
608 # parameter_s, not on what parse_options returns, to avoid the
609 # quote stripping which shlex.split performs on it.
609 # quote stripping which shlex.split performs on it.
610 _,cmd = parameter_s.split('=', 1)
610 _,cmd = parameter_s.split('=', 1)
611 except ValueError:
611 except ValueError:
612 var,cmd = '',''
612 var,cmd = '',''
613 # If all looks ok, proceed
613 # If all looks ok, proceed
614 split = 'l' in opts
614 split = 'l' in opts
615 out = self.shell.getoutput(cmd, split=split)
615 out = self.shell.getoutput(cmd, split=split)
616 if 'v' in opts:
616 if 'v' in opts:
617 print('%s ==\n%s' % (var, pformat(out)))
617 print('%s ==\n%s' % (var, pformat(out)))
618 if var:
618 if var:
619 self.shell.user_ns.update({var:out})
619 self.shell.user_ns.update({var:out})
620 else:
620 else:
621 return out
621 return out
622
622
623 @line_cell_magic
623 @line_cell_magic
624 def sx(self, line='', cell=None):
624 def sx(self, line='', cell=None):
625 """Shell execute - run shell command and capture output (!! is short-hand).
625 """Shell execute - run shell command and capture output (!! is short-hand).
626
626
627 %sx command
627 %sx command
628
628
629 IPython will run the given command using commands.getoutput(), and
629 IPython will run the given command using commands.getoutput(), and
630 return the result formatted as a list (split on '\\n'). Since the
630 return the result formatted as a list (split on '\\n'). Since the
631 output is _returned_, it will be stored in ipython's regular output
631 output is _returned_, it will be stored in ipython's regular output
632 cache Out[N] and in the '_N' automatic variables.
632 cache Out[N] and in the '_N' automatic variables.
633
633
634 Notes:
634 Notes:
635
635
636 1) If an input line begins with '!!', then %sx is automatically
636 1) If an input line begins with '!!', then %sx is automatically
637 invoked. That is, while::
637 invoked. That is, while::
638
638
639 !ls
639 !ls
640
640
641 causes ipython to simply issue system('ls'), typing::
641 causes ipython to simply issue system('ls'), typing::
642
642
643 !!ls
643 !!ls
644
644
645 is a shorthand equivalent to::
645 is a shorthand equivalent to::
646
646
647 %sx ls
647 %sx ls
648
648
649 2) %sx differs from %sc in that %sx automatically splits into a list,
649 2) %sx differs from %sc in that %sx automatically splits into a list,
650 like '%sc -l'. The reason for this is to make it as easy as possible
650 like '%sc -l'. The reason for this is to make it as easy as possible
651 to process line-oriented shell output via further python commands.
651 to process line-oriented shell output via further python commands.
652 %sc is meant to provide much finer control, but requires more
652 %sc is meant to provide much finer control, but requires more
653 typing.
653 typing.
654
654
655 3) Just like %sc -l, this is a list with special attributes:
655 3) Just like %sc -l, this is a list with special attributes:
656 ::
656 ::
657
657
658 .l (or .list) : value as list.
658 .l (or .list) : value as list.
659 .n (or .nlstr): value as newline-separated string.
659 .n (or .nlstr): value as newline-separated string.
660 .s (or .spstr): value as whitespace-separated string.
660 .s (or .spstr): value as whitespace-separated string.
661
661
662 This is very useful when trying to use such lists as arguments to
662 This is very useful when trying to use such lists as arguments to
663 system commands."""
663 system commands."""
664
664
665 if cell is None:
665 if cell is None:
666 # line magic
666 # line magic
667 return self.shell.getoutput(line)
667 return self.shell.getoutput(line)
668 else:
668 else:
669 opts,args = self.parse_options(line, '', 'out=')
669 opts,args = self.parse_options(line, '', 'out=')
670 output = self.shell.getoutput(cell)
670 output = self.shell.getoutput(cell)
671 out_name = opts.get('out', opts.get('o'))
671 out_name = opts.get('out', opts.get('o'))
672 if out_name:
672 if out_name:
673 self.shell.user_ns[out_name] = output
673 self.shell.user_ns[out_name] = output
674 else:
674 else:
675 return output
675 return output
676
676
677 system = line_cell_magic('system')(sx)
677 system = line_cell_magic('system')(sx)
678 bang = cell_magic('!')(sx)
678 bang = cell_magic('!')(sx)
679
679
680 @line_magic
680 @line_magic
681 def bookmark(self, parameter_s=''):
681 def bookmark(self, parameter_s=''):
682 """Manage IPython's bookmark system.
682 """Manage IPython's bookmark system.
683
683
684 %bookmark <name> - set bookmark to current dir
684 %bookmark <name> - set bookmark to current dir
685 %bookmark <name> <dir> - set bookmark to <dir>
685 %bookmark <name> <dir> - set bookmark to <dir>
686 %bookmark -l - list all bookmarks
686 %bookmark -l - list all bookmarks
687 %bookmark -d <name> - remove bookmark
687 %bookmark -d <name> - remove bookmark
688 %bookmark -r - remove all bookmarks
688 %bookmark -r - remove all bookmarks
689
689
690 You can later on access a bookmarked folder with::
690 You can later on access a bookmarked folder with::
691
691
692 %cd -b <name>
692 %cd -b <name>
693
693
694 or simply '%cd <name>' if there is no directory called <name> AND
694 or simply '%cd <name>' if there is no directory called <name> AND
695 there is such a bookmark defined.
695 there is such a bookmark defined.
696
696
697 Your bookmarks persist through IPython sessions, but they are
697 Your bookmarks persist through IPython sessions, but they are
698 associated with each profile."""
698 associated with each profile."""
699
699
700 opts,args = self.parse_options(parameter_s,'drl',mode='list')
700 opts,args = self.parse_options(parameter_s,'drl',mode='list')
701 if len(args) > 2:
701 if len(args) > 2:
702 raise UsageError("%bookmark: too many arguments")
702 raise UsageError("%bookmark: too many arguments")
703
703
704 bkms = self.shell.db.get('bookmarks',{})
704 bkms = self.shell.db.get('bookmarks',{})
705
705
706 if 'd' in opts:
706 if 'd' in opts:
707 try:
707 try:
708 todel = args[0]
708 todel = args[0]
709 except IndexError:
709 except IndexError:
710 raise UsageError(
710 raise UsageError(
711 "%bookmark -d: must provide a bookmark to delete")
711 "%bookmark -d: must provide a bookmark to delete")
712 else:
712 else:
713 try:
713 try:
714 del bkms[todel]
714 del bkms[todel]
715 except KeyError:
715 except KeyError:
716 raise UsageError(
716 raise UsageError(
717 "%%bookmark -d: Can't delete bookmark '%s'" % todel)
717 "%%bookmark -d: Can't delete bookmark '%s'" % todel)
718
718
719 elif 'r' in opts:
719 elif 'r' in opts:
720 bkms = {}
720 bkms = {}
721 elif 'l' in opts:
721 elif 'l' in opts:
722 bks = sorted(bkms)
722 bks = sorted(bkms)
723 if bks:
723 if bks:
724 size = max(map(len, bks))
724 size = max(map(len, bks))
725 else:
725 else:
726 size = 0
726 size = 0
727 fmt = '%-'+str(size)+'s -> %s'
727 fmt = '%-'+str(size)+'s -> %s'
728 print('Current bookmarks:')
728 print('Current bookmarks:')
729 for bk in bks:
729 for bk in bks:
730 print(fmt % (bk, bkms[bk]))
730 print(fmt % (bk, bkms[bk]))
731 else:
731 else:
732 if not args:
732 if not args:
733 raise UsageError("%bookmark: You must specify the bookmark name")
733 raise UsageError("%bookmark: You must specify the bookmark name")
734 elif len(args)==1:
734 elif len(args)==1:
735 bkms[args[0]] = py3compat.getcwd()
735 bkms[args[0]] = py3compat.getcwd()
736 elif len(args)==2:
736 elif len(args)==2:
737 bkms[args[0]] = args[1]
737 bkms[args[0]] = args[1]
738 self.shell.db['bookmarks'] = bkms
738 self.shell.db['bookmarks'] = bkms
739
739
740 @line_magic
740 @line_magic
741 def pycat(self, parameter_s=''):
741 def pycat(self, parameter_s=''):
742 """Show a syntax-highlighted file through a pager.
742 """Show a syntax-highlighted file through a pager.
743
743
744 This magic is similar to the cat utility, but it will assume the file
744 This magic is similar to the cat utility, but it will assume the file
745 to be Python source and will show it with syntax highlighting.
745 to be Python source and will show it with syntax highlighting.
746
746
747 This magic command can either take a local filename, an url,
747 This magic command can either take a local filename, an url,
748 an history range (see %history) or a macro as argument ::
748 an history range (see %history) or a macro as argument ::
749
749
750 %pycat myscript.py
750 %pycat myscript.py
751 %pycat 7-27
751 %pycat 7-27
752 %pycat myMacro
752 %pycat myMacro
753 %pycat http://www.example.com/myscript.py
753 %pycat http://www.example.com/myscript.py
754 """
754 """
755 if not parameter_s:
755 if not parameter_s:
756 raise UsageError('Missing filename, URL, input history range, '
756 raise UsageError('Missing filename, URL, input history range, '
757 'or macro.')
757 'or macro.')
758
758
759 try :
759 try :
760 cont = self.shell.find_user_code(parameter_s, skip_encoding_cookie=False)
760 cont = self.shell.find_user_code(parameter_s, skip_encoding_cookie=False)
761 except (ValueError, IOError):
761 except (ValueError, IOError):
762 print("Error: no such file, variable, URL, history range or macro")
762 print("Error: no such file, variable, URL, history range or macro")
763 return
763 return
764
764
765 page.page(self.shell.pycolorize(source_to_unicode(cont)))
765 page.page(self.shell.pycolorize(source_to_unicode(cont)))
766
766
767 @magic_arguments.magic_arguments()
767 @magic_arguments.magic_arguments()
768 @magic_arguments.argument(
768 @magic_arguments.argument(
769 '-a', '--append', action='store_true', default=False,
769 '-a', '--append', action='store_true', default=False,
770 help='Append contents of the cell to an existing file. '
770 help='Append contents of the cell to an existing file. '
771 'The file will be created if it does not exist.'
771 'The file will be created if it does not exist.'
772 )
772 )
773 @magic_arguments.argument(
773 @magic_arguments.argument(
774 'filename', type=unicode_type,
774 'filename', type=unicode_type,
775 help='file to write'
775 help='file to write'
776 )
776 )
777 @cell_magic
777 @cell_magic
778 def writefile(self, line, cell):
778 def writefile(self, line, cell):
779 """Write the contents of the cell to a file.
779 """Write the contents of the cell to a file.
780
780
781 The file will be overwritten unless the -a (--append) flag is specified.
781 The file will be overwritten unless the -a (--append) flag is specified.
782 """
782 """
783 args = magic_arguments.parse_argstring(self.writefile, line)
783 args = magic_arguments.parse_argstring(self.writefile, line)
784 filename = os.path.expanduser(unquote_filename(args.filename))
784 filename = os.path.expanduser(unquote_filename(args.filename))
785
785
786 if os.path.exists(filename):
786 if os.path.exists(filename):
787 if args.append:
787 if args.append:
788 print("Appending to %s" % filename)
788 print("Appending to %s" % filename)
789 else:
789 else:
790 print("Overwriting %s" % filename)
790 print("Overwriting %s" % filename)
791 else:
791 else:
792 print("Writing %s" % filename)
792 print("Writing %s" % filename)
793
793
794 mode = 'a' if args.append else 'w'
794 mode = 'a' if args.append else 'w'
795 with io.open(filename, mode, encoding='utf-8') as f:
795 with io.open(filename, mode, encoding='utf-8') as f:
796 f.write(cell)
796 f.write(cell)
General Comments 0
You need to be logged in to leave comments. Login now