]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
add explicit overload for composite -> callable
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 17 Mar 2023 12:35:56 +0000 (08:35 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 17 Mar 2023 12:43:22 +0000 (08:43 -0400)
Fixed typing issue where :func:`_orm.composite` would not allow an
arbitrary callable as the source of the composite class.

Fixes: #9502
Change-Id: I5b098b70b2fb7b48f54eaccbb7d5d3d9bdebc781

doc/build/changelog/unreleased_20/9502.rst [new file with mode: 0644]
doc/build/orm/composites.rst
lib/sqlalchemy/orm/_orm_constructors.py
test/ext/mypy/plain_files/composite.py

diff --git a/doc/build/changelog/unreleased_20/9502.rst b/doc/build/changelog/unreleased_20/9502.rst
new file mode 100644 (file)
index 0000000..4409d62
--- /dev/null
@@ -0,0 +1,6 @@
+.. 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.
index 5737b7e73b6e9979479cf1abfd58a143f2c278e9..4eaf7024a93440188d71e530e7f2db893bd2375d 100644 (file)
@@ -399,7 +399,11 @@ For the purposes of the example, the ``Vertex`` composite is then mapped to a
 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
@@ -419,11 +423,11 @@ four source columns ultimately resides::
         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)
 
index 64e7937f11bf52ae70c58463d4a3926d753b0e4a..9f9330ceadc2a5159e8ee7186e2ff97733910840 100644 (file)
@@ -481,6 +481,28 @@ def composite(
     ...
 
 
+@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]
index c69963314e5e0277a4f215065d67510dfd64e643..8ac1f504c26b4bc809dea1811cb61b4b9cc50f0e 100644 (file)
@@ -33,6 +33,10 @@ class Point:
     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"
@@ -47,7 +51,7 @@ class Vertex(Base):
     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))