From: Daniele Varrazzo Date: Wed, 27 Sep 2023 00:38:44 +0000 (+0200) Subject: docs: add docs about generic pool X-Git-Tag: pool-3.2.0~33^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F559%2Fhead;p=thirdparty%2Fpsycopg.git docs: add docs about generic pool --- diff --git a/docs/advanced/typing.rst b/docs/advanced/typing.rst index 71b4e415c..5a91f60ea 100644 --- a/docs/advanced/typing.rst +++ b/docs/advanced/typing.rst @@ -64,6 +64,63 @@ cursors and annotate the returned objects accordingly. See # drec type is Optional[Dict[str, Any]] +.. _pool-generic: + +Generic pool types +------------------ + +.. versionadded:: 3.2 + +The `~psycopg_pool.ConnectionPool` class and similar are generic on their +`!connection_class` argument. The `~psycopg_pool.ConnectionPool.connection()` +method is annotated as returning a connection of that type, and the record +returned will follow the rule as in :ref:`row-factory-static`. + +Note that, at the moment, if you use a generic class as `!connection_class`, +you will need to specify a `!row_factory` consistently in the `!kwargs`, +otherwise the typing system and the runtime will not agree. + +.. code:: python + + from psycopg import Connection + from psycopg.rows import DictRow, dict_row + + with ConnectionPool( + connection_class=Connection[DictRow], # provides type hinting + kwargs={"row_factory": dict_row}, # works at runtime + ) as pool: + # reveal_type(pool): ConnectionPool[Connection[dict[str, Any]]] + + with pool.connection() as conn: + # reveal_type(conn): Connection[dict[str, Any]] + + row = conn.execute("SELECT now()").fetchone() + # reveal_type(row): Optional[dict[str, Any]] + + print(row) # {"now": datetime.datetime(...)} + +If a non-generic `!Connection` subclass is used (one whose returned row +type is not parametric) then it's not necessary to specify `!kwargs`: + +.. code:: python + + class MyConnection(Connection[DictRow]): + def __init__(self, *args, **kwargs): + kwargs["row_factory"] = dict_row + super().__init__(*args, **kwargs) + + with ConnectionPool(connection_class=MyConnection[DictRow]) as pool: + # reveal_type(pool): ConnectionPool[MyConnection] + + with pool.connection() as conn: + # reveal_type(conn): MyConnection + + row = conn.execute("SELECT now()").fetchone() + # reveal_type(row): Optional[dict[str, Any]] + + print(row) # {"now": datetime.datetime(...)} + + .. _example-pydantic: Example: returning records as Pydantic models diff --git a/docs/api/pool.rst b/docs/api/pool.rst index aae0719a5..5e58537db 100644 --- a/docs/api/pool.rst +++ b/docs/api/pool.rst @@ -154,6 +154,11 @@ The `!ConnectionPool` class added `!open` parameter to init method. + .. versionchanged:: 3.2 + + The class is generic and `!connection_class` provides types type + variable. See :ref:`pool-generic`. + .. note:: In a future version, the default value for the `!open` parameter might be changed to `!False`. If you rely on this behaviour (e.g. if you don't use the pool as a context manager) you might want to specify @@ -168,6 +173,10 @@ The `!ConnectionPool` class # the connection is now back in the pool + .. versionchanged:: 3.2 + The connection returned is annotated as defined in `!connection_class`. + See :ref:`pool-generic`. + .. automethod:: open .. versionadded:: 3.1