1
2
3
4
5
6
7
8
9
10
11
12
13 import types
14 import simplejson
15
17
18 return "'%s'" % "''".join(s.split("'"))
19
20 -class Error(Exception): pass
21
23 "Base class for converting to/from javascript"
24 type = 'unknown'
28 return '%s:{type:"%s",label:"%s"}' % (name, self.type, self.label)
39
40 -class Text(WhereJavaScript):
41 "Convert to/from javascript for text entries"
42 type = 'text'
43 - def toJS(self, mode, value):
44 if mode == 'like':
45 if value.startswith('%') and not value.endswith('%'):
46 return '$', [value[1:]]
47 elif not value.startswith('%') and value.endswith('%'):
48 return '^', [value[:-1]]
49 elif value.startswith('%') and value.endswith('%'):
50 return '~', [value[1:-1]]
51 if mode == 'not like':
52 return '!~', [value[1:-1]]
53 if mode == '=':
54 return '', [value]
55 if mode == '!=':
56 return '!', [value]
57 - def buildClause1(self, name, v, mode):
58 if mode == '~':
59 return "%s like %s" % (name, q('%' + v + '%'))
60 if mode == '^':
61 return "%s like %s" % (name, q(v + '%'))
62 if mode == '$':
63 return "%s like %s" % (name, q('%' + v))
64 if mode == '!~':
65 return "%s not like %s" % (name, q('%' + v + '%'))
66 if mode == '':
67 return "%s = %s" % (name, q(v))
68 if mode == '!':
69 return "%s != %s" % (name, q(v))
70
71
73 "Convert to/from javascript and where clause element for select entries"
74 type = 'select'
84 return dict([(v, l) for l, v in self.options]).get(value, -1)
85 - def toJS(self, operator, value):
97 return '%s:{type:"%s",label:"%s", options:%r}' % (
98 name, self.type, self.label, [s[1] for s in self.options])
107
109 "Convert to/from javascript and where clause elements for numeric comparisons"
110 type = 'compare'
111 - def toJS(self, operator, value):
115
117 - def toJS(self, operator, value):
123 if mode == '':
124 return "%s like %s" % (name, q('%|' + v + '%'))
125 else:
126 return "%s not like %s" % (name, q('%|' + v + '%'))
127
129 type = 'evtClass'
130 - def toJS(self, operator, value):
141 if mode == '':
142 return "%s = %s" % (name, q(v))
143 elif mode == '^':
144 return "%s like %s" % (name, q(v + '%'))
145 elif mode == '!^':
146 return "%s not like %s" % (name, q(v + '%'))
147 else:
148 return "%s != %s" % (name, q(v))
149
150
151
153 "Convert to/from javascript and where clause elements for enumerated types"
154 type='cselect'
155 - def toJS(self, operator, value):
159
160 _Definitions = r'''
161 def u(s):
162 # turn string "'fo''o'" -> "fo'o"
163 c = s[0]
164 s = c.join(s.split(c+c))
165 return s[1:-1]
166
167 '''
168
169 _ParseSpec = r'''
170 parser WhereClause:
171 ignore: "[ \r\t\n]+"
172 token END: "$"
173 token NUM: "[0-9]+"
174 token VAR: "[a-zA-Z0-9_]+"
175 token BIN: ">=|<=|==|=|<|>|!=|<>"
176 token STR: r'"([^\\"]+|\\.)*"'
177 token STR2: r"'([^\\']+|\\.)*'"
178
179 rule goal: andexp ? END {{ return locals().get('andexp', None) }}
180
181 rule andexp: orexp {{ e = orexp }}
182 ( "and" orexp {{ e = ('and', e, orexp) }}
183 )* {{ return e }}
184
185 rule orexp: binary {{ e = binary }}
186 ( "or" binary {{ e = ('or', e, binary) }}
187 )* {{ return e }}
188
189 rule binary: term {{ e = term }}
190 ( BIN term {{ e = (BIN, e, term) }}
191 | 'like' term {{ e = ('like', e, term) }}
192 | 'not' 'like' term
193 {{ e = ('not like', e, term) }}
194 )* {{ return e }}
195
196 rule term: NUM {{ return int(NUM) }}
197 | VAR {{ return VAR }}
198 | STR {{ return u(STR) }}
199 | STR2 {{ return u(STR2) }}
200 | "\\(" andexp "\\)" {{ return andexp }}
201 '''
202
203
206 from yapps import grammar, yappsrt
207 from StringIO import StringIO
208 scanner = grammar.ParserDescriptionScanner(spec)
209 parser = grammar.ParserDescription(scanner)
210 parser = yappsrt.wrap_error_reporter(parser, 'Parser')
211 parser.preparser = _Definitions
212 parser.output = StringIO()
213 parser.generate_output()
214 exec parser.output.getvalue() in self.__dict__
215
216 where = _Parser(_ParseSpec)
217
219
220 lmeta = dict([(n.lower(), n) for n in meta.keys()])
221 tree = where.parse('goal', clause)
222 def recurse(root, result):
223 if type(root) == types.TupleType:
224 n = len(root)
225 if n == 1:
226 recurse(root[0], result)
227 op, name, value = root
228 if op in ('and', 'or'):
229 recurse(root[1], result)
230 recurse(root[2], result)
231 else:
232 name = lmeta.get(name.lower(), None)
233 if name is not None:
234 op, value = meta[name].toJS(op, value)
235 result.append([name, op, value])
236 result = []
237 recurse(tree, result)
238 result.sort()
239 return simplejson.dumps(result)
240
253
254
255 if __name__ == '__main__':
256 meta = {}
257 toJavaScript(meta, 'severity = 3 or severity = 4')
258 toJavaScript(meta, "severity >= 4 and eventState = 0 and prodState = 1000")
259 toJavaScript(meta, "severity >= 2 and eventState = 0 and prodState = 1000")
260 print toJavaScript(meta, '(prodState = 1000) and (eventState = 0 or eventState = 1) and (severity >= 3)')
261 print fromFormVariables(dict(severity='Info',
262 severity_mode='>',
263 eventState='New',
264 eventState_mode='=',
265 prodState='Production',
266 prodState_mode='='))
267