]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
docs: add docs for register_composite's make_instance param 932/head
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Thu, 30 Oct 2025 14:39:19 +0000 (14:39 +0000)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Thu, 30 Oct 2025 14:42:15 +0000 (14:42 +0000)
docs/basic/pgtypes.rst
docs/news.rst
psycopg/psycopg/types/composite.py

index 14ee5bee366ee4012257e5c03745f0ccb0a015a2..1d47feec4b6a9db523ef73d0b1bace4753ed8945 100644 (file)
@@ -59,6 +59,13 @@ using `~psycopg.types.composite.register_composite()`.
    that type are created and registered too, so that passing objects of that
    type to a query will adapt them to the registered type.
 
+   The `!factory` callable will be called with the sequence of value from the
+   composite. If passing the sequence of positional arguments is not suitable
+   you can specify a :samp:`make_instance({values}, {names})` callable.
+
+   .. versionadded:: 3.3
+        the `!make_instance` parameter
+
 Example::
 
     >>> from psycopg.types.composite import CompositeInfo, register_composite
@@ -92,6 +99,25 @@ composite components are registered as well::
     >>> conn.execute("SELECT ((8, 'hearts'), 'blue')::card_back").fetchone()[0]
     card_back(face=card(value=8, suit='hearts'), back='blue')
 
+If your Python type takes keyword arguments, or if the sequence of value
+coming from the PostgreSQL type is not suitable, it is possible to specify
+a :samp:`make_instance({values}, {names})` function to adapt the values from
+the composite to the right type requirements. For example::
+
+    >>> from dataclasses import dataclass
+    >>> from typing import Any, Sequence
+
+    >>> @dataclass
+    ... class Card:
+    ...     suit: str
+    ...     value: int
+
+    >>> def card_from_db(values: Sequence[Any], names: Sequence[str]) -> Card:
+    ...     return Card(**dict(zip(names, values)))
+
+    >>> register_composite(info, conn, make_instance=card_from_db)
+    >>> conn.execute("select '(1,spades)'::card").fetchone()[0]
+    Card(suit='spades', value=1)
 
 .. index::
     pair: range; Data types
index bca8a15a78b7de388e444bffeddaee86ff4976e7..337972851553ca94c2499f40d69436252649c3bf 100644 (file)
@@ -16,6 +16,9 @@ Psycopg 3.3.0 (unreleased)
 .. rubric:: New top-level features
 
 - Add :ref:`template strings queries <template-strings>` (:ticket:`#1054`).
+- Add `!make_instance` parameter to `~types.composite.register_composite()`
+  to load objects from composite via keyword arguments or in other ways other
+  than just by values sequence (:ticket:`#932`).
 - Cursors are now iterators, not only iterables. This means you can call
   ``next(cur)`` to fetch the next row (:ticket:`#1064`).
 - Add `Cursor.results()` to iterate over the result sets of the queries
index d880984b8b226c335b6126ebb81cf0d39088698d..d2c299743d1fba11ad17ff3a3b6ac0c8e48464d7 100644 (file)
@@ -287,12 +287,16 @@ def register_composite(
     """Register the adapters to load and dump a composite type.
 
     :param info: The object with the information about the composite to register.
+    :type info: `CompositeInfo`
     :param context: The context where to register the adapters. If `!None`,
         register it globally.
+    :type context: `~psycopg.abc.AdaptContext` | `!None`
     :param factory: Callable to convert the sequence of attributes read from
         the composite into a Python object.
+    :type factory: `!Callable[[Any, ...], T]` | `!None`
     :param make_instance: optional function taking values and names as input and
         returning the new type.
+    :type make_instance: `!Callable[[Sequence[Any], Sequence[str]], T]` | `!None`
 
     .. note::