def _eval_comparison_part(evaluator, context, left, operator, right): l_is_num = is_number(left) r_is_num = is_number(right) if isinstance(operator, unicode): str_operator = operator else: str_operator = force_unicode(str(operator.value)) if str_operator == '*': # for iterables, ignore * operations if isinstance(left, iterable.Sequence) or is_string(left): return ContextSet(left) elif isinstance(right, iterable.Sequence) or is_string(right): return ContextSet(right) elif str_operator == '+': if l_is_num and r_is_num or is_string(left) and is_string(right): return ContextSet(left.execute_operation(right, str_operator)) elif _is_tuple(left) and _is_tuple(right) or _is_list( left) and _is_list(right): return ContextSet(iterable.MergedArray(evaluator, (left, right))) elif str_operator == '-': if l_is_num and r_is_num: return ContextSet(left.execute_operation(right, str_operator)) elif str_operator == '%': # With strings and numbers the left type typically remains. Except for # `int() % float()`. return ContextSet(left) elif str_operator in COMPARISON_OPERATORS: if is_compiled(left) and is_compiled(right): # Possible, because the return is not an option. Just compare. try: return ContextSet(left.execute_operation(right, str_operator)) except TypeError: # Could be True or False. pass else: if str_operator in ('is', '!=', '==', 'is not'): operation = COMPARISON_OPERATORS[str_operator] bool_ = operation(left, right) return ContextSet(_bool_to_context(evaluator, bool_)) return ContextSet(_bool_to_context(evaluator, True), _bool_to_context(evaluator, False)) elif str_operator == 'in': return NO_CONTEXTS def check(obj): """Checks if a Jedi object is either a float or an int.""" return isinstance(obj, CompiledInstance) and \ obj.name.string_name in ('int', 'float') # Static analysis, one is a number, the other one is not. if str_operator in ('+', '-') and l_is_num != r_is_num \ and not (check(left) or check(right)): message = "TypeError: unsupported operand type(s) for +: %s and %s" analysis.add(context, 'type-error-operation', operator, message % (left, right)) return ContextSet(left, right)
def _eval_comparison_part(evaluator, context, left, operator, right): l_is_num = is_number(left) r_is_num = is_number(right) if isinstance(operator, unicode): str_operator = operator else: str_operator = force_unicode(str(operator.value)) if str_operator == '*': # for iterables, ignore * operations if isinstance(left, iterable.Sequence) or is_string(left): return ContextSet(left) elif isinstance(right, iterable.Sequence) or is_string(right): return ContextSet(right) elif str_operator == '+': if l_is_num and r_is_num or is_string(left) and is_string(right): return ContextSet(left.execute_operation(right, str_operator)) elif _is_tuple(left) and _is_tuple(right) or _is_list(left) and _is_list(right): return ContextSet(iterable.MergedArray(evaluator, (left, right))) elif str_operator == '-': if l_is_num and r_is_num: return ContextSet(left.execute_operation(right, str_operator)) elif str_operator == '%': # With strings and numbers the left type typically remains. Except for # `int() % float()`. return ContextSet(left) elif str_operator in COMPARISON_OPERATORS: if is_compiled(left) and is_compiled(right): # Possible, because the return is not an option. Just compare. try: return ContextSet(left.execute_operation(right, str_operator)) except TypeError: # Could be True or False. pass else: if str_operator in ('is', '!=', '==', 'is not'): operation = COMPARISON_OPERATORS[str_operator] bool_ = operation(left, right) return ContextSet(_bool_to_context(evaluator, bool_)) return ContextSet(_bool_to_context(evaluator, True), _bool_to_context(evaluator, False)) elif str_operator == 'in': return NO_CONTEXTS def check(obj): """Checks if a Jedi object is either a float or an int.""" return isinstance(obj, CompiledInstance) and \ obj.name.string_name in ('int', 'float') # Static analysis, one is a number, the other one is not. if str_operator in ('+', '-') and l_is_num != r_is_num \ and not (check(left) or check(right)): message = "TypeError: unsupported operand type(s) for +: %s and %s" analysis.add(context, 'type-error-operation', operator, message % (left, right)) return ContextSet(left, right)
def _eval_comparison_part(evaluator, context, left, operator, right): l_is_num = is_number(left) r_is_num = is_number(right) if operator == '*': # for iterables, ignore * operations if isinstance(left, iterable.AbstractIterable) or is_string(left): return ContextSet(left) elif isinstance(right, iterable.AbstractIterable) or is_string(right): return ContextSet(right) elif operator == '+': if l_is_num and r_is_num or is_string(left) and is_string(right): return ContextSet(compiled.create(evaluator, left.obj + right.obj)) elif _is_tuple(left) and _is_tuple(right) or _is_list( left) and _is_list(right): return ContextSet(iterable.MergedArray(evaluator, (left, right))) elif operator == '-': if l_is_num and r_is_num: return ContextSet(compiled.create(evaluator, left.obj - right.obj)) elif operator == '%': # With strings and numbers the left type typically remains. Except for # `int() % float()`. return ContextSet(left) elif operator in COMPARISON_OPERATORS: operation = COMPARISON_OPERATORS[operator] if is_compiled(left) and is_compiled(right): # Possible, because the return is not an option. Just compare. left = left.obj right = right.obj try: result = operation(left, right) except TypeError: # Could be True or False. return ContextSet(compiled.create(evaluator, True), compiled.create(evaluator, False)) else: return ContextSet(compiled.create(evaluator, result)) elif operator == 'in': return NO_CONTEXTS def check(obj): """Checks if a Jedi object is either a float or an int.""" return isinstance(obj, CompiledInstance) and \ obj.name.string_name in ('int', 'float') # Static analysis, one is a number, the other one is not. if operator in ('+', '-') and l_is_num != r_is_num \ and not (check(left) or check(right)): message = "TypeError: unsupported operand type(s) for +: %s and %s" analysis.add(context, 'type-error-operation', operator, message % (left, right)) return ContextSet(left, right)
def _eval_comparison_part(evaluator, context, left, operator, right): l_is_num = is_number(left) r_is_num = is_number(right) if operator == '*': # for iterables, ignore * operations if isinstance(left, iterable.AbstractIterable) or is_string(left): return ContextSet(left) elif isinstance(right, iterable.AbstractIterable) or is_string(right): return ContextSet(right) elif operator == '+': if l_is_num and r_is_num or is_string(left) and is_string(right): return ContextSet(compiled.create(evaluator, left.obj + right.obj)) elif _is_tuple(left) and _is_tuple(right) or _is_list(left) and _is_list(right): return ContextSet(iterable.MergedArray(evaluator, (left, right))) elif operator == '-': if l_is_num and r_is_num: return ContextSet(compiled.create(evaluator, left.obj - right.obj)) elif operator == '%': # With strings and numbers the left type typically remains. Except for # `int() % float()`. return ContextSet(left) elif operator in COMPARISON_OPERATORS: operation = COMPARISON_OPERATORS[operator] if is_compiled(left) and is_compiled(right): # Possible, because the return is not an option. Just compare. left = left.obj right = right.obj try: result = operation(left, right) except TypeError: # Could be True or False. return ContextSet(compiled.create(evaluator, True), compiled.create(evaluator, False)) else: return ContextSet(compiled.create(evaluator, result)) elif operator == 'in': return NO_CONTEXTS def check(obj): """Checks if a Jedi object is either a float or an int.""" return isinstance(obj, CompiledInstance) and \ obj.name.string_name in ('int', 'float') # Static analysis, one is a number, the other one is not. if operator in ('+', '-') and l_is_num != r_is_num \ and not (check(left) or check(right)): message = "TypeError: unsupported operand type(s) for +: %s and %s" analysis.add(context, 'type-error-operation', operator, message % (left, right)) return ContextSet(left, right)