Fix DriverFilter string evaluations

When trying to compare two values that are non-numeric using the driver
filter, the filter function will give an error. This is not desirable as
it might be interesting to support comparatives with non-numeric values
provided by the filter objects (volume, host, etc). For example, the
following formula failed before the fix:

filter_function = '(volume.project_id == "bb212f09317a4f4a8952ef3f729c2551")'

Change-Id: Ifc9f2d7cf39c0e497e1ed6440d2be4cda6be12d9
This commit is contained in:
Erlon R. Cruz 2019-11-29 16:08:43 -03:00
parent f7a8729572
commit 87a7e80a2c
2 changed files with 16 additions and 15 deletions

View File

@ -45,21 +45,21 @@ class EvalConstant(object):
(which_dict, entry) = result.split('.')
try:
result = _vars[which_dict][entry]
except KeyError as e:
except KeyError:
raise exception.EvaluatorParseException(
_("KeyError: %s") % e)
except TypeError as e:
_("KeyError evaluating string"))
except TypeError:
raise exception.EvaluatorParseException(
_("TypeError: %s") % e)
_("TypeError evaluating string"))
try:
result = int(result)
except ValueError:
try:
result = float(result)
except ValueError as e:
raise exception.EvaluatorParseException(
_("ValueError: %s") % e)
except ValueError:
if isinstance(result, str):
result = result.replace('"', '').replace('\'', '')
return result
@ -232,8 +232,9 @@ def _def_parser():
alphas = pyparsing.alphas
Combine = pyparsing.Combine
Forward = pyparsing.Forward
nums = pyparsing.nums
quoted_string = pyparsing.quotedString
oneOf = pyparsing.oneOf
opAssoc = pyparsing.opAssoc
operatorPrecedence = pyparsing.operatorPrecedence
@ -243,9 +244,8 @@ def _def_parser():
real = Combine(Word(nums) + '.' + Word(nums))
variable = Word(alphas + '_' + '.')
number = real | integer
expr = Forward()
fn = Word(alphas + '_' + '.')
operand = number | variable | fn
operand = number | variable | fn | quoted_string
signop = oneOf('+ -')
addop = oneOf('+ -')

View File

@ -127,11 +127,12 @@ class EvaluatorTestCase(test.TestCase):
def test_nonnumber_comparison(self):
nonnumber = {'test': 'foo'}
request = {'test': 'bar'}
self.assertRaises(
exception.EvaluatorParseException,
evaluator.evaluate,
"nonnumber.test != request.test",
nonnumber=nonnumber, request=request)
self.assertTrue(
evaluator.evaluate("nonnumber.test != request.test",
nonnumber=nonnumber, request=request))
self.assertFalse(
evaluator.evaluate("nonnumber.test == request.test",
nonnumber=nonnumber, request=request))
def test_div_zero(self):
self.assertRaises(exception.EvaluatorParseException,