@@ -398,14 +398,9 @@ def analyze_member_var_access(name: str,
398
398
# the guard this search will always find object.__getattribute__ and conclude
399
399
# that the attribute exists
400
400
if method and method .info .fullname != 'builtins.object' :
401
- if isinstance (method , Decorator ):
402
- # https://github.com/python/mypy/issues/10409
403
- bound_method = analyze_var (method_name , method .var , itype , info , mx )
404
- else :
405
- bound_method = bind_self (
406
- function_type (method , mx .named_type ('builtins.function' )),
407
- mx .self_type ,
408
- )
401
+ bound_method = analyze_decorator_or_funcbase_access (
402
+ defn = method , itype = itype , info = info ,
403
+ self_type = mx .self_type , name = method_name , mx = mx )
409
404
typ = map_instance_to_supertype (itype , method .info )
410
405
getattr_type = get_proper_type (expand_type_by_instance (bound_method , typ ))
411
406
if isinstance (getattr_type , CallableType ):
@@ -423,16 +418,10 @@ def analyze_member_var_access(name: str,
423
418
else :
424
419
setattr_meth = info .get_method ('__setattr__' )
425
420
if setattr_meth and setattr_meth .info .fullname != 'builtins.object' :
426
- if isinstance (setattr_meth , Decorator ):
427
- bound_type = analyze_var (
428
- name , setattr_meth .var , itype , info ,
429
- mx .copy_modified (is_lvalue = False ),
430
- )
431
- else :
432
- bound_type = bind_self (
433
- function_type (setattr_meth , mx .named_type ('builtins.function' )),
434
- mx .self_type ,
435
- )
421
+ bound_type = analyze_decorator_or_funcbase_access (
422
+ defn = setattr_meth , itype = itype , info = info ,
423
+ self_type = mx .self_type , name = name ,
424
+ mx = mx .copy_modified (is_lvalue = False ))
436
425
typ = map_instance_to_supertype (itype , setattr_meth .info )
437
426
setattr_type = get_proper_type (expand_type_by_instance (bound_type , typ ))
438
427
if isinstance (setattr_type , CallableType ) and len (setattr_type .arg_types ) > 0 :
@@ -493,15 +482,9 @@ def analyze_descriptor_access(descriptor_type: Type,
493
482
mx .context )
494
483
return AnyType (TypeOfAny .from_error )
495
484
496
- if isinstance (dunder_get , Decorator ):
497
- bound_method = analyze_var (
498
- '__set__' , dunder_get .var , descriptor_type , descriptor_type .type , mx ,
499
- )
500
- else :
501
- bound_method = bind_self (
502
- function_type (dunder_get , mx .named_type ('builtins.function' )),
503
- descriptor_type ,
504
- )
485
+ bound_method = analyze_decorator_or_funcbase_access (
486
+ defn = dunder_get , itype = descriptor_type , info = descriptor_type .type ,
487
+ self_type = descriptor_type , name = '__set__' , mx = mx )
505
488
506
489
typ = map_instance_to_supertype (descriptor_type , dunder_get .info )
507
490
dunder_get_type = expand_type_by_instance (bound_method , typ )
@@ -1028,6 +1011,27 @@ def type_object_type(info: TypeInfo, named_type: Callable[[str], Instance]) -> P
1028
1011
return type_object_type_from_function (t , info , method .info , fallback , is_new )
1029
1012
1030
1013
1014
+ def analyze_decorator_or_funcbase_access (
1015
+ defn : Union [Decorator , FuncBase ],
1016
+ itype : Instance ,
1017
+ info : TypeInfo ,
1018
+ self_type : Optional [Type ],
1019
+ name : str ,
1020
+ mx : MemberContext ,
1021
+ ) -> Type :
1022
+ """Analyzes the type behind method access.
1023
+
1024
+ The function itself can possibly be decorated.
1025
+ See: https://github.com/python/mypy/issues/10409
1026
+ """
1027
+ if isinstance (defn , Decorator ):
1028
+ return analyze_var (name , defn .var , itype , info , mx )
1029
+ return bind_self (
1030
+ function_type (defn , mx .chk .named_type ('builtins.function' )),
1031
+ original_type = self_type ,
1032
+ )
1033
+
1034
+
1031
1035
def is_valid_constructor (n : Optional [SymbolNode ]) -> bool :
1032
1036
"""Does this node represents a valid constructor method?
1033
1037
0 commit comments