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