I thought python Protocol was only useful for type-hints, without any impact on the runtime behavior (except when using @runtime_checkable or default method implementation).
But see this example:
from typing import Protocol
class PortProto(Protocol):
@property
def port_id(self) -> str:
"""a read-only port id"""
class MyPortA:
port_id: str
class MyPortB(PortProto):
port_id: str
my_port_a = MyPortA()
my_port_a.port_id = "some_id"
print(my_port_a.port_id) # prints "some_id"
my_port_b = MyPortB()
my_port_b.port_id = "some_id" # raises "AttributeError: can't set attribute"
print(my_port_b.port_id)
Where line my_port_b.port_id = "some_id" raises AttributeError: can't set attribute.
The only difference between MyPortA and MyPortB is the inheritance of the Protocol.
Is it a bug in Python or the intended behavior?
Yes, I know this line is a violation of the getter-only attribute defined in the Protocol, but this is a type-hint problem for tools like mypy, not something for the runtime.
(Or maybe it's not even a violation of the type-hint, because a read-and-write attribute is a subtype of a read-only attribute).
I expected to see no difference between classes that inherit a Protocol and classes that do not.
Python version: 3.9.7
Protocoltype that would avoid that error (nor would it make sense for it to).