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

Reply via email to