I'm trying to define helper functions typed with protocols that will later be used on SQLAlchemy 2.0 mapped classes.
In my case, I'd need a specific mapped attribute of my SQLAlchemy class (ie a column) to be represented as a protocol itself. However, from looking at its source code I've found that Mapped
is invariant - hence, if I understand correctly, the error below.
Any idea if there's a better way I could type-hint my classes / functions to make it work?
from typing import Protocol
from sqlalchemy.orm import DeclarativeBase, Mapped
# Protocols
class BarProtocol(Protocol):
bar: Mapped[int]
class FooProtocol(Protocol):
@property
def bar(self) -> Mapped[BarProtocol]:
...
def f(foo: FooProtocol) -> BarProtocol:
return foo.bar
# Implementations
class Base(DeclarativeBase):
pass
class Bar(Base):
bar: Mapped[int]
class Foo(Base):
bar: Mapped[Bar]
f(Foo()) # Doesn't type-check
Mypy output:
error: Argument 1 to "f" has incompatible type "Foo"; expected "FooProtocol" [arg-type]
note: Following member(s) of "Foo" have conflicts:
note: bar: expected "Mapped[BarProtocol]", got "Mapped[Bar]"
Found 1 error in 1 file (checked 1 source file)
Mapped
has been made covariant in 2.0.21 (see release notes).