##// END OF EJS Templates
Merging (slightly modified) Tom Fetherston's demo branch....
Fernando Perez -
r2102:d3a059eb merge
parent child Browse files
Show More
@@ -0,0 +1,85 b''
1 """This is meant to be run from the IPython prompt:
2
3 %run demo-exercizer.py
4
5 It will create demo objects of the example that is embedded in demo.py in a
6 number of ways and allow you to see how they work, just follow the printed
7 directions."""
8
9 #-----------------------------------------------------------------------------
10 # Imports
11 #-----------------------------------------------------------------------------
12
13 # From std lib
14 import StringIO
15 import os
16 import shutil
17 import tempfile
18
19 # From IPython
20 from IPython.demo import (Demo, IPythonDemo, LineDemo, IPythonLineDemo,
21 ClearDemo, ClearIPDemo)
22
23 #-----------------------------------------------------------------------------
24 # Demo code
25 #-----------------------------------------------------------------------------
26
27 example1 = """
28 '''A simple interactive demo to illustrate the use of IPython's Demo class.'''
29
30 print 'Hello, welcome to an interactive IPython demo.'
31
32 # The mark below defines a block boundary, which is a point where IPython will
33 # stop execution and return to the interactive prompt. The dashes are actually
34 # optional and used only as a visual aid to clearly separate blocks while
35 # editing the demo code.
36 # <demo> stop
37
38 x = 1
39 y = 2
40
41 # <demo> stop
42
43 # the mark below makes this block as silent
44 # <demo> silent
45
46 print 'This is a silent block, which gets executed but not printed.'
47
48 # <demo> stop
49 # <demo> auto
50 print 'This is an automatic block.'
51 print 'It is executed without asking for confirmation, but printed.'
52 z = x+y
53
54 print 'z=',x
55
56 # <demo> stop
57 # This is just another normal block.
58 print 'z is now:', z
59
60 print 'bye!'
61 """
62 fp = tempfile.mkdtemp(prefix = 'DemoTmp')
63 fd, filename = tempfile.mkstemp(prefix = 'demoExample1File', suffix = '.py',
64 dir = fp)
65 f = os.fdopen(fd, 'wt')
66
67 f.write(example1)
68 f.close()
69
70 my_d = Demo(filename)
71 my_cd = ClearDemo(filename)
72
73 fobj = StringIO.StringIO(example1)
74 str_d = Demo(fobj, title='via stringio')
75
76 print '''
77 The example that is embeded in demo.py file has been used to create
78 the following 3 demos, and should now be available to use:
79 my_d() -- created from a file
80 my_cd() -- created from a file, a ClearDemo
81 str_d() -- same as above, but created via a StringIO object
82 Call by typing their name, (with parentheses), at the
83 ipython prompt, interact with the block, then call again
84 to run the next block.
85 '''
@@ -111,6 +111,13 b' has a few useful methods for navigation, like again(), edit(), jump(), seek()'
111 and back(). It can be reset for a new run via reset() or reloaded from disk
111 and back(). It can be reset for a new run via reset() or reloaded from disk
112 (in case you've edited the source) via reload(). See their docstrings below.
112 (in case you've edited the source) via reload(). See their docstrings below.
113
113
114 Note: To make this simpler to explore, a file called "demo-exercizer.py" has
115 been added to the "docs/examples/core" directory. Just cd to this directory in
116 an IPython session, and type::
117
118 %run demo-exercizer.py
119
120 and then follow the directions.
114
121
115 Example
122 Example
116 =======
123 =======
@@ -125,7 +132,7 b" print 'Hello, welcome to an interactive IPython demo.'"
125 # The mark below defines a block boundary, which is a point where IPython will
132 # The mark below defines a block boundary, which is a point where IPython will
126 # stop execution and return to the interactive prompt. The dashes are actually
133 # stop execution and return to the interactive prompt. The dashes are actually
127 # optional and used only as a visual aid to clearly separate blocks while
134 # optional and used only as a visual aid to clearly separate blocks while
128 editing the demo code.
135 # editing the demo code.
129 # <demo> stop
136 # <demo> stop
130
137
131 x = 1
138 x = 1
@@ -169,7 +176,7 b' import shlex'
169 import sys
176 import sys
170
177
171 from IPython.PyColorize import Parser
178 from IPython.PyColorize import Parser
172 from IPython.genutils import marquee, file_read, file_readlines
179 from IPython.genutils import marquee, file_read, file_readlines, Term
173
180
174 __all__ = ['Demo','IPythonDemo','LineDemo','IPythonLineDemo','DemoError']
181 __all__ = ['Demo','IPythonDemo','LineDemo','IPythonLineDemo','DemoError']
175
182
@@ -185,7 +192,7 b' class Demo(object):'
185 re_auto = re_mark('auto')
192 re_auto = re_mark('auto')
186 re_auto_all = re_mark('auto_all')
193 re_auto_all = re_mark('auto_all')
187
194
188 def __init__(self,fname,arg_str='',auto_all=None):
195 def __init__(self,src,title='',arg_str='',auto_all=None):
189 """Make a new demo object. To run the demo, simply call the object.
196 """Make a new demo object. To run the demo, simply call the object.
190
197
191 See the module docstring for full details and an example (you can use
198 See the module docstring for full details and an example (you can use
@@ -193,9 +200,14 b' class Demo(object):'
193
200
194 Inputs:
201 Inputs:
195
202
196 - fname = filename.
203 - src is either a file, or file-like object, or a
204 string that can be resolved to a filename.
197
205
198 Optional inputs:
206 Optional inputs:
207
208 - title: a string to use as the demo name. Of most use when the demo
209 you are making comes from an object that has no filename, or if you
210 want an alternate denotation distinct from the filename.
199
211
200 - arg_str(''): a string of arguments, internally converted to a list
212 - arg_str(''): a string of arguments, internally converted to a list
201 just like sys.argv, so the demo script can see a similar
213 just like sys.argv, so the demo script can see a similar
@@ -207,9 +219,24 b' class Demo(object):'
207 can be changed at runtime simply by reassigning it to a boolean
219 can be changed at runtime simply by reassigning it to a boolean
208 value.
220 value.
209 """
221 """
210
222 if hasattr(src, "read"):
211 self.fname = fname
223 # It seems to be a file or a file-like object
212 self.sys_argv = [fname] + shlex.split(arg_str)
224 self.fobj = src
225 self.fname = "from a file-like object"
226 if title == '':
227 self.title = "from a file-like object"
228 else:
229 self.title = title
230 else:
231 # Assume it's a string or something that can be converted to one
232 self.fobj = open(src)
233 self.fname = src
234 if title == '':
235 (filepath, filename) = os.path.split(src)
236 self.title = filename
237 else:
238 self.title = title
239 self.sys_argv = [src] + shlex.split(arg_str)
213 self.auto_all = auto_all
240 self.auto_all = auto_all
214
241
215 # get a few things from ipython. While it's a bit ugly design-wise,
242 # get a few things from ipython. While it's a bit ugly design-wise,
@@ -228,7 +255,7 b' class Demo(object):'
228 def reload(self):
255 def reload(self):
229 """Reload source from disk and initialize state."""
256 """Reload source from disk and initialize state."""
230 # read data and parse into blocks
257 # read data and parse into blocks
231 self.src = file_read(self.fname)
258 self.src = self.fobj.read()
232 src_b = [b.strip() for b in self.re_stop.split(self.src) if b]
259 src_b = [b.strip() for b in self.re_stop.split(self.src) if b]
233 self._silent = [bool(self.re_silent.findall(b)) for b in src_b]
260 self._silent = [bool(self.re_silent.findall(b)) for b in src_b]
234 self._auto = [bool(self.re_auto.findall(b)) for b in src_b]
261 self._auto = [bool(self.re_auto.findall(b)) for b in src_b]
@@ -277,7 +304,7 b' class Demo(object):'
277
304
278 if index is None:
305 if index is None:
279 if self.finished:
306 if self.finished:
280 print 'Demo finished. Use reset() if you want to rerun it.'
307 print >>Term.cout, 'Demo finished. Use <demo_name>.reset() if you want to rerun it.'
281 return None
308 return None
282 index = self.block_index
309 index = self.block_index
283 else:
310 else:
@@ -346,26 +373,27 b' class Demo(object):'
346 if index is None:
373 if index is None:
347 return
374 return
348
375
349 print self.marquee('<%s> block # %s (%s remaining)' %
376 print >>Term.cout, self.marquee('<%s> block # %s (%s remaining)' %
350 (self.fname,index,self.nblocks-index-1))
377 (self.title,index,self.nblocks-index-1))
351 sys.stdout.write(self.src_blocks_colored[index])
378 print >>Term.cout,(self.src_blocks_colored[index])
352 sys.stdout.flush()
379 sys.stdout.flush()
353
380
354 def show_all(self):
381 def show_all(self):
355 """Show entire demo on screen, block by block"""
382 """Show entire demo on screen, block by block"""
356
383
357 fname = self.fname
384 fname = self.title
385 title = self.title
358 nblocks = self.nblocks
386 nblocks = self.nblocks
359 silent = self._silent
387 silent = self._silent
360 marquee = self.marquee
388 marquee = self.marquee
361 for index,block in enumerate(self.src_blocks_colored):
389 for index,block in enumerate(self.src_blocks_colored):
362 if silent[index]:
390 if silent[index]:
363 print marquee('<%s> SILENT block # %s (%s remaining)' %
391 print >>Term.cout, marquee('<%s> SILENT block # %s (%s remaining)' %
364 (fname,index,nblocks-index-1))
392 (title,index,nblocks-index-1))
365 else:
393 else:
366 print marquee('<%s> block # %s (%s remaining)' %
394 print >>Term.cout, marquee('<%s> block # %s (%s remaining)' %
367 (fname,index,nblocks-index-1))
395 (title,index,nblocks-index-1))
368 print block,
396 print >>Term.cout, block,
369 sys.stdout.flush()
397 sys.stdout.flush()
370
398
371 def runlines(self,source):
399 def runlines(self,source):
@@ -390,18 +418,18 b' class Demo(object):'
390 next_block = self.src_blocks[index]
418 next_block = self.src_blocks[index]
391 self.block_index += 1
419 self.block_index += 1
392 if self._silent[index]:
420 if self._silent[index]:
393 print marquee('Executing silent block # %s (%s remaining)' %
421 print >>Term.cout, marquee('Executing silent block # %s (%s remaining)' %
394 (index,self.nblocks-index-1))
422 (index,self.nblocks-index-1))
395 else:
423 else:
396 self.pre_cmd()
424 self.pre_cmd()
397 self.show(index)
425 self.show(index)
398 if self.auto_all or self._auto[index]:
426 if self.auto_all or self._auto[index]:
399 print marquee('output:')
427 print >>Term.cout, marquee('output:')
400 else:
428 else:
401 print marquee('Press <q> to quit, <Enter> to execute...'),
429 print >>Term.cout, marquee('Press <q> to quit, <Enter> to execute...'),
402 ans = raw_input().strip()
430 ans = raw_input().strip()
403 if ans:
431 if ans:
404 print marquee('Block NOT executed')
432 print >>Term.cout, marquee('Block NOT executed')
405 return
433 return
406 try:
434 try:
407 save_argv = sys.argv
435 save_argv = sys.argv
@@ -419,10 +447,10 b' class Demo(object):'
419 if self.block_index == self.nblocks:
447 if self.block_index == self.nblocks:
420 mq1 = self.marquee('END OF DEMO')
448 mq1 = self.marquee('END OF DEMO')
421 if mq1:
449 if mq1:
422 # avoid spurious prints if empty marquees are used
450 # avoid spurious print >>Term.cout,s if empty marquees are used
423 print
451 print >>Term.cout
424 print mq1
452 print >>Term.cout, mq1
425 print self.marquee('Use reset() if you want to rerun it.')
453 print >>Term.cout, self.marquee('Use <demo_name>.reset() if you want to rerun it.')
426 self.finished = True
454 self.finished = True
427
455
428 # These methods are meant to be overridden by subclasses who may wish to
456 # These methods are meant to be overridden by subclasses who may wish to
@@ -471,9 +499,9 b' class LineDemo(Demo):'
471 def reload(self):
499 def reload(self):
472 """Reload source from disk and initialize state."""
500 """Reload source from disk and initialize state."""
473 # read data and parse into blocks
501 # read data and parse into blocks
474 src_b = [l for l in file_readlines(self.fname) if l.strip()]
502 src_b = [l for l in self.fobj.readline() if l.strip()]
475 nblocks = len(src_b)
503 nblocks = len(src_b)
476 self.src = os.linesep.join(file_readlines(self.fname))
504 self.src = os.linesep.join(self.fobj.readlines())
477 self._silent = [False]*nblocks
505 self._silent = [False]*nblocks
478 self._auto = [True]*nblocks
506 self._auto = [True]*nblocks
479 self.auto_all = True
507 self.auto_all = True
@@ -494,29 +522,29 b' class IPythonLineDemo(IPythonDemo,LineDemo):'
494
522
495 class ClearMixin(object):
523 class ClearMixin(object):
496 """Use this mixin to make Demo classes with less visual clutter.
524 """Use this mixin to make Demo classes with less visual clutter.
497
525
498 Demos using this mixin will clear the screen before every block and use
526 Demos using this mixin will clear the screen before every block and use
499 blank marquees.
527 blank marquees.
500
528
501 Note that in order for the methods defined here to actually override those
529 Note that in order for the methods defined here to actually override those
502 of the classes it's mixed with, it must go /first/ in the inheritance
530 of the classes it's mixed with, it must go /first/ in the inheritance
503 tree. For example:
531 tree. For example:
504
532
505 class ClearIPDemo(ClearMixin,IPythonDemo): pass
533 class ClearIPDemo(ClearMixin,IPythonDemo): pass
506
534
507 will provide an IPythonDemo class with the mixin's features.
535 will provide an IPythonDemo class with the mixin's features.
508 """
536 """
509
537
510 def marquee(self,txt='',width=78,mark='*'):
538 def marquee(self,txt='',width=78,mark='*'):
511 """Blank marquee that returns '' no matter what the input."""
539 """Blank marquee that returns '' no matter what the input."""
512 return ''
540 return ''
513
541
514 def pre_cmd(self):
542 def pre_cmd(self):
515 """Method called before executing each block.
543 """Method called before executing each block.
516
544
517 This one simply clears the screen."""
545 This one simply clears the screen."""
518 os.system('clear')
546 import IPython.platutils
519
547 IPython.platutils.term_clear()
520
548
521 class ClearDemo(ClearMixin,Demo):
549 class ClearDemo(ClearMixin,Demo):
522 pass
550 pass
@@ -36,6 +36,9 b' else:'
36 # there is a public, cross-platform way of toggling the term title control on
36 # there is a public, cross-platform way of toggling the term title control on
37 # and off. We should make this a stateful object later on so that each user
37 # and off. We should make this a stateful object later on so that each user
38 # can have its own instance if needed.
38 # can have its own instance if needed.
39 def term_clear():
40 _platutils.term_clear()
41
39 def toggle_set_term_title(val):
42 def toggle_set_term_title(val):
40 """Control whether set_term_title is active or not.
43 """Control whether set_term_title is active or not.
41
44
@@ -101,6 +104,6 b' def get_long_path_name(path):'
101 # Deprecated functions
104 # Deprecated functions
102 #-----------------------------------------------------------------------------
105 #-----------------------------------------------------------------------------
103 def freeze_term_title():
106 def freeze_term_title():
107 import warnings
104 warnings.warn("This function is deprecated, use toggle_set_term_title()")
108 warnings.warn("This function is deprecated, use toggle_set_term_title()")
105 _platutils.ignore_termtitle = True
109 _platutils.ignore_termtitle = True
106
@@ -20,6 +20,7 b' ignore_termtitle = True'
20 def _dummy_op(*a, **b):
20 def _dummy_op(*a, **b):
21 """ A no-op function """
21 """ A no-op function """
22
22
23
23 def _set_term_title_xterm(title):
24 def _set_term_title_xterm(title):
24 """ Change virtual terminal title in xterm-workalikes """
25 """ Change virtual terminal title in xterm-workalikes """
25
26
@@ -31,10 +32,16 b" if os.environ.get('TERM','') == 'xterm':"
31 else:
32 else:
32 set_term_title = _dummy_op
33 set_term_title = _dummy_op
33
34
35
34 def find_cmd(cmd):
36 def find_cmd(cmd):
35 """Find the full path to a command using which."""
37 """Find the full path to a command using which."""
36 return os.popen('which %s' % cmd).read().strip()
38 return os.popen('which %s' % cmd).read().strip()
37
39
40
38 def get_long_path_name(path):
41 def get_long_path_name(path):
39 """Dummy no-op."""
42 """Dummy no-op."""
40 return path
43 return path
44
45
46 def term_clear():
47 os.system('clear')
@@ -42,6 +42,7 b' except ImportError:'
42 # non-zero return code signals error, don't try again
42 # non-zero return code signals error, don't try again
43 ignore_termtitle = True
43 ignore_termtitle = True
44
44
45
45 def find_cmd(cmd):
46 def find_cmd(cmd):
46 """Find the full path to a .bat or .exe using the win32api module."""
47 """Find the full path to a .bat or .exe using the win32api module."""
47 try:
48 try:
@@ -80,3 +81,7 b' def get_long_path_name(path):'
80 return path
81 return path
81 else:
82 else:
82 return buf.value
83 return buf.value
84
85
86 def term_clear():
87 os.system('cls')
General Comments 0
You need to be logged in to leave comments. Login now