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