From: Daniele Varrazzo Date: Thu, 30 Oct 2025 14:39:19 +0000 (+0000) Subject: docs: add docs for register_composite's make_instance param X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ad0ec569377d80b5380bc6be503ae9c65923017a;p=thirdparty%2Fpsycopg.git docs: add docs for register_composite's make_instance param --- diff --git a/docs/basic/pgtypes.rst b/docs/basic/pgtypes.rst index 14ee5bee3..1d47feec4 100644 --- a/docs/basic/pgtypes.rst +++ b/docs/basic/pgtypes.rst @@ -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 diff --git a/docs/news.rst b/docs/news.rst index bca8a15a7..337972851 100644 --- a/docs/news.rst +++ b/docs/news.rst @@ -16,6 +16,9 @@ Psycopg 3.3.0 (unreleased) .. rubric:: New top-level features - Add :ref:`template strings queries ` (: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 diff --git a/psycopg/psycopg/types/composite.py b/psycopg/psycopg/types/composite.py index d880984b8..d2c299743 100644 --- a/psycopg/psycopg/types/composite.py +++ b/psycopg/psycopg/types/composite.py @@ -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::