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

Method visit_comparison_expr

mypy/checkexpr.py:3664–3829  ·  view source on GitHub ↗

Type check a comparison expression. Comparison expressions are type checked consecutive-pair-wise That is, 'a < b > c == d' is check as 'a < b and b > c and c == d'

(self, e: ComparisonExpr)

Source from the content-addressed store, hash-verified

3662 raise RuntimeError(f"Unknown operator {e.op}")
3663
3664 def visit_comparison_expr(self, e: ComparisonExpr) -> Type:
3665 """Type check a comparison expression.
3666
3667 Comparison expressions are type checked consecutive-pair-wise
3668 That is, 'a < b > c == d' is check as 'a < b and b > c and c == d'
3669 """
3670 result: Type | None = None
3671 sub_result: Type
3672
3673 # Check each consecutive operand pair and their operator
3674 for left, right, operator in zip(e.operands, e.operands[1:], e.operators):
3675 left_type = self.accept(left)
3676
3677 if operator == "in" or operator == "not in":
3678 # This case covers both iterables and containers, which have different meanings.
3679 # For a container, the in operator calls the __contains__ method.
3680 # For an iterable, the in operator iterates over the iterable, and compares each item one-by-one.
3681 # We allow `in` for a union of containers and iterables as long as at least one of them matches the
3682 # type of the left operand, as the operation will simply return False if the union's container/iterator
3683 # type doesn't match the left operand.
3684
3685 # If the right operand has partial type, look it up without triggering
3686 # a "Need type annotation ..." message, as it would be noise.
3687 right_type = self.find_partial_type_ref_fast_path(right)
3688 if right_type is None:
3689 right_type = self.accept(right) # Validate the right operand
3690
3691 right_type = get_proper_type(right_type)
3692 item_types: Sequence[Type] = [right_type]
3693 if isinstance(right_type, UnionType):
3694 item_types = list(right_type.relevant_items())
3695
3696 sub_result = self.bool_type()
3697
3698 container_types: list[Type] = []
3699 iterable_types: list[Type] = []
3700 failed_out = False
3701 encountered_partial_type = False
3702
3703 for item_type in item_types:
3704 # Keep track of whether we get type check errors (these won't be reported, they
3705 # are just to verify whether something is valid typing wise).
3706 with self.msg.filter_errors(save_filtered_errors=True) as container_errors:
3707 _, method_type = self.check_method_call_by_name(
3708 method="__contains__",
3709 base_type=item_type,
3710 args=[left],
3711 arg_kinds=[ARG_POS],
3712 context=e,
3713 original_type=right_type,
3714 )
3715 # Container item type for strict type overlap checks. Note: we need to only
3716 # check for nominal type, because a usual "Unsupported operands for in"
3717 # will be reported for types incompatible with __contains__().
3718 # See testCustomContainsCheckStrictEquality for an example.
3719 cont_type = self.chk.analyze_container_item_type(item_type)
3720
3721 if isinstance(item_type, PartialType):

Callers

nothing calls this directly

Calls 15

acceptMethod · 0.95
bool_typeMethod · 0.95
is_valid_var_argMethod · 0.95
named_typeMethod · 0.95
dangerous_comparisonMethod · 0.95
check_opMethod · 0.95
get_proper_typeFunction · 0.90
CallableTypeClass · 0.90
is_subtypeFunction · 0.90
ErrorWatcherClass · 0.90

Tested by

no test coverage detected