##// END OF EJS Templates
DOC: add a note in %profile about %prun
Paul Ivanov -
Show More
@@ -1,648 +1,654 b''
1 1 """Implementation of basic magic functions.
2 2 """
3 3 #-----------------------------------------------------------------------------
4 4 # Copyright (c) 2012 The IPython Development Team.
5 5 #
6 6 # Distributed under the terms of the Modified BSD License.
7 7 #
8 8 # The full license is in the file COPYING.txt, distributed with this software.
9 9 #-----------------------------------------------------------------------------
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Imports
13 13 #-----------------------------------------------------------------------------
14 14 from __future__ import print_function
15 15
16 16 # Stdlib
17 17 import io
18 18 import json
19 19 import sys
20 20 from pprint import pformat
21 21
22 22 # Our own packages
23 23 from IPython.core import magic_arguments, page
24 24 from IPython.core.error import UsageError
25 25 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
26 26 from IPython.utils.text import format_screen, dedent, indent
27 27 from IPython.testing.skipdoctest import skip_doctest
28 28 from IPython.utils.ipstruct import Struct
29 29 from IPython.utils.path import unquote_filename
30 30 from IPython.utils.py3compat import unicode_type
31 31 from IPython.utils.warn import warn, error
32 32
33 33 #-----------------------------------------------------------------------------
34 34 # Magics class implementation
35 35 #-----------------------------------------------------------------------------
36 36
37 37 class MagicsDisplay(object):
38 38 def __init__(self, magics_manager):
39 39 self.magics_manager = magics_manager
40 40
41 41 def _lsmagic(self):
42 42 """The main implementation of the %lsmagic"""
43 43 mesc = magic_escapes['line']
44 44 cesc = magic_escapes['cell']
45 45 mman = self.magics_manager
46 46 magics = mman.lsmagic()
47 47 out = ['Available line magics:',
48 48 mesc + (' '+mesc).join(sorted(magics['line'])),
49 49 '',
50 50 'Available cell magics:',
51 51 cesc + (' '+cesc).join(sorted(magics['cell'])),
52 52 '',
53 53 mman.auto_status()]
54 54 return '\n'.join(out)
55 55
56 56 def _repr_pretty_(self, p, cycle):
57 57 p.text(self._lsmagic())
58 58
59 59 def __str__(self):
60 60 return self._lsmagic()
61 61
62 62 def _jsonable(self):
63 63 """turn magics dict into jsonable dict of the same structure
64 64
65 65 replaces object instances with their class names as strings
66 66 """
67 67 magic_dict = {}
68 68 mman = self.magics_manager
69 69 magics = mman.lsmagic()
70 70 for key, subdict in magics.items():
71 71 d = {}
72 72 magic_dict[key] = d
73 73 for name, obj in subdict.items():
74 74 try:
75 75 classname = obj.__self__.__class__.__name__
76 76 except AttributeError:
77 77 classname = 'Other'
78 78
79 79 d[name] = classname
80 80 return magic_dict
81 81
82 82 def _repr_json_(self):
83 83 return json.dumps(self._jsonable())
84 84
85 85
86 86 @magics_class
87 87 class BasicMagics(Magics):
88 88 """Magics that provide central IPython functionality.
89 89
90 90 These are various magics that don't fit into specific categories but that
91 91 are all part of the base 'IPython experience'."""
92 92
93 93 @magic_arguments.magic_arguments()
94 94 @magic_arguments.argument(
95 95 '-l', '--line', action='store_true',
96 96 help="""Create a line magic alias."""
97 97 )
98 98 @magic_arguments.argument(
99 99 '-c', '--cell', action='store_true',
100 100 help="""Create a cell magic alias."""
101 101 )
102 102 @magic_arguments.argument(
103 103 'name',
104 104 help="""Name of the magic to be created."""
105 105 )
106 106 @magic_arguments.argument(
107 107 'target',
108 108 help="""Name of the existing line or cell magic."""
109 109 )
110 110 @line_magic
111 111 def alias_magic(self, line=''):
112 112 """Create an alias for an existing line or cell magic.
113 113
114 114 Examples
115 115 --------
116 116 ::
117 117
118 118 In [1]: %alias_magic t timeit
119 119 Created `%t` as an alias for `%timeit`.
120 120 Created `%%t` as an alias for `%%timeit`.
121 121
122 122 In [2]: %t -n1 pass
123 123 1 loops, best of 3: 954 ns per loop
124 124
125 125 In [3]: %%t -n1
126 126 ...: pass
127 127 ...:
128 128 1 loops, best of 3: 954 ns per loop
129 129
130 130 In [4]: %alias_magic --cell whereami pwd
131 131 UsageError: Cell magic function `%%pwd` not found.
132 132 In [5]: %alias_magic --line whereami pwd
133 133 Created `%whereami` as an alias for `%pwd`.
134 134
135 135 In [6]: %whereami
136 136 Out[6]: u'/home/testuser'
137 137 """
138 138 args = magic_arguments.parse_argstring(self.alias_magic, line)
139 139 shell = self.shell
140 140 mman = self.shell.magics_manager
141 141 escs = ''.join(magic_escapes.values())
142 142
143 143 target = args.target.lstrip(escs)
144 144 name = args.name.lstrip(escs)
145 145
146 146 # Find the requested magics.
147 147 m_line = shell.find_magic(target, 'line')
148 148 m_cell = shell.find_magic(target, 'cell')
149 149 if args.line and m_line is None:
150 150 raise UsageError('Line magic function `%s%s` not found.' %
151 151 (magic_escapes['line'], target))
152 152 if args.cell and m_cell is None:
153 153 raise UsageError('Cell magic function `%s%s` not found.' %
154 154 (magic_escapes['cell'], target))
155 155
156 156 # If --line and --cell are not specified, default to the ones
157 157 # that are available.
158 158 if not args.line and not args.cell:
159 159 if not m_line and not m_cell:
160 160 raise UsageError(
161 161 'No line or cell magic with name `%s` found.' % target
162 162 )
163 163 args.line = bool(m_line)
164 164 args.cell = bool(m_cell)
165 165
166 166 if args.line:
167 167 mman.register_alias(name, target, 'line')
168 168 print('Created `%s%s` as an alias for `%s%s`.' % (
169 169 magic_escapes['line'], name,
170 170 magic_escapes['line'], target))
171 171
172 172 if args.cell:
173 173 mman.register_alias(name, target, 'cell')
174 174 print('Created `%s%s` as an alias for `%s%s`.' % (
175 175 magic_escapes['cell'], name,
176 176 magic_escapes['cell'], target))
177 177
178 178 @line_magic
179 179 def lsmagic(self, parameter_s=''):
180 180 """List currently available magic functions."""
181 181 return MagicsDisplay(self.shell.magics_manager)
182 182
183 183 def _magic_docs(self, brief=False, rest=False):
184 184 """Return docstrings from magic functions."""
185 185 mman = self.shell.magics_manager
186 186 docs = mman.lsmagic_docs(brief, missing='No documentation')
187 187
188 188 if rest:
189 189 format_string = '**%s%s**::\n\n%s\n\n'
190 190 else:
191 191 format_string = '%s%s:\n%s\n'
192 192
193 193 return ''.join(
194 194 [format_string % (magic_escapes['line'], fname,
195 195 indent(dedent(fndoc)))
196 196 for fname, fndoc in sorted(docs['line'].items())]
197 197 +
198 198 [format_string % (magic_escapes['cell'], fname,
199 199 indent(dedent(fndoc)))
200 200 for fname, fndoc in sorted(docs['cell'].items())]
201 201 )
202 202
203 203 @line_magic
204 204 def magic(self, parameter_s=''):
205 205 """Print information about the magic function system.
206 206
207 207 Supported formats: -latex, -brief, -rest
208 208 """
209 209
210 210 mode = ''
211 211 try:
212 212 mode = parameter_s.split()[0][1:]
213 213 if mode == 'rest':
214 214 rest_docs = []
215 215 except IndexError:
216 216 pass
217 217
218 218 brief = (mode == 'brief')
219 219 rest = (mode == 'rest')
220 220 magic_docs = self._magic_docs(brief, rest)
221 221
222 222 if mode == 'latex':
223 223 print(self.format_latex(magic_docs))
224 224 return
225 225 else:
226 226 magic_docs = format_screen(magic_docs)
227 227
228 228 out = ["""
229 229 IPython's 'magic' functions
230 230 ===========================
231 231
232 232 The magic function system provides a series of functions which allow you to
233 233 control the behavior of IPython itself, plus a lot of system-type
234 234 features. There are two kinds of magics, line-oriented and cell-oriented.
235 235
236 236 Line magics are prefixed with the % character and work much like OS
237 237 command-line calls: they get as an argument the rest of the line, where
238 238 arguments are passed without parentheses or quotes. For example, this will
239 239 time the given statement::
240 240
241 241 %timeit range(1000)
242 242
243 243 Cell magics are prefixed with a double %%, and they are functions that get as
244 244 an argument not only the rest of the line, but also the lines below it in a
245 245 separate argument. These magics are called with two arguments: the rest of the
246 246 call line and the body of the cell, consisting of the lines below the first.
247 247 For example::
248 248
249 249 %%timeit x = numpy.random.randn((100, 100))
250 250 numpy.linalg.svd(x)
251 251
252 252 will time the execution of the numpy svd routine, running the assignment of x
253 253 as part of the setup phase, which is not timed.
254 254
255 255 In a line-oriented client (the terminal or Qt console IPython), starting a new
256 256 input with %% will automatically enter cell mode, and IPython will continue
257 257 reading input until a blank line is given. In the notebook, simply type the
258 258 whole cell as one entity, but keep in mind that the %% escape can only be at
259 259 the very start of the cell.
260 260
261 261 NOTE: If you have 'automagic' enabled (via the command line option or with the
262 262 %automagic function), you don't need to type in the % explicitly for line
263 263 magics; cell magics always require an explicit '%%' escape. By default,
264 264 IPython ships with automagic on, so you should only rarely need the % escape.
265 265
266 266 Example: typing '%cd mydir' (without the quotes) changes you working directory
267 267 to 'mydir', if it exists.
268 268
269 269 For a list of the available magic functions, use %lsmagic. For a description
270 270 of any of them, type %magic_name?, e.g. '%cd?'.
271 271
272 272 Currently the magic system has the following functions:""",
273 273 magic_docs,
274 274 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
275 275 str(self.lsmagic()),
276 276 ]
277 277 page.page('\n'.join(out))
278 278
279 279
280 280 @line_magic
281 281 def page(self, parameter_s=''):
282 282 """Pretty print the object and display it through a pager.
283 283
284 284 %page [options] OBJECT
285 285
286 286 If no object is given, use _ (last output).
287 287
288 288 Options:
289 289
290 290 -r: page str(object), don't pretty-print it."""
291 291
292 292 # After a function contributed by Olivier Aubert, slightly modified.
293 293
294 294 # Process options/args
295 295 opts, args = self.parse_options(parameter_s, 'r')
296 296 raw = 'r' in opts
297 297
298 298 oname = args and args or '_'
299 299 info = self.shell._ofind(oname)
300 300 if info['found']:
301 301 txt = (raw and str or pformat)( info['obj'] )
302 302 page.page(txt)
303 303 else:
304 304 print('Object `%s` not found' % oname)
305 305
306 306 @line_magic
307 307 def profile(self, parameter_s=''):
308 """Print your currently active IPython profile."""
308 """Print your currently active IPython profile.
309
310 See Also
311 --------
312 prun : run code using the Python profiler
313 (:class:`~IPython.core.magics.execution.ExecutionMagics.prun`)
314 """
309 315 from IPython.core.application import BaseIPythonApplication
310 316 if BaseIPythonApplication.initialized():
311 317 print(BaseIPythonApplication.instance().profile)
312 318 else:
313 319 error("profile is an application-level value, but you don't appear to be in an IPython application")
314 320
315 321 @line_magic
316 322 def pprint(self, parameter_s=''):
317 323 """Toggle pretty printing on/off."""
318 324 ptformatter = self.shell.display_formatter.formatters['text/plain']
319 325 ptformatter.pprint = bool(1 - ptformatter.pprint)
320 326 print('Pretty printing has been turned',
321 327 ['OFF','ON'][ptformatter.pprint])
322 328
323 329 @line_magic
324 330 def colors(self, parameter_s=''):
325 331 """Switch color scheme for prompts, info system and exception handlers.
326 332
327 333 Currently implemented schemes: NoColor, Linux, LightBG.
328 334
329 335 Color scheme names are not case-sensitive.
330 336
331 337 Examples
332 338 --------
333 339 To get a plain black and white terminal::
334 340
335 341 %colors nocolor
336 342 """
337 343 def color_switch_err(name):
338 344 warn('Error changing %s color schemes.\n%s' %
339 345 (name, sys.exc_info()[1]))
340 346
341 347
342 348 new_scheme = parameter_s.strip()
343 349 if not new_scheme:
344 350 raise UsageError(
345 351 "%colors: you must specify a color scheme. See '%colors?'")
346 352 # local shortcut
347 353 shell = self.shell
348 354
349 355 import IPython.utils.rlineimpl as readline
350 356
351 357 if not shell.colors_force and \
352 358 not readline.have_readline and \
353 359 (sys.platform == "win32" or sys.platform == "cli"):
354 360 msg = """\
355 361 Proper color support under MS Windows requires the pyreadline library.
356 362 You can find it at:
357 363 http://ipython.org/pyreadline.html
358 364 Gary's readline needs the ctypes module, from:
359 365 http://starship.python.net/crew/theller/ctypes
360 366 (Note that ctypes is already part of Python versions 2.5 and newer).
361 367
362 368 Defaulting color scheme to 'NoColor'"""
363 369 new_scheme = 'NoColor'
364 370 warn(msg)
365 371
366 372 # readline option is 0
367 373 if not shell.colors_force and not shell.has_readline:
368 374 new_scheme = 'NoColor'
369 375
370 376 # Set prompt colors
371 377 try:
372 378 shell.prompt_manager.color_scheme = new_scheme
373 379 except:
374 380 color_switch_err('prompt')
375 381 else:
376 382 shell.colors = \
377 383 shell.prompt_manager.color_scheme_table.active_scheme_name
378 384 # Set exception colors
379 385 try:
380 386 shell.InteractiveTB.set_colors(scheme = new_scheme)
381 387 shell.SyntaxTB.set_colors(scheme = new_scheme)
382 388 except:
383 389 color_switch_err('exception')
384 390
385 391 # Set info (for 'object?') colors
386 392 if shell.color_info:
387 393 try:
388 394 shell.inspector.set_active_scheme(new_scheme)
389 395 except:
390 396 color_switch_err('object inspector')
391 397 else:
392 398 shell.inspector.set_active_scheme('NoColor')
393 399
394 400 @line_magic
395 401 def xmode(self, parameter_s=''):
396 402 """Switch modes for the exception handlers.
397 403
398 404 Valid modes: Plain, Context and Verbose.
399 405
400 406 If called without arguments, acts as a toggle."""
401 407
402 408 def xmode_switch_err(name):
403 409 warn('Error changing %s exception modes.\n%s' %
404 410 (name,sys.exc_info()[1]))
405 411
406 412 shell = self.shell
407 413 new_mode = parameter_s.strip().capitalize()
408 414 try:
409 415 shell.InteractiveTB.set_mode(mode=new_mode)
410 416 print('Exception reporting mode:',shell.InteractiveTB.mode)
411 417 except:
412 418 xmode_switch_err('user')
413 419
414 420 @line_magic
415 421 def quickref(self,arg):
416 422 """ Show a quick reference sheet """
417 423 from IPython.core.usage import quick_reference
418 424 qr = quick_reference + self._magic_docs(brief=True)
419 425 page.page(qr)
420 426
421 427 @line_magic
422 428 def doctest_mode(self, parameter_s=''):
423 429 """Toggle doctest mode on and off.
424 430
425 431 This mode is intended to make IPython behave as much as possible like a
426 432 plain Python shell, from the perspective of how its prompts, exceptions
427 433 and output look. This makes it easy to copy and paste parts of a
428 434 session into doctests. It does so by:
429 435
430 436 - Changing the prompts to the classic ``>>>`` ones.
431 437 - Changing the exception reporting mode to 'Plain'.
432 438 - Disabling pretty-printing of output.
433 439
434 440 Note that IPython also supports the pasting of code snippets that have
435 441 leading '>>>' and '...' prompts in them. This means that you can paste
436 442 doctests from files or docstrings (even if they have leading
437 443 whitespace), and the code will execute correctly. You can then use
438 444 '%history -t' to see the translated history; this will give you the
439 445 input after removal of all the leading prompts and whitespace, which
440 446 can be pasted back into an editor.
441 447
442 448 With these features, you can switch into this mode easily whenever you
443 449 need to do testing and changes to doctests, without having to leave
444 450 your existing IPython session.
445 451 """
446 452
447 453 # Shorthands
448 454 shell = self.shell
449 455 pm = shell.prompt_manager
450 456 meta = shell.meta
451 457 disp_formatter = self.shell.display_formatter
452 458 ptformatter = disp_formatter.formatters['text/plain']
453 459 # dstore is a data store kept in the instance metadata bag to track any
454 460 # changes we make, so we can undo them later.
455 461 dstore = meta.setdefault('doctest_mode',Struct())
456 462 save_dstore = dstore.setdefault
457 463
458 464 # save a few values we'll need to recover later
459 465 mode = save_dstore('mode',False)
460 466 save_dstore('rc_pprint',ptformatter.pprint)
461 467 save_dstore('xmode',shell.InteractiveTB.mode)
462 468 save_dstore('rc_separate_out',shell.separate_out)
463 469 save_dstore('rc_separate_out2',shell.separate_out2)
464 470 save_dstore('rc_prompts_pad_left',pm.justify)
465 471 save_dstore('rc_separate_in',shell.separate_in)
466 472 save_dstore('rc_active_types',disp_formatter.active_types)
467 473 save_dstore('prompt_templates',(pm.in_template, pm.in2_template, pm.out_template))
468 474
469 475 if mode == False:
470 476 # turn on
471 477 pm.in_template = '>>> '
472 478 pm.in2_template = '... '
473 479 pm.out_template = ''
474 480
475 481 # Prompt separators like plain python
476 482 shell.separate_in = ''
477 483 shell.separate_out = ''
478 484 shell.separate_out2 = ''
479 485
480 486 pm.justify = False
481 487
482 488 ptformatter.pprint = False
483 489 disp_formatter.active_types = ['text/plain']
484 490
485 491 shell.magic('xmode Plain')
486 492 else:
487 493 # turn off
488 494 pm.in_template, pm.in2_template, pm.out_template = dstore.prompt_templates
489 495
490 496 shell.separate_in = dstore.rc_separate_in
491 497
492 498 shell.separate_out = dstore.rc_separate_out
493 499 shell.separate_out2 = dstore.rc_separate_out2
494 500
495 501 pm.justify = dstore.rc_prompts_pad_left
496 502
497 503 ptformatter.pprint = dstore.rc_pprint
498 504 disp_formatter.active_types = dstore.rc_active_types
499 505
500 506 shell.magic('xmode ' + dstore.xmode)
501 507
502 508 # Store new mode and inform
503 509 dstore.mode = bool(1-int(mode))
504 510 mode_label = ['OFF','ON'][dstore.mode]
505 511 print('Doctest mode is:', mode_label)
506 512
507 513 @line_magic
508 514 def gui(self, parameter_s=''):
509 515 """Enable or disable IPython GUI event loop integration.
510 516
511 517 %gui [GUINAME]
512 518
513 519 This magic replaces IPython's threaded shells that were activated
514 520 using the (pylab/wthread/etc.) command line flags. GUI toolkits
515 521 can now be enabled at runtime and keyboard
516 522 interrupts should work without any problems. The following toolkits
517 523 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
518 524
519 525 %gui wx # enable wxPython event loop integration
520 526 %gui qt4|qt # enable PyQt4 event loop integration
521 527 %gui gtk # enable PyGTK event loop integration
522 528 %gui gtk3 # enable Gtk3 event loop integration
523 529 %gui tk # enable Tk event loop integration
524 530 %gui osx # enable Cocoa event loop integration
525 531 # (requires %matplotlib 1.1)
526 532 %gui # disable all event loop integration
527 533
528 534 WARNING: after any of these has been called you can simply create
529 535 an application object, but DO NOT start the event loop yourself, as
530 536 we have already handled that.
531 537 """
532 538 opts, arg = self.parse_options(parameter_s, '')
533 539 if arg=='': arg = None
534 540 try:
535 541 return self.shell.enable_gui(arg)
536 542 except Exception as e:
537 543 # print simple error message, rather than traceback if we can't
538 544 # hook up the GUI
539 545 error(str(e))
540 546
541 547 @skip_doctest
542 548 @line_magic
543 549 def precision(self, s=''):
544 550 """Set floating point precision for pretty printing.
545 551
546 552 Can set either integer precision or a format string.
547 553
548 554 If numpy has been imported and precision is an int,
549 555 numpy display precision will also be set, via ``numpy.set_printoptions``.
550 556
551 557 If no argument is given, defaults will be restored.
552 558
553 559 Examples
554 560 --------
555 561 ::
556 562
557 563 In [1]: from math import pi
558 564
559 565 In [2]: %precision 3
560 566 Out[2]: u'%.3f'
561 567
562 568 In [3]: pi
563 569 Out[3]: 3.142
564 570
565 571 In [4]: %precision %i
566 572 Out[4]: u'%i'
567 573
568 574 In [5]: pi
569 575 Out[5]: 3
570 576
571 577 In [6]: %precision %e
572 578 Out[6]: u'%e'
573 579
574 580 In [7]: pi**10
575 581 Out[7]: 9.364805e+04
576 582
577 583 In [8]: %precision
578 584 Out[8]: u'%r'
579 585
580 586 In [9]: pi**10
581 587 Out[9]: 93648.047476082982
582 588 """
583 589 ptformatter = self.shell.display_formatter.formatters['text/plain']
584 590 ptformatter.float_precision = s
585 591 return ptformatter.float_format
586 592
587 593 @magic_arguments.magic_arguments()
588 594 @magic_arguments.argument(
589 595 '-e', '--export', action='store_true', default=False,
590 596 help='Export IPython history as a notebook. The filename argument '
591 597 'is used to specify the notebook name and format. For example '
592 598 'a filename of notebook.ipynb will result in a notebook name '
593 599 'of "notebook" and a format of "json". Likewise using a ".py" '
594 600 'file extension will write the notebook as a Python script'
595 601 )
596 602 @magic_arguments.argument(
597 603 '-f', '--format',
598 604 help='Convert an existing IPython notebook to a new format. This option '
599 605 'specifies the new format and can have the values: json, py. '
600 606 'The target filename is chosen automatically based on the new '
601 607 'format. The filename argument gives the name of the source file.'
602 608 )
603 609 @magic_arguments.argument(
604 610 'filename', type=unicode_type,
605 611 help='Notebook name or filename'
606 612 )
607 613 @line_magic
608 614 def notebook(self, s):
609 615 """Export and convert IPython notebooks.
610 616
611 617 This function can export the current IPython history to a notebook file
612 618 or can convert an existing notebook file into a different format. For
613 619 example, to export the history to "foo.ipynb" do "%notebook -e foo.ipynb".
614 620 To export the history to "foo.py" do "%notebook -e foo.py". To convert
615 621 "foo.ipynb" to "foo.json" do "%notebook -f json foo.ipynb". Possible
616 622 formats include (json/ipynb, py).
617 623 """
618 624 args = magic_arguments.parse_argstring(self.notebook, s)
619 625
620 626 from IPython.nbformat import current
621 627 args.filename = unquote_filename(args.filename)
622 628 if args.export:
623 629 fname, name, format = current.parse_filename(args.filename)
624 630 cells = []
625 631 hist = list(self.shell.history_manager.get_range())
626 632 for session, prompt_number, input in hist[:-1]:
627 633 cells.append(current.new_code_cell(prompt_number=prompt_number,
628 634 input=input))
629 635 worksheet = current.new_worksheet(cells=cells)
630 636 nb = current.new_notebook(name=name,worksheets=[worksheet])
631 637 with io.open(fname, 'w', encoding='utf-8') as f:
632 638 current.write(nb, f, format);
633 639 elif args.format is not None:
634 640 old_fname, old_name, old_format = current.parse_filename(args.filename)
635 641 new_format = args.format
636 642 if new_format == u'xml':
637 643 raise ValueError('Notebooks cannot be written as xml.')
638 644 elif new_format == u'ipynb' or new_format == u'json':
639 645 new_fname = old_name + u'.ipynb'
640 646 new_format = u'json'
641 647 elif new_format == u'py':
642 648 new_fname = old_name + u'.py'
643 649 else:
644 650 raise ValueError('Invalid notebook format: %s' % new_format)
645 651 with io.open(old_fname, 'r', encoding='utf-8') as f:
646 652 nb = current.read(f, old_format)
647 653 with io.open(new_fname, 'w', encoding='utf-8') as f:
648 654 current.write(nb, f, new_format)
General Comments 0
You need to be logged in to leave comments. Login now