Skip to content

Commit 626200a

Browse files
committed
Merge branch evaluate from gemerden
Signed-off-by: Philippe Ombredanne <[email protected]>
2 parents 1eb3ebc + 54aa1f9 commit 626200a

File tree

3 files changed

+80
-0
lines changed

3 files changed

+80
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77
/.cache/
88
/.eggs/
99
/.pytest_cache/
10+
/.idea/

boolean/boolean.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,22 @@
2626

2727
import inspect
2828
import itertools
29+
from operator import and_ as and_operator
30+
from operator import or_ as or_operator
31+
2932

3033
# Python 2 and 3
3134
try:
3235
basestring # NOQA
3336
except NameError:
3437
basestring = str # NOQA
3538

39+
try:
40+
reduce # Python 2
41+
except NameError:
42+
from functools import reduce # Python 3
43+
44+
3645
# Set to True to enable tracing for parsing
3746
TRACE_PARSE = False
3847

@@ -885,6 +894,10 @@ def __init__(self, obj):
885894
self.iscanonical = True
886895
self.isliteral = True
887896

897+
def __call__(self, **kwargs):
898+
""" returns the value for this symbol from kwargs """
899+
return kwargs[self.obj]
900+
888901
def __hash__(self):
889902
if self.obj is None: # Anonymous Symbol.
890903
return id(self)
@@ -1088,6 +1101,10 @@ def demorgan(self):
10881101
op = expr.args[0]
10891102
return op.dual(*(self.__class__(arg).cancel() for arg in op.args))
10901103

1104+
def __call__(self, **kwargs):
1105+
""" negates the value returned from self.args[0].__call__ """
1106+
return not self.args[0](**kwargs)
1107+
10911108
def __lt__(self, other):
10921109
return self.args[0] < other
10931110

@@ -1444,6 +1461,14 @@ def __init__(self, arg1, arg2, *args):
14441461
self.dual = self.OR
14451462
self.operator = '&'
14461463

1464+
def __call__(self, **kwargs):
1465+
"""
1466+
Calls arg.__call__ for each arg in self.args and applies python 'and' operator.
1467+
1468+
reduce is used as in e.g. AND(a, b, c, d) == AND(a, AND(b, AND(c, d)))
1469+
"""
1470+
return reduce(and_operator, (a(**kwargs) for a in self.args))
1471+
14471472

14481473
class OR(DualBase):
14491474
"""
@@ -1467,3 +1492,11 @@ def __init__(self, arg1, arg2, *args):
14671492
self.annihilator = self.TRUE
14681493
self.dual = self.AND
14691494
self.operator = '|'
1495+
1496+
def __call__(self, **kwargs):
1497+
"""
1498+
Calls arg.__call__ for each arg in self.args and applies python 'or' operator.
1499+
1500+
reduce is used as in e.g. OR(a, b, c, d) == OR(a, OR(b, OR(c, d)))
1501+
"""
1502+
return reduce(or_operator, (a(**kwargs) for a in self.args))

boolean/test_boolean.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,5 +1192,51 @@ def __init__(self, name, value='value'):
11921192
self.fail(e)
11931193

11941194

1195+
class CallabilityTestCase(unittest.TestCase):
1196+
1197+
def test_and(self):
1198+
algebra = BooleanAlgebra()
1199+
exp = algebra.parse("a&b&c")
1200+
for a in [True, False]:
1201+
for b in [True, False]:
1202+
for c in [True, False]:
1203+
self.assertEqual(exp(a=a, b=b, c=c), a and b and c)
1204+
1205+
def test_or(self):
1206+
algebra = BooleanAlgebra()
1207+
exp = algebra.parse("a|b|c")
1208+
for a in [True, False]:
1209+
for b in [True, False]:
1210+
for c in [True, False]:
1211+
self.assertEqual(exp(a=a, b=b, c=c), a or b or c)
1212+
1213+
def test_not(self):
1214+
algebra = BooleanAlgebra()
1215+
exp = algebra.parse("!a")
1216+
for a in [True, False]:
1217+
self.assertEqual(exp(a=a), not a)
1218+
1219+
def test_symbol(self):
1220+
algebra = BooleanAlgebra()
1221+
exp = algebra.parse("a")
1222+
for a in [True, False]:
1223+
self.assertEqual(exp(a=a), a)
1224+
1225+
def test_composite(self):
1226+
algebra = BooleanAlgebra()
1227+
exp = algebra.parse("!(a|b&(a|!c))")
1228+
for a in [True, False]:
1229+
for b in [True, False]:
1230+
for c in [True, False]:
1231+
self.assertEqual(exp(a=a, b=b, c=c), not(a or b and (a or not c)))
1232+
1233+
def test_negate_A_or_B(self):
1234+
algebra = BooleanAlgebra()
1235+
exp = algebra.parse("!(a|b)")
1236+
for a in [True, False]:
1237+
for b in [True, False]:
1238+
self.assertEqual(exp(a=a, b=b), not(a or b))
1239+
1240+
11951241
if __name__ == '__main__':
11961242
unittest.main()

0 commit comments

Comments
 (0)