I’m writing an attrs class called SessionInfo that looks like this:
from attrs import define, field
@define(kw_only=True)
class ControllerInfo:
controller_data: int = field(default=0)
@define(kw_only=True)
class SessionInfo:
controllers: dict[str, ControllerInfo] = field(factory=dict)
ControllerInfo should serve as a base class for other classes in order to inherit the original attributes and be able to expand on those.
I’m trying to explain that to the type checker, but for example when doing:
@define
class MyInfo(ControllerInfo):
other_controller_data: str
ctrls = {
"my_controller": MyInfo()
"my_other_controller": MyInfo()
}
session = SessionInfo(ctrls)
mypy returns the following error:
Argument "controllers" to "SessionInfo" has incompatible type "dict[str, MyInfo]"; expected "dict[str, ControllerInfo]"
In itself it’s not a too big of a problem because this is part of a plugin architecture and I know that at runtime it should not cause problems (unless the user specifically doesn’t inherit from ControllerInfo). At the same time it bothers me a bit in testing and I would like to address this.
I tried using dict[str, builtins.type[ControllerInfo] because I’m trying to specify that the values of the dictionary should be of type ControllerInfo and any of its descendants; but apparently that didn’t work, and now my understanding of the differences between builtins.type and typing.Type went out the window as well.
So the question is: how do I instruct mypy to understand that the values of Session.controllers can be descendants of ControllerInfo?
A secondary question: did I misunderstand the definitions of builtins.type and typing.Type? My understanding was:
builtins.type[Class]is used to specify objects that are of typeClassand any of its descendants;typing.Type[Class]is used to specify classes of typeClassand any of its descendants.
EDIT: sorry for the multiple edits, lots of typos