def doCompare(op, left, right):
"""Perform the given AST comparison on the values"""
top = type(op)
if top == ast.Eq:
return left == right
elif top == ast.NotEq:
return left != right
elif top == ast.Lt:
return left < right
elif top == ast.LtE:
return left <= right
elif top == ast.Gt:
return left > right
elif top == ast.GtE:
return left >= right
elif top == ast.Is:
return left is right
elif top == ast.IsNot:
return left is not right
elif top == ast.In:
return left in right
elif top == ast.NotIn:
return left not in right
python类IsNot()的实例源码
def visit_Compare(self, node):
"""
Compare(expr left, cmpop* ops, expr* comparators)
"""
assert len(node.ops) == len(node.comparators)
def compare_pair(left, comp, op):
if (left == '__name__') and (comp == '"__main__"') or \
(left == '"__main__"') and (comp == '__name__'):
""" <Python> __name__ == '__main__':
<Ruby> __FILE__ == $0 """
left = '__FILE__'
comp = '$0'
if isinstance(op, ast.In):
return "%s.include?(%s)" % (comp, left)
elif isinstance(op, ast.NotIn):
return "!%s.include?(%s)" % (comp, left)
elif isinstance(op, ast.Eq):
return "%s == %s" % (left, comp)
elif isinstance(op, ast.NotEq):
return "%s != %s" % (left, comp)
elif isinstance(op, ast.IsNot):
return "!%s.equal?(%s)" % (left, comp)
else:
return "%s %s %s" % (left, self.get_comparison_op(op), comp)
compare_list = []
for i in range(len(node.ops)):
if i == 0:
left = self.visit(node.left)
else:
left = comp
comp = self.visit(node.comparators[i])
op = node.ops[i]
pair = compare_pair(left, comp, op)
if len(node.ops) == 1:
return pair
compare_list.append('(' + pair + ')')
return ' and '.join(compare_list)
# python 3
def visit_Compare(self, node):
if not self.config.constant_folding:
return
if len(node.ops) != 1:
# FIXME: implement 1 < 2 < 3
return
if len(node.comparators) != 1:
# FIXME: support this case? What's the syntax of this case?
return
new_node = self.compare_cst(node)
if new_node is not None:
return new_node
# replace 'None is None' with True
if (isinstance(node.ops[0], (ast.Is, ast.IsNot))
and isinstance(node.left, ast.Constant)
and node.left.value is None
and isinstance(node.comparators[0], ast.Constant)
and node.comparators[0].value is None):
result = isinstance(node.ops[0], ast.Is)
return self.new_constant(node, result)
# replace 'x in {1, 2}' with 'x in frozenset({1, 2})'
# replace 'x in [1, 2]' with 'x in frozenset((1, 2))'
if isinstance(node.ops[0], ast.In):
new_node = self.compare_contains(node)
if new_node is not None:
return new_node
def whereeval(str_, get=None):
"""Evaluate a set operation string, where each Name is fetched"""
if get is None:
import redbiom
config = redbiom.get_config()
get = redbiom._requests.make_get(config)
# Load is subject to indirection to simplify testing
globals()['Load'] = make_Load(get)
formed = ast.parse(str_, mode='eval')
node_types = (ast.Compare, ast.In, ast.NotIn, ast.BoolOp, ast.And,
ast.Name, ast.Or, ast.Eq, ast.Lt, ast.LtE, ast.Gt, ast.GtE,
ast.NotEq, ast.Str, ast.Num, ast.Load, ast.Expression,
ast.Tuple, ast.Is, ast.IsNot)
for node in ast.walk(formed):
if not isinstance(node, node_types):
raise TypeError("Unsupported node type: %s" % ast.dump(node))
result = eval(ast.dump(formed))
# clean up
global Load
del Load
return result
def syn_Compare(self, ctx, e):
left, ops, comparators = e.left, e.ops, e.comparators
for op in ops:
if not isinstance(op, (ast.Eq, ast.NotEq, ast.Is, ast.IsNot)):
raise _errors.TyError("Type bool does not support this operator.", op)
for e_ in _util.tpl_cons(left, comparators):
if hasattr(e_, 'match'):
continue # already synthesized
ctx.ana(e_, self)
return self
def syn_Compare(self, ctx, e):
left, ops, comparators = e.left, e.ops, e.comparators
for op in ops:
if not isinstance(op, (ast.Eq, ast.NotEq, ast.Is, ast.IsNot, ast.In, ast.NotIn)):
raise _errors.TyError("Invalid comparison operator on strings.", e)
for e_ in _util.tpl_cons(left, comparators):
if hasattr(e_, 'match'):
continue # already synthesized
ctx.ana(e_, self)
return _boolean.boolean
def syn_Compare(self, ctx, e):
left, ops, comparators = e.left, e.ops, e.comparators
for op in ops:
if isinstance(op, (ast.Eq, ast.NotEq)):
if not len(self.idx) == 0:
raise _errors.TyError("Can only compare unit values for equality.", e)
elif not isinstance(op, (ast.Is, ast.IsNot)):
raise _errors.TyError("Invalid comparison operator.", op)
for e_ in _util.tpl_cons(left, comparators):
if hasattr(e_, "match"):
continue # already synthesized
ctx.ana(e_, self)
return _boolean.boolean
def areDisjoint(a, b):
"""Are the sets of values that satisfy these two boolean constraints disjoint?"""
# The easiest way to be disjoint is to have comparisons that cover different areas
if type(a) == type(b) == ast.Compare:
aop = a.ops[0]
bop = b.ops[0]
aLeft = a.left
aRight = a.comparators[0]
bLeft = b.left
bRight = b.comparators[0]
alblComp = compareASTs(aLeft, bLeft, checkEquality=True)
albrComp = compareASTs(aLeft, bRight, checkEquality=True)
arblComp = compareASTs(aRight, bLeft, checkEquality=True)
arbrComp = compareASTs(aRight, bRight, checkEquality=True)
altype = type(aLeft) in [ast.Num, ast.Str]
artype = type(aRight) in [ast.Num, ast.Str]
bltype = type(bLeft) in [ast.Num, ast.Str]
brtype = type(bRight) in [ast.Num, ast.Str]
if (type(aop) == ast.Eq and type(bop) == ast.NotEq) or \
(type(bop) == ast.Eq and type(aop) == ast.NotEq):
# x == y, x != y
if (alblComp == 0 and arbrComp == 0) or (albrComp == 0 and arblComp == 0):
return True
elif type(aop) == type(bop) == ast.Eq:
if (alblComp == 0 and arbrComp == 0) or (albrComp == 0 and arblComp == 0):
return False
# x = num1, x = num2
elif alblComp == 0 and artype and brtype:
return True
elif albrComp == 0 and artype and bltype:
return True
elif arblComp == 0 and altype and brtype:
return True
elif arbrComp == 0 and altype and bltype:
return True
elif (type(aop) == ast.Lt and type(bop) == ast.GtE) or \
(type(aop) == ast.Gt and type(bop) == ast.LtE) or \
(type(aop) == ast.LtE and type(bop) == ast.Gt) or \
(type(aop) == ast.GtE and type(bop) == ast.Lt) or \
(type(aop) == ast.Is and type(bop) == ast.IsNot) or \
(type(aop) == ast.IsNot and type(bop) == ast.Is) or \
(type(aop) == ast.In and type(bop) == ast.NotIn) or \
(type(aop) == ast.NotIn and type(bop) == ast.In):
if alblComp == 0 and arbrComp == 0:
return True
elif (type(aop) == ast.Lt and type(bop) == ast.LtE) or \
(type(aop) == ast.Gt and type(bop) == ast.GtE) or \
(type(aop) == ast.LtE and type(bop) == ast.Lt) or \
(type(aop) == ast.GtE and type(bop) == ast.Gt):
if albrComp == 0 and arblComp == 0:
return True
elif type(a) == type(b) == ast.BoolOp:
return False # for now- TODO: when is this not true?
elif type(a) == ast.UnaryOp and type(a.op) == ast.Not:
if compareASTs(a.operand, b, checkEquality=True) == 0:
return True
elif type(b) == ast.UnaryOp and type(b.op) == ast.Not:
if compareASTs(b.operand, a, checkEquality=True) == 0:
return True
return False
def negate(op):
"""Return the negation of the provided operator"""
if op == None:
return None
top = type(op)
neg = not op.negated if hasattr(op, "negated") else True
if top == ast.And:
newOp = ast.Or()
elif top == ast.Or:
newOp = ast.And()
elif top == ast.Eq:
newOp = ast.NotEq()
elif top == ast.NotEq:
newOp = ast.Eq()
elif top == ast.Lt:
newOp = ast.GtE()
elif top == ast.GtE:
newOp = ast.Lt()
elif top == ast.Gt:
newOp = ast.LtE()
elif top == ast.LtE:
newOp = ast.Gt()
elif top == ast.Is:
newOp = ast.IsNot()
elif top == ast.IsNot:
newOp = ast.Is()
elif top == ast.In:
newOp = ast.NotIn()
elif top == ast.NotIn:
newOp = ast.In()
elif top == ast.NameConstant and op.value in [True, False]:
op.value = not op.value
op.negated = neg
return op
elif top == ast.Compare:
if len(op.ops) == 1:
op.ops[0] = negate(op.ops[0])
op.negated = neg
return op
else:
values = []
allOperands = [op.left] + op.comparators
for i in range(len(op.ops)):
values.append(ast.Compare(allOperands[i], [negate(op.ops[i])],
[allOperands[i+1]], multiCompPart=True))
newOp = ast.BoolOp(ast.Or(multiCompOp=True), values, multiComp=True)
elif top == ast.UnaryOp and type(op.op) == ast.Not and \
eventualType(op.operand) == bool: # this can mess things up type-wise
return op.operand
else:
# this is a normal value, so put a not around it
newOp = ast.UnaryOp(ast.Not(addedNot=True), op)
transferMetaData(op, newOp)
newOp.negated = neg
return newOp