On 30 June 2018 at 23:54, Tin Tvrtković <tinches...@gmail.com> wrote:
> [...] > > An attrs class has a special class-level field, __attrs_attrs__, which > holds the attribute definitions. So maybe we can define a protocol: > > class AttrsClass(Protocol): > __attrs_attrs__: ClassVar[Tuple[Attribute, ...]] > > then we could define asdict as (simplified): > > def asdict(inst: AttrsClass) -> Dict[str, Any]: > ... > > and it should work out. My question is how to actually add this protocol > to attrs classes. Now, we currently have an attrs plugin in mypy so maybe > some magic in there could make it happen in this particular case. > Just add a Var with an appropriate name and type to the TypeInfo. This is literary a dozen lines of code, you can ask on mypy tracker or typing Gitter chat for more help. > My second use case is a small library I've developed for work, which > basically wraps attrs and generates and sticks methods on a class for > serialization/deserialization. Consider the following short program, which > does not typecheck on the current mypy. > > class Serializable(Protocol): > def __serialize__(self) -> int: > ... > > def make_serializable(cl: Type) -> Type: > cl = attr.s(cl) > cl.__serialize__ = lambda self: 1 > return cl > > > @make_serializable > class A: > a: int = attr.ib() > > > def serialize(inst: Serializable) -> int: > return inst.__serialize__() > > > serialize(A(1)) > > error: Argument 1 to "serialize" has incompatible type "A"; expected > "Serializable" > error: Too many arguments for "A" > > I have no desire to write a mypy plugin for this library. So I guess what > is needed is a way to annotate the class decorator, telling mypy it's > adding a protocol to a class. It seems to have trouble getting to this > conclusion by itself. > A proper solution for this would be to introduce intersection types, and type your decorator as following: T = TypeVar('T') def make_serializable(cls: Type[T]) -> Type[Intersection[T, Serializable]]: ... However, intersection types are unlikely to appear in mypy this year. In best case they could appear around mid-2019, so you are better with writing a plugin for now. > (The second error implies the attrs plugin doesn't handle wrapping attr.s, > which is unfortunate but a different issue.) > Your decorator is typed as (Type) -> Type, thats it, the function is a black box for mypy (with few special exceptions), if some effect of a function is not declared in its signature, then it is lost forever. -- Ivan
_______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com