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