##// END OF EJS Templates
Merge pull request #13581 from Carreau/pep-rename...
Matthias Bussonnier -
r27592:2f0efaca merge
parent child Browse files
Show More
@@ -1,854 +1,854 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 def _isexec_POSIX(self, file):
67 67 """
68 68 Test for executable on a POSIX system
69 69 """
70 70 if os.access(file.path, os.X_OK):
71 71 # will fail on maxOS if access is not X_OK
72 72 return file.is_file()
73 73 return False
74 74
75 75
76 76
77 77 def _isexec_WIN(self, file):
78 78 """
79 79 Test for executable file on non POSIX system
80 80 """
81 81 return file.is_file() and self.execre.match(file.name) is not None
82 82
83 83 def isexec(self, file):
84 84 """
85 85 Test for executable file on non POSIX system
86 86 """
87 87 if self.is_posix:
88 88 return self._isexec_POSIX(file)
89 89 else:
90 90 return self._isexec_WIN(file)
91 91
92 92
93 93 @skip_doctest
94 94 @line_magic
95 95 def alias(self, parameter_s=''):
96 96 """Define an alias for a system command.
97 97
98 98 '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd'
99 99
100 100 Then, typing 'alias_name params' will execute the system command 'cmd
101 101 params' (from your underlying operating system).
102 102
103 103 Aliases have lower precedence than magic functions and Python normal
104 104 variables, so if 'foo' is both a Python variable and an alias, the
105 105 alias can not be executed until 'del foo' removes the Python variable.
106 106
107 107 You can use the %l specifier in an alias definition to represent the
108 108 whole line when the alias is called. For example::
109 109
110 110 In [2]: alias bracket echo "Input in brackets: <%l>"
111 111 In [3]: bracket hello world
112 112 Input in brackets: <hello world>
113 113
114 114 You can also define aliases with parameters using %s specifiers (one
115 115 per parameter)::
116 116
117 117 In [1]: alias parts echo first %s second %s
118 118 In [2]: %parts A B
119 119 first A second B
120 120 In [3]: %parts A
121 121 Incorrect number of arguments: 2 expected.
122 122 parts is an alias to: 'echo first %s second %s'
123 123
124 124 Note that %l and %s are mutually exclusive. You can only use one or
125 125 the other in your aliases.
126 126
127 127 Aliases expand Python variables just like system calls using ! or !!
128 128 do: all expressions prefixed with '$' get expanded. For details of
129 129 the semantic rules, see PEP-215:
130 https://www.python.org/dev/peps/pep-0215/. This is the library used by
130 https://peps.python.org/pep-0215/. This is the library used by
131 131 IPython for variable expansion. If you want to access a true shell
132 132 variable, an extra $ is necessary to prevent its expansion by
133 133 IPython::
134 134
135 135 In [6]: alias show echo
136 136 In [7]: PATH='A Python string'
137 137 In [8]: show $PATH
138 138 A Python string
139 139 In [9]: show $$PATH
140 140 /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:...
141 141
142 142 You can use the alias facility to access all of $PATH. See the %rehashx
143 143 function, which automatically creates aliases for the contents of your
144 144 $PATH.
145 145
146 146 If called with no parameters, %alias prints the current alias table
147 147 for your system. For posix systems, the default aliases are 'cat',
148 148 'cp', 'mv', 'rm', 'rmdir', and 'mkdir', and other platform-specific
149 149 aliases are added. For windows-based systems, the default aliases are
150 150 'copy', 'ddir', 'echo', 'ls', 'ldir', 'mkdir', 'ren', and 'rmdir'.
151 151
152 152 You can see the definition of alias by adding a question mark in the
153 153 end::
154 154
155 155 In [1]: cat?
156 156 Repr: <alias cat for 'cat'>"""
157 157
158 158 par = parameter_s.strip()
159 159 if not par:
160 160 aliases = sorted(self.shell.alias_manager.aliases)
161 161 # stored = self.shell.db.get('stored_aliases', {} )
162 162 # for k, v in stored:
163 163 # atab.append(k, v[0])
164 164
165 165 print("Total number of aliases:", len(aliases))
166 166 sys.stdout.flush()
167 167 return aliases
168 168
169 169 # Now try to define a new one
170 170 try:
171 171 alias,cmd = par.split(None, 1)
172 172 except TypeError:
173 173 print(oinspect.getdoc(self.alias))
174 174 return
175 175
176 176 try:
177 177 self.shell.alias_manager.define_alias(alias, cmd)
178 178 except AliasError as e:
179 179 print(e)
180 180 # end magic_alias
181 181
182 182 @line_magic
183 183 def unalias(self, parameter_s=''):
184 184 """Remove an alias"""
185 185
186 186 aname = parameter_s.strip()
187 187 try:
188 188 self.shell.alias_manager.undefine_alias(aname)
189 189 except ValueError as e:
190 190 print(e)
191 191 return
192 192
193 193 stored = self.shell.db.get('stored_aliases', {} )
194 194 if aname in stored:
195 195 print("Removing %stored alias",aname)
196 196 del stored[aname]
197 197 self.shell.db['stored_aliases'] = stored
198 198
199 199 @line_magic
200 200 def rehashx(self, parameter_s=''):
201 201 """Update the alias table with all executable files in $PATH.
202 202
203 203 rehashx explicitly checks that every entry in $PATH is a file
204 204 with execute access (os.X_OK).
205 205
206 206 Under Windows, it checks executability as a match against a
207 207 '|'-separated string of extensions, stored in the IPython config
208 208 variable win_exec_ext. This defaults to 'exe|com|bat'.
209 209
210 210 This function also resets the root module cache of module completer,
211 211 used on slow filesystems.
212 212 """
213 213 from IPython.core.alias import InvalidAliasError
214 214
215 215 # for the benefit of module completer in ipy_completers.py
216 216 del self.shell.db['rootmodules_cache']
217 217
218 218 path = [os.path.abspath(os.path.expanduser(p)) for p in
219 219 os.environ.get('PATH','').split(os.pathsep)]
220 220
221 221 syscmdlist = []
222 222 savedir = os.getcwd()
223 223
224 224 # Now walk the paths looking for executables to alias.
225 225 try:
226 226 # write the whole loop for posix/Windows so we don't have an if in
227 227 # the innermost part
228 228 if self.is_posix:
229 229 for pdir in path:
230 230 try:
231 231 os.chdir(pdir)
232 232 except OSError:
233 233 continue
234 234
235 235 # for python 3.6+ rewrite to: with os.scandir(pdir) as dirlist:
236 236 dirlist = os.scandir(path=pdir)
237 237 for ff in dirlist:
238 238 if self.isexec(ff):
239 239 fname = ff.name
240 240 try:
241 241 # Removes dots from the name since ipython
242 242 # will assume names with dots to be python.
243 243 if not self.shell.alias_manager.is_alias(fname):
244 244 self.shell.alias_manager.define_alias(
245 245 fname.replace('.',''), fname)
246 246 except InvalidAliasError:
247 247 pass
248 248 else:
249 249 syscmdlist.append(fname)
250 250 else:
251 251 no_alias = Alias.blacklist
252 252 for pdir in path:
253 253 try:
254 254 os.chdir(pdir)
255 255 except OSError:
256 256 continue
257 257
258 258 # for python 3.6+ rewrite to: with os.scandir(pdir) as dirlist:
259 259 dirlist = os.scandir(pdir)
260 260 for ff in dirlist:
261 261 fname = ff.name
262 262 base, ext = os.path.splitext(fname)
263 263 if self.isexec(ff) and base.lower() not in no_alias:
264 264 if ext.lower() == '.exe':
265 265 fname = base
266 266 try:
267 267 # Removes dots from the name since ipython
268 268 # will assume names with dots to be python.
269 269 self.shell.alias_manager.define_alias(
270 270 base.lower().replace('.',''), fname)
271 271 except InvalidAliasError:
272 272 pass
273 273 syscmdlist.append(fname)
274 274
275 275 self.shell.db['syscmdlist'] = syscmdlist
276 276 finally:
277 277 os.chdir(savedir)
278 278
279 279 @skip_doctest
280 280 @line_magic
281 281 def pwd(self, parameter_s=''):
282 282 """Return the current working directory path.
283 283
284 284 Examples
285 285 --------
286 286 ::
287 287
288 288 In [9]: pwd
289 289 Out[9]: '/home/tsuser/sprint/ipython'
290 290 """
291 291 try:
292 292 return os.getcwd()
293 293 except FileNotFoundError as e:
294 294 raise UsageError("CWD no longer exists - please use %cd to change directory.") from e
295 295
296 296 @skip_doctest
297 297 @line_magic
298 298 def cd(self, parameter_s=''):
299 299 """Change the current working directory.
300 300
301 301 This command automatically maintains an internal list of directories
302 302 you visit during your IPython session, in the variable ``_dh``. The
303 303 command :magic:`%dhist` shows this history nicely formatted. You can
304 304 also do ``cd -<tab>`` to see directory history conveniently.
305 305 Usage:
306 306
307 307 - ``cd 'dir'``: changes to directory 'dir'.
308 308 - ``cd -``: changes to the last visited directory.
309 309 - ``cd -<n>``: changes to the n-th directory in the directory history.
310 310 - ``cd --foo``: change to directory that matches 'foo' in history
311 311 - ``cd -b <bookmark_name>``: jump to a bookmark set by %bookmark
312 312 - Hitting a tab key after ``cd -b`` allows you to tab-complete
313 313 bookmark names.
314 314
315 315 .. note::
316 316 ``cd <bookmark_name>`` is enough if there is no directory
317 317 ``<bookmark_name>``, but a bookmark with the name exists.
318 318
319 319 Options:
320 320
321 321 -q Be quiet. Do not print the working directory after the
322 322 cd command is executed. By default IPython's cd
323 323 command does print this directory, since the default
324 324 prompts do not display path information.
325 325
326 326 .. note::
327 327 Note that ``!cd`` doesn't work for this purpose because the shell
328 328 where ``!command`` runs is immediately discarded after executing
329 329 'command'.
330 330
331 331 Examples
332 332 --------
333 333 ::
334 334
335 335 In [10]: cd parent/child
336 336 /home/tsuser/parent/child
337 337 """
338 338
339 339 try:
340 340 oldcwd = os.getcwd()
341 341 except FileNotFoundError:
342 342 # Happens if the CWD has been deleted.
343 343 oldcwd = None
344 344
345 345 numcd = re.match(r'(-)(\d+)$',parameter_s)
346 346 # jump in directory history by number
347 347 if numcd:
348 348 nn = int(numcd.group(2))
349 349 try:
350 350 ps = self.shell.user_ns['_dh'][nn]
351 351 except IndexError:
352 352 print('The requested directory does not exist in history.')
353 353 return
354 354 else:
355 355 opts = {}
356 356 elif parameter_s.startswith('--'):
357 357 ps = None
358 358 fallback = None
359 359 pat = parameter_s[2:]
360 360 dh = self.shell.user_ns['_dh']
361 361 # first search only by basename (last component)
362 362 for ent in reversed(dh):
363 363 if pat in os.path.basename(ent) and os.path.isdir(ent):
364 364 ps = ent
365 365 break
366 366
367 367 if fallback is None and pat in ent and os.path.isdir(ent):
368 368 fallback = ent
369 369
370 370 # if we have no last part match, pick the first full path match
371 371 if ps is None:
372 372 ps = fallback
373 373
374 374 if ps is None:
375 375 print("No matching entry in directory history")
376 376 return
377 377 else:
378 378 opts = {}
379 379
380 380
381 381 else:
382 382 opts, ps = self.parse_options(parameter_s, 'qb', mode='string')
383 383 # jump to previous
384 384 if ps == '-':
385 385 try:
386 386 ps = self.shell.user_ns['_dh'][-2]
387 387 except IndexError as e:
388 388 raise UsageError('%cd -: No previous directory to change to.') from e
389 389 # jump to bookmark if needed
390 390 else:
391 391 if not os.path.isdir(ps) or 'b' in opts:
392 392 bkms = self.shell.db.get('bookmarks', {})
393 393
394 394 if ps in bkms:
395 395 target = bkms[ps]
396 396 print('(bookmark:%s) -> %s' % (ps, target))
397 397 ps = target
398 398 else:
399 399 if 'b' in opts:
400 400 raise UsageError("Bookmark '%s' not found. "
401 401 "Use '%%bookmark -l' to see your bookmarks." % ps)
402 402
403 403 # at this point ps should point to the target dir
404 404 if ps:
405 405 try:
406 406 os.chdir(os.path.expanduser(ps))
407 407 if hasattr(self.shell, 'term_title') and self.shell.term_title:
408 408 set_term_title(self.shell.term_title_format.format(cwd=abbrev_cwd()))
409 409 except OSError:
410 410 print(sys.exc_info()[1])
411 411 else:
412 412 cwd = os.getcwd()
413 413 dhist = self.shell.user_ns['_dh']
414 414 if oldcwd != cwd:
415 415 dhist.append(cwd)
416 416 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
417 417
418 418 else:
419 419 os.chdir(self.shell.home_dir)
420 420 if hasattr(self.shell, 'term_title') and self.shell.term_title:
421 421 set_term_title(self.shell.term_title_format.format(cwd="~"))
422 422 cwd = os.getcwd()
423 423 dhist = self.shell.user_ns['_dh']
424 424
425 425 if oldcwd != cwd:
426 426 dhist.append(cwd)
427 427 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
428 428 if not 'q' in opts and not self.cd_force_quiet and self.shell.user_ns['_dh']:
429 429 print(self.shell.user_ns['_dh'][-1])
430 430
431 431 @line_magic
432 432 def env(self, parameter_s=''):
433 433 """Get, set, or list environment variables.
434 434
435 435 Usage:\\
436 436
437 437 :``%env``: lists all environment variables/values
438 438 :``%env var``: get value for var
439 439 :``%env var val``: set value for var
440 440 :``%env var=val``: set value for var
441 441 :``%env var=$val``: set value for var, using python expansion if possible
442 442 """
443 443 if parameter_s.strip():
444 444 split = '=' if '=' in parameter_s else ' '
445 445 bits = parameter_s.split(split)
446 446 if len(bits) == 1:
447 447 key = parameter_s.strip()
448 448 if key in os.environ:
449 449 return os.environ[key]
450 450 else:
451 451 err = "Environment does not have key: {0}".format(key)
452 452 raise UsageError(err)
453 453 if len(bits) > 1:
454 454 return self.set_env(parameter_s)
455 455 env = dict(os.environ)
456 456 # hide likely secrets when printing the whole environment
457 457 for key in list(env):
458 458 if any(s in key.lower() for s in ('key', 'token', 'secret')):
459 459 env[key] = '<hidden>'
460 460
461 461 return env
462 462
463 463 @line_magic
464 464 def set_env(self, parameter_s):
465 465 """Set environment variables. Assumptions are that either "val" is a
466 466 name in the user namespace, or val is something that evaluates to a
467 467 string.
468 468
469 469 Usage:\\
470 470 %set_env var val: set value for var
471 471 %set_env var=val: set value for var
472 472 %set_env var=$val: set value for var, using python expansion if possible
473 473 """
474 474 split = '=' if '=' in parameter_s else ' '
475 475 bits = parameter_s.split(split, 1)
476 476 if not parameter_s.strip() or len(bits)<2:
477 477 raise UsageError("usage is 'set_env var=val'")
478 478 var = bits[0].strip()
479 479 val = bits[1].strip()
480 480 if re.match(r'.*\s.*', var):
481 481 # an environment variable with whitespace is almost certainly
482 482 # not what the user intended. what's more likely is the wrong
483 483 # split was chosen, ie for "set_env cmd_args A=B", we chose
484 484 # '=' for the split and should have chosen ' '. to get around
485 485 # this, users should just assign directly to os.environ or use
486 486 # standard magic {var} expansion.
487 487 err = "refusing to set env var with whitespace: '{0}'"
488 488 err = err.format(val)
489 489 raise UsageError(err)
490 490 os.environ[var] = val
491 491 print('env: {0}={1}'.format(var,val))
492 492
493 493 @line_magic
494 494 def pushd(self, parameter_s=''):
495 495 """Place the current dir on stack and change directory.
496 496
497 497 Usage:\\
498 498 %pushd ['dirname']
499 499 """
500 500
501 501 dir_s = self.shell.dir_stack
502 502 tgt = os.path.expanduser(parameter_s)
503 503 cwd = os.getcwd().replace(self.shell.home_dir,'~')
504 504 if tgt:
505 505 self.cd(parameter_s)
506 506 dir_s.insert(0,cwd)
507 507 return self.shell.run_line_magic('dirs', '')
508 508
509 509 @line_magic
510 510 def popd(self, parameter_s=''):
511 511 """Change to directory popped off the top of the stack.
512 512 """
513 513 if not self.shell.dir_stack:
514 514 raise UsageError("%popd on empty stack")
515 515 top = self.shell.dir_stack.pop(0)
516 516 self.cd(top)
517 517 print("popd ->",top)
518 518
519 519 @line_magic
520 520 def dirs(self, parameter_s=''):
521 521 """Return the current directory stack."""
522 522
523 523 return self.shell.dir_stack
524 524
525 525 @line_magic
526 526 def dhist(self, parameter_s=''):
527 527 """Print your history of visited directories.
528 528
529 529 %dhist -> print full history\\
530 530 %dhist n -> print last n entries only\\
531 531 %dhist n1 n2 -> print entries between n1 and n2 (n2 not included)\\
532 532
533 533 This history is automatically maintained by the %cd command, and
534 534 always available as the global list variable _dh. You can use %cd -<n>
535 535 to go to directory number <n>.
536 536
537 537 Note that most of time, you should view directory history by entering
538 538 cd -<TAB>.
539 539
540 540 """
541 541
542 542 dh = self.shell.user_ns['_dh']
543 543 if parameter_s:
544 544 try:
545 545 args = map(int,parameter_s.split())
546 546 except:
547 547 self.arg_err(self.dhist)
548 548 return
549 549 if len(args) == 1:
550 550 ini,fin = max(len(dh)-(args[0]),0),len(dh)
551 551 elif len(args) == 2:
552 552 ini,fin = args
553 553 fin = min(fin, len(dh))
554 554 else:
555 555 self.arg_err(self.dhist)
556 556 return
557 557 else:
558 558 ini,fin = 0,len(dh)
559 559 print('Directory history (kept in _dh)')
560 560 for i in range(ini, fin):
561 561 print("%d: %s" % (i, dh[i]))
562 562
563 563 @skip_doctest
564 564 @line_magic
565 565 def sc(self, parameter_s=''):
566 566 """Shell capture - run shell command and capture output (DEPRECATED use !).
567 567
568 568 DEPRECATED. Suboptimal, retained for backwards compatibility.
569 569
570 570 You should use the form 'var = !command' instead. Example:
571 571
572 572 "%sc -l myfiles = ls ~" should now be written as
573 573
574 574 "myfiles = !ls ~"
575 575
576 576 myfiles.s, myfiles.l and myfiles.n still apply as documented
577 577 below.
578 578
579 579 --
580 580 %sc [options] varname=command
581 581
582 582 IPython will run the given command using commands.getoutput(), and
583 583 will then update the user's interactive namespace with a variable
584 584 called varname, containing the value of the call. Your command can
585 585 contain shell wildcards, pipes, etc.
586 586
587 587 The '=' sign in the syntax is mandatory, and the variable name you
588 588 supply must follow Python's standard conventions for valid names.
589 589
590 590 (A special format without variable name exists for internal use)
591 591
592 592 Options:
593 593
594 594 -l: list output. Split the output on newlines into a list before
595 595 assigning it to the given variable. By default the output is stored
596 596 as a single string.
597 597
598 598 -v: verbose. Print the contents of the variable.
599 599
600 600 In most cases you should not need to split as a list, because the
601 601 returned value is a special type of string which can automatically
602 602 provide its contents either as a list (split on newlines) or as a
603 603 space-separated string. These are convenient, respectively, either
604 604 for sequential processing or to be passed to a shell command.
605 605
606 606 For example::
607 607
608 608 # Capture into variable a
609 609 In [1]: sc a=ls *py
610 610
611 611 # a is a string with embedded newlines
612 612 In [2]: a
613 613 Out[2]: 'setup.py\\nwin32_manual_post_install.py'
614 614
615 615 # which can be seen as a list:
616 616 In [3]: a.l
617 617 Out[3]: ['setup.py', 'win32_manual_post_install.py']
618 618
619 619 # or as a whitespace-separated string:
620 620 In [4]: a.s
621 621 Out[4]: 'setup.py win32_manual_post_install.py'
622 622
623 623 # a.s is useful to pass as a single command line:
624 624 In [5]: !wc -l $a.s
625 625 146 setup.py
626 626 130 win32_manual_post_install.py
627 627 276 total
628 628
629 629 # while the list form is useful to loop over:
630 630 In [6]: for f in a.l:
631 631 ...: !wc -l $f
632 632 ...:
633 633 146 setup.py
634 634 130 win32_manual_post_install.py
635 635
636 636 Similarly, the lists returned by the -l option are also special, in
637 637 the sense that you can equally invoke the .s attribute on them to
638 638 automatically get a whitespace-separated string from their contents::
639 639
640 640 In [7]: sc -l b=ls *py
641 641
642 642 In [8]: b
643 643 Out[8]: ['setup.py', 'win32_manual_post_install.py']
644 644
645 645 In [9]: b.s
646 646 Out[9]: 'setup.py win32_manual_post_install.py'
647 647
648 648 In summary, both the lists and strings used for output capture have
649 649 the following special attributes::
650 650
651 651 .l (or .list) : value as list.
652 652 .n (or .nlstr): value as newline-separated string.
653 653 .s (or .spstr): value as space-separated string.
654 654 """
655 655
656 656 opts,args = self.parse_options(parameter_s, 'lv')
657 657 # Try to get a variable name and command to run
658 658 try:
659 659 # the variable name must be obtained from the parse_options
660 660 # output, which uses shlex.split to strip options out.
661 661 var,_ = args.split('=', 1)
662 662 var = var.strip()
663 663 # But the command has to be extracted from the original input
664 664 # parameter_s, not on what parse_options returns, to avoid the
665 665 # quote stripping which shlex.split performs on it.
666 666 _,cmd = parameter_s.split('=', 1)
667 667 except ValueError:
668 668 var,cmd = '',''
669 669 # If all looks ok, proceed
670 670 split = 'l' in opts
671 671 out = self.shell.getoutput(cmd, split=split)
672 672 if 'v' in opts:
673 673 print('%s ==\n%s' % (var, pformat(out)))
674 674 if var:
675 675 self.shell.user_ns.update({var:out})
676 676 else:
677 677 return out
678 678
679 679 @line_cell_magic
680 680 def sx(self, line='', cell=None):
681 681 """Shell execute - run shell command and capture output (!! is short-hand).
682 682
683 683 %sx command
684 684
685 685 IPython will run the given command using commands.getoutput(), and
686 686 return the result formatted as a list (split on '\\n'). Since the
687 687 output is _returned_, it will be stored in ipython's regular output
688 688 cache Out[N] and in the '_N' automatic variables.
689 689
690 690 Notes:
691 691
692 692 1) If an input line begins with '!!', then %sx is automatically
693 693 invoked. That is, while::
694 694
695 695 !ls
696 696
697 697 causes ipython to simply issue system('ls'), typing::
698 698
699 699 !!ls
700 700
701 701 is a shorthand equivalent to::
702 702
703 703 %sx ls
704 704
705 705 2) %sx differs from %sc in that %sx automatically splits into a list,
706 706 like '%sc -l'. The reason for this is to make it as easy as possible
707 707 to process line-oriented shell output via further python commands.
708 708 %sc is meant to provide much finer control, but requires more
709 709 typing.
710 710
711 711 3) Just like %sc -l, this is a list with special attributes:
712 712 ::
713 713
714 714 .l (or .list) : value as list.
715 715 .n (or .nlstr): value as newline-separated string.
716 716 .s (or .spstr): value as whitespace-separated string.
717 717
718 718 This is very useful when trying to use such lists as arguments to
719 719 system commands."""
720 720
721 721 if cell is None:
722 722 # line magic
723 723 return self.shell.getoutput(line)
724 724 else:
725 725 opts,args = self.parse_options(line, '', 'out=')
726 726 output = self.shell.getoutput(cell)
727 727 out_name = opts.get('out', opts.get('o'))
728 728 if out_name:
729 729 self.shell.user_ns[out_name] = output
730 730 else:
731 731 return output
732 732
733 733 system = line_cell_magic('system')(sx)
734 734 bang = cell_magic('!')(sx)
735 735
736 736 @line_magic
737 737 def bookmark(self, parameter_s=''):
738 738 """Manage IPython's bookmark system.
739 739
740 740 %bookmark <name> - set bookmark to current dir
741 741 %bookmark <name> <dir> - set bookmark to <dir>
742 742 %bookmark -l - list all bookmarks
743 743 %bookmark -d <name> - remove bookmark
744 744 %bookmark -r - remove all bookmarks
745 745
746 746 You can later on access a bookmarked folder with::
747 747
748 748 %cd -b <name>
749 749
750 750 or simply '%cd <name>' if there is no directory called <name> AND
751 751 there is such a bookmark defined.
752 752
753 753 Your bookmarks persist through IPython sessions, but they are
754 754 associated with each profile."""
755 755
756 756 opts,args = self.parse_options(parameter_s,'drl',mode='list')
757 757 if len(args) > 2:
758 758 raise UsageError("%bookmark: too many arguments")
759 759
760 760 bkms = self.shell.db.get('bookmarks',{})
761 761
762 762 if 'd' in opts:
763 763 try:
764 764 todel = args[0]
765 765 except IndexError as e:
766 766 raise UsageError(
767 767 "%bookmark -d: must provide a bookmark to delete") from e
768 768 else:
769 769 try:
770 770 del bkms[todel]
771 771 except KeyError as e:
772 772 raise UsageError(
773 773 "%%bookmark -d: Can't delete bookmark '%s'" % todel) from e
774 774
775 775 elif 'r' in opts:
776 776 bkms = {}
777 777 elif 'l' in opts:
778 778 bks = sorted(bkms)
779 779 if bks:
780 780 size = max(map(len, bks))
781 781 else:
782 782 size = 0
783 783 fmt = '%-'+str(size)+'s -> %s'
784 784 print('Current bookmarks:')
785 785 for bk in bks:
786 786 print(fmt % (bk, bkms[bk]))
787 787 else:
788 788 if not args:
789 789 raise UsageError("%bookmark: You must specify the bookmark name")
790 790 elif len(args)==1:
791 791 bkms[args[0]] = os.getcwd()
792 792 elif len(args)==2:
793 793 bkms[args[0]] = args[1]
794 794 self.shell.db['bookmarks'] = bkms
795 795
796 796 @line_magic
797 797 def pycat(self, parameter_s=''):
798 798 """Show a syntax-highlighted file through a pager.
799 799
800 800 This magic is similar to the cat utility, but it will assume the file
801 801 to be Python source and will show it with syntax highlighting.
802 802
803 803 This magic command can either take a local filename, an url,
804 804 an history range (see %history) or a macro as argument.
805 805
806 806 If no parameter is given, prints out history of current session up to
807 807 this point. ::
808 808
809 809 %pycat myscript.py
810 810 %pycat 7-27
811 811 %pycat myMacro
812 812 %pycat http://www.example.com/myscript.py
813 813 """
814 814 try:
815 815 cont = self.shell.find_user_code(parameter_s, skip_encoding_cookie=False)
816 816 except (ValueError, IOError):
817 817 print("Error: no such file, variable, URL, history range or macro")
818 818 return
819 819
820 820 page.page(self.shell.pycolorize(source_to_unicode(cont)))
821 821
822 822 @magic_arguments.magic_arguments()
823 823 @magic_arguments.argument(
824 824 '-a', '--append', action='store_true', default=False,
825 825 help='Append contents of the cell to an existing file. '
826 826 'The file will be created if it does not exist.'
827 827 )
828 828 @magic_arguments.argument(
829 829 'filename', type=str,
830 830 help='file to write'
831 831 )
832 832 @cell_magic
833 833 def writefile(self, line, cell):
834 834 """Write the contents of the cell to a file.
835 835
836 836 The file will be overwritten unless the -a (--append) flag is specified.
837 837 """
838 838 args = magic_arguments.parse_argstring(self.writefile, line)
839 839 if re.match(r'^(\'.*\')|(".*")$', args.filename):
840 840 filename = os.path.expanduser(args.filename[1:-1])
841 841 else:
842 842 filename = os.path.expanduser(args.filename)
843 843
844 844 if os.path.exists(filename):
845 845 if args.append:
846 846 print("Appending to %s" % filename)
847 847 else:
848 848 print("Overwriting %s" % filename)
849 849 else:
850 850 print("Writing %s" % filename)
851 851
852 852 mode = 'a' if args.append else 'w'
853 853 with io.open(filename, mode, encoding='utf-8') as f:
854 854 f.write(cell)
@@ -1,101 +1,97 b''
1 1 .. This (-*- rst -*-) format file contains commonly used link targets
2 2 and name substitutions. It may be included in many files,
3 3 therefore it should only contain link targets and name
4 4 substitutions. Try grepping for "^\.\. _" to find plausible
5 5 candidates for this list.
6 6
7 7 NOTE: this file must have an extension *opposite* to that of the main reST
8 8 files in the manuals, so that we can include it with ".. include::"
9 9 directives, but without triggering warnings from Sphinx for not being listed
10 10 in any toctree. Since IPython uses .txt for the main files, this one will
11 11 use .rst.
12 12
13 13 NOTE: reST targets are
14 14 __not_case_sensitive__, so only one target definition is needed for
15 15 ipython, IPython, etc.
16 16
17 17 NOTE: Some of these were taken from the nipy links compendium.
18 18
19 19 .. Main IPython links
20 20 .. _ipython: https://ipython.org
21 21 .. _`ipython manual`: https://ipython.org/documentation.html
22 22 .. _ipython_github: http://github.com/ipython/ipython/
23 .. _ipython_github_repo: http://github.com/ipython/ipython/
24 .. _ipython_downloads: https://ipython.org/download.html
25 .. _ipython_pypi: http://pypi.python.org/pypi/ipython
26 23 .. _nbviewer: http://nbviewer.ipython.org
27 24
28 25 .. _ZeroMQ: http://zeromq.org
29 26
30 27 .. Documentation tools and related links
31 28 .. _graphviz: http://www.graphviz.org
32 29 .. _Sphinx: http://sphinx.pocoo.org
33 30 .. _`Sphinx reST`: http://sphinx.pocoo.org/rest.html
34 31 .. _sampledoc: http://matplotlib.org/sampledoc
35 32 .. _reST: http://docutils.sourceforge.net/rst.html
36 33 .. _docutils: http://docutils.sourceforge.net
37 34 .. _lyx: http://www.lyx.org
38 .. _pep8: http://www.python.org/dev/peps/pep-0008
39 .. _numpy_coding_guide: https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
35 .. _pep8: https://peps.python.org/pep-0008/
40 36
41 37 .. Licenses
42 38 .. _GPL: http://www.gnu.org/licenses/gpl.html
43 39 .. _BSD: http://www.opensource.org/licenses/bsd-license.php
44 40 .. _LGPL: http://www.gnu.org/copyleft/lesser.html
45 41
46 42 .. Other python projects
47 43 .. _numpy: http://numpy.scipy.org
48 44 .. _scipy: http://www.scipy.org
49 45 .. _scipy_conference: http://conference.scipy.org
50 46 .. _matplotlib: http://matplotlib.org
51 47 .. _pythonxy: https://code.google.com/p/pythonxy/
52 48 .. _ETS: http://code.enthought.com/projects/tool-suite.php
53 49 .. _EPD: http://www.enthought.com/products/epd.php
54 50 .. _python: http://www.python.org
55 51 .. _mayavi: http://code.enthought.com/projects/mayavi
56 52 .. _sympy: http://code.google.com/p/sympy
57 53 .. _sage: http://sagemath.org
58 54 .. _pydy: http://code.google.com/p/pydy
59 55 .. _vpython: http://vpython.org
60 56 .. _cython: http://cython.org
61 57 .. _software carpentry: http://software-carpentry.org
62 58
63 59 .. Not so python scientific computing tools
64 60 .. _matlab: http://www.mathworks.com
65 61 .. _VTK: http://vtk.org
66 62
67 63 .. Other organizations
68 64 .. _enthought: http://www.enthought.com
69 65 .. _kitware: http://www.kitware.com
70 66 .. _netlib: http://netlib.org
71 67
72 68 .. Other tools and projects
73 69 .. _indefero: http://www.indefero.net
74 70 .. _git: http://git-scm.com
75 71 .. _github: http://github.com
76 72 .. _Markdown: http://daringfireball.net/projects/markdown/syntax
77 73
78 74 .. _Running Code in the IPython Notebook: notebook_p1_
79 75 .. _notebook_p1: http://nbviewer.ipython.org/urls/raw.github.com/ipython/ipython/1.x/examples/notebooks/Part%25201%2520-%2520Running%2520Code.ipynb
80 76
81 77 .. _Basic Output: notebook_p2_
82 78 .. _notebook_p2: http://nbviewer.ipython.org/urls/raw.github.com/ipython/ipython/1.x/examples/notebooks/Part%202%20-%20Basic%20Output.ipynb
83 79
84 80 .. _Plotting with Matplotlib: notebook_p3_
85 81 .. _notebook_p3: http://nbviewer.ipython.org/urls/raw.github.com/ipython/ipython/1.x/examples/notebooks/Part%203%20-%20Plotting%20with%20Matplotlib.ipynb
86 82
87 83 .. _Markdown Cells: notebook_p4_
88 84 .. _notebook_p4: http://nbviewer.ipython.org/urls/raw.github.com/ipython/ipython/1.x/examples/notebooks/Part%204%20-%20Markdown%20Cells.ipynb
89 85
90 86 .. _Rich Display System: notebook_p5_
91 87 .. _notebook_p5: http://nbviewer.ipython.org/urls/raw.github.com/ipython/ipython/1.x/examples/notebooks/Part%205%20-%20Rich%20Display%20System.ipynb
92 88
93 89 .. _notebook_custom_display: http://nbviewer.ipython.org/urls/raw.github.com/ipython/ipython/1.x/examples/notebooks/Custom%20Display%20Logic.ipynb
94 90
95 91 .. _Frontend/Kernel Model: notebook_two_proc_
96 92 .. _notebook_two_proc: http://nbviewer.ipython.org/urls/raw.github.com/ipython/ipython/1.x/examples/notebooks/Frontend-Kernel%20Model.ipynb
97 93
98 94 .. _Cell magics: notebook_cell_magics_
99 95 .. _notebook_cell_magics: http://nbviewer.ipython.org/urls/raw.github.com/ipython/ipython/1.x/examples/notebooks/Cell%20Magics.ipynb
100 96
101 97
@@ -1,364 +1,364 b''
1 1 ============
2 2 6.x Series
3 3 ============
4 4
5 5 .. _whatsnew650:
6 6
7 7 IPython 6.5.0
8 8 =============
9 9
10 10 Miscellaneous bug fixes and compatibility with Python 3.7.
11 11
12 12 * Autocompletion fix for modules with out ``__init__.py`` :ghpull:`11227`
13 13 * update the ``%pastebin`` magic to use ``dpaste.com`` instead og GitHub Gist
14 14 which now requires authentication :ghpull:`11182`
15 15 * Fix crash with multiprocessing :ghpull:`11185`
16 16
17 17 .. _whatsnew640:
18 18
19 19 IPython 6.4.0
20 20 =============
21 21
22 22 Everything new in :ref:`IPython 5.7 <whatsnew570>`
23 23
24 24 * Fix display object not emitting metadata :ghpull:`11106`
25 25 * Comments failing Jedi test :ghpull:`11110`
26 26
27 27
28 28 .. _whatsnew631:
29 29
30 30 IPython 6.3.1
31 31 =============
32 32
33 33 This is a bugfix release to switch the default completions back to IPython's
34 34 own completion machinery. We discovered some problems with the completions
35 35 from Jedi, including completing column names on pandas data frames.
36 36
37 37 You can switch the completions source with the config option
38 38 :configtrait:`Completer.use_jedi`.
39 39
40 40 .. _whatsnew630:
41 41
42 42 IPython 6.3
43 43 ===========
44 44
45 45 IPython 6.3 contains all the bug fixes and features in
46 46 :ref:`IPython 5.6 <whatsnew560>`. In addition:
47 47
48 48 * A new display class :class:`IPython.display.Code` can be used to display
49 49 syntax highlighted code in a notebook (:ghpull:`10978`).
50 50 * The :cellmagic:`html` magic now takes a ``--isolated`` option to put the
51 51 content in an iframe (:ghpull:`10962`).
52 52 * The code to find completions using the Jedi library has had various
53 53 adjustments. This is still a work in progress, but we hope this version has
54 54 fewer annoyances (:ghpull:`10956`, :ghpull:`10969`, :ghpull:`10999`,
55 55 :ghpull:`11035`, :ghpull:`11063`, :ghpull:`11065`).
56 56 * The *post* event callbacks are now always called, even when the execution failed
57 57 (for example because of a ``SyntaxError``).
58 58 * The execution info and result objects are now made available in the
59 59 corresponding *pre* or *post* ``*_run_cell`` :doc:`event callbacks </config/callbacks>`
60 60 in a backward compatible manner (:ghissue:`10774` and :ghpull:`10795`).
61 61 * Performance with very long code cells (hundreds of lines) is greatly improved
62 62 (:ghpull:`10898`). Further improvements are planned for IPython 7.
63 63
64 64 You can see all `pull requests for the 6.3 milestone
65 65 <https://github.com/ipython/ipython/pulls?utf8=%E2%9C%93&q=is%3Apr+milestone%3A6.3+is%3Aclosed>`__.
66 66
67 67 .. _whatsnew620:
68 68
69 69 IPython 6.2
70 70 ===========
71 71
72 72 IPython 6.2 contains all the bugs fixes and features :ref:`available in IPython 5.5 <whatsnew550>`,
73 73 like built in progress bar support, and system-wide configuration
74 74
75 75 The following features are specific to IPython 6.2:
76 76
77 77 Function signature in completions
78 78 ---------------------------------
79 79
80 80 Terminal IPython will now show the signature of the function while completing.
81 81 Only the currently highlighted function will show its signature on the line
82 82 below the completer by default. This functionality is recent, so it might be
83 83 limited; we welcome bug reports and requests for enhancements. :ghpull:`10507`
84 84
85 85 Assignments return values
86 86 -------------------------
87 87
88 88 IPython can now trigger the display hook on the last assignment of cells.
89 89 Up until 6.2 the following code wouldn't show the value of the assigned
90 90 variable::
91 91
92 92 In[1]: xyz = "something"
93 93 # nothing shown
94 94
95 95 You would have to actually make it the last statement::
96 96
97 97 In [2]: xyz = "something else"
98 98 ... : xyz
99 99 Out[2]: "something else"
100 100
101 101 With the option ``InteractiveShell.ast_node_interactivity='last_expr_or_assign'``
102 102 you can now do::
103 103
104 104 In [2]: xyz = "something else"
105 105 Out[2]: "something else"
106 106
107 107 This option can be toggled at runtime with the ``%config`` magic, and will
108 108 trigger on assignment ``a = 1``, augmented assignment ``+=``, ``-=``, ``|=`` ...
109 109 as well as type annotated assignments: ``a:int = 2``.
110 110
111 111 See :ghpull:`10598`
112 112
113 113 Recursive Call of ipdb
114 114 ----------------------
115 115
116 116 Advanced users of the debugger can now correctly recursively enter ipdb. This is
117 117 thanks to ``@segevfiner`` on :ghpull:`10721`.
118 118
119 119 .. _whatsnew610:
120 120
121 121 IPython 6.1
122 122 ===========
123 123
124 124 - Quotes in a filename are always escaped during tab-completion on non-Windows.
125 125 :ghpull:`10069`
126 126
127 127 - Variables now shadow magics in autocompletion. See :ghissue:`4877` and :ghpull:`10542`.
128 128
129 129 - Added the ability to add parameters to alias_magic. For example::
130 130
131 131 In [2]: %alias_magic hist history --params "-l 2" --line
132 132 Created `%hist` as an alias for `%history -l 2`.
133 133
134 134 In [3]: hist
135 135 %alias_magic hist history --params "-l 30" --line
136 136 %alias_magic hist history --params "-l 2" --line
137 137
138 138 Previously it was only possible to have an alias attached to a single function,
139 139 and you would have to pass in the given parameters every time::
140 140
141 141 In [4]: %alias_magic hist history --line
142 142 Created `%hist` as an alias for `%history`.
143 143
144 144 In [5]: hist -l 2
145 145 hist
146 146 %alias_magic hist history --line
147 147
148 148 - To suppress log state messages, you can now either use ``%logstart -q``, pass
149 149 ``--LoggingMagics.quiet=True`` on the command line, or set
150 150 ``c.LoggingMagics.quiet=True`` in your configuration file.
151 151
152 152 - An additional flag ``--TerminalInteractiveShell.term_title_format`` is
153 153 introduced to allow the user to control the format of the terminal title. It
154 154 is specified as a python format string, and currently the only variable it
155 155 will format is ``{cwd}``.
156 156
157 157 - ``??``/``%pinfo2`` will now show object docstrings if the source can't be retrieved. :ghpull:`10532`
158 158 - ``IPython.display`` has gained a ``%markdown`` cell magic. :ghpull:`10563`
159 159 - ``%config`` options can now be tab completed. :ghpull:`10555`
160 160 - ``%config`` with no arguments are now unique and sorted. :ghpull:`10548`
161 161 - Completion on keyword arguments does not duplicate ``=`` sign if already present. :ghpull:`10547`
162 162 - ``%run -m <module>`` now ``<module>`` passes extra arguments to ``<module>``. :ghpull:`10546`
163 163 - completer now understand "snake case auto complete": if ``foo_bar_kittens`` is
164 164 a valid completion, I can type ``f_b<tab>`` will complete to it. :ghpull:`10537`
165 165 - tracebacks are better standardized and will compress `/path/to/home` to `~`. :ghpull:`10515`
166 166
167 167 The following changes were also added to IPython 5.4, see :ref:`what's new in IPython 5.4 <whatsnew540>`
168 168 for more detail description:
169 169
170 170 - ``TerminalInteractiveShell`` is configurable and can be configured to
171 171 (re)-use the readline interface.
172 172
173 173 - objects can now define a ``_repr_mimebundle_``
174 174
175 175 - Execution heuristics improve for single line statements
176 176 - ``display()`` can now return a display id to update display areas.
177 177
178 178
179 179 .. _whatsnew600:
180 180
181 181 IPython 6.0
182 182 ===========
183 183
184 184 Released April 19th, 2017
185 185
186 186 IPython 6 features a major improvement in the completion machinery which is now
187 187 capable of completing non-executed code. It is also the first version of IPython
188 188 to stop compatibility with Python 2, which is still supported on the bugfix only
189 189 5.x branch. Read below for a non-exhaustive list of new features.
190 190
191 191 Make sure you have pip > 9.0 before upgrading.
192 192 You should be able to update by using:
193 193
194 194 .. code::
195 195
196 196 pip install ipython --upgrade
197 197
198 198
199 199 .. note::
200 200
201 201 If your pip version is greater than or equal to pip 9.0.1 you will automatically get
202 202 the most recent version of IPython compatible with your system: on Python 2 you
203 203 will get the latest IPython 5.x bugfix, while in Python 3
204 204 you will get the latest 6.x stable version.
205 205
206 206 New completion API and Interface
207 207 --------------------------------
208 208
209 209 The completer Completion API has seen an overhaul, and the new completer has
210 210 plenty of improvements both from the end users of terminal IPython and for
211 211 consumers of the API.
212 212
213 213 This new API is capable of pulling completions from :any:`jedi`, thus allowing
214 214 type inference on non-executed code. If :any:`jedi` is installed, completions like
215 215 the following are now possible without code evaluation:
216 216
217 217 >>> data = ['Number of users', 123_456]
218 218 ... data[0].<tab>
219 219
220 220 That is to say, IPython is now capable of inferring that `data[0]` is a string,
221 221 and will suggest completions like `.capitalize`. The completion power of IPython
222 222 will increase with new Jedi releases, and a number of bug-fixes and more completions
223 223 are already available on the development version of :any:`jedi` if you are curious.
224 224
225 225 With the help of prompt toolkit, types of completions can be shown in the
226 226 completer interface:
227 227
228 228 .. image:: ../_images/jedi_type_inference_60.png
229 229 :alt: Jedi showing ability to do type inference
230 230 :align: center
231 231 :width: 400px
232 232 :target: ../_images/jedi_type_inference_60.png
233 233
234 234 The appearance of the completer is controlled by the
235 235 ``c.TerminalInteractiveShell.display_completions`` option that will show the
236 236 type differently depending on the value among ``'column'``, ``'multicolumn'``
237 237 and ``'readlinelike'``
238 238
239 239 The use of Jedi also fulfills a number of requests and fixes a number of bugs
240 240 like case-insensitive completion and completion after division operator: See
241 241 :ghpull:`10182`.
242 242
243 243 Extra patches and updates will be needed to the :mod:`ipykernel` package for
244 244 this feature to be available to other clients like Jupyter Notebook, Lab,
245 245 Nteract, Hydrogen...
246 246
247 247 The use of Jedi should be barely noticeable on recent machines, but
248 248 can be slower on older ones. To tweak the performance, the amount
249 249 of time given to Jedi to compute type inference can be adjusted with
250 250 ``c.IPCompleter.jedi_compute_type_timeout``. The objects whose type were not
251 251 inferred will be shown as ``<unknown>``. Jedi can also be completely deactivated
252 252 by using the ``c.Completer.use_jedi=False`` option.
253 253
254 254
255 255 The old ``Completer.complete()`` API is waiting deprecation and should be
256 256 replaced replaced by ``Completer.completions()`` in the near future. Feedback on
257 257 the current state of the API and suggestions are welcome.
258 258
259 259 Python 3 only codebase
260 260 ----------------------
261 261
262 262 One of the large challenges in IPython 6.0 has been the adoption of a pure
263 263 Python 3 codebase, which has led to upstream patches in pip,
264 264 pypi and warehouse to make sure Python 2 systems still upgrade to the latest
265 265 compatible Python version.
266 266
267 267 We remind our Python 2 users that IPython 5 is still compatible with Python 2.7,
268 268 still maintained and will get regular releases. Using pip 9+, upgrading IPython will
269 269 automatically upgrade to the latest version compatible with your system.
270 270
271 271 .. warning::
272 272
273 273 If you are on a system using an older version of pip on Python 2, pip may
274 274 still install IPython 6.0 on your system, and IPython will refuse to start.
275 275 You can fix this by upgrading pip, and reinstalling ipython, or forcing pip to
276 276 install an earlier version: ``pip install 'ipython<6'``
277 277
278 278 The ability to use only Python 3 on the code base of IPython brings a number
279 279 of advantages. Most of the newly written code make use of `optional function type
280 annotation <https://www.python.org/dev/peps/pep-0484/>`_ leading to clearer code
280 annotation <https://peps.python.org/pep-0484/>`_ leading to clearer code
281 281 and better documentation.
282 282
283 283 The total size of the repository has also decreased by about 1500 lines (for the
284 284 first time excluding the big split for 4.0). The decrease is potentially
285 285 a bit more for the sour as some documents like this one are append only and
286 286 are about 300 lines long.
287 287
288 288 The removal of the Python2/Python3 shim layer has made the code quite a lot clearer and
289 289 more idiomatic in a number of locations, and much friendlier to work with and
290 290 understand. We hope to further embrace Python 3 capabilities in the next release
291 291 cycle and introduce more of the Python 3 only idioms (yield from, kwarg only,
292 292 general unpacking) in the IPython code base, and see if we can take advantage
293 293 of these to improve user experience with better error messages and
294 294 hints.
295 295
296 296
297 297 Configurable TerminalInteractiveShell, readline interface
298 298 ---------------------------------------------------------
299 299
300 300 IPython gained a new ``c.TerminalIPythonApp.interactive_shell_class`` option
301 301 that allows customizing the class used to start the terminal frontend. This
302 302 should allow a user to use custom interfaces, like reviving the former readline
303 303 interface which is now a separate package not actively maintained by the core
304 304 team. See the project to bring back the readline interface: `rlipython
305 305 <https://github.com/ipython/rlipython>`_.
306 306
307 307 This change will be backported to the IPython 5.x series.
308 308
309 309 Misc improvements
310 310 -----------------
311 311
312 312
313 313 - The :cellmagic:`capture` magic can now capture the result of a cell (from
314 314 an expression on the last line), as well as printed and displayed output.
315 315 :ghpull:`9851`.
316 316
317 317 - Pressing Ctrl-Z in the terminal debugger now suspends IPython, as it already
318 318 does in the main terminal prompt.
319 319
320 320 - Autoreload can now reload ``Enum``. See :ghissue:`10232` and :ghpull:`10316`
321 321
322 322 - IPython.display has gained a :any:`GeoJSON <IPython.display.GeoJSON>` object.
323 323 :ghpull:`10288` and :ghpull:`10253`
324 324
325 325 Functions Deprecated in 6.x Development cycle
326 326 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
327 327
328 328 - Loading extensions from ``ipython_extension_dir`` prints a warning that this
329 329 location is pending deprecation. This should only affect users still having
330 330 extensions installed with ``%install_ext`` which has been deprecated since
331 331 IPython 4.0, and removed in 5.0. Extensions still present in
332 332 ``ipython_extension_dir`` may shadow more recently installed versions using
333 333 pip. It is thus recommended to clean ``ipython_extension_dir`` of any
334 334 extension now available as a package.
335 335
336 336
337 337 - ``IPython.utils.warn`` was deprecated in IPython 4.0, and has now been removed.
338 338 instead of ``IPython.utils.warn`` inbuilt :any:`warnings` module is used.
339 339
340 340
341 341 - The function `IPython.core.oinspect.py:call_tip` is unused, was marked as
342 342 deprecated (raising a `DeprecationWarning`) and marked for later removal.
343 343 :ghpull:`10104`
344 344
345 345 Backward incompatible changes
346 346 ------------------------------
347 347
348 348 Functions Removed in 6.x Development cycle
349 349 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
350 350
351 351 The following functions have been removed in the
352 352 development cycle marked for Milestone 6.0.
353 353
354 354 - ``IPython/utils/process.py`` - ``is_cmd_found``
355 355 - ``IPython/utils/process.py`` - ``pycmd2argv``
356 356
357 357 - The `--deep-reload` flag and the corresponding options to inject `dreload` or
358 358 `reload` into the interactive namespace have been removed. You have to
359 359 explicitly import `reload` from `IPython.lib.deepreload` to use it.
360 360
361 361 - The :magic:`profile` used to print the current IPython profile, and which
362 362 was deprecated in IPython 2.0 does now raise a `DeprecationWarning` error when
363 363 used. It is often confused with the :magic:`prun` and the deprecation removal
364 364 should free up the ``profile`` name in future versions.
@@ -1,763 +1,763 b''
1 1 {
2 2 "cells": [
3 3 {
4 4 "cell_type": "markdown",
5 5 "metadata": {},
6 6 "source": [
7 7 "# Importing IPython Notebooks as Modules"
8 8 ]
9 9 },
10 10 {
11 11 "cell_type": "markdown",
12 12 "metadata": {},
13 13 "source": [
14 14 "It is a common problem that people want to import code from IPython Notebooks.\n",
15 15 "This is made difficult by the fact that Notebooks are not plain Python files,\n",
16 16 "and thus cannot be imported by the regular Python machinery.\n",
17 17 "\n",
18 "Fortunately, Python provides some fairly sophisticated [hooks](http://www.python.org/dev/peps/pep-0302/) into the import machinery,\n",
18 "Fortunately, Python provides some fairly sophisticated [hooks](https://peps.python.org/pep-0302/) into the import machinery,\n",
19 19 "so we can actually make IPython notebooks importable without much difficulty,\n",
20 20 "and only using public APIs."
21 21 ]
22 22 },
23 23 {
24 24 "cell_type": "code",
25 25 "execution_count": 1,
26 26 "metadata": {
27 27 "collapsed": false
28 28 },
29 29 "outputs": [],
30 30 "source": [
31 31 "import io, os, sys, types"
32 32 ]
33 33 },
34 34 {
35 35 "cell_type": "code",
36 36 "execution_count": 2,
37 37 "metadata": {
38 38 "collapsed": false
39 39 },
40 40 "outputs": [],
41 41 "source": [
42 42 "import nbformat\n",
43 43 "\n",
44 44 "from IPython import get_ipython\n",
45 45 "from IPython.core.interactiveshell import InteractiveShell"
46 46 ]
47 47 },
48 48 {
49 49 "cell_type": "markdown",
50 50 "metadata": {},
51 51 "source": [
52 52 "Import hooks typically take the form of two objects:\n",
53 53 "\n",
54 54 "1. a Module **Loader**, which takes a module name (e.g. `'IPython.display'`), and returns a Module\n",
55 55 "2. a Module **Finder**, which figures out whether a module might exist, and tells Python what **Loader** to use"
56 56 ]
57 57 },
58 58 {
59 59 "cell_type": "code",
60 60 "execution_count": 3,
61 61 "metadata": {
62 62 "collapsed": false
63 63 },
64 64 "outputs": [],
65 65 "source": [
66 66 "def find_notebook(fullname, path=None):\n",
67 67 " \"\"\"find a notebook, given its fully qualified name and an optional path\n",
68 68 " \n",
69 69 " This turns \"foo.bar\" into \"foo/bar.ipynb\"\n",
70 70 " and tries turning \"Foo_Bar\" into \"Foo Bar\" if Foo_Bar\n",
71 71 " does not exist.\n",
72 72 " \"\"\"\n",
73 73 " name = fullname.rsplit('.', 1)[-1]\n",
74 74 " if not path:\n",
75 75 " path = ['']\n",
76 76 " for d in path:\n",
77 77 " nb_path = os.path.join(d, name + \".ipynb\")\n",
78 78 " if os.path.isfile(nb_path):\n",
79 79 " return nb_path\n",
80 80 " # let import Notebook_Name find \"Notebook Name.ipynb\"\n",
81 81 " nb_path = nb_path.replace(\"_\", \" \")\n",
82 82 " if os.path.isfile(nb_path):\n",
83 83 " return nb_path\n",
84 84 " "
85 85 ]
86 86 },
87 87 {
88 88 "cell_type": "markdown",
89 89 "metadata": {},
90 90 "source": [
91 91 "## Notebook Loader"
92 92 ]
93 93 },
94 94 {
95 95 "cell_type": "markdown",
96 96 "metadata": {},
97 97 "source": [
98 98 "Here we have our Notebook Loader.\n",
99 99 "It's actually quite simple - once we figure out the filename of the module,\n",
100 100 "all it does is:\n",
101 101 "\n",
102 102 "1. load the notebook document into memory\n",
103 103 "2. create an empty Module\n",
104 104 "3. execute every cell in the Module namespace\n",
105 105 "\n",
106 106 "Since IPython cells can have extended syntax,\n",
107 107 "the IPython transform is applied to turn each of these cells into their pure-Python counterparts before executing them.\n",
108 108 "If all of your notebook cells are pure-Python,\n",
109 109 "this step is unnecessary."
110 110 ]
111 111 },
112 112 {
113 113 "cell_type": "code",
114 114 "execution_count": 4,
115 115 "metadata": {
116 116 "collapsed": false
117 117 },
118 118 "outputs": [],
119 119 "source": [
120 120 "class NotebookLoader(object):\n",
121 121 " \"\"\"Module Loader for IPython Notebooks\"\"\"\n",
122 122 " def __init__(self, path=None):\n",
123 123 " self.shell = InteractiveShell.instance()\n",
124 124 " self.path = path\n",
125 125 " \n",
126 126 " def load_module(self, fullname):\n",
127 127 " \"\"\"import a notebook as a module\"\"\"\n",
128 128 " path = find_notebook(fullname, self.path)\n",
129 129 " \n",
130 130 " print (\"importing notebook from %s\" % path)\n",
131 131 " \n",
132 132 " # load the notebook object\n",
133 133 " nb = nbformat.read(path, as_version=4)\n",
134 134 " \n",
135 135 " \n",
136 136 " # create the module and add it to sys.modules\n",
137 137 " # if name in sys.modules:\n",
138 138 " # return sys.modules[name]\n",
139 139 " mod = types.ModuleType(fullname)\n",
140 140 " mod.__file__ = path\n",
141 141 " mod.__loader__ = self\n",
142 142 " mod.__dict__['get_ipython'] = get_ipython\n",
143 143 " sys.modules[fullname] = mod\n",
144 144 " \n",
145 145 " # extra work to ensure that magics that would affect the user_ns\n",
146 146 " # actually affect the notebook module's ns\n",
147 147 " save_user_ns = self.shell.user_ns\n",
148 148 " self.shell.user_ns = mod.__dict__\n",
149 149 " \n",
150 150 " try:\n",
151 151 " for cell in nb.cells:\n",
152 152 " if cell.cell_type == 'code':\n",
153 153 " # transform the input to executable Python\n",
154 154 " code = self.shell.input_transformer_manager.transform_cell(cell.source)\n",
155 155 " # run the code in themodule\n",
156 156 " exec(code, mod.__dict__)\n",
157 157 " finally:\n",
158 158 " self.shell.user_ns = save_user_ns\n",
159 159 " return mod\n"
160 160 ]
161 161 },
162 162 {
163 163 "cell_type": "markdown",
164 164 "metadata": {},
165 165 "source": [
166 166 "## The Module Finder"
167 167 ]
168 168 },
169 169 {
170 170 "cell_type": "markdown",
171 171 "metadata": {},
172 172 "source": [
173 173 "The finder is a simple object that tells you whether a name can be imported,\n",
174 174 "and returns the appropriate loader.\n",
175 175 "All this one does is check, when you do:\n",
176 176 "\n",
177 177 "```python\n",
178 178 "import mynotebook\n",
179 179 "```\n",
180 180 "\n",
181 181 "it checks whether `mynotebook.ipynb` exists.\n",
182 182 "If a notebook is found, then it returns a NotebookLoader.\n",
183 183 "\n",
184 184 "Any extra logic is just for resolving paths within packages."
185 185 ]
186 186 },
187 187 {
188 188 "cell_type": "code",
189 189 "execution_count": 5,
190 190 "metadata": {
191 191 "collapsed": false
192 192 },
193 193 "outputs": [],
194 194 "source": [
195 195 "class NotebookFinder(object):\n",
196 196 " \"\"\"Module finder that locates IPython Notebooks\"\"\"\n",
197 197 " def __init__(self):\n",
198 198 " self.loaders = {}\n",
199 199 " \n",
200 200 " def find_module(self, fullname, path=None):\n",
201 201 " nb_path = find_notebook(fullname, path)\n",
202 202 " if not nb_path:\n",
203 203 " return\n",
204 204 " \n",
205 205 " key = path\n",
206 206 " if path:\n",
207 207 " # lists aren't hashable\n",
208 208 " key = os.path.sep.join(path)\n",
209 209 " \n",
210 210 " if key not in self.loaders:\n",
211 211 " self.loaders[key] = NotebookLoader(path)\n",
212 212 " return self.loaders[key]\n"
213 213 ]
214 214 },
215 215 {
216 216 "cell_type": "markdown",
217 217 "metadata": {},
218 218 "source": [
219 219 "## Register the hook"
220 220 ]
221 221 },
222 222 {
223 223 "cell_type": "markdown",
224 224 "metadata": {},
225 225 "source": [
226 226 "Now we register the `NotebookFinder` with `sys.meta_path`"
227 227 ]
228 228 },
229 229 {
230 230 "cell_type": "code",
231 231 "execution_count": 6,
232 232 "metadata": {
233 233 "collapsed": false
234 234 },
235 235 "outputs": [],
236 236 "source": [
237 237 "sys.meta_path.append(NotebookFinder())"
238 238 ]
239 239 },
240 240 {
241 241 "cell_type": "markdown",
242 242 "metadata": {},
243 243 "source": [
244 244 "After this point, my notebooks should be importable.\n",
245 245 "\n",
246 246 "Let's look at what we have in the CWD:"
247 247 ]
248 248 },
249 249 {
250 250 "cell_type": "code",
251 251 "execution_count": 7,
252 252 "metadata": {
253 253 "collapsed": false
254 254 },
255 255 "outputs": [
256 256 {
257 257 "name": "stdout",
258 258 "output_type": "stream",
259 259 "text": [
260 260 "__init__.py \u001b[34m__pycache__\u001b[m\u001b[m/ mynotebook.ipynb \u001b[34mnbs\u001b[m\u001b[m/\r\n"
261 261 ]
262 262 }
263 263 ],
264 264 "source": [
265 265 "ls nbpackage"
266 266 ]
267 267 },
268 268 {
269 269 "cell_type": "markdown",
270 270 "metadata": {},
271 271 "source": [
272 272 "So I should be able to `import nbimp.mynotebook`.\n"
273 273 ]
274 274 },
275 275 {
276 276 "cell_type": "markdown",
277 277 "metadata": {},
278 278 "source": [
279 279 "### Aside: displaying notebooks"
280 280 ]
281 281 },
282 282 {
283 283 "cell_type": "markdown",
284 284 "metadata": {},
285 285 "source": [
286 286 "Here is some simple code to display the contents of a notebook\n",
287 287 "with syntax highlighting, etc."
288 288 ]
289 289 },
290 290 {
291 291 "cell_type": "code",
292 292 "execution_count": 8,
293 293 "metadata": {
294 294 "collapsed": false
295 295 },
296 296 "outputs": [
297 297 {
298 298 "data": {
299 299 "text/html": [
300 300 "\n",
301 301 "<style type='text/css'>\n",
302 302 ".hll { background-color: #ffffcc }\n",
303 303 ".c { color: #408080; font-style: italic } /* Comment */\n",
304 304 ".err { border: 1px solid #FF0000 } /* Error */\n",
305 305 ".k { color: #008000; font-weight: bold } /* Keyword */\n",
306 306 ".o { color: #666666 } /* Operator */\n",
307 307 ".cm { color: #408080; font-style: italic } /* Comment.Multiline */\n",
308 308 ".cp { color: #BC7A00 } /* Comment.Preproc */\n",
309 309 ".c1 { color: #408080; font-style: italic } /* Comment.Single */\n",
310 310 ".cs { color: #408080; font-style: italic } /* Comment.Special */\n",
311 311 ".gd { color: #A00000 } /* Generic.Deleted */\n",
312 312 ".ge { font-style: italic } /* Generic.Emph */\n",
313 313 ".gr { color: #FF0000 } /* Generic.Error */\n",
314 314 ".gh { color: #000080; font-weight: bold } /* Generic.Heading */\n",
315 315 ".gi { color: #00A000 } /* Generic.Inserted */\n",
316 316 ".go { color: #888888 } /* Generic.Output */\n",
317 317 ".gp { color: #000080; font-weight: bold } /* Generic.Prompt */\n",
318 318 ".gs { font-weight: bold } /* Generic.Strong */\n",
319 319 ".gu { color: #800080; font-weight: bold } /* Generic.Subheading */\n",
320 320 ".gt { color: #0044DD } /* Generic.Traceback */\n",
321 321 ".kc { color: #008000; font-weight: bold } /* Keyword.Constant */\n",
322 322 ".kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\n",
323 323 ".kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\n",
324 324 ".kp { color: #008000 } /* Keyword.Pseudo */\n",
325 325 ".kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\n",
326 326 ".kt { color: #B00040 } /* Keyword.Type */\n",
327 327 ".m { color: #666666 } /* Literal.Number */\n",
328 328 ".s { color: #BA2121 } /* Literal.String */\n",
329 329 ".na { color: #7D9029 } /* Name.Attribute */\n",
330 330 ".nb { color: #008000 } /* Name.Builtin */\n",
331 331 ".nc { color: #0000FF; font-weight: bold } /* Name.Class */\n",
332 332 ".no { color: #880000 } /* Name.Constant */\n",
333 333 ".nd { color: #AA22FF } /* Name.Decorator */\n",
334 334 ".ni { color: #999999; font-weight: bold } /* Name.Entity */\n",
335 335 ".ne { color: #D2413A; font-weight: bold } /* Name.Exception */\n",
336 336 ".nf { color: #0000FF } /* Name.Function */\n",
337 337 ".nl { color: #A0A000 } /* Name.Label */\n",
338 338 ".nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\n",
339 339 ".nt { color: #008000; font-weight: bold } /* Name.Tag */\n",
340 340 ".nv { color: #19177C } /* Name.Variable */\n",
341 341 ".ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\n",
342 342 ".w { color: #bbbbbb } /* Text.Whitespace */\n",
343 343 ".mb { color: #666666 } /* Literal.Number.Bin */\n",
344 344 ".mf { color: #666666 } /* Literal.Number.Float */\n",
345 345 ".mh { color: #666666 } /* Literal.Number.Hex */\n",
346 346 ".mi { color: #666666 } /* Literal.Number.Integer */\n",
347 347 ".mo { color: #666666 } /* Literal.Number.Oct */\n",
348 348 ".sb { color: #BA2121 } /* Literal.String.Backtick */\n",
349 349 ".sc { color: #BA2121 } /* Literal.String.Char */\n",
350 350 ".sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\n",
351 351 ".s2 { color: #BA2121 } /* Literal.String.Double */\n",
352 352 ".se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */\n",
353 353 ".sh { color: #BA2121 } /* Literal.String.Heredoc */\n",
354 354 ".si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */\n",
355 355 ".sx { color: #008000 } /* Literal.String.Other */\n",
356 356 ".sr { color: #BB6688 } /* Literal.String.Regex */\n",
357 357 ".s1 { color: #BA2121 } /* Literal.String.Single */\n",
358 358 ".ss { color: #19177C } /* Literal.String.Symbol */\n",
359 359 ".bp { color: #008000 } /* Name.Builtin.Pseudo */\n",
360 360 ".vc { color: #19177C } /* Name.Variable.Class */\n",
361 361 ".vg { color: #19177C } /* Name.Variable.Global */\n",
362 362 ".vi { color: #19177C } /* Name.Variable.Instance */\n",
363 363 ".il { color: #666666 } /* Literal.Number.Integer.Long */\n",
364 364 "</style>\n"
365 365 ],
366 366 "text/plain": [
367 367 "<IPython.core.display.HTML object>"
368 368 ]
369 369 },
370 370 "metadata": {},
371 371 "output_type": "display_data"
372 372 }
373 373 ],
374 374 "source": [
375 375 "from pygments import highlight\n",
376 376 "from pygments.lexers import PythonLexer\n",
377 377 "from pygments.formatters import HtmlFormatter\n",
378 378 "\n",
379 379 "from IPython.display import display, HTML\n",
380 380 "\n",
381 381 "formatter = HtmlFormatter()\n",
382 382 "lexer = PythonLexer()\n",
383 383 "\n",
384 384 "# publish the CSS for pygments highlighting\n",
385 385 "display(HTML(\"\"\"\n",
386 386 "<style type='text/css'>\n",
387 387 "%s\n",
388 388 "</style>\n",
389 389 "\"\"\" % formatter.get_style_defs()\n",
390 390 "))"
391 391 ]
392 392 },
393 393 {
394 394 "cell_type": "code",
395 395 "execution_count": 9,
396 396 "metadata": {
397 397 "collapsed": false
398 398 },
399 399 "outputs": [
400 400 {
401 401 "data": {
402 402 "text/html": [
403 403 "<h4>markdown cell</h4>\n",
404 404 "<pre># My Notebook</pre>\n",
405 405 "<h4>code cell</h4>\n",
406 406 "<div class=\"highlight\"><pre><span class=\"k\">def</span> <span class=\"nf\">foo</span><span class=\"p\">():</span>\n",
407 407 " <span class=\"k\">return</span> <span class=\"s\">&quot;foo&quot;</span>\n",
408 408 "</pre></div>\n",
409 409 "\n",
410 410 "<h4>code cell</h4>\n",
411 411 "<div class=\"highlight\"><pre><span class=\"k\">def</span> <span class=\"nf\">has_ip_syntax</span><span class=\"p\">():</span>\n",
412 412 " <span class=\"n\">listing</span> <span class=\"o\">=</span> <span class=\"err\">!</span><span class=\"n\">ls</span>\n",
413 413 " <span class=\"k\">return</span> <span class=\"n\">listing</span>\n",
414 414 "</pre></div>\n",
415 415 "\n",
416 416 "<h4>code cell</h4>\n",
417 417 "<div class=\"highlight\"><pre><span class=\"k\">def</span> <span class=\"nf\">whatsmyname</span><span class=\"p\">():</span>\n",
418 418 " <span class=\"k\">return</span> <span class=\"n\">__name__</span>\n",
419 419 "</pre></div>\n"
420 420 ],
421 421 "text/plain": [
422 422 "<IPython.core.display.HTML object>"
423 423 ]
424 424 },
425 425 "metadata": {},
426 426 "output_type": "display_data"
427 427 }
428 428 ],
429 429 "source": [
430 430 "def show_notebook(fname):\n",
431 431 " \"\"\"display a short summary of the cells of a notebook\"\"\"\n",
432 432 " nb = nbformat.read(fname, as_version=4)\n",
433 433 " html = []\n",
434 434 " for cell in nb.cells:\n",
435 435 " html.append(\"<h4>%s cell</h4>\" % cell.cell_type)\n",
436 436 " if cell.cell_type == 'code':\n",
437 437 " html.append(highlight(cell.source, lexer, formatter))\n",
438 438 " else:\n",
439 439 " html.append(\"<pre>%s</pre>\" % cell.source)\n",
440 440 " display(HTML('\\n'.join(html)))\n",
441 441 "\n",
442 442 "show_notebook(os.path.join(\"nbpackage\", \"mynotebook.ipynb\"))"
443 443 ]
444 444 },
445 445 {
446 446 "cell_type": "markdown",
447 447 "metadata": {},
448 448 "source": [
449 449 "So my notebook has a heading cell and some code cells,\n",
450 450 "one of which contains some IPython syntax.\n",
451 451 "\n",
452 452 "Let's see what happens when we import it"
453 453 ]
454 454 },
455 455 {
456 456 "cell_type": "code",
457 457 "execution_count": 10,
458 458 "metadata": {
459 459 "collapsed": false
460 460 },
461 461 "outputs": [
462 462 {
463 463 "name": "stdout",
464 464 "output_type": "stream",
465 465 "text": [
466 466 "importing notebook from /Users/minrk/dev/ip/mine/examples/IPython Kernel/nbpackage/mynotebook.ipynb\n"
467 467 ]
468 468 }
469 469 ],
470 470 "source": [
471 471 "from nbpackage import mynotebook"
472 472 ]
473 473 },
474 474 {
475 475 "cell_type": "markdown",
476 476 "metadata": {},
477 477 "source": [
478 478 "Hooray, it imported! Does it work?"
479 479 ]
480 480 },
481 481 {
482 482 "cell_type": "code",
483 483 "execution_count": 11,
484 484 "metadata": {
485 485 "collapsed": false
486 486 },
487 487 "outputs": [
488 488 {
489 489 "data": {
490 490 "text/plain": [
491 491 "'foo'"
492 492 ]
493 493 },
494 494 "execution_count": 11,
495 495 "metadata": {},
496 496 "output_type": "execute_result"
497 497 }
498 498 ],
499 499 "source": [
500 500 "mynotebook.foo()"
501 501 ]
502 502 },
503 503 {
504 504 "cell_type": "markdown",
505 505 "metadata": {},
506 506 "source": [
507 507 "Hooray again!\n",
508 508 "\n",
509 509 "Even the function that contains IPython syntax works:"
510 510 ]
511 511 },
512 512 {
513 513 "cell_type": "code",
514 514 "execution_count": 12,
515 515 "metadata": {
516 516 "collapsed": false
517 517 },
518 518 "outputs": [
519 519 {
520 520 "data": {
521 521 "text/plain": [
522 522 "['Animations Using clear_output.ipynb',\n",
523 523 " 'Background Jobs.ipynb',\n",
524 524 " 'Beyond Plain Python.ipynb',\n",
525 525 " 'Capturing Output.ipynb',\n",
526 526 " 'Cell Magics.ipynb',\n",
527 527 " 'Custom Display Logic.ipynb',\n",
528 528 " 'Importing Notebooks.ipynb',\n",
529 529 " 'Index.ipynb',\n",
530 530 " 'Plotting in the Notebook.ipynb',\n",
531 531 " 'Raw Input in the Notebook.ipynb',\n",
532 532 " 'Rich Output.ipynb',\n",
533 533 " 'Script Magics.ipynb',\n",
534 534 " 'SymPy.ipynb',\n",
535 535 " 'Terminal Usage.ipynb',\n",
536 536 " 'Third Party Rich Output.ipynb',\n",
537 537 " 'Trapezoid Rule.ipynb',\n",
538 538 " 'Working With External Code.ipynb',\n",
539 539 " '__pycache__',\n",
540 540 " 'data',\n",
541 541 " 'example-demo.py',\n",
542 542 " 'gui',\n",
543 543 " 'ipython-completion.bash',\n",
544 544 " 'ipython-get-history.py',\n",
545 545 " 'ipython.desktop',\n",
546 546 " 'nbpackage']"
547 547 ]
548 548 },
549 549 "execution_count": 12,
550 550 "metadata": {},
551 551 "output_type": "execute_result"
552 552 }
553 553 ],
554 554 "source": [
555 555 "mynotebook.has_ip_syntax()"
556 556 ]
557 557 },
558 558 {
559 559 "cell_type": "markdown",
560 560 "metadata": {},
561 561 "source": [
562 562 "## Notebooks in packages"
563 563 ]
564 564 },
565 565 {
566 566 "cell_type": "markdown",
567 567 "metadata": {},
568 568 "source": [
569 569 "We also have a notebook inside the `nb` package,\n",
570 570 "so let's make sure that works as well."
571 571 ]
572 572 },
573 573 {
574 574 "cell_type": "code",
575 575 "execution_count": 13,
576 576 "metadata": {
577 577 "collapsed": false
578 578 },
579 579 "outputs": [
580 580 {
581 581 "name": "stdout",
582 582 "output_type": "stream",
583 583 "text": [
584 584 "__init__.py \u001b[34m__pycache__\u001b[m\u001b[m/ other.ipynb\r\n"
585 585 ]
586 586 }
587 587 ],
588 588 "source": [
589 589 "ls nbpackage/nbs"
590 590 ]
591 591 },
592 592 {
593 593 "cell_type": "markdown",
594 594 "metadata": {},
595 595 "source": [
596 596 "Note that the `__init__.py` is necessary for `nb` to be considered a package,\n",
597 597 "just like usual."
598 598 ]
599 599 },
600 600 {
601 601 "cell_type": "code",
602 602 "execution_count": 14,
603 603 "metadata": {
604 604 "collapsed": false
605 605 },
606 606 "outputs": [
607 607 {
608 608 "data": {
609 609 "text/html": [
610 610 "<h4>markdown cell</h4>\n",
611 611 "<pre>This notebook just defines `bar`</pre>\n",
612 612 "<h4>code cell</h4>\n",
613 613 "<div class=\"highlight\"><pre><span class=\"k\">def</span> <span class=\"nf\">bar</span><span class=\"p\">(</span><span class=\"n\">x</span><span class=\"p\">):</span>\n",
614 614 " <span class=\"k\">return</span> <span class=\"s\">&quot;bar&quot;</span> <span class=\"o\">*</span> <span class=\"n\">x</span>\n",
615 615 "</pre></div>\n"
616 616 ],
617 617 "text/plain": [
618 618 "<IPython.core.display.HTML object>"
619 619 ]
620 620 },
621 621 "metadata": {},
622 622 "output_type": "display_data"
623 623 }
624 624 ],
625 625 "source": [
626 626 "show_notebook(os.path.join(\"nbpackage\", \"nbs\", \"other.ipynb\"))"
627 627 ]
628 628 },
629 629 {
630 630 "cell_type": "code",
631 631 "execution_count": 15,
632 632 "metadata": {
633 633 "collapsed": false
634 634 },
635 635 "outputs": [
636 636 {
637 637 "name": "stdout",
638 638 "output_type": "stream",
639 639 "text": [
640 640 "importing notebook from /Users/minrk/dev/ip/mine/examples/IPython Kernel/nbpackage/nbs/other.ipynb\n"
641 641 ]
642 642 },
643 643 {
644 644 "data": {
645 645 "text/plain": [
646 646 "'barbarbarbarbar'"
647 647 ]
648 648 },
649 649 "execution_count": 15,
650 650 "metadata": {},
651 651 "output_type": "execute_result"
652 652 }
653 653 ],
654 654 "source": [
655 655 "from nbpackage.nbs import other\n",
656 656 "other.bar(5)"
657 657 ]
658 658 },
659 659 {
660 660 "cell_type": "markdown",
661 661 "metadata": {},
662 662 "source": [
663 663 "So now we have importable notebooks, from both the local directory and inside packages.\n",
664 664 "\n",
665 665 "I can even put a notebook inside IPython, to further demonstrate that this is working properly:"
666 666 ]
667 667 },
668 668 {
669 669 "cell_type": "code",
670 670 "execution_count": 16,
671 671 "metadata": {
672 672 "collapsed": false
673 673 },
674 674 "outputs": [
675 675 {
676 676 "data": {
677 677 "text/plain": [
678 678 "'/Users/minrk/dev/ip/mine/IPython/utils/inside_ipython.ipynb'"
679 679 ]
680 680 },
681 681 "execution_count": 16,
682 682 "metadata": {},
683 683 "output_type": "execute_result"
684 684 }
685 685 ],
686 686 "source": [
687 687 "import shutil\n",
688 688 "from IPython.paths import get_ipython_package_dir\n",
689 689 "\n",
690 690 "utils = os.path.join(get_ipython_package_dir(), 'utils')\n",
691 691 "shutil.copy(os.path.join(\"nbpackage\", \"mynotebook.ipynb\"),\n",
692 692 " os.path.join(utils, \"inside_ipython.ipynb\")\n",
693 693 ")"
694 694 ]
695 695 },
696 696 {
697 697 "cell_type": "markdown",
698 698 "metadata": {},
699 699 "source": [
700 700 "and import the notebook from `IPython.utils`"
701 701 ]
702 702 },
703 703 {
704 704 "cell_type": "code",
705 705 "execution_count": 17,
706 706 "metadata": {
707 707 "collapsed": false
708 708 },
709 709 "outputs": [
710 710 {
711 711 "name": "stdout",
712 712 "output_type": "stream",
713 713 "text": [
714 714 "importing notebook from /Users/minrk/dev/ip/mine/IPython/utils/inside_ipython.ipynb\n"
715 715 ]
716 716 },
717 717 {
718 718 "data": {
719 719 "text/plain": [
720 720 "'IPython.utils.inside_ipython'"
721 721 ]
722 722 },
723 723 "execution_count": 17,
724 724 "metadata": {},
725 725 "output_type": "execute_result"
726 726 }
727 727 ],
728 728 "source": [
729 729 "from IPython.utils import inside_ipython\n",
730 730 "inside_ipython.whatsmyname()"
731 731 ]
732 732 },
733 733 {
734 734 "cell_type": "markdown",
735 735 "metadata": {},
736 736 "source": [
737 737 "This approach can even import functions and classes that are defined in a notebook using the `%%cython` magic."
738 738 ]
739 739 }
740 740 ],
741 741 "metadata": {
742 742 "gist_id": "6011986",
743 743 "kernelspec": {
744 744 "display_name": "Python 3",
745 745 "language": "python",
746 746 "name": "python3"
747 747 },
748 748 "language_info": {
749 749 "codemirror_mode": {
750 750 "name": "ipython",
751 751 "version": 3
752 752 },
753 753 "file_extension": ".py",
754 754 "mimetype": "text/x-python",
755 755 "name": "python",
756 756 "nbconvert_exporter": "python",
757 757 "pygments_lexer": "ipython3",
758 758 "version": "3.4.3"
759 759 }
760 760 },
761 761 "nbformat": 4,
762 762 "nbformat_minor": 0
763 763 }
General Comments 0
You need to be logged in to leave comments. Login now