root / lib / qlang.py @ 178ad717
History | View | Annotate | Download (9.5 kB)
1 | a123dc19 | Michael Hanselmann | #
|
---|---|---|---|
2 | a123dc19 | Michael Hanselmann | #
|
3 | a123dc19 | Michael Hanselmann | |
4 | 2cfbc784 | Iustin Pop | # Copyright (C) 2010, 2011, 2012 Google Inc.
|
5 | a123dc19 | Michael Hanselmann | #
|
6 | a123dc19 | Michael Hanselmann | # This program is free software; you can redistribute it and/or modify
|
7 | a123dc19 | Michael Hanselmann | # it under the terms of the GNU General Public License as published by
|
8 | a123dc19 | Michael Hanselmann | # the Free Software Foundation; either version 2 of the License, or
|
9 | a123dc19 | Michael Hanselmann | # (at your option) any later version.
|
10 | a123dc19 | Michael Hanselmann | #
|
11 | a123dc19 | Michael Hanselmann | # This program is distributed in the hope that it will be useful, but
|
12 | a123dc19 | Michael Hanselmann | # WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 | a123dc19 | Michael Hanselmann | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 | a123dc19 | Michael Hanselmann | # General Public License for more details.
|
15 | a123dc19 | Michael Hanselmann | #
|
16 | a123dc19 | Michael Hanselmann | # You should have received a copy of the GNU General Public License
|
17 | a123dc19 | Michael Hanselmann | # along with this program; if not, write to the Free Software
|
18 | a123dc19 | Michael Hanselmann | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
19 | a123dc19 | Michael Hanselmann | # 02110-1301, USA.
|
20 | a123dc19 | Michael Hanselmann | |
21 | a123dc19 | Michael Hanselmann | |
22 | 341ff8e9 | Michael Hanselmann | """Module for a simple query language
|
23 | 341ff8e9 | Michael Hanselmann |
|
24 | 341ff8e9 | Michael Hanselmann | A query filter is always a list. The first item in the list is the operator
|
25 | 341ff8e9 | Michael Hanselmann | (e.g. C{[OP_AND, ...]}), while the other items depend on the operator. For
|
26 | 341ff8e9 | Michael Hanselmann | logic operators (e.g. L{OP_AND}, L{OP_OR}), they are subfilters whose results
|
27 | 341ff8e9 | Michael Hanselmann | are combined. Unary operators take exactly one other item (e.g. a subfilter for
|
28 | 341ff8e9 | Michael Hanselmann | L{OP_NOT} and a field name for L{OP_TRUE}). Binary operators take exactly two
|
29 | 341ff8e9 | Michael Hanselmann | operands, usually a field name and a value to compare against. Filters are
|
30 | 341ff8e9 | Michael Hanselmann | converted to callable functions by L{query._CompileFilter}.
|
31 | 341ff8e9 | Michael Hanselmann |
|
32 | 341ff8e9 | Michael Hanselmann | """
|
33 | a123dc19 | Michael Hanselmann | |
34 | 7578ab0a | Michael Hanselmann | import re |
35 | f8638e28 | Michael Hanselmann | import logging |
36 | 7578ab0a | Michael Hanselmann | |
37 | 7578ab0a | Michael Hanselmann | import pyparsing as pyp |
38 | 7578ab0a | Michael Hanselmann | |
39 | 67620dff | Jose A. Lopes | from ganeti import constants |
40 | 7578ab0a | Michael Hanselmann | from ganeti import errors |
41 | 16629d10 | Michael Hanselmann | from ganeti import utils |
42 | f8638e28 | Michael Hanselmann | from ganeti import compat |
43 | 7578ab0a | Michael Hanselmann | |
44 | 7578ab0a | Michael Hanselmann | |
45 | 67620dff | Jose A. Lopes | OP_OR = constants.QLANG_OP_OR |
46 | 67620dff | Jose A. Lopes | OP_AND = constants.QLANG_OP_AND |
47 | 67620dff | Jose A. Lopes | OP_NOT = constants.QLANG_OP_NOT |
48 | 67620dff | Jose A. Lopes | OP_TRUE = constants.QLANG_OP_TRUE |
49 | 67620dff | Jose A. Lopes | OP_EQUAL = constants.QLANG_OP_EQUAL |
50 | 67620dff | Jose A. Lopes | OP_NOT_EQUAL = constants.QLANG_OP_NOT_EQUAL |
51 | 67620dff | Jose A. Lopes | OP_LT = constants.QLANG_OP_LT |
52 | 67620dff | Jose A. Lopes | OP_LE = constants.QLANG_OP_LE |
53 | 67620dff | Jose A. Lopes | OP_GT = constants.QLANG_OP_GT |
54 | 67620dff | Jose A. Lopes | OP_GE = constants.QLANG_OP_GE |
55 | 67620dff | Jose A. Lopes | OP_REGEXP = constants.QLANG_OP_REGEXP |
56 | 67620dff | Jose A. Lopes | OP_CONTAINS = constants.QLANG_OP_CONTAINS |
57 | 67620dff | Jose A. Lopes | FILTER_DETECTION_CHARS = constants.QLANG_FILTER_DETECTION_CHARS |
58 | 67620dff | Jose A. Lopes | GLOB_DETECTION_CHARS = constants.QLANG_GLOB_DETECTION_CHARS |
59 | 3f2f55bb | Michael Hanselmann | |
60 | 3f2f55bb | Michael Hanselmann | |
61 | 60cba7f8 | Michael Hanselmann | def MakeSimpleFilter(namefield, values): |
62 | 31554d0a | Michael Hanselmann | """Builds simple a filter.
|
63 | 60cba7f8 | Michael Hanselmann |
|
64 | 60cba7f8 | Michael Hanselmann | @param namefield: Name of field containing item name
|
65 | 60cba7f8 | Michael Hanselmann | @param values: List of names
|
66 | 60cba7f8 | Michael Hanselmann |
|
67 | 60cba7f8 | Michael Hanselmann | """
|
68 | 60cba7f8 | Michael Hanselmann | if values:
|
69 | 60cba7f8 | Michael Hanselmann | return [OP_OR] + [[OP_EQUAL, namefield, i] for i in values] |
70 | 60cba7f8 | Michael Hanselmann | |
71 | 60cba7f8 | Michael Hanselmann | return None |
72 | 7578ab0a | Michael Hanselmann | |
73 | 7578ab0a | Michael Hanselmann | |
74 | 7578ab0a | Michael Hanselmann | def _ConvertLogicOp(op): |
75 | 7578ab0a | Michael Hanselmann | """Creates parsing action function for logic operator.
|
76 | 7578ab0a | Michael Hanselmann |
|
77 | 7578ab0a | Michael Hanselmann | @type op: string
|
78 | 7578ab0a | Michael Hanselmann | @param op: Operator for data structure, e.g. L{OP_AND}
|
79 | 7578ab0a | Michael Hanselmann |
|
80 | 7578ab0a | Michael Hanselmann | """
|
81 | 7578ab0a | Michael Hanselmann | def fn(toks): |
82 | 7578ab0a | Michael Hanselmann | """Converts parser tokens to query operator structure.
|
83 | 7578ab0a | Michael Hanselmann |
|
84 | 7578ab0a | Michael Hanselmann | @rtype: list
|
85 | 7578ab0a | Michael Hanselmann | @return: Query operator structure, e.g. C{[OP_AND, ["=", "foo", "bar"]]}
|
86 | 7578ab0a | Michael Hanselmann |
|
87 | 7578ab0a | Michael Hanselmann | """
|
88 | 7578ab0a | Michael Hanselmann | operands = toks[0]
|
89 | 7578ab0a | Michael Hanselmann | |
90 | 7578ab0a | Michael Hanselmann | if len(operands) == 1: |
91 | 7578ab0a | Michael Hanselmann | return operands[0] |
92 | 7578ab0a | Michael Hanselmann | |
93 | 7578ab0a | Michael Hanselmann | # Build query operator structure
|
94 | 7578ab0a | Michael Hanselmann | return [[op] + operands.asList()]
|
95 | 7578ab0a | Michael Hanselmann | |
96 | 7578ab0a | Michael Hanselmann | return fn
|
97 | 7578ab0a | Michael Hanselmann | |
98 | 7578ab0a | Michael Hanselmann | |
99 | 7578ab0a | Michael Hanselmann | _KNOWN_REGEXP_DELIM = "/#^|"
|
100 | 7578ab0a | Michael Hanselmann | _KNOWN_REGEXP_FLAGS = frozenset("si") |
101 | 7578ab0a | Michael Hanselmann | |
102 | 7578ab0a | Michael Hanselmann | |
103 | 7578ab0a | Michael Hanselmann | def _ConvertRegexpValue(_, loc, toks): |
104 | 7578ab0a | Michael Hanselmann | """Regular expression value for condition.
|
105 | 7578ab0a | Michael Hanselmann |
|
106 | 7578ab0a | Michael Hanselmann | """
|
107 | 7578ab0a | Michael Hanselmann | (regexp, flags) = toks[0]
|
108 | 7578ab0a | Michael Hanselmann | |
109 | 7578ab0a | Michael Hanselmann | # Ensure only whitelisted flags are used
|
110 | 7578ab0a | Michael Hanselmann | unknown_flags = (frozenset(flags) - _KNOWN_REGEXP_FLAGS)
|
111 | 7578ab0a | Michael Hanselmann | if unknown_flags:
|
112 | 7578ab0a | Michael Hanselmann | raise pyp.ParseFatalException("Unknown regular expression flags: '%s'" % |
113 | 7578ab0a | Michael Hanselmann | "".join(unknown_flags), loc)
|
114 | 7578ab0a | Michael Hanselmann | |
115 | 7578ab0a | Michael Hanselmann | if flags:
|
116 | 7578ab0a | Michael Hanselmann | re_flags = "(?%s)" % "".join(sorted(flags)) |
117 | 7578ab0a | Michael Hanselmann | else:
|
118 | 7578ab0a | Michael Hanselmann | re_flags = ""
|
119 | 7578ab0a | Michael Hanselmann | |
120 | 7578ab0a | Michael Hanselmann | re_cond = re_flags + regexp |
121 | 7578ab0a | Michael Hanselmann | |
122 | 7578ab0a | Michael Hanselmann | # Test if valid
|
123 | 7578ab0a | Michael Hanselmann | try:
|
124 | 7578ab0a | Michael Hanselmann | re.compile(re_cond) |
125 | 7578ab0a | Michael Hanselmann | except re.error, err:
|
126 | 7578ab0a | Michael Hanselmann | raise pyp.ParseFatalException("Invalid regular expression (%s)" % err, loc) |
127 | 7578ab0a | Michael Hanselmann | |
128 | 7578ab0a | Michael Hanselmann | return [re_cond]
|
129 | 7578ab0a | Michael Hanselmann | |
130 | 7578ab0a | Michael Hanselmann | |
131 | 7578ab0a | Michael Hanselmann | def BuildFilterParser(): |
132 | 7578ab0a | Michael Hanselmann | """Builds a parser for query filter strings.
|
133 | 7578ab0a | Michael Hanselmann |
|
134 | 7578ab0a | Michael Hanselmann | @rtype: pyparsing.ParserElement
|
135 | 7578ab0a | Michael Hanselmann |
|
136 | 7578ab0a | Michael Hanselmann | """
|
137 | 7578ab0a | Michael Hanselmann | field_name = pyp.Word(pyp.alphas, pyp.alphanums + "_/.")
|
138 | 7578ab0a | Michael Hanselmann | |
139 | 7578ab0a | Michael Hanselmann | # Integer
|
140 | 7578ab0a | Michael Hanselmann | num_sign = pyp.Word("-+", exact=1) |
141 | 7578ab0a | Michael Hanselmann | number = pyp.Combine(pyp.Optional(num_sign) + pyp.Word(pyp.nums)) |
142 | 7578ab0a | Michael Hanselmann | number.setParseAction(lambda toks: int(toks[0])) |
143 | 7578ab0a | Michael Hanselmann | |
144 | 16629d10 | Michael Hanselmann | quoted_string = pyp.quotedString.copy().setParseAction(pyp.removeQuotes) |
145 | 16629d10 | Michael Hanselmann | |
146 | 7578ab0a | Michael Hanselmann | # Right-hand-side value
|
147 | 16629d10 | Michael Hanselmann | rval = (number | quoted_string) |
148 | 7578ab0a | Michael Hanselmann | |
149 | 7578ab0a | Michael Hanselmann | # Boolean condition
|
150 | 7578ab0a | Michael Hanselmann | bool_cond = field_name.copy() |
151 | 7578ab0a | Michael Hanselmann | bool_cond.setParseAction(lambda (fname, ): [[OP_TRUE, fname]])
|
152 | 7578ab0a | Michael Hanselmann | |
153 | 7578ab0a | Michael Hanselmann | # Simple binary conditions
|
154 | 7578ab0a | Michael Hanselmann | binopstbl = { |
155 | 7578ab0a | Michael Hanselmann | "==": OP_EQUAL,
|
156 | 7578ab0a | Michael Hanselmann | "!=": OP_NOT_EQUAL,
|
157 | ad48eacc | Michael Hanselmann | "<": OP_LT,
|
158 | ad48eacc | Michael Hanselmann | "<=": OP_LE,
|
159 | ad48eacc | Michael Hanselmann | ">": OP_GT,
|
160 | ad48eacc | Michael Hanselmann | ">=": OP_GE,
|
161 | 7578ab0a | Michael Hanselmann | } |
162 | 7578ab0a | Michael Hanselmann | |
163 | 7578ab0a | Michael Hanselmann | binary_cond = (field_name + pyp.oneOf(binopstbl.keys()) + rval) |
164 | 7578ab0a | Michael Hanselmann | binary_cond.setParseAction(lambda (lhs, op, rhs): [[binopstbl[op], lhs, rhs]])
|
165 | 7578ab0a | Michael Hanselmann | |
166 | 7578ab0a | Michael Hanselmann | # "in" condition
|
167 | 7578ab0a | Michael Hanselmann | in_cond = (rval + pyp.Suppress("in") + field_name)
|
168 | 7578ab0a | Michael Hanselmann | in_cond.setParseAction(lambda (value, field): [[OP_CONTAINS, field, value]])
|
169 | 7578ab0a | Michael Hanselmann | |
170 | 7578ab0a | Michael Hanselmann | # "not in" condition
|
171 | 7578ab0a | Michael Hanselmann | not_in_cond = (rval + pyp.Suppress("not") + pyp.Suppress("in") + field_name) |
172 | 7578ab0a | Michael Hanselmann | not_in_cond.setParseAction(lambda (value, field): [[OP_NOT, [OP_CONTAINS,
|
173 | 7578ab0a | Michael Hanselmann | field, value]]]) |
174 | 7578ab0a | Michael Hanselmann | |
175 | 7578ab0a | Michael Hanselmann | # Regular expression, e.g. m/foobar/i
|
176 | 7578ab0a | Michael Hanselmann | regexp_val = pyp.Group(pyp.Optional("m").suppress() +
|
177 | 7578ab0a | Michael Hanselmann | pyp.MatchFirst([pyp.QuotedString(i, escChar="\\")
|
178 | 7578ab0a | Michael Hanselmann | for i in _KNOWN_REGEXP_DELIM]) + |
179 | 7578ab0a | Michael Hanselmann | pyp.Optional(pyp.Word(pyp.alphas), default=""))
|
180 | 7578ab0a | Michael Hanselmann | regexp_val.setParseAction(_ConvertRegexpValue) |
181 | 7578ab0a | Michael Hanselmann | regexp_cond = (field_name + pyp.Suppress("=~") + regexp_val)
|
182 | 7578ab0a | Michael Hanselmann | regexp_cond.setParseAction(lambda (field, value): [[OP_REGEXP, field, value]])
|
183 | 7578ab0a | Michael Hanselmann | |
184 | 7578ab0a | Michael Hanselmann | not_regexp_cond = (field_name + pyp.Suppress("!~") + regexp_val)
|
185 | 7578ab0a | Michael Hanselmann | not_regexp_cond.setParseAction(lambda (field, value):
|
186 | 7578ab0a | Michael Hanselmann | [[OP_NOT, [OP_REGEXP, field, value]]]) |
187 | 7578ab0a | Michael Hanselmann | |
188 | 16629d10 | Michael Hanselmann | # Globbing, e.g. name =* "*.site"
|
189 | 16629d10 | Michael Hanselmann | glob_cond = (field_name + pyp.Suppress("=*") + quoted_string)
|
190 | 16629d10 | Michael Hanselmann | glob_cond.setParseAction(lambda (field, value):
|
191 | 16629d10 | Michael Hanselmann | [[OP_REGEXP, field, |
192 | 16629d10 | Michael Hanselmann | utils.DnsNameGlobPattern(value)]]) |
193 | 16629d10 | Michael Hanselmann | |
194 | 16629d10 | Michael Hanselmann | not_glob_cond = (field_name + pyp.Suppress("!*") + quoted_string)
|
195 | 16629d10 | Michael Hanselmann | not_glob_cond.setParseAction(lambda (field, value):
|
196 | 16629d10 | Michael Hanselmann | [[OP_NOT, [OP_REGEXP, field, |
197 | 16629d10 | Michael Hanselmann | utils.DnsNameGlobPattern(value)]]]) |
198 | 16629d10 | Michael Hanselmann | |
199 | 7578ab0a | Michael Hanselmann | # All possible conditions
|
200 | 7578ab0a | Michael Hanselmann | condition = (binary_cond ^ bool_cond ^ |
201 | 7578ab0a | Michael Hanselmann | in_cond ^ not_in_cond ^ |
202 | 16629d10 | Michael Hanselmann | regexp_cond ^ not_regexp_cond ^ |
203 | 16629d10 | Michael Hanselmann | glob_cond ^ not_glob_cond) |
204 | 7578ab0a | Michael Hanselmann | |
205 | 7578ab0a | Michael Hanselmann | # Associativity operators
|
206 | 7578ab0a | Michael Hanselmann | filter_expr = pyp.operatorPrecedence(condition, [ |
207 | 7578ab0a | Michael Hanselmann | (pyp.Keyword("not").suppress(), 1, pyp.opAssoc.RIGHT, |
208 | 7578ab0a | Michael Hanselmann | lambda toks: [[OP_NOT, toks[0][0]]]), |
209 | 7578ab0a | Michael Hanselmann | (pyp.Keyword("and").suppress(), 2, pyp.opAssoc.LEFT, |
210 | 7578ab0a | Michael Hanselmann | _ConvertLogicOp(OP_AND)), |
211 | 7578ab0a | Michael Hanselmann | (pyp.Keyword("or").suppress(), 2, pyp.opAssoc.LEFT, |
212 | 7578ab0a | Michael Hanselmann | _ConvertLogicOp(OP_OR)), |
213 | 7578ab0a | Michael Hanselmann | ]) |
214 | 7578ab0a | Michael Hanselmann | |
215 | 7578ab0a | Michael Hanselmann | parser = pyp.StringStart() + filter_expr + pyp.StringEnd() |
216 | 7578ab0a | Michael Hanselmann | parser.parseWithTabs() |
217 | 7578ab0a | Michael Hanselmann | |
218 | 7578ab0a | Michael Hanselmann | # Originally C{parser.validate} was called here, but there seems to be some
|
219 | 7578ab0a | Michael Hanselmann | # issue causing it to fail whenever the "not" operator is included above.
|
220 | 7578ab0a | Michael Hanselmann | |
221 | 7578ab0a | Michael Hanselmann | return parser
|
222 | 7578ab0a | Michael Hanselmann | |
223 | 7578ab0a | Michael Hanselmann | |
224 | 7578ab0a | Michael Hanselmann | def ParseFilter(text, parser=None): |
225 | 7578ab0a | Michael Hanselmann | """Parses a query filter.
|
226 | 7578ab0a | Michael Hanselmann |
|
227 | 7578ab0a | Michael Hanselmann | @type text: string
|
228 | 7578ab0a | Michael Hanselmann | @param text: Query filter
|
229 | 7578ab0a | Michael Hanselmann | @type parser: pyparsing.ParserElement
|
230 | 7578ab0a | Michael Hanselmann | @param parser: Pyparsing object
|
231 | 7578ab0a | Michael Hanselmann | @rtype: list
|
232 | 7578ab0a | Michael Hanselmann |
|
233 | 7578ab0a | Michael Hanselmann | """
|
234 | f8638e28 | Michael Hanselmann | logging.debug("Parsing as query filter: %s", text)
|
235 | f8638e28 | Michael Hanselmann | |
236 | 7578ab0a | Michael Hanselmann | if parser is None: |
237 | 7578ab0a | Michael Hanselmann | parser = BuildFilterParser() |
238 | 7578ab0a | Michael Hanselmann | |
239 | 7578ab0a | Michael Hanselmann | try:
|
240 | 7578ab0a | Michael Hanselmann | return parser.parseString(text)[0] |
241 | 7578ab0a | Michael Hanselmann | except pyp.ParseBaseException, err:
|
242 | 7578ab0a | Michael Hanselmann | raise errors.QueryFilterParseError("Failed to parse query filter" |
243 | 7578ab0a | Michael Hanselmann | " '%s': %s" % (text, err), err)
|
244 | 3f2f55bb | Michael Hanselmann | |
245 | 3f2f55bb | Michael Hanselmann | |
246 | f8638e28 | Michael Hanselmann | def _CheckFilter(text): |
247 | f8638e28 | Michael Hanselmann | """CHecks if a string could be a filter.
|
248 | f8638e28 | Michael Hanselmann |
|
249 | f8638e28 | Michael Hanselmann | @rtype: bool
|
250 | f8638e28 | Michael Hanselmann |
|
251 | f8638e28 | Michael Hanselmann | """
|
252 | f8638e28 | Michael Hanselmann | return bool(frozenset(text) & FILTER_DETECTION_CHARS) |
253 | f8638e28 | Michael Hanselmann | |
254 | f8638e28 | Michael Hanselmann | |
255 | f8638e28 | Michael Hanselmann | def _CheckGlobbing(text): |
256 | f8638e28 | Michael Hanselmann | """Checks if a string could be a globbing pattern.
|
257 | f8638e28 | Michael Hanselmann |
|
258 | f8638e28 | Michael Hanselmann | @rtype: bool
|
259 | f8638e28 | Michael Hanselmann |
|
260 | f8638e28 | Michael Hanselmann | """
|
261 | f8638e28 | Michael Hanselmann | return bool(frozenset(text) & GLOB_DETECTION_CHARS) |
262 | f8638e28 | Michael Hanselmann | |
263 | f8638e28 | Michael Hanselmann | |
264 | 6f287cf3 | Iustin Pop | def _MakeFilterPart(namefield, text, isnumeric=False): |
265 | f8638e28 | Michael Hanselmann | """Generates filter for one argument.
|
266 | f8638e28 | Michael Hanselmann |
|
267 | f8638e28 | Michael Hanselmann | """
|
268 | 6f287cf3 | Iustin Pop | if isnumeric:
|
269 | 6f287cf3 | Iustin Pop | try:
|
270 | 6f287cf3 | Iustin Pop | number = int(text)
|
271 | 6f287cf3 | Iustin Pop | except (TypeError, ValueError), err: |
272 | 76b62028 | Iustin Pop | raise errors.OpPrereqError("Invalid job ID passed: %s" % str(err), |
273 | 6f287cf3 | Iustin Pop | errors.ECODE_INVAL) |
274 | 6f287cf3 | Iustin Pop | return [OP_EQUAL, namefield, number]
|
275 | 6f287cf3 | Iustin Pop | elif _CheckGlobbing(text):
|
276 | f8638e28 | Michael Hanselmann | return [OP_REGEXP, namefield, utils.DnsNameGlobPattern(text)]
|
277 | f8638e28 | Michael Hanselmann | else:
|
278 | f8638e28 | Michael Hanselmann | return [OP_EQUAL, namefield, text]
|
279 | f8638e28 | Michael Hanselmann | |
280 | f8638e28 | Michael Hanselmann | |
281 | 6f287cf3 | Iustin Pop | def MakeFilter(args, force_filter, namefield=None, isnumeric=False): |
282 | f8638e28 | Michael Hanselmann | """Try to make a filter from arguments to a command.
|
283 | f8638e28 | Michael Hanselmann |
|
284 | f8638e28 | Michael Hanselmann | If the name could be a filter it is parsed as such. If it's just a globbing
|
285 | f8638e28 | Michael Hanselmann | pattern, e.g. "*.site", such a filter is constructed. As a last resort the
|
286 | f8638e28 | Michael Hanselmann | names are treated just as a plain name filter.
|
287 | f8638e28 | Michael Hanselmann |
|
288 | f8638e28 | Michael Hanselmann | @type args: list of string
|
289 | f8638e28 | Michael Hanselmann | @param args: Arguments to command
|
290 | f8638e28 | Michael Hanselmann | @type force_filter: bool
|
291 | f8638e28 | Michael Hanselmann | @param force_filter: Whether to force treatment as a full-fledged filter
|
292 | 03ec545a | Michael Hanselmann | @type namefield: string
|
293 | 03ec545a | Michael Hanselmann | @param namefield: Name of field to use for simple filters (use L{None} for
|
294 | 03ec545a | Michael Hanselmann | a default of "name")
|
295 | 6f287cf3 | Iustin Pop | @type isnumeric: bool
|
296 | 6f287cf3 | Iustin Pop | @param isnumeric: Whether the namefield type is numeric, as opposed to
|
297 | 6f287cf3 | Iustin Pop | the default string type; this influences how the filter is built
|
298 | f8638e28 | Michael Hanselmann | @rtype: list
|
299 | f8638e28 | Michael Hanselmann | @return: Query filter
|
300 | f8638e28 | Michael Hanselmann |
|
301 | f8638e28 | Michael Hanselmann | """
|
302 | 03ec545a | Michael Hanselmann | if namefield is None: |
303 | 03ec545a | Michael Hanselmann | namefield = "name"
|
304 | 03ec545a | Michael Hanselmann | |
305 | f8638e28 | Michael Hanselmann | if (force_filter or |
306 | f8638e28 | Michael Hanselmann | (args and len(args) == 1 and _CheckFilter(args[0]))): |
307 | f8638e28 | Michael Hanselmann | try:
|
308 | f8638e28 | Michael Hanselmann | (filter_text, ) = args |
309 | f8638e28 | Michael Hanselmann | except (TypeError, ValueError): |
310 | f8638e28 | Michael Hanselmann | raise errors.OpPrereqError("Exactly one argument must be given as a" |
311 | 2cfbc784 | Iustin Pop | " filter", errors.ECODE_INVAL)
|
312 | f8638e28 | Michael Hanselmann | |
313 | f8638e28 | Michael Hanselmann | result = ParseFilter(filter_text) |
314 | f8638e28 | Michael Hanselmann | elif args:
|
315 | 6f287cf3 | Iustin Pop | result = [OP_OR] + map(compat.partial(_MakeFilterPart, namefield,
|
316 | 6f287cf3 | Iustin Pop | isnumeric=isnumeric), args) |
317 | f8638e28 | Michael Hanselmann | else:
|
318 | f8638e28 | Michael Hanselmann | result = None
|
319 | f8638e28 | Michael Hanselmann | |
320 | f8638e28 | Michael Hanselmann | return result |