class BitwiseExpressionTests(LeftOperatorRightExpresisonTestsBase): ExpressionClass = ast.BitwiseExpression false_value = 0.0 left_value = three = ast.FloatExpression(context, 3.0) right_value = five = ast.FloatExpression(context, 5.0) def test_ast_expression_left_operator_right_bitwise(self): self.assertExpressionTests('bwand', equals_value=1.0) self.assertExpressionTests('bwor', equals_value=7.0) self.assertExpressionTests('bwxor', equals_value=6.0) def test_ast_expression_left_operator_right_bitwise_type_errors(self): for operation in ('bwand', 'bwor', 'bwxor'): with self.assertRaises(errors.EvaluationError): self.assertExpressionTests(operation, ast.FloatExpression(context, 3.1), ast.FloatExpression(context, 5.0)) with self.assertRaises(errors.EvaluationError): self.assertExpressionTests(operation, ast.FloatExpression(context, 3.0), ast.FloatExpression(context, 5.1)) with self.assertRaises(errors.EvaluationError): self.assertExpressionTests(operation, ast.FloatExpression(context, -3.0), ast.FloatExpression(context, 5.0)) with self.assertRaises(errors.EvaluationError): self.assertExpressionTests(operation, ast.FloatExpression(context, 3.0), ast.FloatExpression(context, -5.0)) for left, right in itertools.product(trueish, falseish): if isinstance(left, ast.FloatExpression) and isinstance( right, ast.FloatExpression): continue with self.assertRaises(errors.EvaluationError): self.assertExpressionTests(operation, left, right)
class ArithmeticExpressionTests(LeftOperatorRightExpresisonTestsBase): ExpressionClass = ast.ArithmeticExpression false_value = 0.0 left_value = two = ast.FloatExpression(context, 2.0) right_value = four = ast.FloatExpression(context, 4.0) def test_ast_expression_left_operator_right_arithmetic(self): self.assertExpressionTests('add', equals_value=6.0) self.assertExpressionTests('sub', equals_value=-2.0) self.assertExpressionTests('fdiv', equals_value=0.0) self.assertExpressionTests('tdiv', equals_value=0.5) self.assertExpressionTests('mod', equals_value=2.0) self.assertExpressionTests('mul', equals_value=8.0) self.assertExpressionTests('pow', equals_value=16.0) def test_ast_expression_left_operator_right_arithmetic_type_errors(self): for operation in ('add', 'sub', 'fdiv', 'tdiv', 'mod', 'mul', 'pow'): with self.assertRaises(errors.EvaluationError): self.assertExpressionTests( operation, ast.FloatExpression(context, 2.0), ast.StringExpression(context, '4.0')) with self.assertRaises(errors.EvaluationError): self.assertExpressionTests( operation, ast.StringExpression(context, '2.0'), ast.FloatExpression(context, 4.0)) with self.assertRaises(errors.EvaluationError): self.assertExpressionTests( operation, ast.FloatExpression(context, 2.0), ast.BooleanExpression(context, True)) with self.assertRaises(errors.EvaluationError): self.assertExpressionTests( operation, ast.BooleanExpression(context, True), ast.FloatExpression(context, 4.0))
def test_ast_expression_getitem_error(self): container = ast.StringExpression(context, 'Rule Engine') member = ast.FloatExpression(context, 100.0) with self.assertRaises(errors.LookupError): ast.GetItemExpression(context, container, member).evaluate(None) member = ast.FloatExpression(context, 1.1) with self.assertRaises(errors.EvaluationError): ast.GetItemExpression(context, container, member).evaluate(None)
def test_ast_expression_contains_error(self): container = ast.StringExpression(context, 'Rule Engine') member = ast.FloatExpression(context, 1.0) with self.assertRaises(errors.EvaluationError): ast.ContainsExpression(context, container, member).evaluate(None) container = ast.FloatExpression(context, 1.0) with self.assertRaises(errors.EvaluationError): ast.ContainsExpression(context, container, member).evaluate(None)
def test_ast_expression_left_operator_right_arithmeticcomparison_numeric( self): neg_one = ast.FloatExpression(context, -1.0) zero = ast.FloatExpression(context, 0.0) one = ast.FloatExpression(context, 1.0) values = (neg_one, zero, one) for number in values: self.assertExpressionTests('ge', number, zero, number is zero or number is one) self.assertExpressionTests('gt', number, zero, number is one) self.assertExpressionTests('le', number, zero, number is zero or number is neg_one) self.assertExpressionTests('lt', number, zero, number is neg_one)
def test_ast_expression_getitem_error(self): for container in self.containers.values(): member = ast.FloatExpression(context, 100.0) with self.assertRaises(errors.LookupError): ast.GetItemExpression(context, container, member).evaluate(None) member = ast.FloatExpression(context, 1.1) with self.assertRaises(errors.EvaluationError): ast.GetItemExpression(context, container, member).evaluate(None) member = ast.NullExpression(context) with self.assertRaises(errors.EvaluationError): ast.GetItemExpression(context, container, member)
def test_ast_expression_getslice_safe(self): sym_name = ''.join( random.choice(string.ascii_letters) for _ in range(10)) container = ast.SymbolExpression(context, sym_name) start = ast.FloatExpression(context, 0) stop = ast.FloatExpression(context, -1) get_slice = ast.GetSliceExpression(context, container, start, stop) with self.assertRaises(errors.EvaluationError): get_slice.evaluate({sym_name: None}) get_slice = ast.GetSliceExpression(context, container, start, stop, safe=True) self.assertIsNone(get_slice.evaluate({sym_name: None}))
def test_ast_expression_getitem_reduces(self): container = ast.MappingExpression(context, (('one', 1), ('two', 2))) member = ast.FloatExpression(context, 0) with self.assertRaises(errors.LookupError): get_item = ast.GetItemExpression(context, container, member) get_item = ast.GetItemExpression(context, container, member, safe=True) self.assertIsInstance(get_item.reduce(), ast.NullExpression)
def test_ast_expression_literal_float(self): trueish_floats = (expression.value for expression in trueish if isinstance(expression, ast.FloatExpression)) self.assertLiteralTests(ast.FloatExpression, 0.0, float('nan'), *trueish_floats) # converts ints to floats automatically int_float = ast.FloatExpression(context, 1) self.assertIsInstance(int_float.value, decimal.Decimal) self.assertEqual(int_float.value, 1.0)
def test_ast_expression_left_operator_right_arithmetic_type_errors(self): for operation in ('add', 'sub', 'fdiv', 'tdiv', 'mod', 'mul', 'pow'): with self.assertRaises(errors.EvaluationError): self.assertExpressionTests( operation, ast.FloatExpression(context, 2.0), ast.StringExpression(context, '4.0')) with self.assertRaises(errors.EvaluationError): self.assertExpressionTests( operation, ast.StringExpression(context, '2.0'), ast.FloatExpression(context, 4.0)) with self.assertRaises(errors.EvaluationError): self.assertExpressionTests( operation, ast.FloatExpression(context, 2.0), ast.BooleanExpression(context, True)) with self.assertRaises(errors.EvaluationError): self.assertExpressionTests( operation, ast.BooleanExpression(context, True), ast.FloatExpression(context, 4.0))
def test_ast_expression_getitem_safe(self): sym_name = ''.join( random.choice(string.ascii_letters) for _ in range(10)) container = ast.SymbolExpression(context, sym_name) member = ast.FloatExpression(context, 0) get_item = ast.GetItemExpression(context, container, member) with self.assertRaises(errors.EvaluationError): get_item.evaluate({sym_name: None}) get_item = ast.GetItemExpression(context, container, member, safe=True) self.assertIsNone(get_item.evaluate({sym_name: None}))
def test_ast_expression_getitem(self): container = self.containers[types.DataType.ARRAY] item_0 = ast.FloatExpression(context, 0.0) get_item = ast.GetItemExpression(context, container, item_0) self.assertEqual(get_item.evaluate(None), 'one') self.assertIsInstance(get_item.reduce(), ast.StringExpression) item_n1 = ast.FloatExpression(context, -1.0) get_item = ast.GetItemExpression(context, container, item_n1) self.assertEqual(get_item.evaluate(None), 'two') self.assertIsInstance(get_item.reduce(), ast.StringExpression) container = self.containers[types.DataType.STRING] get_item = ast.GetItemExpression(context, container, item_0) self.assertEqual(get_item.evaluate(None), 'R') self.assertIsInstance(get_item.reduce(), ast.StringExpression) get_item = ast.GetItemExpression(context, container, item_n1) self.assertEqual(get_item.evaluate(None), '!') self.assertIsInstance(get_item.reduce(), ast.StringExpression)
def test_ast_expression_getitem(self): container = ast.LiteralExpressionBase.from_value(context, range(5)) item_1 = ast.FloatExpression(context, 1.0) get_item = ast.GetItemExpression(context, container, item_1) self.assertEqual(get_item.evaluate(None), 1) self.assertIsInstance(get_item.reduce(), ast.FloatExpression) item_n1 = ast.FloatExpression(context, -1.0) get_item = ast.GetItemExpression(context, container, item_n1) self.assertEqual(get_item.evaluate(None), 4) self.assertIsInstance(get_item.reduce(), ast.FloatExpression) container = ast.StringExpression(context, 'Rule Engine') get_item = ast.GetItemExpression(context, container, item_1) self.assertEqual(get_item.evaluate(None), 'u') self.assertIsInstance(get_item.reduce(), ast.StringExpression) get_item = ast.GetItemExpression(context, container, item_n1) self.assertEqual(get_item.evaluate(None), 'e') self.assertIsInstance(get_item.reduce(), ast.StringExpression)
def test_ast_expression_contains(self): container = ast.LiteralExpressionBase.from_value(context, range(3)) member = ast.FloatExpression(context, 1.0) contains = ast.ContainsExpression(context, container, member) self.assertTrue(contains.evaluate(None)) self.assertIsInstance(contains.reduce(), ast.BooleanExpression) member = ast.FloatExpression(context, -1.0) contains = ast.ContainsExpression(context, container, member) self.assertFalse(contains.evaluate(None)) self.assertIsInstance(contains.reduce(), ast.BooleanExpression) container = ast.StringExpression(context, 'Rule Engine') member = ast.StringExpression(context, ' ') self.assertTrue( ast.ContainsExpression(context, container, member).evaluate(None)) member = ast.StringExpression(context, 'x') self.assertFalse( ast.ContainsExpression(context, container, member).evaluate(None))
def test_ast_comprehension_result_type(self): iterable = (None, ) iterable_expression = ast.LiteralExpressionBase.from_value( context, iterable) comprehension = ast.ComprehensionExpression( context, ast.NullExpression(context), 'test', iterable_expression) self.assertEqual(comprehension.result_type, types.DataType.ARRAY(types.DataType.NULL)) comprehension = ast.ComprehensionExpression( context, ast.FloatExpression(context, 1), 'test', iterable_expression) self.assertEqual(comprehension.result_type, types.DataType.ARRAY(types.DataType.FLOAT))
def test_ast_expression_left_operator_right_bitwise_type_errors(self): for operation in ('bwand', 'bwor', 'bwxor', 'bwlsh', 'bwrsh'): with self.assertRaises(errors.EvaluationError): self.assertExpressionTests(operation, ast.FloatExpression(context, 3.1), ast.FloatExpression(context, 5.0)) with self.assertRaises(errors.EvaluationError): self.assertExpressionTests(operation, ast.FloatExpression(context, 3.0), ast.FloatExpression(context, 5.1)) with self.assertRaises(errors.EvaluationError): self.assertExpressionTests(operation, ast.FloatExpression(context, -3.0), ast.FloatExpression(context, 5.0)) with self.assertRaises(errors.EvaluationError): self.assertExpressionTests(operation, ast.FloatExpression(context, 3.0), ast.FloatExpression(context, -5.0)) for left, right in itertools.product(trueish, falseish): if isinstance(left, ast.FloatExpression) and isinstance( right, ast.FloatExpression): continue with self.assertRaises(errors.EvaluationError): self.assertExpressionTests(operation, left, right)
import unittest import rule_engine.ast as ast import rule_engine.engine as engine __all__ = ('LiteralExpressionTests',) context = engine.Context() context.builtins = engine.Builtins.from_defaults( {'test': {'one': 1.0, 'two': 2.0}} ) # literal expressions which should evaluate to false falseish = ( ast.ArrayExpression(context, tuple()), ast.BooleanExpression(context, False), ast.FloatExpression(context, 0.0), ast.NullExpression(context), ast.StringExpression(context, '') ) # literal expressions which should evaluate to true trueish = ( ast.ArrayExpression(context, tuple((ast.NullExpression(context),))), ast.BooleanExpression(context, True), ast.DatetimeExpression(context, datetime.datetime.now()), ast.FloatExpression(context, float('-inf')), ast.FloatExpression(context, -1.0), ast.FloatExpression(context, 1.0), ast.FloatExpression(context, float('inf')), ast.StringExpression(context, 'non-empty') )
import rule_engine.ast as ast import rule_engine.engine as engine __all__ = ('LiteralExpressionTests', ) context = engine.Context() context.builtins = engine.Builtins.from_defaults( {'test': { 'one': 1.0, 'two': 2.0 }}) # literal expressions which should evaluate to false falseish = (ast.ArrayExpression(context, tuple()), ast.BooleanExpression(context, False), ast.FloatExpression(context, 0.0), ast.NullExpression(context), ast.StringExpression(context, '')) # literal expressions which should evaluate to true trueish = (ast.ArrayExpression(context, tuple( (ast.NullExpression(context), ))), ast.ArrayExpression(context, tuple((ast.FloatExpression(context, 1.0), ))), ast.BooleanExpression(context, True), ast.DatetimeExpression(context, datetime.datetime.now()), ast.FloatExpression(context, float('-inf')), ast.FloatExpression(context, -1.0), ast.FloatExpression(context, 1.0), ast.FloatExpression(context, float('inf')), ast.StringExpression(context, 'non-empty'))
def test_ast_expression_literall_array_error(self): with self.assertRaises(TypeError): ast.ArrayExpression( self.context, tuple((ast.FloatExpression(self.context, 1.0), ast.StringExpression(self.context, 'error'))))