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