root / lib / qlang.py @ 596b2459
History | View | Annotate | Download (9 kB)
1 | a123dc19 | Michael Hanselmann | #
|
---|---|---|---|
2 | a123dc19 | Michael Hanselmann | #
|
3 | a123dc19 | Michael Hanselmann | |
4 | 341ff8e9 | Michael Hanselmann | # Copyright (C) 2010, 2011 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 | b459a848 | Andrea Spadaccini | import string # pylint: disable=W0402 |
36 | f8638e28 | Michael Hanselmann | import logging |
37 | 7578ab0a | Michael Hanselmann | |
38 | 7578ab0a | Michael Hanselmann | import pyparsing as pyp |
39 | 7578ab0a | Michael Hanselmann | |
40 | 7578ab0a | Michael Hanselmann | from ganeti import errors |
41 | 3f2f55bb | Michael Hanselmann | from ganeti import netutils |
42 | 16629d10 | Michael Hanselmann | from ganeti import utils |
43 | f8638e28 | Michael Hanselmann | from ganeti import compat |
44 | 7578ab0a | Michael Hanselmann | |
45 | 7578ab0a | Michael Hanselmann | |
46 | 341ff8e9 | Michael Hanselmann | # Logic operators with one or more operands, each of which is a filter on its
|
47 | 341ff8e9 | Michael Hanselmann | # own
|
48 | a123dc19 | Michael Hanselmann | OP_OR = "|"
|
49 | 88076fd1 | Michael Hanselmann | OP_AND = "&"
|
50 | 88076fd1 | Michael Hanselmann | |
51 | 88076fd1 | Michael Hanselmann | |
52 | 341ff8e9 | Michael Hanselmann | # Unary operators with exactly one operand
|
53 | 88076fd1 | Michael Hanselmann | OP_NOT = "!"
|
54 | 3b877f08 | Michael Hanselmann | OP_TRUE = "?"
|
55 | 88076fd1 | Michael Hanselmann | |
56 | 88076fd1 | Michael Hanselmann | |
57 | 341ff8e9 | Michael Hanselmann | # Binary operators with exactly two operands, the field name and an
|
58 | 341ff8e9 | Michael Hanselmann | # operator-specific value
|
59 | a123dc19 | Michael Hanselmann | OP_EQUAL = "="
|
60 | 88076fd1 | Michael Hanselmann | OP_NOT_EQUAL = "!="
|
61 | 88076fd1 | Michael Hanselmann | OP_REGEXP = "=~"
|
62 | 88076fd1 | Michael Hanselmann | OP_CONTAINS = "=[]"
|
63 | a123dc19 | Michael Hanselmann | |
64 | a123dc19 | Michael Hanselmann | |
65 | 0b0ca0c0 | Michael Hanselmann | #: Characters used for detecting user-written filters (see L{_CheckFilter})
|
66 | f8638e28 | Michael Hanselmann | FILTER_DETECTION_CHARS = frozenset("()=/!~'\"\\" + string.whitespace) |
67 | f8638e28 | Michael Hanselmann | |
68 | 0b0ca0c0 | Michael Hanselmann | #: Characters used to detect globbing filters (see L{_CheckGlobbing})
|
69 | f8638e28 | Michael Hanselmann | GLOB_DETECTION_CHARS = frozenset("*?") |
70 | 3f2f55bb | Michael Hanselmann | |
71 | 3f2f55bb | Michael Hanselmann | |
72 | 60cba7f8 | Michael Hanselmann | def MakeSimpleFilter(namefield, values): |
73 | 31554d0a | Michael Hanselmann | """Builds simple a filter.
|
74 | 60cba7f8 | Michael Hanselmann |
|
75 | 60cba7f8 | Michael Hanselmann | @param namefield: Name of field containing item name
|
76 | 60cba7f8 | Michael Hanselmann | @param values: List of names
|
77 | 60cba7f8 | Michael Hanselmann |
|
78 | 60cba7f8 | Michael Hanselmann | """
|
79 | 60cba7f8 | Michael Hanselmann | if values:
|
80 | 60cba7f8 | Michael Hanselmann | return [OP_OR] + [[OP_EQUAL, namefield, i] for i in values] |
81 | 60cba7f8 | Michael Hanselmann | |
82 | 60cba7f8 | Michael Hanselmann | return None |
83 | 7578ab0a | Michael Hanselmann | |
84 | 7578ab0a | Michael Hanselmann | |
85 | 7578ab0a | Michael Hanselmann | def _ConvertLogicOp(op): |
86 | 7578ab0a | Michael Hanselmann | """Creates parsing action function for logic operator.
|
87 | 7578ab0a | Michael Hanselmann |
|
88 | 7578ab0a | Michael Hanselmann | @type op: string
|
89 | 7578ab0a | Michael Hanselmann | @param op: Operator for data structure, e.g. L{OP_AND}
|
90 | 7578ab0a | Michael Hanselmann |
|
91 | 7578ab0a | Michael Hanselmann | """
|
92 | 7578ab0a | Michael Hanselmann | def fn(toks): |
93 | 7578ab0a | Michael Hanselmann | """Converts parser tokens to query operator structure.
|
94 | 7578ab0a | Michael Hanselmann |
|
95 | 7578ab0a | Michael Hanselmann | @rtype: list
|
96 | 7578ab0a | Michael Hanselmann | @return: Query operator structure, e.g. C{[OP_AND, ["=", "foo", "bar"]]}
|
97 | 7578ab0a | Michael Hanselmann |
|
98 | 7578ab0a | Michael Hanselmann | """
|
99 | 7578ab0a | Michael Hanselmann | operands = toks[0]
|
100 | 7578ab0a | Michael Hanselmann | |
101 | 7578ab0a | Michael Hanselmann | if len(operands) == 1: |
102 | 7578ab0a | Michael Hanselmann | return operands[0] |
103 | 7578ab0a | Michael Hanselmann | |
104 | 7578ab0a | Michael Hanselmann | # Build query operator structure
|
105 | 7578ab0a | Michael Hanselmann | return [[op] + operands.asList()]
|
106 | 7578ab0a | Michael Hanselmann | |
107 | 7578ab0a | Michael Hanselmann | return fn
|
108 | 7578ab0a | Michael Hanselmann | |
109 | 7578ab0a | Michael Hanselmann | |
110 | 7578ab0a | Michael Hanselmann | _KNOWN_REGEXP_DELIM = "/#^|"
|
111 | 7578ab0a | Michael Hanselmann | _KNOWN_REGEXP_FLAGS = frozenset("si") |
112 | 7578ab0a | Michael Hanselmann | |
113 | 7578ab0a | Michael Hanselmann | |
114 | 7578ab0a | Michael Hanselmann | def _ConvertRegexpValue(_, loc, toks): |
115 | 7578ab0a | Michael Hanselmann | """Regular expression value for condition.
|
116 | 7578ab0a | Michael Hanselmann |
|
117 | 7578ab0a | Michael Hanselmann | """
|
118 | 7578ab0a | Michael Hanselmann | (regexp, flags) = toks[0]
|
119 | 7578ab0a | Michael Hanselmann | |
120 | 7578ab0a | Michael Hanselmann | # Ensure only whitelisted flags are used
|
121 | 7578ab0a | Michael Hanselmann | unknown_flags = (frozenset(flags) - _KNOWN_REGEXP_FLAGS)
|
122 | 7578ab0a | Michael Hanselmann | if unknown_flags:
|
123 | 7578ab0a | Michael Hanselmann | raise pyp.ParseFatalException("Unknown regular expression flags: '%s'" % |
124 | 7578ab0a | Michael Hanselmann | "".join(unknown_flags), loc)
|
125 | 7578ab0a | Michael Hanselmann | |
126 | 7578ab0a | Michael Hanselmann | if flags:
|
127 | 7578ab0a | Michael Hanselmann | re_flags = "(?%s)" % "".join(sorted(flags)) |
128 | 7578ab0a | Michael Hanselmann | else:
|
129 | 7578ab0a | Michael Hanselmann | re_flags = ""
|
130 | 7578ab0a | Michael Hanselmann | |
131 | 7578ab0a | Michael Hanselmann | re_cond = re_flags + regexp |
132 | 7578ab0a | Michael Hanselmann | |
133 | 7578ab0a | Michael Hanselmann | # Test if valid
|
134 | 7578ab0a | Michael Hanselmann | try:
|
135 | 7578ab0a | Michael Hanselmann | re.compile(re_cond) |
136 | 7578ab0a | Michael Hanselmann | except re.error, err:
|
137 | 7578ab0a | Michael Hanselmann | raise pyp.ParseFatalException("Invalid regular expression (%s)" % err, loc) |
138 | 7578ab0a | Michael Hanselmann | |
139 | 7578ab0a | Michael Hanselmann | return [re_cond]
|
140 | 7578ab0a | Michael Hanselmann | |
141 | 7578ab0a | Michael Hanselmann | |
142 | 7578ab0a | Michael Hanselmann | def BuildFilterParser(): |
143 | 7578ab0a | Michael Hanselmann | """Builds a parser for query filter strings.
|
144 | 7578ab0a | Michael Hanselmann |
|
145 | 7578ab0a | Michael Hanselmann | @rtype: pyparsing.ParserElement
|
146 | 7578ab0a | Michael Hanselmann |
|
147 | 7578ab0a | Michael Hanselmann | """
|
148 | 7578ab0a | Michael Hanselmann | field_name = pyp.Word(pyp.alphas, pyp.alphanums + "_/.")
|
149 | 7578ab0a | Michael Hanselmann | |
150 | 7578ab0a | Michael Hanselmann | # Integer
|
151 | 7578ab0a | Michael Hanselmann | num_sign = pyp.Word("-+", exact=1) |
152 | 7578ab0a | Michael Hanselmann | number = pyp.Combine(pyp.Optional(num_sign) + pyp.Word(pyp.nums)) |
153 | 7578ab0a | Michael Hanselmann | number.setParseAction(lambda toks: int(toks[0])) |
154 | 7578ab0a | Michael Hanselmann | |
155 | 16629d10 | Michael Hanselmann | quoted_string = pyp.quotedString.copy().setParseAction(pyp.removeQuotes) |
156 | 16629d10 | Michael Hanselmann | |
157 | 7578ab0a | Michael Hanselmann | # Right-hand-side value
|
158 | 16629d10 | Michael Hanselmann | rval = (number | quoted_string) |
159 | 7578ab0a | Michael Hanselmann | |
160 | 7578ab0a | Michael Hanselmann | # Boolean condition
|
161 | 7578ab0a | Michael Hanselmann | bool_cond = field_name.copy() |
162 | 7578ab0a | Michael Hanselmann | bool_cond.setParseAction(lambda (fname, ): [[OP_TRUE, fname]])
|
163 | 7578ab0a | Michael Hanselmann | |
164 | 7578ab0a | Michael Hanselmann | # Simple binary conditions
|
165 | 7578ab0a | Michael Hanselmann | binopstbl = { |
166 | 7578ab0a | Michael Hanselmann | "==": OP_EQUAL,
|
167 | 7578ab0a | Michael Hanselmann | "!=": OP_NOT_EQUAL,
|
168 | 7578ab0a | Michael Hanselmann | } |
169 | 7578ab0a | Michael Hanselmann | |
170 | 7578ab0a | Michael Hanselmann | binary_cond = (field_name + pyp.oneOf(binopstbl.keys()) + rval) |
171 | 7578ab0a | Michael Hanselmann | binary_cond.setParseAction(lambda (lhs, op, rhs): [[binopstbl[op], lhs, rhs]])
|
172 | 7578ab0a | Michael Hanselmann | |
173 | 7578ab0a | Michael Hanselmann | # "in" condition
|
174 | 7578ab0a | Michael Hanselmann | in_cond = (rval + pyp.Suppress("in") + field_name)
|
175 | 7578ab0a | Michael Hanselmann | in_cond.setParseAction(lambda (value, field): [[OP_CONTAINS, field, value]])
|
176 | 7578ab0a | Michael Hanselmann | |
177 | 7578ab0a | Michael Hanselmann | # "not in" condition
|
178 | 7578ab0a | Michael Hanselmann | not_in_cond = (rval + pyp.Suppress("not") + pyp.Suppress("in") + field_name) |
179 | 7578ab0a | Michael Hanselmann | not_in_cond.setParseAction(lambda (value, field): [[OP_NOT, [OP_CONTAINS,
|
180 | 7578ab0a | Michael Hanselmann | field, value]]]) |
181 | 7578ab0a | Michael Hanselmann | |
182 | 7578ab0a | Michael Hanselmann | # Regular expression, e.g. m/foobar/i
|
183 | 7578ab0a | Michael Hanselmann | regexp_val = pyp.Group(pyp.Optional("m").suppress() +
|
184 | 7578ab0a | Michael Hanselmann | pyp.MatchFirst([pyp.QuotedString(i, escChar="\\")
|
185 | 7578ab0a | Michael Hanselmann | for i in _KNOWN_REGEXP_DELIM]) + |
186 | 7578ab0a | Michael Hanselmann | pyp.Optional(pyp.Word(pyp.alphas), default=""))
|
187 | 7578ab0a | Michael Hanselmann | regexp_val.setParseAction(_ConvertRegexpValue) |
188 | 7578ab0a | Michael Hanselmann | regexp_cond = (field_name + pyp.Suppress("=~") + regexp_val)
|
189 | 7578ab0a | Michael Hanselmann | regexp_cond.setParseAction(lambda (field, value): [[OP_REGEXP, field, value]])
|
190 | 7578ab0a | Michael Hanselmann | |
191 | 7578ab0a | Michael Hanselmann | not_regexp_cond = (field_name + pyp.Suppress("!~") + regexp_val)
|
192 | 7578ab0a | Michael Hanselmann | not_regexp_cond.setParseAction(lambda (field, value):
|
193 | 7578ab0a | Michael Hanselmann | [[OP_NOT, [OP_REGEXP, field, value]]]) |
194 | 7578ab0a | Michael Hanselmann | |
195 | 16629d10 | Michael Hanselmann | # Globbing, e.g. name =* "*.site"
|
196 | 16629d10 | Michael Hanselmann | glob_cond = (field_name + pyp.Suppress("=*") + quoted_string)
|
197 | 16629d10 | Michael Hanselmann | glob_cond.setParseAction(lambda (field, value):
|
198 | 16629d10 | Michael Hanselmann | [[OP_REGEXP, field, |
199 | 16629d10 | Michael Hanselmann | utils.DnsNameGlobPattern(value)]]) |
200 | 16629d10 | Michael Hanselmann | |
201 | 16629d10 | Michael Hanselmann | not_glob_cond = (field_name + pyp.Suppress("!*") + quoted_string)
|
202 | 16629d10 | Michael Hanselmann | not_glob_cond.setParseAction(lambda (field, value):
|
203 | 16629d10 | Michael Hanselmann | [[OP_NOT, [OP_REGEXP, field, |
204 | 16629d10 | Michael Hanselmann | utils.DnsNameGlobPattern(value)]]]) |
205 | 16629d10 | Michael Hanselmann | |
206 | 7578ab0a | Michael Hanselmann | # All possible conditions
|
207 | 7578ab0a | Michael Hanselmann | condition = (binary_cond ^ bool_cond ^ |
208 | 7578ab0a | Michael Hanselmann | in_cond ^ not_in_cond ^ |
209 | 16629d10 | Michael Hanselmann | regexp_cond ^ not_regexp_cond ^ |
210 | 16629d10 | Michael Hanselmann | glob_cond ^ not_glob_cond) |
211 | 7578ab0a | Michael Hanselmann | |
212 | 7578ab0a | Michael Hanselmann | # Associativity operators
|
213 | 7578ab0a | Michael Hanselmann | filter_expr = pyp.operatorPrecedence(condition, [ |
214 | 7578ab0a | Michael Hanselmann | (pyp.Keyword("not").suppress(), 1, pyp.opAssoc.RIGHT, |
215 | 7578ab0a | Michael Hanselmann | lambda toks: [[OP_NOT, toks[0][0]]]), |
216 | 7578ab0a | Michael Hanselmann | (pyp.Keyword("and").suppress(), 2, pyp.opAssoc.LEFT, |
217 | 7578ab0a | Michael Hanselmann | _ConvertLogicOp(OP_AND)), |
218 | 7578ab0a | Michael Hanselmann | (pyp.Keyword("or").suppress(), 2, pyp.opAssoc.LEFT, |
219 | 7578ab0a | Michael Hanselmann | _ConvertLogicOp(OP_OR)), |
220 | 7578ab0a | Michael Hanselmann | ]) |
221 | 7578ab0a | Michael Hanselmann | |
222 | 7578ab0a | Michael Hanselmann | parser = pyp.StringStart() + filter_expr + pyp.StringEnd() |
223 | 7578ab0a | Michael Hanselmann | parser.parseWithTabs() |
224 | 7578ab0a | Michael Hanselmann | |
225 | 7578ab0a | Michael Hanselmann | # Originally C{parser.validate} was called here, but there seems to be some
|
226 | 7578ab0a | Michael Hanselmann | # issue causing it to fail whenever the "not" operator is included above.
|
227 | 7578ab0a | Michael Hanselmann | |
228 | 7578ab0a | Michael Hanselmann | return parser
|
229 | 7578ab0a | Michael Hanselmann | |
230 | 7578ab0a | Michael Hanselmann | |
231 | 7578ab0a | Michael Hanselmann | def ParseFilter(text, parser=None): |
232 | 7578ab0a | Michael Hanselmann | """Parses a query filter.
|
233 | 7578ab0a | Michael Hanselmann |
|
234 | 7578ab0a | Michael Hanselmann | @type text: string
|
235 | 7578ab0a | Michael Hanselmann | @param text: Query filter
|
236 | 7578ab0a | Michael Hanselmann | @type parser: pyparsing.ParserElement
|
237 | 7578ab0a | Michael Hanselmann | @param parser: Pyparsing object
|
238 | 7578ab0a | Michael Hanselmann | @rtype: list
|
239 | 7578ab0a | Michael Hanselmann |
|
240 | 7578ab0a | Michael Hanselmann | """
|
241 | f8638e28 | Michael Hanselmann | logging.debug("Parsing as query filter: %s", text)
|
242 | f8638e28 | Michael Hanselmann | |
243 | 7578ab0a | Michael Hanselmann | if parser is None: |
244 | 7578ab0a | Michael Hanselmann | parser = BuildFilterParser() |
245 | 7578ab0a | Michael Hanselmann | |
246 | 7578ab0a | Michael Hanselmann | try:
|
247 | 7578ab0a | Michael Hanselmann | return parser.parseString(text)[0] |
248 | 7578ab0a | Michael Hanselmann | except pyp.ParseBaseException, err:
|
249 | 7578ab0a | Michael Hanselmann | raise errors.QueryFilterParseError("Failed to parse query filter" |
250 | 7578ab0a | Michael Hanselmann | " '%s': %s" % (text, err), err)
|
251 | 3f2f55bb | Michael Hanselmann | |
252 | 3f2f55bb | Michael Hanselmann | |
253 | f8638e28 | Michael Hanselmann | def _IsHostname(text): |
254 | f8638e28 | Michael Hanselmann | """Checks if a string could be a hostname.
|
255 | 3f2f55bb | Michael Hanselmann |
|
256 | 3f2f55bb | Michael Hanselmann | @rtype: bool
|
257 | 3f2f55bb | Michael Hanselmann |
|
258 | 3f2f55bb | Michael Hanselmann | """
|
259 | 3f2f55bb | Michael Hanselmann | try:
|
260 | 3f2f55bb | Michael Hanselmann | netutils.Hostname.GetNormalizedName(text) |
261 | 3f2f55bb | Michael Hanselmann | except errors.OpPrereqError:
|
262 | f8638e28 | Michael Hanselmann | return False |
263 | f8638e28 | Michael Hanselmann | else:
|
264 | 3f2f55bb | Michael Hanselmann | return True |
265 | 3f2f55bb | Michael Hanselmann | |
266 | f8638e28 | Michael Hanselmann | |
267 | f8638e28 | Michael Hanselmann | def _CheckFilter(text): |
268 | f8638e28 | Michael Hanselmann | """CHecks if a string could be a filter.
|
269 | f8638e28 | Michael Hanselmann |
|
270 | f8638e28 | Michael Hanselmann | @rtype: bool
|
271 | f8638e28 | Michael Hanselmann |
|
272 | f8638e28 | Michael Hanselmann | """
|
273 | f8638e28 | Michael Hanselmann | return bool(frozenset(text) & FILTER_DETECTION_CHARS) |
274 | f8638e28 | Michael Hanselmann | |
275 | f8638e28 | Michael Hanselmann | |
276 | f8638e28 | Michael Hanselmann | def _CheckGlobbing(text): |
277 | f8638e28 | Michael Hanselmann | """Checks if a string could be a globbing pattern.
|
278 | f8638e28 | Michael Hanselmann |
|
279 | f8638e28 | Michael Hanselmann | @rtype: bool
|
280 | f8638e28 | Michael Hanselmann |
|
281 | f8638e28 | Michael Hanselmann | """
|
282 | f8638e28 | Michael Hanselmann | return bool(frozenset(text) & GLOB_DETECTION_CHARS) |
283 | f8638e28 | Michael Hanselmann | |
284 | f8638e28 | Michael Hanselmann | |
285 | f8638e28 | Michael Hanselmann | def _MakeFilterPart(namefield, text): |
286 | f8638e28 | Michael Hanselmann | """Generates filter for one argument.
|
287 | f8638e28 | Michael Hanselmann |
|
288 | f8638e28 | Michael Hanselmann | """
|
289 | f8638e28 | Michael Hanselmann | if _CheckGlobbing(text):
|
290 | f8638e28 | Michael Hanselmann | return [OP_REGEXP, namefield, utils.DnsNameGlobPattern(text)]
|
291 | f8638e28 | Michael Hanselmann | else:
|
292 | f8638e28 | Michael Hanselmann | return [OP_EQUAL, namefield, text]
|
293 | f8638e28 | Michael Hanselmann | |
294 | f8638e28 | Michael Hanselmann | |
295 | f8638e28 | Michael Hanselmann | def MakeFilter(args, force_filter): |
296 | f8638e28 | Michael Hanselmann | """Try to make a filter from arguments to a command.
|
297 | f8638e28 | Michael Hanselmann |
|
298 | f8638e28 | Michael Hanselmann | If the name could be a filter it is parsed as such. If it's just a globbing
|
299 | f8638e28 | Michael Hanselmann | pattern, e.g. "*.site", such a filter is constructed. As a last resort the
|
300 | f8638e28 | Michael Hanselmann | names are treated just as a plain name filter.
|
301 | f8638e28 | Michael Hanselmann |
|
302 | f8638e28 | Michael Hanselmann | @type args: list of string
|
303 | f8638e28 | Michael Hanselmann | @param args: Arguments to command
|
304 | f8638e28 | Michael Hanselmann | @type force_filter: bool
|
305 | f8638e28 | Michael Hanselmann | @param force_filter: Whether to force treatment as a full-fledged filter
|
306 | f8638e28 | Michael Hanselmann | @rtype: list
|
307 | f8638e28 | Michael Hanselmann | @return: Query filter
|
308 | f8638e28 | Michael Hanselmann |
|
309 | f8638e28 | Michael Hanselmann | """
|
310 | f8638e28 | Michael Hanselmann | if (force_filter or |
311 | f8638e28 | Michael Hanselmann | (args and len(args) == 1 and _CheckFilter(args[0]))): |
312 | f8638e28 | Michael Hanselmann | try:
|
313 | f8638e28 | Michael Hanselmann | (filter_text, ) = args |
314 | f8638e28 | Michael Hanselmann | except (TypeError, ValueError): |
315 | f8638e28 | Michael Hanselmann | raise errors.OpPrereqError("Exactly one argument must be given as a" |
316 | f8638e28 | Michael Hanselmann | " filter")
|
317 | f8638e28 | Michael Hanselmann | |
318 | f8638e28 | Michael Hanselmann | result = ParseFilter(filter_text) |
319 | f8638e28 | Michael Hanselmann | elif args:
|
320 | f8638e28 | Michael Hanselmann | result = [OP_OR] + map(compat.partial(_MakeFilterPart, "name"), args) |
321 | f8638e28 | Michael Hanselmann | else:
|
322 | f8638e28 | Michael Hanselmann | result = None
|
323 | f8638e28 | Michael Hanselmann | |
324 | f8638e28 | Michael Hanselmann | return result |