126
126
validate_instance ,
127
127
)
128
128
from mypy .typeops import (
129
+ bind_self ,
129
130
callable_type ,
130
131
custom_special_method ,
131
132
erase_to_union_or_bound ,
@@ -354,7 +355,9 @@ def visit_name_expr(self, e: NameExpr) -> Type:
354
355
"""
355
356
self .chk .module_refs .update (extract_refexpr_names (e ))
356
357
result = self .analyze_ref_expr (e )
357
- return self .narrow_type_from_binder (e , result )
358
+ narrowed = self .narrow_type_from_binder (e , result )
359
+ self .chk .check_deprecated (e .node , e )
360
+ return narrowed
358
361
359
362
def analyze_ref_expr (self , e : RefExpr , lvalue : bool = False ) -> Type :
360
363
result : Type | None = None
@@ -1479,6 +1482,10 @@ def check_call_expr_with_callee_type(
1479
1482
object_type = object_type ,
1480
1483
)
1481
1484
proper_callee = get_proper_type (callee_type )
1485
+ if isinstance (e .callee , NameExpr ) and isinstance (e .callee .node , OverloadedFuncDef ):
1486
+ for item in e .callee .node .items :
1487
+ if isinstance (item , Decorator ) and (item .func .type == callee_type ):
1488
+ self .chk .check_deprecated (item .func , e )
1482
1489
if isinstance (e .callee , RefExpr ) and isinstance (proper_callee , CallableType ):
1483
1490
# Cache it for find_isinstance_check()
1484
1491
if proper_callee .type_guard is not None :
@@ -3267,7 +3274,9 @@ def visit_member_expr(self, e: MemberExpr, is_lvalue: bool = False) -> Type:
3267
3274
"""Visit member expression (of form e.id)."""
3268
3275
self .chk .module_refs .update (extract_refexpr_names (e ))
3269
3276
result = self .analyze_ordinary_member_access (e , is_lvalue )
3270
- return self .narrow_type_from_binder (e , result )
3277
+ narrowed = self .narrow_type_from_binder (e , result )
3278
+ self .chk .warn_deprecated (e .node , e )
3279
+ return narrowed
3271
3280
3272
3281
def analyze_ordinary_member_access (self , e : MemberExpr , is_lvalue : bool ) -> Type :
3273
3282
"""Analyse member expression or member lvalue."""
@@ -3956,7 +3965,7 @@ def lookup_definer(typ: Instance, attr_name: str) -> str | None:
3956
3965
# This is the case even if the __add__ method is completely missing and the __radd__
3957
3966
# method is defined.
3958
3967
3959
- variants_raw = [(left_op , left_type , right_expr )]
3968
+ variants_raw = [(op_name , left_op , left_type , right_expr )]
3960
3969
elif (
3961
3970
is_subtype (right_type , left_type )
3962
3971
and isinstance (left_type , Instance )
@@ -3977,19 +3986,25 @@ def lookup_definer(typ: Instance, attr_name: str) -> str | None:
3977
3986
# As a special case, the alt_promote check makes sure that we don't use the
3978
3987
# __radd__ method of int if the LHS is a native int type.
3979
3988
3980
- variants_raw = [(right_op , right_type , left_expr ), (left_op , left_type , right_expr )]
3989
+ variants_raw = [
3990
+ (rev_op_name , right_op , right_type , left_expr ),
3991
+ (op_name , left_op , left_type , right_expr ),
3992
+ ]
3981
3993
else :
3982
3994
# In all other cases, we do the usual thing and call __add__ first and
3983
3995
# __radd__ second when doing "A() + B()".
3984
3996
3985
- variants_raw = [(left_op , left_type , right_expr ), (right_op , right_type , left_expr )]
3997
+ variants_raw = [
3998
+ (op_name , left_op , left_type , right_expr ),
3999
+ (rev_op_name , right_op , right_type , left_expr ),
4000
+ ]
3986
4001
3987
4002
# STEP 3:
3988
4003
# We now filter out all non-existent operators. The 'variants' list contains
3989
4004
# all operator methods that are actually present, in the order that Python
3990
4005
# attempts to invoke them.
3991
4006
3992
- variants = [(op , obj , arg ) for (op , obj , arg ) in variants_raw if op is not None ]
4007
+ variants = [(na , op , obj , arg ) for (na , op , obj , arg ) in variants_raw if op is not None ]
3993
4008
3994
4009
# STEP 4:
3995
4010
# We now try invoking each one. If an operation succeeds, end early and return
@@ -3998,13 +4013,23 @@ def lookup_definer(typ: Instance, attr_name: str) -> str | None:
3998
4013
3999
4014
errors = []
4000
4015
results = []
4001
- for method , obj , arg in variants :
4016
+ for name , method , obj , arg in variants :
4002
4017
with self .msg .filter_errors (save_filtered_errors = True ) as local_errors :
4003
4018
result = self .check_method_call (op_name , obj , method , [arg ], [ARG_POS ], context )
4004
4019
if local_errors .has_new_errors ():
4005
4020
errors .append (local_errors .filtered_errors ())
4006
4021
results .append (result )
4007
4022
else :
4023
+ if isinstance (obj , Instance ) and isinstance (
4024
+ defn := obj .type .get_method (name ), OverloadedFuncDef
4025
+ ):
4026
+ for item in defn .items :
4027
+ if (
4028
+ isinstance (item , Decorator )
4029
+ and isinstance (typ := item .func .type , CallableType )
4030
+ and bind_self (typ ) == result [1 ]
4031
+ ):
4032
+ self .chk .check_deprecated (item .func , context )
4008
4033
return result
4009
4034
4010
4035
# We finish invoking above operators and no early return happens. Therefore,
0 commit comments