\r
from datetime import datetime\r
from typing import Protocol\r
+from typing import Sequence\r
+from typing import TypeVar\r
from typing import Union\r
\r
from sqlalchemy import ForeignKey\r
from sqlalchemy import func\r
from sqlalchemy import Nullable\r
from sqlalchemy.orm import DeclarativeBase\r
+from sqlalchemy.orm import InstrumentedAttribute\r
from sqlalchemy.orm import Mapped\r
from sqlalchemy.orm import mapped_column\r
from sqlalchemy.orm import relationship\r
# Read-only for simplicity, mutable protocol members are complicated,\r
# see https://mypy.readthedocs.io/en/latest/common_issues.html#covariant-subtyping-of-mutable-protocol-members-is-rejected\r
@property\r
- def parent(self) -> Mapped[ParentProtocol]: ...\r
+ def parent(self) -> Mapped[ParentProtocol]:\r
+ ...\r
\r
\r
def get_parent_name(child: ChildProtocol) -> str:\r
\r
name: Mapped[str] = mapped_column(primary_key=True)\r
\r
+ children: Mapped[Sequence["Child"]] = relationship("Child")\r
+\r
\r
class Child(Base):\r
__tablename__ = "child"\r
\r
assert get_parent_name(Child(parent=Parent(name="foo"))) == "foo"\r
\r
+# Make sure that relationships are covariant as well\r
+_BaseT = TypeVar("_BaseT", bound=Base, covariant=True)\r
+RelationshipType = (\r
+ InstrumentedAttribute[_BaseT]\r
+ | InstrumentedAttribute[Sequence[_BaseT]]\r
+ | InstrumentedAttribute[_BaseT | None]\r
+)\r
+\r
+\r
+def operate_on_relationships(\r
+ relationships: list[RelationshipType[_BaseT]],\r
+) -> int:\r
+ return len(relationships)\r
+\r
+\r
+assert operate_on_relationships([Parent.children, Child.parent]) == 2\r
+\r
# other test\r
\r
\r