return getattr(entity, key)
-class InstrumentedAttribute(QueryableAttribute[_T]):
+class InstrumentedAttribute(QueryableAttribute[_T_co]):
"""Class bound instrumented attribute which adds basic
:term:`descriptor` methods.
@overload
def __get__(
self, instance: None, owner: Any
- ) -> InstrumentedAttribute[_T]: ...
+ ) -> InstrumentedAttribute[_T_co]: ...
@overload
- def __get__(self, instance: object, owner: Any) -> _T: ...
+ def __get__(self, instance: object, owner: Any) -> _T_co: ...
def __get__(
self, instance: Optional[object], owner: Any
- ) -> Union[InstrumentedAttribute[_T], _T]:
+ ) -> Union[InstrumentedAttribute[_T_co], _T_co]:
if instance is None:
return self
\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
\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