changeset 32:2224a52256ca trunk

A couple more operators supported in expressions.
author cmlenz
date Wed, 28 Jun 2006 19:13:47 +0000
parents 2ab5fa60575d
children 1fdb7054fb42
files markup/eval.py markup/tests/eval.py
diffstat 2 files changed, 49 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/markup/eval.py
+++ b/markup/eval.py
@@ -13,6 +13,8 @@
 
 """Support for "safe" evaluation of Python expressions."""
 
+from __future__ import division
+
 import __builtin__
 try:
     import _ast # Python 2.5
@@ -155,9 +157,18 @@
             return reduce(lambda x, y: x or y,
                           [self._visit(n, data) for n in node.nodes])
 
+        def _visit_bitand(self, node, data):
+            return reduce(operator.and_,
+                          [self._visit(n, data) for n in node.nodes])
+
+        def _visit_bitor(self, node, data):
+            return reduce(operator.or_,
+                          [self._visit(n, data) for n in node.nodes])
+
         _OP_MAP = {'==': operator.eq, '!=': operator.ne,
                    '<':  operator.lt, '<=': operator.le,
                    '>':  operator.gt, '>=': operator.ge,
+                   'is': operator.is_, 'is not': operator.is_not,
                    'in': lambda x, y: operator.contains(y, x),
                    'not in': lambda x, y: not operator.contains(y, x)}
         def _visit_compare(self, node, data):
@@ -189,15 +200,18 @@
         def _visit_sub(self, node, data):
             return self._visit(node.left, data) - self._visit(node.right, data)
 
-        def _visit_not(self, node, data):
-            return not self._visit(node.expr, data)
-
         def _visit_unaryadd(self, node, data):
             return +self._visit(node.expr, data)
 
         def _visit_unarysub(self, node, data):
             return -self._visit(node.expr, data)
 
+        def _visit_not(self, node, data):
+            return not self._visit(node.expr, data)
+
+        def _visit_invert(self, node, data):
+            return ~self._visit(node.expr, data)
+
         # Identifiers & Literals
 
         def _visit_name(self, node, data):
@@ -286,10 +300,12 @@
         # Operators
 
         _OP_MAP = {_ast.Add: operator.add, _ast.And: lambda l, r: l and r,
-                   _ast.Div: operator.div, _ast.Eq: operator.eq,
+                   _ast.BitAnd: operator.and_, _ast.BitOr: operator.or_,
+                   _ast.Div: operator.truediv, _ast.Eq: operator.eq,
                    _ast.FloorDiv: operator.floordiv, _ast.Gt: operator.gt,
-                   _ast.GtE: operator.ge,
+                   _ast.GtE: operator.ge, _ast.Invert: operator.inv,
                    _ast.In: lambda l, r: operator.contains(r, l),
+                   _ast.Is: operator.is_, _ast.IsNot: operator.is_not,
                    _ast.Lt: operator.lt, _ast.LtE: operator.le,
                    _ast.Mod: operator.mod, _ast.Mult: operator.mul,
                    _ast.Not: operator.not_, _ast.NotEq: operator.ne,
--- a/markup/tests/eval.py
+++ b/markup/tests/eval.py
@@ -64,6 +64,10 @@
         self.assertEqual(False, Expression("not True").evaluate({}))
         self.assertEqual(False, Expression("not x").evaluate({'x': True}))
 
+    def test_unaryop_inv(self):
+        self.assertEqual(-2, Expression("~1").evaluate({}))
+        self.assertEqual(-2, Expression("~x").evaluate({'x': 1}))
+
     def test_binop_add(self):
         self.assertEqual(3, Expression("2 + 1").evaluate({}))
         self.assertEqual(3, Expression("x + y").evaluate({'x': 2, 'y': 1}))
@@ -96,6 +100,14 @@
         self.assertEqual(1, Expression("3 % 2").evaluate({}))
         self.assertEqual(1, Expression("x % y").evaluate({'x': 3, 'y': 2}))
 
+    def test_binop_and(self):
+        self.assertEqual(0, Expression("1 & 0").evaluate({}))
+        self.assertEqual(0, Expression("x & y").evaluate({'x': 1, 'y': 0}))
+
+    def test_binop_or(self):
+        self.assertEqual(1, Expression("1 | 0").evaluate({}))
+        self.assertEqual(1, Expression("x | y").evaluate({'x': 1, 'y': 0}))
+
     def test_binop_contains(self):
         self.assertEqual(True, Expression("1 in (1, 2, 3)").evaluate({}))
         self.assertEqual(True, Expression("x in y").evaluate({'x': 1,
@@ -106,6 +118,20 @@
         self.assertEqual(True, Expression("x not in y").evaluate({'x': 4,
                                                                   'y': (1, 2, 3)}))
 
+    def test_binop_is(self):
+        self.assertEqual(True, Expression("1 is 1").evaluate({}))
+        self.assertEqual(True, Expression("x is y").evaluate({'x': 1, 'y': 1}))
+        self.assertEqual(False, Expression("1 is 2").evaluate({}))
+        self.assertEqual(False, Expression("x is y").evaluate({'x': 1, 'y': 2}))
+
+    def test_binop_is_not(self):
+        self.assertEqual(True, Expression("1 is not 2").evaluate({}))
+        self.assertEqual(True, Expression("x is not y").evaluate({'x': 1,
+                                                                  'y': 2}))
+        self.assertEqual(False, Expression("1 is not 1").evaluate({}))
+        self.assertEqual(False, Expression("x is not y").evaluate({'x': 1,
+                                                                   'y': 1}))
+
     def test_boolop_and(self):
         self.assertEqual(False, Expression("True and False").evaluate({}))
         self.assertEqual(False, Expression("x and y").evaluate({'x': True,
@@ -123,6 +149,8 @@
     def test_compare_ne(self):
         self.assertEqual(False, Expression("1 != 1").evaluate({}))
         self.assertEqual(False, Expression("x != y").evaluate({'x': 1, 'y': 1}))
+        self.assertEqual(False, Expression("1 <> 1").evaluate({}))
+        self.assertEqual(False, Expression("x <> y").evaluate({'x': 1, 'y': 1}))
 
     def test_compare_lt(self):
         self.assertEqual(True, Expression("1 < 2").evaluate({}))
Copyright (C) 2012-2017 Edgewall Software