Merge "Move nova extra_specs_ops to oslo.utils"
This commit is contained in:
commit
2b36107f0b
69
oslo_utils/specs_matcher.py
Normal file
69
oslo_utils/specs_matcher.py
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
# Copyright (c) 2011 OpenStack Foundation
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import operator
|
||||||
|
|
||||||
|
# 1. The following operations are supported:
|
||||||
|
# =, s==, s!=, s>=, s>, s<=, s<, <in>, <all-in>, <or>, ==, !=, >=, <=
|
||||||
|
# 2. Note that <or> is handled in a different way below.
|
||||||
|
# 3. If the first word in the extra_specs is not one of the operators,
|
||||||
|
# it is ignored.
|
||||||
|
op_methods = {
|
||||||
|
'=': lambda x, y: float(x) >= float(y),
|
||||||
|
'<in>': lambda x, y: y in x,
|
||||||
|
'<all-in>': lambda x, y: all(val in x for val in y),
|
||||||
|
'==': lambda x, y: float(x) == float(y),
|
||||||
|
'!=': lambda x, y: float(x) != float(y),
|
||||||
|
'>=': lambda x, y: float(x) >= float(y),
|
||||||
|
'<=': lambda x, y: float(x) <= float(y),
|
||||||
|
's==': operator.eq,
|
||||||
|
's!=': operator.ne,
|
||||||
|
's<': operator.lt,
|
||||||
|
's<=': operator.le,
|
||||||
|
's>': operator.gt,
|
||||||
|
's>=': operator.ge
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def match(value, req):
|
||||||
|
words = req.split()
|
||||||
|
|
||||||
|
op = method = None
|
||||||
|
if words:
|
||||||
|
op = words.pop(0)
|
||||||
|
method = op_methods.get(op)
|
||||||
|
|
||||||
|
if op != '<or>' and not method:
|
||||||
|
return value == req
|
||||||
|
|
||||||
|
if value is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if op == '<or>': # Ex: <or> v1 <or> v2 <or> v3
|
||||||
|
while True:
|
||||||
|
if words.pop(0) == value:
|
||||||
|
return True
|
||||||
|
if not words:
|
||||||
|
break
|
||||||
|
words.pop(0) # remove a keyword <or>
|
||||||
|
if not words:
|
||||||
|
break
|
||||||
|
return False
|
||||||
|
|
||||||
|
if words:
|
||||||
|
if op == '<all-in>': # requires a list not a string
|
||||||
|
return method(value, words)
|
||||||
|
return method(value, words[0])
|
||||||
|
return False
|
236
oslo_utils/tests/test_specs_matcher.py
Normal file
236
oslo_utils/tests/test_specs_matcher.py
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
from oslotest import base as test_base
|
||||||
|
|
||||||
|
from oslo_utils import specs_matcher
|
||||||
|
|
||||||
|
|
||||||
|
class SpecsMatcherTestCase(test_base.BaseTestCase):
|
||||||
|
def _do_specs_matcher_test(self, value, req, matches):
|
||||||
|
assertion = self.assertTrue if matches else self.assertFalse
|
||||||
|
assertion(specs_matcher.match(value, req))
|
||||||
|
|
||||||
|
def test_specs_matches_simple(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='1',
|
||||||
|
req='1',
|
||||||
|
matches=True)
|
||||||
|
|
||||||
|
def test_specs_fails_simple(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='',
|
||||||
|
req='1',
|
||||||
|
matches=False)
|
||||||
|
|
||||||
|
def test_specs_fails_simple2(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='3',
|
||||||
|
req='1',
|
||||||
|
matches=False)
|
||||||
|
|
||||||
|
def test_specs_fails_simple3(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='222',
|
||||||
|
req='2',
|
||||||
|
matches=False)
|
||||||
|
|
||||||
|
def test_specs_fails_with_bogus_ops(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='4',
|
||||||
|
req='> 2',
|
||||||
|
matches=False)
|
||||||
|
|
||||||
|
def test_specs_matches_with_op_eq(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='123',
|
||||||
|
req='= 123',
|
||||||
|
matches=True)
|
||||||
|
|
||||||
|
def test_specs_matches_with_op_eq2(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='124',
|
||||||
|
req='= 123',
|
||||||
|
matches=True)
|
||||||
|
|
||||||
|
def test_specs_fails_with_op_eq(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='34',
|
||||||
|
req='= 234',
|
||||||
|
matches=False)
|
||||||
|
|
||||||
|
def test_specs_fails_with_op_eq3(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='34',
|
||||||
|
req='=',
|
||||||
|
matches=False)
|
||||||
|
|
||||||
|
def test_specs_matches_with_op_seq(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='123',
|
||||||
|
req='s== 123',
|
||||||
|
matches=True)
|
||||||
|
|
||||||
|
def test_specs_fails_with_op_seq(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='1234',
|
||||||
|
req='s== 123',
|
||||||
|
matches=False)
|
||||||
|
|
||||||
|
def test_specs_matches_with_op_sneq(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='1234',
|
||||||
|
req='s!= 123',
|
||||||
|
matches=True)
|
||||||
|
|
||||||
|
def test_specs_fails_with_op_sneq(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='123',
|
||||||
|
req='s!= 123',
|
||||||
|
matches=False)
|
||||||
|
|
||||||
|
def test_specs_fails_with_op_sge(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='1000',
|
||||||
|
req='s>= 234',
|
||||||
|
matches=False)
|
||||||
|
|
||||||
|
def test_specs_fails_with_op_sle(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='1234',
|
||||||
|
req='s<= 1000',
|
||||||
|
matches=False)
|
||||||
|
|
||||||
|
def test_specs_fails_with_op_sl(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='2',
|
||||||
|
req='s< 12',
|
||||||
|
matches=False)
|
||||||
|
|
||||||
|
def test_specs_fails_with_op_sg(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='12',
|
||||||
|
req='s> 2',
|
||||||
|
matches=False)
|
||||||
|
|
||||||
|
def test_specs_matches_with_op_in(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='12311321',
|
||||||
|
req='<in> 11',
|
||||||
|
matches=True)
|
||||||
|
|
||||||
|
def test_specs_matches_with_op_in2(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='12311321',
|
||||||
|
req='<in> 12311321',
|
||||||
|
matches=True)
|
||||||
|
|
||||||
|
def test_specs_matches_with_op_in3(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='12311321',
|
||||||
|
req='<in> 12311321 <in>',
|
||||||
|
matches=True)
|
||||||
|
|
||||||
|
def test_specs_fails_with_op_in(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='12310321',
|
||||||
|
req='<in> 11',
|
||||||
|
matches=False)
|
||||||
|
|
||||||
|
def test_specs_fails_with_op_in2(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='12310321',
|
||||||
|
req='<in> 11 <in>',
|
||||||
|
matches=False)
|
||||||
|
|
||||||
|
def test_specs_matches_with_op_or(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='12',
|
||||||
|
req='<or> 11 <or> 12',
|
||||||
|
matches=True)
|
||||||
|
|
||||||
|
def test_specs_matches_with_op_or2(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='12',
|
||||||
|
req='<or> 11 <or> 12 <or>',
|
||||||
|
matches=True)
|
||||||
|
|
||||||
|
def test_specs_fails_with_op_or(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='13',
|
||||||
|
req='<or> 11 <or> 12',
|
||||||
|
matches=False)
|
||||||
|
|
||||||
|
def test_specs_fails_with_op_or2(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='13',
|
||||||
|
req='<or> 11 <or> 12 <or>',
|
||||||
|
matches=False)
|
||||||
|
|
||||||
|
def test_specs_matches_with_op_le(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='2',
|
||||||
|
req='<= 10',
|
||||||
|
matches=True)
|
||||||
|
|
||||||
|
def test_specs_fails_with_op_le(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='3',
|
||||||
|
req='<= 2',
|
||||||
|
matches=False)
|
||||||
|
|
||||||
|
def test_specs_matches_with_op_ge(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='3',
|
||||||
|
req='>= 1',
|
||||||
|
matches=True)
|
||||||
|
|
||||||
|
def test_specs_fails_with_op_ge(self):
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value='2',
|
||||||
|
req='>= 3',
|
||||||
|
matches=False)
|
||||||
|
|
||||||
|
def test_specs_matches_all_with_op_allin(self):
|
||||||
|
values = ['aes', 'mmx', 'aux']
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value=str(values),
|
||||||
|
req='<all-in> aes mmx',
|
||||||
|
matches=True)
|
||||||
|
|
||||||
|
def test_specs_matches_one_with_op_allin(self):
|
||||||
|
values = ['aes', 'mmx', 'aux']
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value=str(values),
|
||||||
|
req='<all-in> mmx',
|
||||||
|
matches=True)
|
||||||
|
|
||||||
|
def test_specs_fails_with_op_allin(self):
|
||||||
|
values = ['aes', 'mmx', 'aux']
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value=str(values),
|
||||||
|
req='<all-in> txt',
|
||||||
|
matches=False)
|
||||||
|
|
||||||
|
def test_specs_fails_all_with_op_allin(self):
|
||||||
|
values = ['aes', 'mmx', 'aux']
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value=str(values),
|
||||||
|
req='<all-in> txt 3dnow',
|
||||||
|
matches=False)
|
||||||
|
|
||||||
|
def test_specs_fails_match_one_with_op_allin(self):
|
||||||
|
values = ['aes', 'mmx', 'aux']
|
||||||
|
self._do_specs_matcher_test(
|
||||||
|
value=str(values),
|
||||||
|
req='<all-in> txt aes',
|
||||||
|
matches=False)
|
Loading…
Reference in New Issue
Block a user