I'm using pythons attrs package to @define some classes containing some members with little logic for isolation purposes.
However, when I run the following stripped down example:
from attrs import define
@define
class DefTest:
attr1: int = 123
attr2: int = 456
attr3: str = "abcdef"
x = DefTest()
print(type(x))
it justs outputs <class '__main__.DefTest'>, with now hint which type it is derived from.
Even type(x).mro() outputs [<class '__main__.DefTest'>, <class 'object'>], with no reference to some internally defined attrs class.
Now, imagine a function which takes an attrs class instance and performs some action on it. How can I add a proper type annotation, instead of the placeholder?
from attrs import asdict, define
import json
def asjson(attrsclass: "DefineDecoratedClass"):
return json.dumps(asdict(attrsclass))
I tried annotating using attrs.AttrsInstance which seems to be wrong from the linters perspective.
Any idea?
I'm an attrs maintainer and I sometimes work on the attrs Mypy plugin.
attrs will not inject a class into your MRO; this is entirely by design to let you have complete control over your class tree. The way to recognize an attrs class is to look for the presence of an
__attrs_attrs__class attribute, which is how theAttrsInstanceprotocol is defined in the first place.Note that you need to use
type[AttrsInstance]if you're looking for an attrs class, as opposed to an instance of an attrs class.The Mypy plugin correctly generates the
__attrs_attrs__marker, so this protocol should work with the latest version of Mypy. Pyright doesn't, and since PEP 681 (dataclass transforms) makes no provisions for this and Pyright has no plugin system, I believe there's nothing we can do about it.