--- /dev/null
+.. change::
+ :tags: bug, typing
+ :tickets: 9502
+
+ Fixed typing issue where :func:`_orm.composite` would not allow an
+ arbitrary callable as the source of the composite class.
class called ``HasVertex``, which is where the :class:`.Table` containing the
four source columns ultimately resides::
+ from __future__ import annotations
+
import dataclasses
+ from typing import Any
+ from typing import Tuple
from sqlalchemy.orm import composite
from sqlalchemy.orm import DeclarativeBase
end: Point
@classmethod
- def _generate(self, x1, y1, x2, y2):
+ def _generate(cls, x1: int, y1: int, x2: int, y2: int) -> Vertex:
"""generate a Vertex from a row"""
return Vertex(Point(x1, y1), Point(x2, y2))
- def __composite_values__(self):
+ def __composite_values__(self) -> Tuple[Any, ...]:
"""generate a row from a Vertex"""
return dataclasses.astuple(self.start) + dataclasses.astuple(self.end)
...
+@overload
+def composite(
+ _class_or_attr: Callable[..., _CC],
+ *attrs: _CompositeAttrType[Any],
+ group: Optional[str] = None,
+ deferred: bool = False,
+ raiseload: bool = False,
+ comparator_factory: Optional[Type[Composite.Comparator[_T]]] = None,
+ active_history: bool = False,
+ init: Union[_NoArg, bool] = _NoArg.NO_ARG,
+ repr: Union[_NoArg, bool] = _NoArg.NO_ARG, # noqa: A002
+ default: Optional[Any] = _NoArg.NO_ARG,
+ default_factory: Union[_NoArg, Callable[[], _T]] = _NoArg.NO_ARG,
+ compare: Union[_NoArg, bool] = _NoArg.NO_ARG,
+ kw_only: Union[_NoArg, bool] = _NoArg.NO_ARG,
+ info: Optional[_InfoType] = None,
+ doc: Optional[str] = None,
+ **__kw: Any,
+) -> Composite[_CC]:
+ ...
+
+
def composite(
_class_or_attr: Union[
None, Type[_CC], Callable[..., _CC], _CompositeAttrType[Any]
def __ne__(self, other: Any) -> bool:
return not self.__eq__(other)
+ @classmethod
+ def _generate(cls, x1: int, y1: int) -> "Point":
+ return Point(x1, y1)
+
class Vertex(Base):
__tablename__ = "vertices"
start = composite(Point, "x1", "y1")
# taken from left hand side
- end: Mapped[Point] = composite(Point, "x2", "y2")
+ end: Mapped[Point] = composite(Point._generate, "x2", "y2")
v1 = Vertex(start=Point(3, 4), end=Point(5, 6))