MCPcopy Index your code
hub / github.com/python/mypy / visit_op_expr

Method visit_op_expr

mypy/checkexpr.py:3555–3662  ·  view source on GitHub ↗

Type check a binary operator expression.

(self, e: OpExpr)

Source from the content-addressed store, hash-verified

3553 return self.named_type("builtins.ellipsis")
3554
3555 def visit_op_expr(self, e: OpExpr) -> Type:
3556 """Type check a binary operator expression."""
3557 if e.analyzed:
3558 # It's actually a type expression X | Y.
3559 return self.accept(e.analyzed)
3560 if e.op == "and" or e.op == "or":
3561 return self.check_boolean_op(e)
3562 if e.op == "*" and isinstance(e.left, ListExpr):
3563 # Expressions of form [...] * e get special type inference.
3564 return self.check_list_multiply(e)
3565 if e.op == "%":
3566 if isinstance(e.left, BytesExpr):
3567 return self.strfrm_checker.check_str_interpolation(e.left, e.right)
3568 if isinstance(e.left, StrExpr):
3569 return self.strfrm_checker.check_str_interpolation(e.left, e.right)
3570 left_type = self.accept(e.left)
3571
3572 proper_left_type = get_proper_type(left_type)
3573 if isinstance(proper_left_type, TupleType) and e.op == "+":
3574 left_add_method = proper_left_type.partial_fallback.type.get("__add__")
3575 if left_add_method and left_add_method.fullname == "builtins.tuple.__add__":
3576 proper_right_type = get_proper_type(self.accept(e.right))
3577 if isinstance(proper_right_type, TupleType):
3578 right_radd_method = proper_right_type.partial_fallback.type.get("__radd__")
3579 if right_radd_method is None:
3580 # One cannot have two variadic items in the same tuple.
3581 if (
3582 find_unpack_in_list(proper_left_type.items) is None
3583 or find_unpack_in_list(proper_right_type.items) is None
3584 ):
3585 return self.concat_tuples(proper_left_type, proper_right_type)
3586 elif (
3587 PRECISE_TUPLE_TYPES in self.chk.options.enable_incomplete_feature
3588 and isinstance(proper_right_type, Instance)
3589 and self.chk.type_is_iterable(proper_right_type)
3590 ):
3591 # Handle tuple[X, Y] + tuple[Z, ...] = tuple[X, Y, *tuple[Z, ...]].
3592 right_radd_method = proper_right_type.type.get("__radd__")
3593 if (
3594 right_radd_method is None
3595 and proper_left_type.partial_fallback.type.fullname == "builtins.tuple"
3596 and find_unpack_in_list(proper_left_type.items) is None
3597 ):
3598 item_type = self.chk.iterable_item_type(proper_right_type, e)
3599 mapped = self.chk.named_generic_type("builtins.tuple", [item_type])
3600 return proper_left_type.copy_modified(
3601 items=proper_left_type.items + [UnpackType(mapped)]
3602 )
3603
3604 use_reverse: UseReverse = USE_REVERSE_DEFAULT
3605 if e.op == "|":
3606 if is_named_instance(proper_left_type, "builtins.dict"):
3607 # This is a special case for `dict | TypedDict`.
3608 # 1. Find `dict | TypedDict` case
3609 # 2. Switch `dict.__or__` to `TypedDict.__ror__` (the same from both runtime and typing perspective)
3610 proper_right_type = get_proper_type(self.accept(e.right))
3611 if isinstance(proper_right_type, TypedDictType):
3612 use_reverse = USE_REVERSE_ALWAYS

Callers

nothing calls this directly

Calls 15

acceptMethod · 0.95
check_boolean_opMethod · 0.95
check_list_multiplyMethod · 0.95
concat_tuplesMethod · 0.95
check_opMethod · 0.95
get_proper_typeFunction · 0.90
find_unpack_in_listFunction · 0.90
UnpackTypeClass · 0.90
is_named_instanceFunction · 0.90
isinstanceFunction · 0.85
RuntimeErrorClass · 0.85

Tested by

no test coverage detected