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 the AttrsInstance
protocol 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.