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