Skip to content

[Attrs] Invalid typing of init arguments in subclasses of generics #5744

Closed

Description

@galcik
from typing import Generic, List, TypeVar
import attr

T_BASE_ITEM = TypeVar("T_BASE_ITEM", bound="BaseItem")


class BaseItem(object):
    pass


class ConcreteItem(BaseItem):
    pass


@attr.s
class Container(Generic[T_BASE_ITEM]):
    items = attr.ib(type=List[T_BASE_ITEM], factory=list)


@attr.s
class ConcreteContainer(Container[ConcreteItem]):
    pass


container1 = ConcreteContainer()
container1.items.append(ConcreteItem())
container1.items.extend([ConcreteItem()])
container1.items = [ConcreteItem()]

container2 = ConcreteContainer(items=[ConcreteItem()])

fails ONLY on the last line:

List item 0 has incompatible type "ConcreteItem"; expected "T_BASE_ITEM"

It seems that typing for the attribute items works as expected. However, if items is used as a keyword argument of the __init__ generated by attrs, typing fails.

Note also that if the following class is added:

@attr.s
class ItemWrapper(Generic[T_BASE_ITEM]):
    item = attr.ib(type=T_BASE_ITEM)

mypy fails with error:

'T_BASE_ITEM' is a type variable and only valid in type context

Activity

  1. ilevkivskyi commented on Oct 8, 2018

    @ilevkivskyi
    Member

    Yes, this is clearly a bug. The cause is that __init__ is generated for every subclass that is an attrs class. When __init__ (or any other attribute) is accessed on a superclass of a normal class, mypy takes care to map_instance_to_supertype/expand_type_by_instance, while the plugin doesn't do this.

    @euresti will you have time to work on this?

  2. ilevkivskyi commented on Oct 8, 2018

    @ilevkivskyi
    Member

    Btw, most likely dataclasses have the same problem.

  3. natemcmaster commented on Aug 30, 2020

    @natemcmaster
    Contributor

    Thanks for the tip about map_instance_to_supertype. I have proposed a fix in #9383 which uses that API to resolve typevars.

  4. added a commit that references this issue on Nov 28, 2020
    fc212ef
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions