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