##// END OF EJS Templates
support running outside jupyter/ipython...
Moez Bouhlel -
Show More
@@ -41,6 +41,9 b' Subclassing'
41 The classes here all include a few methods meant to make customization by
41 The classes here all include a few methods meant to make customization by
42 subclassing more convenient. Their docstrings below have some more details:
42 subclassing more convenient. Their docstrings below have some more details:
43
43
44 - highlight(): format every block and optionally highlight comments and
45 docstring content.
46
44 - marquee(): generates a marquee to provide visible on-screen markers at each
47 - marquee(): generates a marquee to provide visible on-screen markers at each
45 block start and end.
48 block start and end.
46
49
@@ -182,6 +185,7 b' import os'
182 import re
185 import re
183 import shlex
186 import shlex
184 import sys
187 import sys
188 import pygments
185
189
186 from IPython.utils.text import marquee
190 from IPython.utils.text import marquee
187 from IPython.utils import openpy
191 from IPython.utils import openpy
@@ -200,7 +204,8 b' class Demo(object):'
200 re_auto = re_mark('auto')
204 re_auto = re_mark('auto')
201 re_auto_all = re_mark('auto_all')
205 re_auto_all = re_mark('auto_all')
202
206
203 def __init__(self,src,title='',arg_str='',auto_all=None):
207 def __init__(self,src,title='',arg_str='',auto_all=None, format_rst=False,
208 formatter='terminal', style='default'):
204 """Make a new demo object. To run the demo, simply call the object.
209 """Make a new demo object. To run the demo, simply call the object.
205
210
206 See the module docstring for full details and an example (you can use
211 See the module docstring for full details and an example (you can use
@@ -226,6 +231,15 b' class Demo(object):'
226 applies to the whole demo. It is an attribute of the object, and
231 applies to the whole demo. It is an attribute of the object, and
227 can be changed at runtime simply by reassigning it to a boolean
232 can be changed at runtime simply by reassigning it to a boolean
228 value.
233 value.
234
235 - format_rst(False): a bool to enable comments and doc strings
236 formating with pygments rst lexer
237
238 - formatter('terminal'): a string of pygments formatter name to be
239 used. Useful values for terminals: terminal, terminal256,
240 terminal16m
241
242 - style('default'): a string of pygments style name to be used.
229 """
243 """
230 if hasattr(src, "read"):
244 if hasattr(src, "read"):
231 # It seems to be a file or a file-like object
245 # It seems to be a file or a file-like object
@@ -246,16 +260,25 b' class Demo(object):'
246 self.auto_all = auto_all
260 self.auto_all = auto_all
247 self.src = src
261 self.src = src
248
262
249 # get a few things from ipython. While it's a bit ugly design-wise,
263 self.inside_ipython = "get_ipython" in globals()
250 # it ensures that things like color scheme and the like are always in
264 if self.inside_ipython:
251 # sync with the ipython mode being used. This class is only meant to
265 # get a few things from ipython. While it's a bit ugly design-wise,
252 # be used inside ipython anyways, so it's OK.
266 # it ensures that things like color scheme and the like are always in
253 ip = get_ipython() # this is in builtins whenever IPython is running
267 # sync with the ipython mode being used. This class is only meant to
254 self.ip_ns = ip.user_ns
268 # be used inside ipython anyways, so it's OK.
255 self.ip_colorize = ip.pycolorize
269 ip = get_ipython() # this is in builtins whenever IPython is running
256 self.ip_showtb = ip.showtraceback
270 self.ip_ns = ip.user_ns
257 self.ip_run_cell = ip.run_cell
271 self.ip_colorize = ip.pycolorize
258 self.shell = ip
272 self.ip_showtb = ip.showtraceback
273 self.ip_run_cell = ip.run_cell
274 self.shell = ip
275
276 self.formatter = pygments.formatters.get_formatter_by_name(formatter,
277 style=style)
278 self.python_lexer = pygments.lexers.get_lexer_by_name("py3")
279 self.format_rst = format_rst
280 if format_rst:
281 self.rst_lexer = pygments.lexers.get_lexer_by_name("rst")
259
282
260 # load user data and initialize data structures
283 # load user data and initialize data structures
261 self.reload()
284 self.reload()
@@ -303,7 +326,7 b' class Demo(object):'
303 self.src_blocks = src_blocks
326 self.src_blocks = src_blocks
304
327
305 # also build syntax-highlighted source
328 # also build syntax-highlighted source
306 self.src_blocks_colored = list(map(self.ip_colorize,self.src_blocks))
329 self.src_blocks_colored = list(map(self.highlight,self.src_blocks))
307
330
308 # ensure clean namespace and seek offset
331 # ensure clean namespace and seek offset
309 self.reset()
332 self.reset()
@@ -383,7 +406,7 b' class Demo(object):'
383 new_block = f.read()
406 new_block = f.read()
384 # update the source and colored block
407 # update the source and colored block
385 self.src_blocks[index] = new_block
408 self.src_blocks[index] = new_block
386 self.src_blocks_colored[index] = self.ip_colorize(new_block)
409 self.src_blocks_colored[index] = self.highlight(new_block)
387 self.block_index = index
410 self.block_index = index
388 # call to run with the newly edited index
411 # call to run with the newly edited index
389 self()
412 self()
@@ -462,9 +485,11 b' class Demo(object):'
462 sys.argv = save_argv
485 sys.argv = save_argv
463
486
464 except:
487 except:
465 self.ip_showtb(filename=self.fname)
488 if self.inside_ipython:
489 self.ip_showtb(filename=self.fname)
466 else:
490 else:
467 self.ip_ns.update(self.user_ns)
491 if self.inside_ipython:
492 self.ip_ns.update(self.user_ns)
468
493
469 if self.block_index == self.nblocks:
494 if self.block_index == self.nblocks:
470 mq1 = self.marquee('END OF DEMO')
495 mq1 = self.marquee('END OF DEMO')
@@ -489,6 +514,28 b' class Demo(object):'
489 """Method called after executing each block."""
514 """Method called after executing each block."""
490 pass
515 pass
491
516
517 def highlight(self, block):
518 """Method called on each block to highlight it content"""
519 tokens = pygments.lex(block, self.python_lexer)
520 if self.format_rst:
521 from pygments.token import Token
522 toks = []
523 for token in tokens:
524 if token[0] == Token.String.Doc and len(token[1]) > 6:
525 toks += pygments.lex(token[1][:3], self.python_lexer)
526 # parse doc string content by rst lexer
527 toks += pygments.lex(token[1][3:-3], self.rst_lexer)
528 toks += pygments.lex(token[1][-3:], self.python_lexer)
529 elif token[0] == Token.Comment.Single:
530 toks.append((Token.Comment.Single, token[1][0]))
531 # parse comment content by rst lexer
532 # remove the extrat newline added by rst lexer
533 toks += list(pygments.lex(token[1][1:], self.rst_lexer))[:-1]
534 else:
535 toks.append(token)
536 tokens = toks
537 return pygments.format(tokens, self.formatter)
538
492
539
493 class IPythonDemo(Demo):
540 class IPythonDemo(Demo):
494 """Class for interactive demos with IPython's input processing applied.
541 """Class for interactive demos with IPython's input processing applied.
@@ -537,7 +584,7 b' class LineDemo(Demo):'
537 self.src_blocks = src_b
584 self.src_blocks = src_b
538
585
539 # also build syntax-highlighted source
586 # also build syntax-highlighted source
540 self.src_blocks_colored = list(map(self.ip_colorize,self.src_blocks))
587 self.src_blocks_colored = list(map(self.highlight,self.src_blocks))
541
588
542 # ensure clean namespace and seek offset
589 # ensure clean namespace and seek offset
543 self.reset()
590 self.reset()
General Comments 0
You need to be logged in to leave comments. Login now