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