From d330033a99fd0c6f0c035e67d47ad31fccc2e3d6 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Sat, 4 Dec 2021 21:18:04 +0300 Subject: [PATCH 1/2] Follow up to #11150, refactors `if`s into a util function --- mypy/checker.py | 16 +++++-------- mypy/checkmember.py | 57 ++++++++++++++++++++++++--------------------- 2 files changed, 36 insertions(+), 37 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 9dc8eaea2a99..5a1d8c676b8b 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -46,8 +46,9 @@ ) import mypy.checkexpr from mypy.checkmember import ( - MemberContext, analyze_member_access, analyze_descriptor_access, analyze_var, + MemberContext, analyze_member_access, analyze_descriptor_access, type_object_type, + analyze_decorator_or_funcbase_access, ) from mypy.typeops import ( map_type_from_supertype, bind_self, erase_to_bound, make_simplified_union, @@ -3225,15 +3226,10 @@ def check_member_assignment(self, instance_type: Type, attribute_type: Type, if dunder_set is None: self.fail(message_registry.DESCRIPTOR_SET_NOT_CALLABLE.format(attribute_type), context) return AnyType(TypeOfAny.from_error), get_type, False - if isinstance(dunder_set, Decorator): - bound_method = analyze_var( - '__set__', dunder_set.var, attribute_type, attribute_type.type, mx, - ) - else: - bound_method = bind_self( - function_type(dunder_set, self.named_type('builtins.function')), - attribute_type, - ) + + bound_method = analyze_decorator_or_funcbase_access( + defn=dunder_set, itype=attribute_type, info=attribute_type.type, + self_type=attribute_type, name='__set__', mx=mx) typ = map_instance_to_supertype(attribute_type, dunder_set.info) dunder_set_type = expand_type_by_instance(bound_method, typ) diff --git a/mypy/checkmember.py b/mypy/checkmember.py index 3ab85b850689..f4ed98da1675 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -398,14 +398,9 @@ def analyze_member_var_access(name: str, # the guard this search will always find object.__getattribute__ and conclude # that the attribute exists if method and method.info.fullname != 'builtins.object': - if isinstance(method, Decorator): - # https://github.com/python/mypy/issues/10409 - bound_method = analyze_var(method_name, method.var, itype, info, mx) - else: - bound_method = bind_self( - function_type(method, mx.named_type('builtins.function')), - mx.self_type, - ) + bound_method = analyze_decorator_or_funcbase_access( + defn=method, itype=itype, info=info, + self_type=mx.self_type, name=method_name, mx=mx) typ = map_instance_to_supertype(itype, method.info) getattr_type = get_proper_type(expand_type_by_instance(bound_method, typ)) if isinstance(getattr_type, CallableType): @@ -423,16 +418,9 @@ def analyze_member_var_access(name: str, else: setattr_meth = info.get_method('__setattr__') if setattr_meth and setattr_meth.info.fullname != 'builtins.object': - if isinstance(setattr_meth, Decorator): - bound_type = analyze_var( - name, setattr_meth.var, itype, info, - mx.copy_modified(is_lvalue=False), - ) - else: - bound_type = bind_self( - function_type(setattr_meth, mx.named_type('builtins.function')), - mx.self_type, - ) + bound_type = analyze_decorator_or_funcbase_access( + defn=setattr_meth, itype=itype, info=info, + self_type=mx.self_type, name=name, mx=mx) typ = map_instance_to_supertype(itype, setattr_meth.info) setattr_type = get_proper_type(expand_type_by_instance(bound_type, typ)) if isinstance(setattr_type, CallableType) and len(setattr_type.arg_types) > 0: @@ -493,15 +481,9 @@ def analyze_descriptor_access(descriptor_type: Type, mx.context) return AnyType(TypeOfAny.from_error) - if isinstance(dunder_get, Decorator): - bound_method = analyze_var( - '__set__', dunder_get.var, descriptor_type, descriptor_type.type, mx, - ) - else: - bound_method = bind_self( - function_type(dunder_get, mx.named_type('builtins.function')), - descriptor_type, - ) + bound_method = analyze_decorator_or_funcbase_access( + defn=dunder_get, itype=descriptor_type, info=descriptor_type.type, + self_type=descriptor_type, name='__set__', mx=mx) typ = map_instance_to_supertype(descriptor_type, dunder_get.info) dunder_get_type = expand_type_by_instance(bound_method, typ) @@ -1028,6 +1010,27 @@ def type_object_type(info: TypeInfo, named_type: Callable[[str], Instance]) -> P return type_object_type_from_function(t, info, method.info, fallback, is_new) +def analyze_decorator_or_funcbase_access( + defn: Union[Decorator, FuncBase], + itype: Instance, + info: TypeInfo, + self_type: Optional[Type], + name: str, + mx: MemberContext, +) -> Type: + """Analyzes the type behind method access. + + The function itself can possibly be decorated. + See: https://github.com/python/mypy/issues/10409 + """ + if isinstance(defn, Decorator): + return analyze_var(name, defn.var, itype, info, mx) + return bind_self( + function_type(defn, mx.chk.named_type('builtins.function')), + original_type=self_type, + ) + + def is_valid_constructor(n: Optional[SymbolNode]) -> bool: """Does this node represents a valid constructor method? From 4e23f0c85942c99ad2e4804a2308476ac9c95baf Mon Sep 17 00:00:00 2001 From: sobolevn Date: Sat, 4 Dec 2021 21:34:28 +0300 Subject: [PATCH 2/2] Follow up to #11150, refactors `if`s into a util function --- mypy/checkmember.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mypy/checkmember.py b/mypy/checkmember.py index f4ed98da1675..c01f52de5a77 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -420,7 +420,8 @@ def analyze_member_var_access(name: str, if setattr_meth and setattr_meth.info.fullname != 'builtins.object': bound_type = analyze_decorator_or_funcbase_access( defn=setattr_meth, itype=itype, info=info, - self_type=mx.self_type, name=name, mx=mx) + self_type=mx.self_type, name=name, + mx=mx.copy_modified(is_lvalue=False)) typ = map_instance_to_supertype(itype, setattr_meth.info) setattr_type = get_proper_type(expand_type_by_instance(bound_type, typ)) if isinstance(setattr_type, CallableType) and len(setattr_type.arg_types) > 0: