6262 LiteralType ,
6363 NoneType ,
6464 Overloaded ,
65+ ProperType ,
6566 TupleType ,
6667 Type ,
6768 TypeOfAny ,
@@ -942,6 +943,14 @@ def _get_attrs_init_type(typ: Instance) -> CallableType | None:
942943 return init_method .type
943944
944945
946+ def _get_attrs_cls_and_init (typ : ProperType ) -> tuple [Instance | None , CallableType | None ]:
947+ if isinstance (typ , TypeVarType ):
948+ typ = get_proper_type (typ .upper_bound )
949+ if not isinstance (typ , Instance ):
950+ return None , None
951+ return typ , _get_attrs_init_type (typ )
952+
953+
945954def evolve_function_sig_callback (ctx : mypy .plugin .FunctionSigContext ) -> CallableType :
946955 """
947956 Generates a signature for the 'attr.evolve' function that's specific to the call site
@@ -966,21 +975,16 @@ def evolve_function_sig_callback(ctx: mypy.plugin.FunctionSigContext) -> Callabl
966975 if isinstance (inst_type , AnyType ):
967976 return ctx .default_signature # evolve(Any, ....) -> Any
968977 inst_type_str = format_type_bare (inst_type )
969- attrs_type = get_proper_type (
970- inst_type .upper_bound if isinstance (inst_type , TypeVarType ) else inst_type
971- )
972- attrs_init_type = None
973- if isinstance (attrs_type , Instance ):
974- attrs_init_type = _get_attrs_init_type (attrs_type )
975- if attrs_init_type is None :
978+
979+ attrs_type , attrs_init_type = _get_attrs_cls_and_init (inst_type )
980+ if attrs_type is None or attrs_init_type is None :
976981 ctx .api .fail (
977982 f'Argument 1 to "evolve" has a variable type "{ inst_type_str } " not bound to an attrs class'
978983 if isinstance (inst_type , TypeVarType )
979984 else f'Argument 1 to "evolve" has incompatible type "{ inst_type_str } "; expected an attrs class' ,
980985 ctx .context ,
981986 )
982987 return ctx .default_signature
983- assert isinstance (attrs_type , Instance )
984988
985989 # AttrClass.__init__ has the following signature (or similar, if having kw-only & defaults):
986990 # def __init__(self, attr1: Type1, attr2: Type2) -> None:
0 commit comments