1 import math
2 from gmisclib import die
3 from gmisclib import avio
4 try:
5 from gmisclib import load_mod
6 except ImportError:
7 pass
8
9 """This lets you select lines from a list of dictionaries
10 by means of a little snippet of python code.
11 It can be used to select lines in a fiat or avio format file
12 (as read in by fiatio.read or avio.read).
13 """
14
16 """This filters a list of dictionaries, passing ones where
17 the X{selector} returns true.
18 @param s: the selector -- a little snippet of python
19 @type s: L{str}
20 @param d: the list of dictionaries.
21 Each dictionary is temporarily used as the local variable
22 space and the selector is evaluated.
23 @type d: C{ list(dict(str:value)) }
24 @return: a subset of the input list, whichever dictionaries cause
25 C{s} to return True when evaluated.
26 @rtype: C{ list(dict(str: value)) }
27 """
28 return list(filter_iter(s, d, verbose=verbose))
29
30
32 """This filters a list of lines, passing ones where
33 the selector returns true.
34 S is the selector -- a little snippet of python,
35 and d is the list of data : a list of {k:v} mappings.
36 """
37 nok = 0
38 nne = 0
39 x = None
40 cs = _compile(s)
41 for t in d:
42 try:
43 tmp = cs.eval(t)
44 if tmp:
45 if verbose:
46 die.info('filter_iter: %s -> %s' % (str(t), str(tmp)))
47 nok += 1
48 yield(t)
49 except NameError, x:
50 nne += 1
51 if verbose:
52 die.info('filter_iter: %s exception: %s' % (str(t), str(x)))
53 if nne>0 and nok==0:
54 die.warn('Name Error (%s) on each of the %d data.' % (str(x), nne))
55
56
58 if len(s) > 15:
59 return s[:12] + "..."
60 return s
61
62
64 - def __init__(self, code, global_values=None):
65 """Code = a string containing python code.
66 Global_values = a dictionary containing values to be used by
67 that python code. Note that the dictionary is not copied,
68 so that it is shared and changes will be noticed.
69 """
70 self.code = None
71 self.set_code(code)
72 if global_values is None:
73 self.g = {'math': math}
74 try:
75 self.g['load_mod'] = load_mod
76 except NameError:
77 pass
78 else:
79 self.g = global_values
80 self.traptuple = ()
81 self.trapmap = []
82
84 self.cc = compile(code, '<g2_select: %s>' % _compact(code), 'eval')
85 self.code = code
86
88 """This adds to a list of exceptions. If any of those exceptions
89 happen later, when you run C{self.eval()}, then they will be
90 caught and turned into the specified result.
91
92 For instance, if you call C{set_trap(ValueError, False)}, and
93 when you execute C{self.cc} in C{self.eval} a C{ValueError} is
94 raised, then C{self.eval()} will return C{False}. You have
95 mapped a C{ValueError} exception into a returned value of C{False}.
96 """
97 self.traptuple = self.traptuple + (exc,)
98 self.trapmap.append( (exc, result) )
99
100 - def eval(self, locals):
101 try:
102 return eval(self.cc, self.g, locals)
103 except self.traptuple, x:
104 for (e,r) in self.trapmap:
105 if isinstance(x, e):
106 return r
107 raise
108
111
112
113 CCSZ = 100
114 _ccache = {}
125
126
128 """This checks a single dictionary, and returns
129 the result of the selector. Errors in the evaluation
130 are trapped and cause accept() to return False.
131 S is the selector -- a little snippet of python,
132 and d is the data : a {k:v} mapping.
133 """
134 try:
135 return evaluate(s, d)
136 except NameError, x:
137 die.warn('Name Error: %s on %s in %s' % (str(x), avio.concoct(d), s))
138 return False
139
140
142 """Returns an explanation of why d was not accepted, given s, or None of d was accepted."""
143 try:
144 if _compile(s).eval(d):
145 return None
146 else:
147 return "Sorry, not implemented yet."
148 except NameError, x:
149 return "data does not contain attribute=%s (d=%s) (selector=%s)" % (x.args[0],
150 _compact(avio.concoct(d)),
151 _compact(s)
152 )
153
155 """Returns an explanation of why d was accepted, given s, or None if d was not accepted."""
156 if not accept(s, d):
157 return None
158 return "Sorry, not implemented yet."
159
160
162 """This checks a single dictionary, and returns
163 the result of the selector.
164 S is the selector -- a little snippet of python,
165 and d is the data : a {k:v} mapping.
166 """
167 return _compile(s).eval(d)
168
169
171 x = selector_c('y')
172 assert x.eval( {'y': 1} ) == 1
173 try:
174 x.eval( {} )
175 except NameError:
176 pass
177 else:
178 assert 0, 'Whoops! no exception when one was expected.'
179 z = selector_c('y+w', {'w':1})
180 assert z.eval( {'y': 1} ) == 2
181 z.globals('w=2')
182 assert z.eval( {'y': 1} ) == 3
183 x = selector_c('y')
184 x.set_trap(NameError, 44)
185 assert x.eval({}) == 44
186
187
188
189 if __name__ == '__main__':
190 test()
191