def _element_calculate(evaluator, context, left, operator, right): from jedi.evaluate import iterable, instance l_is_num = _is_number(left) r_is_num = _is_number(right) if operator == '*': # for iterables, ignore * operations if isinstance(left, iterable.AbstractSequence) or is_string(left): return set([left]) elif isinstance(right, iterable.AbstractSequence) or is_string(right): return set([right]) elif operator == '+': if l_is_num and r_is_num or is_string(left) and is_string(right): return set([create(evaluator, left.obj + right.obj)]) elif _is_tuple(left) and _is_tuple(right) or _is_list( left) and _is_list(right): return set([iterable.MergedArray(evaluator, (left, right))]) elif operator == '-': if l_is_num and r_is_num: return set([create(evaluator, left.obj - right.obj)]) elif operator == '%': # With strings and numbers the left type typically remains. Except for # `int() % float()`. return set([left]) elif operator in COMPARISON_OPERATORS: operation = COMPARISON_OPERATORS[operator] if isinstance(left, CompiledObject) and isinstance( right, CompiledObject): # 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 set([create(evaluator, True), create(evaluator, False)]) else: return set([create(evaluator, result)]) elif operator == 'in': return set() def check(obj): """Checks if a Jedi object is either a float or an int.""" return isinstance(obj, instance.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 set([left, right])
def _element_calculate(evaluator, left, operator, right): from jedi.evaluate import iterable, representation as er l_is_num = _is_number(left) r_is_num = _is_number(right) if operator == '*': # for iterables, ignore * operations if isinstance(left, iterable.Array) or is_string(left): return [left] elif isinstance(right, iterable.Array) or is_string(right): return [right] elif operator == '+': if l_is_num and r_is_num or is_string(left) and is_string(right): return [create(evaluator, left.obj + right.obj)] elif _is_tuple(left) and _is_tuple(right) or _is_list( left) and _is_list(right): return [iterable.MergedArray(evaluator, (left, right))] elif operator == '-': if l_is_num and r_is_num: return [create(evaluator, left.obj - right.obj)] elif operator == '%': # With strings and numbers the left type typically remains. Except for # `int() % float()`. return [left] elif operator in COMPARISON_OPERATORS: operation = COMPARISON_OPERATORS[operator] if isinstance(left, CompiledObject) and isinstance( right, CompiledObject): # Possible, because the return is not an option. Just compare. left = left.obj right = right.obj try: return [keyword_from_value(operation(left, right))] except TypeError: # Could be True or False. return [true_obj, false_obj] elif operator == 'in': return [] def check(obj): """Checks if a Jedi object is either a float or an int.""" return isinstance( obj, er.Instance) and obj.name.get_code() 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(evaluator, 'type-error-operation', operator, message % (left, right)) return [left, right]
def _element_calculate(evaluator, left, operator, right): from jedi.evaluate import iterable, representation as er l_is_num = _is_number(left) r_is_num = _is_number(right) if operator == '*': # for iterables, ignore * operations if isinstance(left, iterable.Array) or _is_string(left): return [left] elif isinstance(right, iterable.Array) or _is_string(right): return [right] elif operator == '+': if l_is_num and r_is_num or _is_string(left) and _is_string(right): return [create(evaluator, left.obj + right.obj)] elif _is_tuple(left) and _is_tuple(right) or _is_list( left) and _is_list(right): return [iterable.MergedArray(evaluator, (left, right))] elif operator == '-': if l_is_num and r_is_num: return [create(evaluator, left.obj - right.obj)] elif operator == '%': # With strings and numbers the left type typically remains. Except for # `int() % float()`. return [left] def check(obj): """Checks if a Jedi object is either a float or an int.""" return isinstance(obj, er.Instance) and obj.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(evaluator, 'type-error-operation', operator, message % (left, right)) return [left, right]