PEP 767: Annotating Read-Only Attributes

Removal of the mentions of descriptors from the PEP means that the combination of explicit protocol implementation (via inheritance) and implementing a ReadOnly member via property won’t be possible.

It’s sad to have to compromise, but I’d rather do that than wait for yet another specification. Hopefully the eventual clarification to instance & class variables will enable what I want.


Imo the current interaction of type and Protocol attributes makes little sense.
Given:

class HasName(Protocol):
    name: str

I think the following shouldn’t reveal anything but unknown. [1]

def takes_cls(cls: type[HasName]):
    reveal_type(foo.name)

I don’t really know what type[HasName] is supposed to convey. For most intents and purposes, I think it’s about as wide as just using plain type, since the instance variable speaks nothing of the type object.
It could be str, it could not exist, or if it was ReadOnly in the protocol, it could be a property (or other descriptor).
If the intent is to use the type as a factory, one is likely better off using Callable[<params>, HasName].
If the type itself is expected to have an attribute name, it should be assignable to HasName anyway.


  1. or at best the equivalent of T | Unbound, like pyright reports for loop variables outside the loop, which wouldn’t be very useful either ↩︎