我们从Python开源项目中,提取了以下50个代码示例,用于说明如何使用ast.UnaryOp()。
def __init__(self, expr, context): self.expr = expr self.context = context self.expr_table = { LLLnode: self.get_expr, ast.Num: self.number, ast.Str: self.string, ast.NameConstant: self.constants, ast.Name: self.variables, ast.Attribute: self.attribute, ast.Subscript: self.subscript, ast.BinOp: self.arithmetic, ast.Compare: self.compare, ast.BoolOp: self.boolean_operations, ast.UnaryOp: self.unary_operations, ast.Call: self.call, ast.List: self.list_literals, ast.Dict: self.struct_literals, ast.Tuple: self.tuple_literals, } expr_type = self.expr.__class__ if expr_type in self.expr_table: self.lll_node = self.expr_table[expr_type]() else: raise Exception("Unsupported operator: %r" % ast.dump(self.expr))
def _is_numeric_pow(self, node: ast.BinOp) -> bool: if isinstance(node.op, ast.Pow): left, right = node.left, node.right if isinstance(left, (ast.Name, ast.Num)): if isinstance(right, ast.Num): degree = right.n elif isinstance(right, ast.UnaryOp)\ and isinstance(right.op, (ast.USub, ast.UAdd))\ and isinstance(right.operand, ast.Num): degree = right.operand.n else: return False if isinstance(degree, float): degree = int(degree) if degree.is_integer() else degree return isinstance(degree, int) return False
def eval_expr(expr): """ Eval and expression inside a #define using a suppart of python grammar """ def _eval(node): if isinstance(node, ast.Num): return node.n elif isinstance(node, ast.BinOp): return OPERATORS[type(node.op)](_eval(node.left), _eval(node.right)) elif isinstance(node, ast.UnaryOp): return OPERATORS[type(node.op)](_eval(node.operand)) elif isinstance(node, ast.BoolOp): values = [_eval(x) for x in node.values] return OPERATORS[type(node.op)](**values) else: raise TypeError(node) return _eval(ast.parse(expr, mode='eval').body)
def num_negate(op): top = type(op) neg = not op.num_negated if hasattr(op, "num_negated") else True if top == ast.Add: newOp = ast.Sub() elif top == ast.Sub: newOp = ast.Add() elif top in [ast.Mult, ast.Div, ast.Mod, ast.Pow, ast.LShift, ast.RShift, ast.BitOr, ast.BitXor, ast.BitAnd, ast.FloorDiv]: return None # can't negate this elif top in [ast.Num, ast.Name]: # this is a normal value, so put a - in front of it newOp = ast.UnaryOp(ast.USub(addedNeg=True), op) else: log("astTools\tnum_negate\tUnusual type: " + str(top), "bug") transferMetaData(op, newOp) newOp.num_negated = neg return newOp
def visit_If(self, node): new_node = self._visit_if_while(node) if new_node is not None: return new_node if node.orelse and is_empty_body(node.orelse): self.log_node_removal("Remove dead code (empty else block of if)", node.orelse) new_node = copy_node(node) del new_node.orelse[:] node = new_node if is_empty_body(node.body) and not is_empty_body(node.orelse): self.log_node_removal("Remove dead code (empty if block)", node.body) new_node = copy_node(node) not_test = ast.UnaryOp(op=ast.Not(), operand=node.test) copy_lineno(node.test, not_test) new_node = ast.If(test=not_test, body=new_node.orelse, orelse=[]) copy_lineno(node, new_node) return new_node return node
def eval_numeric_constexpr(node: ast.AST) -> int: if isinstance(node, ast.Num): return node.n if isinstance(node, ast.UnaryOp): if isinstance(node.op, ast.UAdd): return +eval_numeric_constexpr(node.operand) elif isinstance(node.op, ast.USub): return -eval_numeric_constexpr(node.operand) else: return None if isinstance(node, ast.BinOp): if isinstance(node.op, ast.Add): return eval_numeric_constexpr(node.left) + eval_numeric_constexpr(node.right) if isinstance(node.op, ast.Sub): return eval_numeric_constexpr(node.left) - eval_numeric_constexpr(node.right) if isinstance(node.op, ast.Mult): return eval_numeric_constexpr(node.left) * eval_numeric_constexpr(node.right) if isinstance(node.op, ast.Div): return eval_numeric_constexpr(node.left) / eval_numeric_constexpr(node.right) return None
def eval_expr(expr): import ast import operator as op op = { ast.Add: op.add, ast.Sub: op.sub, ast.Mult: op.mul, ast.Div: op.truediv, ast.Pow: op.pow, ast.BitXor: op.xor, ast.USub: op.neg, } def eval_(node): if isinstance(node, ast.Num): return fractions.Fraction(node.n) elif isinstance(node, ast.BinOp): return op[type(node.op)](eval_(node.left), eval_(node.right)) elif isinstance(node, ast.UnaryOp): return op[type(node.op)](eval_(node.operand)) raise TypeError(node) return eval_(ast.parse(str(expr), mode='eval').body)
def visit_BoolOp(self, boolop): res_var = self.variable() expl_list = self.assign(ast.List([], ast.Load())) app = ast.Attribute(expl_list, "append", ast.Load()) is_or = int(isinstance(boolop.op, ast.Or)) body = save = self.statements fail_save = self.on_failure levels = len(boolop.values) - 1 self.push_format_context() # Process each operand, short-circuting if needed. for i, v in enumerate(boolop.values): if i: fail_inner = [] # cond is set in a prior loop iteration below self.on_failure.append(ast.If(cond, fail_inner, [])) # noqa self.on_failure = fail_inner self.push_format_context() res, expl = self.visit(v) body.append(ast.Assign([ast.Name(res_var, ast.Store())], res)) expl_format = self.pop_format_context(ast.Str(expl)) call = ast_Call(app, [expl_format], []) self.on_failure.append(ast.Expr(call)) if i < levels: cond = res if is_or: cond = ast.UnaryOp(ast.Not(), cond) inner = [] self.statements.append(ast.If(cond, inner, [])) self.statements = body = inner self.statements = save self.on_failure = fail_save expl_template = self.helper("format_boolop", expl_list, ast.Num(is_or)) expl = self.pop_format_context(expl_template) return ast.Name(res_var, ast.Load()), self.explanation_param(expl)
def visit_UnaryOp(self, unary): pattern = unary_map[unary.op.__class__] operand_res, operand_expl = self.visit(unary.operand) res = self.assign(ast.UnaryOp(unary.op, operand_res)) return res, pattern % (operand_expl,)
def visit_If(self, node): node = self.generic_visit(node) if (node.orelse and len(node.orelse) == 1 and isinstance(node.orelse[0], ast.Pass) ): node.orelse = [] if (len(node.body) == 1 and isinstance(node.body[0], ast.Pass) ): if node.orelse: node_test = ast.UnaryOp(op=ast.Not(), operand=node.test) if (len(node.orelse) == 1 and isinstance(node.orelse[0], ast.If) ): node_test = ast.BoolOp\ ( op = ast.And() , values = [node_test, node.orelse[0].test] ) node.test = ast.copy_location(node_test, node.orelse[0].test) node.body = node.orelse[0].body node.orelse = node.orelse[0].orelse else: node.test = ast.copy_location(node_test, node.test) node.body = node.orelse node.orelse = [] else: node = None return node
def isNegation(a, b): """Is a the negation of b?""" return compareASTs(deMorganize(ast.UnaryOp(ast.Not(), deepcopy(a))), b, checkEquality=True) == 0
def cleanupEquals(a): """Gets rid of silly blah == True statements that students make""" if not isinstance(a, ast.AST): return a if type(a) == ast.Call: a.func = cleanupEquals(a.func) for i in range(len(a.args)): # But test expressions don't carry through to function arguments a.args[i] = cleanupEquals(a.args[i]) return a elif type(a) == ast.Compare and type(a.ops[0]) in [ast.Eq, ast.NotEq]: l = a.left = cleanupEquals(a.left) r = cleanupEquals(a.comparators[0]) a.comparators = [r] if type(l) == ast.NameConstant and l.value in [True, False]: (l,r) = (r,l) # If we have (boolean expression) == True if type(r) == ast.NameConstant and r.value in [True, False] and (eventualType(l) == bool): # Matching types if (type(a.ops[0]) == ast.Eq and r.value == True) or \ (type(a.ops[0]) == ast.NotEq and r.value == False): transferMetaData(a, l) # make sure to keep the original location return l else: tmp = ast.UnaryOp(ast.Not(addedNotOp=True), l) transferMetaData(a, tmp) return tmp else: return a else: return applyToChildren(a, cleanupEquals)
def isNegative(a): """Is the give number negative?""" if type(a) == ast.UnaryOp and type(a.op) == ast.USub: return True elif type(a) == ast.Num and type(a.n) != complex and a.n < 0: return True else: return False
def _unop(self, *, _opnode=opnode, _sym=sym): return __class__( '%s%s' % (_sym, self._pname), ast.UnaryOp( op=_opnode(), operand=self._tree, ), self._constants, )
def visit_BinOp(self, node): if node.op.__class__ in self.operators: sympy_class = self.operators[node.op.__class__] right = self.visit(node.right) if isinstance(node.op, ast.Sub): right = ast.UnaryOp(op=ast.USub(), operand=right) elif isinstance(node.op, ast.Div): right = ast.Call( func=ast.Name(id='Pow', ctx=ast.Load()), args=[right, ast.UnaryOp(op=ast.USub(), operand=ast.Num(1))], keywords=[ast.keyword(arg='evaluate', value=ast.Name(id='False', ctx=ast.Load()))], starargs=None, kwargs=None ) new_node = ast.Call( func=ast.Name(id=sympy_class, ctx=ast.Load()), args=[self.visit(node.left), right], keywords=[ast.keyword(arg='evaluate', value=ast.Name(id='False', ctx=ast.Load()))], starargs=None, kwargs=None ) if sympy_class in ('Add', 'Mul'): # Denest Add or Mul as appropriate new_node.args = self.flatten(new_node.args, sympy_class) return new_node return node
def get_type(self, node): if isinstance(node, ast.BinOp): left_type = self.get_type(node.left) right_type = self.get_type(node.right) if isinstance(node.op, ast.Add): if left_type.is_number and right_type.is_number: return Type.NUMBER else: return Type.STRING elif left_type.is_number and right_type.is_number: return Type.NUMBER else: raise CompileError("Can not '%s' operator with string." % node.op.__class__.__name__) elif isinstance(node, ast.UnaryOp): if isinstance(operand, ast.Num): return Type.NUMBER else: raise SyntaxNotSupportError("Not support unary operator except number.") elif isinstance(node, ast.Num): return Type.NUMBER elif isinstance(node, ast.Str): return Type.STRING elif isinstance(node, ast.List): return Type.LIST elif isinstance(node, ast.Call): args_type = [self.get_type(arg) for arg in node.args] return self.get_function_return_type(node.func.id, args_type) elif isinstance(node, ast.Name): return self.variables[node.id].var_type
def eval_(node): """Calculate a mathematical expression.""" if isinstance(node, ast.Num): # <number> return node.n elif isinstance(node, ast.BinOp): # <left> <operator> <right> return operators[type(node.op)](eval_(node.left), eval_(node.right)) elif isinstance(node, ast.UnaryOp): # <operator> <operand> e.g., -1 return operators[type(node.op)](eval_(node.operand)) else: raise TypeError(node)
def _safe_eval(node, default): """ Safely evaluate the Boolean expression under the given AST node. Substitute `default` for all sub-expressions that cannot be evaluated (because variables or functions are undefined). We could use eval() to evaluate more sub-expressions. However, this function is not safe for arbitrary Python code. Even after overwriting the "__builtins__" dictionary, the original dictionary can be restored (https://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html). """ if isinstance(node, ast.BoolOp): results = [_safe_eval(value, default) for value in node.values] if isinstance(node.op, ast.And): return all(results) else: return any(results) elif isinstance(node, ast.UnaryOp) and isinstance(node.op, ast.Not): return not _safe_eval(node.operand, not default) else: try: return ast.literal_eval(node) except ValueError: return default
def test_unaryop(self): u = ast.UnaryOp(ast.Not(), ast.Name("x", ast.Store())) self.expr(u, "must have Load context")
def _get_constant(node, *, types=None): if isinstance(node, ast.Constant): return node.value if isinstance(node, ast.UnaryOp) and isinstance(node.op, ast.USub): # FIXME: rely on constant folding for that! value = get_constant(node.operand, types=types) if value is UNSET: return UNSET return (-value) return UNSET
def rewrite_expr_z3(r, is_py_ast=True): # Rewrites py_ast expression to a str expression that could be used in z3 # Return (z3_expr_str, z3_varnames) z3_expr_str = (py_ast.dump_ast(r) if is_py_ast else r).strip() z3_expr_str = z3_expr_str.replace('.', '_').replace('[', '_').replace(']', '_') rp = py_ast.get_ast(z3_expr_str).body[0].value for node in py_ast.find_all(rp, ast.UnaryOp): if isinstance(node.op, ast.Not): if rp == node: rp = py_ast.get_ast('z3.Not(' + py_ast.dump_ast(node.operand) + ')').body[0].value else: py_ast.replace_node(rp, node, py_ast.get_ast('z3.Not(' + py_ast.dump_ast(node.operand) + ')').body[0].value) for node in py_ast.find_all(rp, ast.BoolOp): if isinstance(node.op, ast.And): if rp == node: rp = py_ast.get_ast('z3.And(' + py_ast.dump_ast(node.values[0]) + ',' + py_ast.dump_ast(node.values[1]) + ')') else: py_ast.replace_node(rp, node, py_ast.get_ast('z3.And(' + py_ast.dump_ast(node.values[0]) + ',' + py_ast.dump_ast(node.values[1]) + ')')) elif isinstance(node.op, ast.Or): if rp == node: rp = py_ast.get_ast('z3.Or(' + py_ast.dump_ast(node.values[0]) + ',' + py_ast.dump_ast(node.values[1]) + ')') else: py_ast.replace_node(rp, node, py_ast.get_ast('z3.Or(' + py_ast.dump_ast(node.values[0]) + ',' + py_ast.dump_ast(node.values[1]) + ')')) z3_expr_str = py_ast.dump_ast(rp) z3_vars = set() for node in py_ast.find_all(rp, ast.Name): z3_vars.add(node.id) return (z3_expr_str, z3_vars)
def is_int_constant_py_ast(s): """ py_ast version on is_int_constant in redbaron_util.py """ s = s.strip() rootnode = get_ast(s).body if len(rootnode) == 1 and isinstance(rootnode[0], ast.Expr): node = rootnode[0].value if isinstance(node, ast.UnaryOp): if isinstance(node.op, (ast.USub, ast.UAdd)): return isinstance(node.operand, ast.Num) else: return isinstance(node, ast.Num) return False
def TO_INT(node: ast) -> (bool, int): if isinstance(node, ast.Num): return (True, node.n) if isinstance(node, ast.UnaryOp) and isinstance(node.operand, ast.Num): if isinstance(node.op, ast.UAdd): return (True, +node.operand.n) if isinstance(node.op, ast.USub): return (True, -node.operand.n) error(loc(node), "Expected +/- Num") return (False, 0) error(loc(node), "Expected signed integer") return (False, 0)
def rhs_function(node): if not isinstance(node, ast.Assign): return None rhs = node.value if isinstance(rhs, ast.Call): return rhs elif isinstance(rhs, ast.BinOp): return rhs elif isinstance(rhs, ast.UnaryOp): return rhs elif isinstance(rhs, ast.Subscript): return rhs
def __init__(self, operators=None, functions=None, names=None): """ Create the evaluator instance. Set up valid operators (+,-, etc) functions (add, random, get_val, whatever) and names. """ if not operators: operators = DEFAULT_OPERATORS if not functions: functions = DEFAULT_FUNCTIONS if not names: names = DEFAULT_NAMES self.operators = operators self.functions = functions self.names = names self.nodes = { ast.Num: self._eval_num, ast.Str: self._eval_str, ast.Name: self._eval_name, ast.UnaryOp: self._eval_unaryop, ast.BinOp: self._eval_binop, ast.BoolOp: self._eval_boolop, ast.Compare: self._eval_compare, ast.IfExp: self._eval_ifexp, ast.Call: self._eval_call, ast.keyword: self._eval_keyword, ast.Subscript: self._eval_subscript, ast.Attribute: self._eval_attribute, ast.Index: self._eval_index, ast.Slice: self._eval_slice, } # py3k stuff: if hasattr(ast, 'NameConstant'): self.nodes[ast.NameConstant] = self._eval_nameconstant elif isinstance(self.names, dict) and "None" not in self.names: self.names["None"] = None
def negate_test(self, node): not_node = ast.UnaryOp(op=ast.Not(), operand=node.test) node.test = not_node return node
def test_generate_if_node_child(self): node = ast.Sub(children=[]) mutations = [ self.aor_mutation(node=ast.UnaryOp(children=[node])), self.aor_mutation(node=node), ] changes_to_apply = self.apply_strategy_to_mutations_with_order_2(controller.FirstToLastHOMStrategy, mutations) self.assert_num_changesets(changes_to_apply, 2) self.assert_num_changeset_entries(changes_to_apply, 0, 1) self.assert_mutation_in_changeset_at_position_equals(changes_to_apply, 0, 0, mutations[0]) self.assert_num_changeset_entries(changes_to_apply, 1, 1) self.assert_mutation_in_changeset_at_position_equals(changes_to_apply, 1, 0, mutations[1])
def pythonast(self, args, tonative=False): return ast.UnaryOp(ast.UAdd(), args[0])
def pythonast(self, args, tonative=False): return ast.UnaryOp(ast.USub(), args[0])
def pythonast(self, args, tonative=False): return ast.UnaryOp(ast.Not(), args[0])
def Subscript_default(t, x): assert isinstance(x.slice, ast.Index) v = x.slice.value if isinstance(v, ast.UnaryOp) and isinstance(v.op, ast.USub): return JSSubscript( JSCall(JSAttribute(x.value, 'slice'), [v]), JSNum(0)) return JSSubscript(x.value, v)
def UnaryOp(t, x): return JSUnaryOp(x.op, x.operand)
def ast(self): """Python AST of this predicate (construct transitively for all indirect children as well). :return: AST of describing all children predicates """ return ast.UnaryOp(ast.Not(), ast.Expr(value=self._child.ast()))
def handle_UnaryOp(state, node, ctx): state, result = peval_call( state, ctx, UNARY_OPS[type(node.op)], args=[node.operand]) if not is_known_value(result): state = state.update(temp_bindings=state.temp_bindings.del_(result.func.id)) result = ast.UnaryOp(op=node.op, operand=result.args[0]) return state, result
def translate_pat_Name_constructor(self, ctx, pat, scrutinee): id = pat.id if id == "True": return (scrutinee, typy.odict()) elif id == "False": return (ast.UnaryOp(op=ast.Not(), operand=scrutinee), typy.odict())
def visit_UAdd(self, node): trailing_nodes = list(map(type, self.node_window[-4:])) if trailing_nodes == [ast.UnaryOp, ast.UAdd, ast.UnaryOp, ast.UAdd]: originator = self.node_window[-4] self.errors.append( B002(originator.lineno, originator.col_offset) ) self.generic_visit(node)
def _update(self): """update tkk """ # we don't need to update the base TKK value when it is still valid now = math.floor(int(time.time() * 1000) / 3600000.0) if self.tkk and int(self.tkk.split('.')[0]) == now: return r = self.session.get(self.host) # this will be the same as python code after stripping out a reserved word 'var' code = unicode(self.RE_TKK.search(r.text).group(1)).replace('var ', '') # unescape special ascii characters such like a \x3d(=) if PY3: # pragma: no cover code = code.encode().decode('unicode-escape') else: # pragma: no cover code = code.decode('string_escape') if code: tree = ast.parse(code) visit_return = False operator = '+' n, keys = 0, dict(a=0, b=0) for node in ast.walk(tree): if isinstance(node, ast.Assign): name = node.targets[0].id if name in keys: if isinstance(node.value, ast.Num): keys[name] = node.value.n # the value can sometimes be negative elif isinstance(node.value, ast.UnaryOp) and \ isinstance(node.value.op, ast.USub): # pragma: nocover keys[name] = -node.value.operand.n elif isinstance(node, ast.Return): # parameters should be set after this point visit_return = True elif visit_return and isinstance(node, ast.Num): n = node.n elif visit_return and n > 0: # the default operator is '+' but implement some more for # all possible scenarios if isinstance(node, ast.Add): # pragma: nocover pass elif isinstance(node, ast.Sub): # pragma: nocover operator = '-' elif isinstance(node, ast.Mult): # pragma: nocover operator = '*' elif isinstance(node, ast.Pow): # pragma: nocover operator = '**' elif isinstance(node, ast.BitXor): # pragma: nocover operator = '^' # a safety way to avoid Exceptions clause = compile('{1}{0}{2}'.format( operator, keys['a'], keys['b']), '', 'eval') value = eval(clause, dict(__builtin__={})) result = '{}.{}'.format(n, value) self.tkk = result
def visit_Assert(self, assert_): """Return the AST statements to replace the ast.Assert instance. This re-writes the test of an assertion to provide intermediate values and replace it with an if statement which raises an assertion error with a detailed explanation in case the expression is false. """ if isinstance(assert_.test, ast.Tuple) and self.config is not None: fslocation = (self.module_path, assert_.lineno) self.config.warn('R1', 'assertion is always true, perhaps ' 'remove parentheses?', fslocation=fslocation) self.statements = [] self.variables = [] self.variable_counter = itertools.count() self.stack = [] self.on_failure = [] self.push_format_context() # Rewrite assert into a bunch of statements. top_condition, explanation = self.visit(assert_.test) # Create failure message. body = self.on_failure negation = ast.UnaryOp(ast.Not(), top_condition) self.statements.append(ast.If(negation, body, [])) if assert_.msg: assertmsg = self.helper('format_assertmsg', assert_.msg) explanation = "\n>assert " + explanation else: assertmsg = ast.Str("") explanation = "assert " + explanation template = ast.BinOp(assertmsg, ast.Add(), ast.Str(explanation)) msg = self.pop_format_context(template) fmt = self.helper("format_explanation", msg) err_name = ast.Name("AssertionError", ast.Load()) exc = ast_Call(err_name, [fmt], []) if sys.version_info[0] >= 3: raise_ = ast.Raise(exc, None) else: raise_ = ast.Raise(exc, None, None) body.append(raise_) # Clear temporary variables by setting them to None. if self.variables: variables = [ast.Name(name, ast.Store()) for name in self.variables] clear = ast.Assign(variables, _NameConstant(None)) self.statements.append(clear) # Fix line numbers. for stmt in self.statements: set_location(stmt, assert_.lineno, assert_.col_offset) return self.statements
def specialFunctions(cv, old, new): if type(old) == type(new) == list: log("individualize\tspecialFunctions\tWhy are we comparing lists?: " + str(cv) + ";" + printFunction(old) + ";" + printFunction(new), "bug") return cv rev = neg = False if (hasattr(old, "reversed") and old.reversed and (not hasattr(old, "multCompFixed"))): rev = True if (hasattr(old, "negated") and old.negated): neg = True if rev and neg: (old, new) = (negate(undoReverse(old)), negate(undoReverse(new))) elif rev: (old, new) = (undoReverse(old), undoReverse(new)) elif neg: (old, new) = (negate(old), negate(new)) if type(old) == ast.UnaryOp and type(old.op) == ast.Not and \ type(new) == ast.UnaryOp and type(new.op) == ast.Not: # Just get rid of them old = old.operand new = new.operand if hasattr(old, "num_negated") and old.num_negated: origNew = deepcopy(new) (old, new) = (num_negate(old), num_negate(new)) if new == None: # couldn't reverse the new operator # To get here, we must have a binary operator. Go up a level and negate the right side cvCopy = cv.deepcopy() parentSpot = deepcopy(cvCopy.traverseTree(cvCopy.start)) if type(parentSpot) == ast.BinOp: cvCopy.path = cvCopy.path[1:] cvCopy.oldSubtree = parentSpot cvCopy.newSubtree = deepcopy(parentSpot) cvCopy.newSubtree.op = origNew cvCopy.newSubtree.right = num_negate(cvCopy.newSubtree.right) cvCopy = orderedBinOpSpecialFunction(cvCopy) # just in case return cvCopy else: log("individualize\tspecialFunctions\tWhere are we? " + str(type(parentSpot)), "bug") #if (hasattr(old, "inverted") and old.inverted): # (old, new) = (invert(old), invert(new)) cv.oldSubtree = old cv.newSubtree = new return cv
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