##// END OF EJS Templates
Update python2 code example to python3, print '' -> print('')
TenzinRabgy -
Show More
@@ -1,672 +1,672 b''
1 1 """Module for interactive demos using IPython.
2 2
3 3 This module implements a few classes for running Python scripts interactively
4 4 in IPython for demonstrations. With very simple markup (a few tags in
5 5 comments), you can control points where the script stops executing and returns
6 6 control to IPython.
7 7
8 8
9 9 Provided classes
10 10 ----------------
11 11
12 12 The classes are (see their docstrings for further details):
13 13
14 14 - Demo: pure python demos
15 15
16 16 - IPythonDemo: demos with input to be processed by IPython as if it had been
17 17 typed interactively (so magics work, as well as any other special syntax you
18 18 may have added via input prefilters).
19 19
20 20 - LineDemo: single-line version of the Demo class. These demos are executed
21 21 one line at a time, and require no markup.
22 22
23 23 - IPythonLineDemo: IPython version of the LineDemo class (the demo is
24 24 executed a line at a time, but processed via IPython).
25 25
26 26 - ClearMixin: mixin to make Demo classes with less visual clutter. It
27 27 declares an empty marquee and a pre_cmd that clears the screen before each
28 28 block (see Subclassing below).
29 29
30 30 - ClearDemo, ClearIPDemo: mixin-enabled versions of the Demo and IPythonDemo
31 31 classes.
32 32
33 33 Inheritance diagram:
34 34
35 35 .. inheritance-diagram:: IPython.lib.demo
36 36 :parts: 3
37 37
38 38 Subclassing
39 39 -----------
40 40
41 41 The classes here all include a few methods meant to make customization by
42 42 subclassing more convenient. Their docstrings below have some more details:
43 43
44 44 - highlight(): format every block and optionally highlight comments and
45 45 docstring content.
46 46
47 47 - marquee(): generates a marquee to provide visible on-screen markers at each
48 48 block start and end.
49 49
50 50 - pre_cmd(): run right before the execution of each block.
51 51
52 52 - post_cmd(): run right after the execution of each block. If the block
53 53 raises an exception, this is NOT called.
54 54
55 55
56 56 Operation
57 57 ---------
58 58
59 59 The file is run in its own empty namespace (though you can pass it a string of
60 60 arguments as if in a command line environment, and it will see those as
61 61 sys.argv). But at each stop, the global IPython namespace is updated with the
62 62 current internal demo namespace, so you can work interactively with the data
63 63 accumulated so far.
64 64
65 65 By default, each block of code is printed (with syntax highlighting) before
66 66 executing it and you have to confirm execution. This is intended to show the
67 67 code to an audience first so you can discuss it, and only proceed with
68 68 execution once you agree. There are a few tags which allow you to modify this
69 69 behavior.
70 70
71 71 The supported tags are:
72 72
73 73 # <demo> stop
74 74
75 75 Defines block boundaries, the points where IPython stops execution of the
76 76 file and returns to the interactive prompt.
77 77
78 78 You can optionally mark the stop tag with extra dashes before and after the
79 79 word 'stop', to help visually distinguish the blocks in a text editor:
80 80
81 81 # <demo> --- stop ---
82 82
83 83
84 84 # <demo> silent
85 85
86 86 Make a block execute silently (and hence automatically). Typically used in
87 87 cases where you have some boilerplate or initialization code which you need
88 88 executed but do not want to be seen in the demo.
89 89
90 90 # <demo> auto
91 91
92 92 Make a block execute automatically, but still being printed. Useful for
93 93 simple code which does not warrant discussion, since it avoids the extra
94 94 manual confirmation.
95 95
96 96 # <demo> auto_all
97 97
98 98 This tag can _only_ be in the first block, and if given it overrides the
99 99 individual auto tags to make the whole demo fully automatic (no block asks
100 100 for confirmation). It can also be given at creation time (or the attribute
101 101 set later) to override what's in the file.
102 102
103 103 While _any_ python file can be run as a Demo instance, if there are no stop
104 104 tags the whole file will run in a single block (no different that calling
105 105 first %pycat and then %run). The minimal markup to make this useful is to
106 106 place a set of stop tags; the other tags are only there to let you fine-tune
107 107 the execution.
108 108
109 109 This is probably best explained with the simple example file below. You can
110 110 copy this into a file named ex_demo.py, and try running it via::
111 111
112 112 from IPython.lib.demo import Demo
113 113 d = Demo('ex_demo.py')
114 114 d()
115 115
116 116 Each time you call the demo object, it runs the next block. The demo object
117 117 has a few useful methods for navigation, like again(), edit(), jump(), seek()
118 118 and back(). It can be reset for a new run via reset() or reloaded from disk
119 119 (in case you've edited the source) via reload(). See their docstrings below.
120 120
121 121 Note: To make this simpler to explore, a file called "demo-exercizer.py" has
122 122 been added to the "docs/examples/core" directory. Just cd to this directory in
123 123 an IPython session, and type::
124 124
125 125 %run demo-exercizer.py
126 126
127 127 and then follow the directions.
128 128
129 129 Example
130 130 -------
131 131
132 132 The following is a very simple example of a valid demo file.
133 133
134 134 ::
135 135
136 136 #################### EXAMPLE DEMO <ex_demo.py> ###############################
137 137 '''A simple interactive demo to illustrate the use of IPython's Demo class.'''
138 138
139 print 'Hello, welcome to an interactive IPython demo.'
139 print('Hello, welcome to an interactive IPython demo.')
140 140
141 141 # The mark below defines a block boundary, which is a point where IPython will
142 142 # stop execution and return to the interactive prompt. The dashes are actually
143 143 # optional and used only as a visual aid to clearly separate blocks while
144 144 # editing the demo code.
145 145 # <demo> stop
146 146
147 147 x = 1
148 148 y = 2
149 149
150 150 # <demo> stop
151 151
152 152 # the mark below makes this block as silent
153 153 # <demo> silent
154 154
155 print 'This is a silent block, which gets executed but not printed.'
155 print('This is a silent block, which gets executed but not printed.')
156 156
157 157 # <demo> stop
158 158 # <demo> auto
159 print 'This is an automatic block.'
160 print 'It is executed without asking for confirmation, but printed.'
161 z = x+y
159 print('This is an automatic block.')
160 print('It is executed without asking for confirmation, but printed.')
161 z = x + y
162 162
163 print 'z=',x
163 print('z =', x)
164 164
165 165 # <demo> stop
166 166 # This is just another normal block.
167 print 'z is now:', z
167 print('z is now:', z)
168 168
169 print 'bye!'
169 print('bye!')
170 170 ################### END EXAMPLE DEMO <ex_demo.py> ############################
171 171 """
172 172
173 173
174 174 #*****************************************************************************
175 175 # Copyright (C) 2005-2006 Fernando Perez. <Fernando.Perez@colorado.edu>
176 176 #
177 177 # Distributed under the terms of the BSD License. The full license is in
178 178 # the file COPYING, distributed as part of this software.
179 179 #
180 180 #*****************************************************************************
181 181
182 182 import os
183 183 import re
184 184 import shlex
185 185 import sys
186 186 import pygments
187 187 from pathlib import Path
188 188
189 189 from IPython.utils.text import marquee
190 190 from IPython.utils import openpy
191 191 from IPython.utils import py3compat
192 192 __all__ = ['Demo','IPythonDemo','LineDemo','IPythonLineDemo','DemoError']
193 193
194 194 class DemoError(Exception): pass
195 195
196 196 def re_mark(mark):
197 197 return re.compile(r'^\s*#\s+<demo>\s+%s\s*$' % mark,re.MULTILINE)
198 198
199 199 class Demo(object):
200 200
201 201 re_stop = re_mark(r'-*\s?stop\s?-*')
202 202 re_silent = re_mark('silent')
203 203 re_auto = re_mark('auto')
204 204 re_auto_all = re_mark('auto_all')
205 205
206 206 def __init__(self,src,title='',arg_str='',auto_all=None, format_rst=False,
207 207 formatter='terminal', style='default'):
208 208 """Make a new demo object. To run the demo, simply call the object.
209 209
210 210 See the module docstring for full details and an example (you can use
211 211 IPython.Demo? in IPython to see it).
212 212
213 213 Inputs:
214 214
215 215 - src is either a file, or file-like object, or a
216 216 string that can be resolved to a filename.
217 217
218 218 Optional inputs:
219 219
220 220 - title: a string to use as the demo name. Of most use when the demo
221 221 you are making comes from an object that has no filename, or if you
222 222 want an alternate denotation distinct from the filename.
223 223
224 224 - arg_str(''): a string of arguments, internally converted to a list
225 225 just like sys.argv, so the demo script can see a similar
226 226 environment.
227 227
228 228 - auto_all(None): global flag to run all blocks automatically without
229 229 confirmation. This attribute overrides the block-level tags and
230 230 applies to the whole demo. It is an attribute of the object, and
231 231 can be changed at runtime simply by reassigning it to a boolean
232 232 value.
233 233
234 234 - format_rst(False): a bool to enable comments and doc strings
235 235 formatting with pygments rst lexer
236 236
237 237 - formatter('terminal'): a string of pygments formatter name to be
238 238 used. Useful values for terminals: terminal, terminal256,
239 239 terminal16m
240 240
241 241 - style('default'): a string of pygments style name to be used.
242 242 """
243 243 if hasattr(src, "read"):
244 244 # It seems to be a file or a file-like object
245 245 self.fname = "from a file-like object"
246 246 if title == '':
247 247 self.title = "from a file-like object"
248 248 else:
249 249 self.title = title
250 250 else:
251 251 # Assume it's a string or something that can be converted to one
252 252 self.fname = src
253 253 if title == '':
254 254 (filepath, filename) = os.path.split(src)
255 255 self.title = filename
256 256 else:
257 257 self.title = title
258 258 self.sys_argv = [src] + shlex.split(arg_str)
259 259 self.auto_all = auto_all
260 260 self.src = src
261 261
262 262 try:
263 263 ip = get_ipython() # this is in builtins whenever IPython is running
264 264 self.inside_ipython = True
265 265 except NameError:
266 266 self.inside_ipython = False
267 267
268 268 if self.inside_ipython:
269 269 # get a few things from ipython. While it's a bit ugly design-wise,
270 270 # it ensures that things like color scheme and the like are always in
271 271 # sync with the ipython mode being used. This class is only meant to
272 272 # be used inside ipython anyways, so it's OK.
273 273 self.ip_ns = ip.user_ns
274 274 self.ip_colorize = ip.pycolorize
275 275 self.ip_showtb = ip.showtraceback
276 276 self.ip_run_cell = ip.run_cell
277 277 self.shell = ip
278 278
279 279 self.formatter = pygments.formatters.get_formatter_by_name(formatter,
280 280 style=style)
281 281 self.python_lexer = pygments.lexers.get_lexer_by_name("py3")
282 282 self.format_rst = format_rst
283 283 if format_rst:
284 284 self.rst_lexer = pygments.lexers.get_lexer_by_name("rst")
285 285
286 286 # load user data and initialize data structures
287 287 self.reload()
288 288
289 289 def fload(self):
290 290 """Load file object."""
291 291 # read data and parse into blocks
292 292 if hasattr(self, 'fobj') and self.fobj is not None:
293 293 self.fobj.close()
294 294 if hasattr(self.src, "read"):
295 295 # It seems to be a file or a file-like object
296 296 self.fobj = self.src
297 297 else:
298 298 # Assume it's a string or something that can be converted to one
299 299 self.fobj = openpy.open(self.fname)
300 300
301 301 def reload(self):
302 302 """Reload source from disk and initialize state."""
303 303 self.fload()
304 304
305 305 self.src = "".join(openpy.strip_encoding_cookie(self.fobj))
306 306 src_b = [b.strip() for b in self.re_stop.split(self.src) if b]
307 307 self._silent = [bool(self.re_silent.findall(b)) for b in src_b]
308 308 self._auto = [bool(self.re_auto.findall(b)) for b in src_b]
309 309
310 310 # if auto_all is not given (def. None), we read it from the file
311 311 if self.auto_all is None:
312 312 self.auto_all = bool(self.re_auto_all.findall(src_b[0]))
313 313 else:
314 314 self.auto_all = bool(self.auto_all)
315 315
316 316 # Clean the sources from all markup so it doesn't get displayed when
317 317 # running the demo
318 318 src_blocks = []
319 319 auto_strip = lambda s: self.re_auto.sub('',s)
320 320 for i,b in enumerate(src_b):
321 321 if self._auto[i]:
322 322 src_blocks.append(auto_strip(b))
323 323 else:
324 324 src_blocks.append(b)
325 325 # remove the auto_all marker
326 326 src_blocks[0] = self.re_auto_all.sub('',src_blocks[0])
327 327
328 328 self.nblocks = len(src_blocks)
329 329 self.src_blocks = src_blocks
330 330
331 331 # also build syntax-highlighted source
332 332 self.src_blocks_colored = list(map(self.highlight,self.src_blocks))
333 333
334 334 # ensure clean namespace and seek offset
335 335 self.reset()
336 336
337 337 def reset(self):
338 338 """Reset the namespace and seek pointer to restart the demo"""
339 339 self.user_ns = {}
340 340 self.finished = False
341 341 self.block_index = 0
342 342
343 343 def _validate_index(self,index):
344 344 if index<0 or index>=self.nblocks:
345 345 raise ValueError('invalid block index %s' % index)
346 346
347 347 def _get_index(self,index):
348 348 """Get the current block index, validating and checking status.
349 349
350 350 Returns None if the demo is finished"""
351 351
352 352 if index is None:
353 353 if self.finished:
354 354 print('Demo finished. Use <demo_name>.reset() if you want to rerun it.')
355 355 return None
356 356 index = self.block_index
357 357 else:
358 358 self._validate_index(index)
359 359 return index
360 360
361 361 def seek(self,index):
362 362 """Move the current seek pointer to the given block.
363 363
364 364 You can use negative indices to seek from the end, with identical
365 365 semantics to those of Python lists."""
366 366 if index<0:
367 367 index = self.nblocks + index
368 368 self._validate_index(index)
369 369 self.block_index = index
370 370 self.finished = False
371 371
372 372 def back(self,num=1):
373 373 """Move the seek pointer back num blocks (default is 1)."""
374 374 self.seek(self.block_index-num)
375 375
376 376 def jump(self,num=1):
377 377 """Jump a given number of blocks relative to the current one.
378 378
379 379 The offset can be positive or negative, defaults to 1."""
380 380 self.seek(self.block_index+num)
381 381
382 382 def again(self):
383 383 """Move the seek pointer back one block and re-execute."""
384 384 self.back(1)
385 385 self()
386 386
387 387 def edit(self,index=None):
388 388 """Edit a block.
389 389
390 390 If no number is given, use the last block executed.
391 391
392 392 This edits the in-memory copy of the demo, it does NOT modify the
393 393 original source file. If you want to do that, simply open the file in
394 394 an editor and use reload() when you make changes to the file. This
395 395 method is meant to let you change a block during a demonstration for
396 396 explanatory purposes, without damaging your original script."""
397 397
398 398 index = self._get_index(index)
399 399 if index is None:
400 400 return
401 401 # decrease the index by one (unless we're at the very beginning), so
402 402 # that the default demo.edit() call opens up the sblock we've last run
403 403 if index>0:
404 404 index -= 1
405 405
406 406 filename = self.shell.mktempfile(self.src_blocks[index])
407 407 self.shell.hooks.editor(filename, 1)
408 408 with open(Path(filename), "r", encoding="utf-8") as f:
409 409 new_block = f.read()
410 410 # update the source and colored block
411 411 self.src_blocks[index] = new_block
412 412 self.src_blocks_colored[index] = self.highlight(new_block)
413 413 self.block_index = index
414 414 # call to run with the newly edited index
415 415 self()
416 416
417 417 def show(self,index=None):
418 418 """Show a single block on screen"""
419 419
420 420 index = self._get_index(index)
421 421 if index is None:
422 422 return
423 423
424 424 print(self.marquee('<%s> block # %s (%s remaining)' %
425 425 (self.title,index,self.nblocks-index-1)))
426 426 print(self.src_blocks_colored[index])
427 427 sys.stdout.flush()
428 428
429 429 def show_all(self):
430 430 """Show entire demo on screen, block by block"""
431 431
432 432 fname = self.title
433 433 title = self.title
434 434 nblocks = self.nblocks
435 435 silent = self._silent
436 436 marquee = self.marquee
437 437 for index,block in enumerate(self.src_blocks_colored):
438 438 if silent[index]:
439 439 print(marquee('<%s> SILENT block # %s (%s remaining)' %
440 440 (title,index,nblocks-index-1)))
441 441 else:
442 442 print(marquee('<%s> block # %s (%s remaining)' %
443 443 (title,index,nblocks-index-1)))
444 444 print(block, end=' ')
445 445 sys.stdout.flush()
446 446
447 447 def run_cell(self,source):
448 448 """Execute a string with one or more lines of code"""
449 449
450 450 exec(source, self.user_ns)
451 451
452 452 def __call__(self,index=None):
453 453 """run a block of the demo.
454 454
455 455 If index is given, it should be an integer >=1 and <= nblocks. This
456 456 means that the calling convention is one off from typical Python
457 457 lists. The reason for the inconsistency is that the demo always
458 458 prints 'Block n/N, and N is the total, so it would be very odd to use
459 459 zero-indexing here."""
460 460
461 461 index = self._get_index(index)
462 462 if index is None:
463 463 return
464 464 try:
465 465 marquee = self.marquee
466 466 next_block = self.src_blocks[index]
467 467 self.block_index += 1
468 468 if self._silent[index]:
469 469 print(marquee('Executing silent block # %s (%s remaining)' %
470 470 (index,self.nblocks-index-1)))
471 471 else:
472 472 self.pre_cmd()
473 473 self.show(index)
474 474 if self.auto_all or self._auto[index]:
475 475 print(marquee('output:'))
476 476 else:
477 477 print(marquee('Press <q> to quit, <Enter> to execute...'), end=' ')
478 478 ans = py3compat.input().strip()
479 479 if ans:
480 480 print(marquee('Block NOT executed'))
481 481 return
482 482 try:
483 483 save_argv = sys.argv
484 484 sys.argv = self.sys_argv
485 485 self.run_cell(next_block)
486 486 self.post_cmd()
487 487 finally:
488 488 sys.argv = save_argv
489 489
490 490 except:
491 491 if self.inside_ipython:
492 492 self.ip_showtb(filename=self.fname)
493 493 else:
494 494 if self.inside_ipython:
495 495 self.ip_ns.update(self.user_ns)
496 496
497 497 if self.block_index == self.nblocks:
498 498 mq1 = self.marquee('END OF DEMO')
499 499 if mq1:
500 500 # avoid spurious print if empty marquees are used
501 501 print()
502 502 print(mq1)
503 503 print(self.marquee('Use <demo_name>.reset() if you want to rerun it.'))
504 504 self.finished = True
505 505
506 506 # These methods are meant to be overridden by subclasses who may wish to
507 507 # customize the behavior of of their demos.
508 508 def marquee(self,txt='',width=78,mark='*'):
509 509 """Return the input string centered in a 'marquee'."""
510 510 return marquee(txt,width,mark)
511 511
512 512 def pre_cmd(self):
513 513 """Method called before executing each block."""
514 514 pass
515 515
516 516 def post_cmd(self):
517 517 """Method called after executing each block."""
518 518 pass
519 519
520 520 def highlight(self, block):
521 521 """Method called on each block to highlight it content"""
522 522 tokens = pygments.lex(block, self.python_lexer)
523 523 if self.format_rst:
524 524 from pygments.token import Token
525 525 toks = []
526 526 for token in tokens:
527 527 if token[0] == Token.String.Doc and len(token[1]) > 6:
528 528 toks += pygments.lex(token[1][:3], self.python_lexer)
529 529 # parse doc string content by rst lexer
530 530 toks += pygments.lex(token[1][3:-3], self.rst_lexer)
531 531 toks += pygments.lex(token[1][-3:], self.python_lexer)
532 532 elif token[0] == Token.Comment.Single:
533 533 toks.append((Token.Comment.Single, token[1][0]))
534 534 # parse comment content by rst lexer
535 535 # remove the extra newline added by rst lexer
536 536 toks += list(pygments.lex(token[1][1:], self.rst_lexer))[:-1]
537 537 else:
538 538 toks.append(token)
539 539 tokens = toks
540 540 return pygments.format(tokens, self.formatter)
541 541
542 542
543 543 class IPythonDemo(Demo):
544 544 """Class for interactive demos with IPython's input processing applied.
545 545
546 546 This subclasses Demo, but instead of executing each block by the Python
547 547 interpreter (via exec), it actually calls IPython on it, so that any input
548 548 filters which may be in place are applied to the input block.
549 549
550 550 If you have an interactive environment which exposes special input
551 551 processing, you can use this class instead to write demo scripts which
552 552 operate exactly as if you had typed them interactively. The default Demo
553 553 class requires the input to be valid, pure Python code.
554 554 """
555 555
556 556 def run_cell(self,source):
557 557 """Execute a string with one or more lines of code"""
558 558
559 559 self.shell.run_cell(source)
560 560
561 561 class LineDemo(Demo):
562 562 """Demo where each line is executed as a separate block.
563 563
564 564 The input script should be valid Python code.
565 565
566 566 This class doesn't require any markup at all, and it's meant for simple
567 567 scripts (with no nesting or any kind of indentation) which consist of
568 568 multiple lines of input to be executed, one at a time, as if they had been
569 569 typed in the interactive prompt.
570 570
571 571 Note: the input can not have *any* indentation, which means that only
572 572 single-lines of input are accepted, not even function definitions are
573 573 valid."""
574 574
575 575 def reload(self):
576 576 """Reload source from disk and initialize state."""
577 577 # read data and parse into blocks
578 578 self.fload()
579 579 lines = self.fobj.readlines()
580 580 src_b = [l for l in lines if l.strip()]
581 581 nblocks = len(src_b)
582 582 self.src = ''.join(lines)
583 583 self._silent = [False]*nblocks
584 584 self._auto = [True]*nblocks
585 585 self.auto_all = True
586 586 self.nblocks = nblocks
587 587 self.src_blocks = src_b
588 588
589 589 # also build syntax-highlighted source
590 590 self.src_blocks_colored = list(map(self.highlight,self.src_blocks))
591 591
592 592 # ensure clean namespace and seek offset
593 593 self.reset()
594 594
595 595
596 596 class IPythonLineDemo(IPythonDemo,LineDemo):
597 597 """Variant of the LineDemo class whose input is processed by IPython."""
598 598 pass
599 599
600 600
601 601 class ClearMixin(object):
602 602 """Use this mixin to make Demo classes with less visual clutter.
603 603
604 604 Demos using this mixin will clear the screen before every block and use
605 605 blank marquees.
606 606
607 607 Note that in order for the methods defined here to actually override those
608 608 of the classes it's mixed with, it must go /first/ in the inheritance
609 609 tree. For example:
610 610
611 611 class ClearIPDemo(ClearMixin,IPythonDemo): pass
612 612
613 613 will provide an IPythonDemo class with the mixin's features.
614 614 """
615 615
616 616 def marquee(self,txt='',width=78,mark='*'):
617 617 """Blank marquee that returns '' no matter what the input."""
618 618 return ''
619 619
620 620 def pre_cmd(self):
621 621 """Method called before executing each block.
622 622
623 623 This one simply clears the screen."""
624 624 from IPython.utils.terminal import _term_clear
625 625 _term_clear()
626 626
627 627 class ClearDemo(ClearMixin,Demo):
628 628 pass
629 629
630 630
631 631 class ClearIPDemo(ClearMixin,IPythonDemo):
632 632 pass
633 633
634 634
635 635 def slide(file_path, noclear=False, format_rst=True, formatter="terminal",
636 636 style="native", auto_all=False, delimiter='...'):
637 637 if noclear:
638 638 demo_class = Demo
639 639 else:
640 640 demo_class = ClearDemo
641 641 demo = demo_class(file_path, format_rst=format_rst, formatter=formatter,
642 642 style=style, auto_all=auto_all)
643 643 while not demo.finished:
644 644 demo()
645 645 try:
646 646 py3compat.input('\n' + delimiter)
647 647 except KeyboardInterrupt:
648 648 exit(1)
649 649
650 650 if __name__ == '__main__':
651 651 import argparse
652 652 parser = argparse.ArgumentParser(description='Run python demos')
653 653 parser.add_argument('--noclear', '-C', action='store_true',
654 654 help='Do not clear terminal on each slide')
655 655 parser.add_argument('--rst', '-r', action='store_true',
656 656 help='Highlight comments and dostrings as rst')
657 657 parser.add_argument('--formatter', '-f', default='terminal',
658 658 help='pygments formatter name could be: terminal, '
659 659 'terminal256, terminal16m')
660 660 parser.add_argument('--style', '-s', default='default',
661 661 help='pygments style name')
662 662 parser.add_argument('--auto', '-a', action='store_true',
663 663 help='Run all blocks automatically without'
664 664 'confirmation')
665 665 parser.add_argument('--delimiter', '-d', default='...',
666 666 help='slides delimiter added after each slide run')
667 667 parser.add_argument('file', nargs=1,
668 668 help='python demo file')
669 669 args = parser.parse_args()
670 670 slide(args.file[0], noclear=args.noclear, format_rst=args.rst,
671 671 formatter=args.formatter, style=args.style, auto_all=args.auto,
672 672 delimiter=args.delimiter)
General Comments 0
You need to be logged in to leave comments. Login now