Package gmisclib :: Module g2_select
[frames] | no frames]

Source Code for Module gmisclib.g2_select

  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   
15 -def filterlist(s, d, verbose=False):
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
31 -def filter_iter(s, d, verbose=False):
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
57 -def _compact(s):
58 if len(s) > 15: 59 return s[:12] + "..." 60 return s
61 62
63 -class selector_c(object):
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
83 - def set_code(self, code):
84 self.cc = compile(code, '<g2_select: %s>' % _compact(code), 'eval') 85 self.code = code
86
87 - def set_trap(self, exc, result):
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
109 - def globals(self, s):
110 exec s in self.g
111 112 113 CCSZ = 100 114 _ccache = {}
115 -def _compile(s):
116 # print 'Compile', s 117 try: 118 selector = _ccache[s] 119 except KeyError: 120 if len(_ccache) > CCSZ: 121 _ccache.pop() 122 _ccache[s] = selector_c(s) 123 selector = _ccache[s] 124 return selector
125 126
127 -def accept(s, d):
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
141 -def whynot(s, d):
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
154 -def why(s, d):
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
161 -def evaluate(s, d):
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
170 -def test():
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