##// END OF EJS Templates
Demo fixes, see changelog
fperez -
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,115 +1,149 b''
1 """Module for interactive demos using IPython.
1 """Module for interactive demos using IPython.
2
3 Sorry, but this uses Python 2.3 features, so it won't work in 2.2 environments.
2 """
4 """
3 #*****************************************************************************
5 #*****************************************************************************
4 # Copyright (C) 2005 Fernando Perez. <Fernando.Perez@colorado.edu>
6 # Copyright (C) 2005 Fernando Perez. <Fernando.Perez@colorado.edu>
5 #
7 #
6 # Distributed under the terms of the BSD License. The full license is in
8 # Distributed under the terms of the BSD License. The full license is in
7 # the file COPYING, distributed as part of this software.
9 # the file COPYING, distributed as part of this software.
8 #
10 #
9 #*****************************************************************************
11 #*****************************************************************************
10
12
11 import exceptions
13 import exceptions
14 import re
12
15
13 from IPython.PyColorize import Parser
16 from IPython.PyColorize import Parser
14 from IPython.genutils import marquee
17 from IPython.genutils import marquee
15
18
16 class DemoError(exceptions.Exception): pass
19 class DemoError(exceptions.Exception): pass
17
20
18 class Demo:
21 class Demo:
19 def __init__(self,fname,pause_mark='# pause',auto=False):
22 def __init__(self,fname,mark_pause='# pause',mark_silent='# silent',
23 auto=False):
24 """The marks are turned into regexps which match them as standalone in
25 a line, with all leading/trailing whitespace ignored."""
20
26
21 self.fname = fname
27 self.fname = fname
22 self.pause_mark = pause_mark
28 self.mark_pause = mark_pause
29 self.re_pause = re.compile(r'^\s*%s\s*$' % mark_pause,re.MULTILINE)
30 self.mark_silent = mark_silent
31 self.re_silent = re.compile(r'^\s*%s\s*$' % mark_silent,re.MULTILINE)
23 self.auto = auto
32 self.auto = auto
24
33
25 # get a few things from ipython. While it's a bit ugly design-wise,
34 # get a few things from ipython. While it's a bit ugly design-wise,
26 # it ensures that things like color scheme and the like are always in
35 # it ensures that things like color scheme and the like are always in
27 # sync with the ipython mode being used. This class is only meant to
36 # sync with the ipython mode being used. This class is only meant to
28 # be used inside ipython anyways, so it's OK.
37 # be used inside ipython anyways, so it's OK.
29 self.ip_showtraceback = __IPYTHON__.showtraceback
38 self.ip_showtraceback = __IPYTHON__.showtraceback
30 self.ip_ns = __IPYTHON__.user_ns
39 self.ip_ns = __IPYTHON__.user_ns
31 self.ip_colors = __IPYTHON__.rc['colors']
40 self.ip_colors = __IPYTHON__.rc['colors']
32
41
33 # read data and parse into blocks
42 # read data and parse into blocks
34 fobj = file(fname,'r')
43 fobj = file(fname,'r')
35 self.src = fobj.read()
44 self.src = fobj.read()
36 fobj.close()
45 fobj.close()
37 self.src_blocks = [b.strip() for b in self.src.split(pause_mark) if b]
46 self.src_blocks = [b.strip() for b in self.re_pause.split(self.src) if b]
47 self.silent = [bool(self.re_silent.findall(b)) for b in self.src_blocks]
38 self.nblocks = len(self.src_blocks)
48 self.nblocks = len(self.src_blocks)
39
49
40 # try to colorize blocks
50 # try to colorize blocks
41 colorize = Parser().format
51 colorize = Parser().format
42 col_scheme = self.ip_colors
52 col_scheme = self.ip_colors
43 self.src_blocks_colored = [colorize(s_blk,'str',col_scheme)
53 self.src_blocks_colored = [colorize(s_blk,'str',col_scheme)
44 for s_blk in self.src_blocks]
54 for s_blk in self.src_blocks]
45
55
46 # finish initialization
56 # finish initialization
47 self.reset()
57 self.reset()
48
58
49 def reset(self):
59 def reset(self):
60 """Reset the namespace and seek pointer to restart the demo"""
50 self.user_ns = {}
61 self.user_ns = {}
51 self.finished = False
62 self.finished = False
52 self.block_index = 0
63 self.block_index = 0
53
64
54 def again(self):
65 def again(self):
66 """Repeat the last block"""
55 self.block_index -= 1
67 self.block_index -= 1
56 self()
68 self()
57
69
58
59 def _validate_index(self,index):
70 def _validate_index(self,index):
60 if index<0 or index>=self.nblocks:
71 if index<0 or index>=self.nblocks:
61 raise ValueError('invalid block index %s' % index)
72 raise ValueError('invalid block index %s' % index)
62
73
63 def seek(self,index):
74 def seek(self,index):
75 """Move the current seek pointer to the given block"""
64 self._validate_index(index)
76 self._validate_index(index)
65 self.block_index = index-1
77 self.block_index = index-1
66 self.finished = False
78 self.finished = False
67
79
68 def show(self,index=None):
80 def show_block(self,index=None):
81 """Show a single block on screen"""
69 if index is None:
82 if index is None:
83 if self.finished:
84 print 'Demo finished. Use reset() if you want to rerun it.'
85 return
70 index = self.block_index
86 index = self.block_index
71 else:
87 else:
72 self._validate_index(index)
88 self._validate_index(index)
73 print marquee('<%s> block # %s (%s/%s)' %
89 print marquee('<%s> block # %s (%s/%s)' %
74 (self.fname,index,index+1,self.nblocks))
90 (self.fname,index,index+1,self.nblocks))
75 print self.src_blocks_colored[index],
91 print self.src_blocks_colored[index],
76
92
93 def show(self):
94 """Show entire demo on screen, block by block"""
95
96 fname = self.fname
97 nblocks = self.nblocks
98 silent = self.silent
99 for index,block in enumerate(self.src_blocks_colored):
100 if silent[index]:
101 print marquee('<%s> SILENT block # %s (%s/%s)' %
102 (fname,index,index+1,nblocks))
103 else:
104 print marquee('<%s> block # %s (%s/%s)' %
105 (fname,index,index+1,nblocks))
106 print block,
107
77 def __call__(self,index=None):
108 def __call__(self,index=None):
78 """run a block of the demo.
109 """run a block of the demo.
79
110
80 If index is given, it should be an integer >=1 and <= nblocks. This
111 If index is given, it should be an integer >=1 and <= nblocks. This
81 means that the calling convention is one off from typical Python
112 means that the calling convention is one off from typical Python
82 lists. The reason for the inconsistency is that the demo always
113 lists. The reason for the inconsistency is that the demo always
83 prints 'Block n/N, and N is the total, so it would be very odd to use
114 prints 'Block n/N, and N is the total, so it would be very odd to use
84 zero-indexing here."""
115 zero-indexing here."""
85
116
86 if index is None and self.finished:
117 if index is None and self.finished:
87 print 'Demo finished. Use reset() if you want to rerun it.'
118 print 'Demo finished. Use reset() if you want to rerun it.'
88 return
119 return
89 if index is None:
120 if index is None:
90 index = self.block_index
121 index = self.block_index
91 self._validate_index(index)
122 self._validate_index(index)
92 try:
123 try:
93 next_block = self.src_blocks[index]
124 next_block = self.src_blocks[index]
94 self.block_index += 1
125 self.block_index += 1
95 self.show(index)
126 if self.silent[index]:
127 print marquee('Executing silent block # %s (%s/%s)' %
128 (index,index+1,self.nblocks))
129 else:
130 self.show_block(index)
96 if not self.auto:
131 if not self.auto:
97 print marquee('Press <q> to quit, <Enter> to execute...'),
132 print marquee('Press <q> to quit, <Enter> to execute...'),
98 ans = raw_input().strip()
133 ans = raw_input().strip()
99 if ans:
134 if ans:
100 print marquee('Block NOT executed')
135 print marquee('Block NOT executed')
101 return
136 return
102
137
103 exec next_block in self.user_ns
138 exec next_block in self.user_ns
104
139
105 except:
140 except:
106 self.ip_showtraceback(filename=self.fname)
141 self.ip_showtraceback(filename=self.fname)
107 else:
142 else:
108 self.ip_ns.update(self.user_ns)
143 self.ip_ns.update(self.user_ns)
109
144
110 if self.block_index == self.nblocks:
145 if self.block_index == self.nblocks:
111 print
146 print
112 print marquee(' END OF DEMO ')
147 print marquee(' END OF DEMO ')
113 print marquee('Use reset() if you want to rerun it.')
148 print marquee('Use reset() if you want to rerun it.')
114 self.finished = True
149 self.finished = True
115
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now