How to declare a Protocol with a field which supports both a simple type and property?

Question:

(Related, but not duplicated: How to annotate attribute that can be implemented as property?)

I want to create a Protocol, in which a field can be implemented by both a simple type and property. For example:

class P(Protocol):
    v: int


@dataclass
class Foo(P):
    v: int


class Bar(P):
    @property
    def v(self) -> int: # ERROR
        return

But the code above doesn’t type check. How should I fix it?

Note: I want to solve this issue without rewriting Foo and Bar, because Foo and Bar are not what I implemented.

According to this issue the below code is not a solution because read-only property and a simple member have subtly different semantics.

class P(Protocol):
    @property
    def v(self) -> int: # declare as property
        ...

Pyright denies this Protocol due to the difference.

Asked By: tamuhey

||

Answers:

In general, declare the Protocol using a read-only property, not a read/write field:

class P(Protocol):
    @property
    def v(self) -> int:
        pass

This is needed because a read-only protocol attribute is satisfied by both a read-only property and a read/write field. In contrast, a read/write protocol attribute is satisfied only by a read/write field, not a read-only property.


As PyRight insists that fields and properties are different kinds of attributes, the attribute must be declared with both variants – once as a field and once as an attribute. For simple protocols, this can be done by declaring a separate field and property variant of the property:

# field only
class Pf(Protocol):
    v: int

# property only
class Pp(Protocol):
    @property
    def v(self) -> int:
        return 1

# Either field or property
P = Union[Pf, Pp]

This is valid for both MyPy and PyRight.

Answered By: MisterMiyagi

If you are not strict about the type annotated for the property’s getter, you could define P as:

from typing import Protocol, Union, ClassVar

class P(Protocol):
    v: Union[int, ClassVar]
Answered By: truhanen
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.