]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
refactor: drop use of typing.List
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Thu, 30 May 2024 01:03:57 +0000 (03:03 +0200)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Tue, 4 Jun 2024 14:52:16 +0000 (16:52 +0200)
63 files changed:
psycopg/psycopg/_adapters_map.py
psycopg/psycopg/_connection_base.py
psycopg/psycopg/_copy_base.py
psycopg/psycopg/_cursor_base.py
psycopg/psycopg/_dns.py
psycopg/psycopg/_pipeline.py
psycopg/psycopg/_py_transformer.py
psycopg/psycopg/_queries.py
psycopg/psycopg/abc.py
psycopg/psycopg/connection.py
psycopg/psycopg/connection_async.py
psycopg/psycopg/cursor.py
psycopg/psycopg/cursor_async.py
psycopg/psycopg/errors.py
psycopg/psycopg/generators.py
psycopg/psycopg/pq/__init__.py
psycopg/psycopg/pq/_pq_ctypes.py
psycopg/psycopg/pq/abc.py
psycopg/psycopg/pq/pq_ctypes.py
psycopg/psycopg/rows.py
psycopg/psycopg/server_cursor.py
psycopg/psycopg/sql.py
psycopg/psycopg/types/array.py
psycopg/psycopg/types/composite.py
psycopg/psycopg/types/hstore.py
psycopg/psycopg/types/multirange.py
psycopg/psycopg/types/range.py
psycopg_c/build_backend/cython_backend.py
psycopg_c/psycopg_c/_psycopg.pyi
psycopg_c/psycopg_c/_psycopg/generators.pyx
psycopg_c/psycopg_c/_psycopg/transform.pyx
psycopg_c/psycopg_c/pq/conninfo.pyx
psycopg_c/psycopg_c/pq/pgconn.pyx
psycopg_c/psycopg_c/pq/pgresult.pyx
psycopg_pool/psycopg_pool/pool.py
psycopg_pool/psycopg_pool/pool_async.py
psycopg_pool/psycopg_pool/sched.py
psycopg_pool/psycopg_pool/sched_async.py
tests/_test_connection.py
tests/_test_cursor.py
tests/conftest.py
tests/fix_faker.py
tests/fix_pq.py
tests/pool/test_pool.py
tests/pool/test_pool_async.py
tests/pool/test_pool_common.py
tests/pool/test_pool_common_async.py
tests/pool/test_pool_null.py
tests/pool/test_pool_null_async.py
tests/scripts/bench-411.py
tests/test_adapt.py
tests/test_concurrency.py
tests/test_concurrency_async.py
tests/test_connection.py
tests/test_connection_async.py
tests/test_cursor_common.py
tests/test_cursor_common_async.py
tests/test_dns_srv.py
tests/test_errors.py
tests/test_generators.py
tests/test_typing.py
tests/types/test_array.py
tools/update_oids.py

index 28b63956b42ca71161a9074fa71ecd81e8db7c27..70a5586b00790857286881cf25ff5df8ff31e491 100644 (file)
@@ -6,7 +6,7 @@ Mapping from types/oids to Dumpers/Loaders
 
 from __future__ import annotations
 
-from typing import Any, Dict, List, Type, cast, TYPE_CHECKING
+from typing import Any, Dict, Type, cast, TYPE_CHECKING
 
 from . import pq
 from . import errors as e
@@ -62,8 +62,8 @@ class AdaptersMap:
     types: TypesRegistry
 
     _dumpers: Dict[PyFormat, Dict[type | str, Type[Dumper]]]
-    _dumpers_by_oid: List[Dict[int, Type[Dumper]]]
-    _loaders: List[Dict[int, Type[Loader]]]
+    _dumpers_by_oid: list[Dict[int, Type[Dumper]]]
+    _loaders: list[Dict[int, Type[Loader]]]
 
     # Record if a dumper or loader has an optimised version.
     _optimised: Dict[type, type] = {}
index 9230408622c4bc1d219fdd4a4317569b9d03c2f0..98eda8a747caef390c1ce5c3e403e3ce6fe58336 100644 (file)
@@ -8,9 +8,7 @@ from __future__ import annotations
 
 import sys
 import logging
-from typing import Callable, Generic
-from typing import List, NamedTuple, Tuple
-from typing import TYPE_CHECKING
+from typing import Callable, Generic, NamedTuple, Tuple, TYPE_CHECKING
 from weakref import ref, ReferenceType
 from warnings import warn
 from functools import partial
@@ -108,8 +106,8 @@ class BaseConnection(Generic[Row]):
         # None, but set to a copy of the global adapters map as soon as requested.
         self._adapters: AdaptersMap | None = None
 
-        self._notice_handlers: List[NoticeHandler] = []
-        self._notify_handlers: List[NotifyHandler] = []
+        self._notice_handlers: list[NoticeHandler] = []
+        self._notify_handlers: list[NotifyHandler] = []
 
         # Number of transaction blocks currently entered
         self._num_transactions = 0
index 60b455cca3ea2a6ec03c041a115ee2e8f57a3745..3f1ddabe495aba283343a4e4cd9b08af05979ae7 100644 (file)
@@ -10,7 +10,7 @@ import re
 import sys
 import struct
 from abc import ABC, abstractmethod
-from typing import Any, Dict, Generic, List, Match, Sequence, Tuple, TYPE_CHECKING
+from typing import Any, Dict, Generic, Match, Sequence, Tuple, TYPE_CHECKING
 
 from . import pq
 from . import adapt
@@ -375,7 +375,7 @@ def _parse_row_text(data: Buffer, tx: Transformer) -> Tuple[Any, ...]:
 
 
 def _parse_row_binary(data: Buffer, tx: Transformer) -> Tuple[Any, ...]:
-    row: List[Buffer | None] = []
+    row: list[Buffer | None] = []
     nfields = _unpack_int2(data, 0)[0]
     pos = 2
     for i in range(nfields):
index 587b821908c61b5c9337989da9436d78cd8508f8..6e02586bd9a634f1dabf588b234439b1f4fde0b1 100644 (file)
@@ -7,8 +7,7 @@ Psycopg BaseCursor object
 from __future__ import annotations
 
 from functools import partial
-from typing import Any, Generic, Iterable, List
-from typing import NoReturn, Sequence, Tuple, Type
+from typing import Any, Generic, Iterable, NoReturn, Sequence, Tuple, Type
 from typing import TYPE_CHECKING
 
 from . import pq
@@ -69,7 +68,7 @@ class BaseCursor(Generic[ConnectionType, Row]):
         self._reset()
 
     def _reset(self, reset_query: bool = True) -> None:
-        self._results: List["PGresult"] = []
+        self._results: list["PGresult"] = []
         self.pgresult: "PGresult" | None = None
         self._pos = 0
         self._iresult = 0
@@ -106,7 +105,7 @@ class BaseCursor(Generic[ConnectionType, Row]):
         return self._closed
 
     @property
-    def description(self) -> List[Column] | None:
+    def description(self) -> list[Column] | None:
         """
         A list of `Column` objects describing the current resultset.
 
@@ -447,7 +446,7 @@ class BaseCursor(Generic[ConnectionType, Row]):
         pgq.convert(query, params)
         return pgq
 
-    def _check_results(self, results: List["PGresult"]) -> None:
+    def _check_results(self, results: list["PGresult"]) -> None:
         """
         Verify that the results of a query are valid.
 
@@ -506,7 +505,7 @@ class BaseCursor(Generic[ConnectionType, Row]):
 
         self._make_row = self._make_row_maker()
 
-    def _set_results(self, results: List["PGresult"]) -> None:
+    def _set_results(self, results: list["PGresult"]) -> None:
         if self._execmany_returning is None:
             # Received from execute()
             self._results[:] = results
index 0701de482b46b2e5b96c9d7418a48fd0e46b52ef..612d4cfabcd77f2e2eb7dd08cd699639afa7d80b 100644 (file)
@@ -11,8 +11,7 @@ import os
 import re
 import warnings
 from random import randint
-from typing import Any, DefaultDict, Dict, List, NamedTuple, Sequence
-from typing import TYPE_CHECKING
+from typing import Any, DefaultDict, Dict, NamedTuple, Sequence, TYPE_CHECKING
 from collections import defaultdict
 
 try:
@@ -132,7 +131,7 @@ class Rfc2782Resolver:
 
         return self._return_params(params, hps)
 
-    def _get_attempts(self, params: Dict[str, Any]) -> List[HostPort]:
+    def _get_attempts(self, params: Dict[str, Any]) -> list[HostPort]:
         """
         Return the list of host, and for each host if SRV lookup must be tried.
 
@@ -171,14 +170,14 @@ class Rfc2782Resolver:
 
         return out if srv_found else []
 
-    def _resolve_srv(self, hp: HostPort) -> List[HostPort]:
+    def _resolve_srv(self, hp: HostPort) -> list[HostPort]:
         try:
             ans = resolver.resolve(hp.host, "SRV")
         except DNSException:
             ans = ()
         return self._get_solved_entries(hp, ans)
 
-    async def _resolve_srv_async(self, hp: HostPort) -> List[HostPort]:
+    async def _resolve_srv_async(self, hp: HostPort) -> list[HostPort]:
         try:
             ans = await async_resolver.resolve(hp.host, "SRV")
         except DNSException:
@@ -187,7 +186,7 @@ class Rfc2782Resolver:
 
     def _get_solved_entries(
         self, hp: HostPort, entries: "Sequence[SRV]"
-    ) -> List[HostPort]:
+    ) -> list[HostPort]:
         if not entries:
             # No SRV entry found. Delegate the libpq a QNAME=target lookup
             if hp.target and hp.port.lower() != "srv":
@@ -206,7 +205,7 @@ class Rfc2782Resolver:
         ]
 
     def _return_params(
-        self, params: Dict[str, Any], hps: List[HostPort]
+        self, params: Dict[str, Any], hps: list[HostPort]
     ) -> Dict[str, Any]:
         if not hps:
             # Nothing found, we ended up with an empty list
@@ -217,13 +216,13 @@ class Rfc2782Resolver:
         out["port"] = ",".join(str(hp.port) for hp in hps)
         return out
 
-    def sort_rfc2782(self, ans: "Sequence[SRV]") -> "List[SRV]":
+    def sort_rfc2782(self, ans: "Sequence[SRV]") -> "list[SRV]":
         """
         Implement the priority/weight ordering defined in RFC 2782.
         """
         # Divide the entries by priority:
-        priorities: DefaultDict[int, "List[SRV]"] = defaultdict(list)
-        out: "List[SRV]" = []
+        priorities: DefaultDict[int, "list[SRV]"] = defaultdict(list)
+        out: "list[SRV]" = []
         for entry in ans:
             priorities[entry.priority].append(entry)
 
index 72dfe911134effa67594aeb823226495f59b3b8a..09be343bbda6b231ab84463b0776dd9d5829ee60 100644 (file)
@@ -8,7 +8,7 @@ from __future__ import annotations
 
 import logging
 from types import TracebackType
-from typing import Any, List, Tuple, Type, TYPE_CHECKING
+from typing import Any, Tuple, Type, TYPE_CHECKING
 
 from . import pq
 from . import errors as e
@@ -158,7 +158,7 @@ class BasePipeline:
             raise exception
 
     def _process_results(
-        self, queued: PendingResult, results: List["PGresult"]
+        self, queued: PendingResult, results: list["PGresult"]
     ) -> None:
         """Process a results set fetched from the current pipeline.
 
index 6c3b8550e6fdfd61484fbfbfc443a490a1dfb302..f8726c94996900ff42b9189edbeb48e764ce2430 100644 (file)
@@ -11,8 +11,7 @@ dependencies problems).
 
 from __future__ import annotations
 
-from typing import Any, Dict, List, Sequence, Tuple
-from typing import DefaultDict, TYPE_CHECKING
+from typing import Any, Dict, Sequence, Tuple, DefaultDict, TYPE_CHECKING
 from collections import defaultdict
 
 from . import pq
@@ -57,7 +56,7 @@ class Transformer(AdaptContext):
         """.split()
 
     types: Tuple[int, ...] | None
-    formats: List[pq.Format] | None
+    formats: list[pq.Format] | None
 
     _adapters: "AdaptersMap"
     _pgresult: "PGresult" | None
@@ -88,11 +87,11 @@ class Transformer(AdaptContext):
         # mapping fmt, oid -> Loader instance
         self._loaders: Tuple[LoaderCache, LoaderCache] = ({}, {})
 
-        self._row_dumpers: List[abc.Dumper] | None = None
+        self._row_dumpers: list[abc.Dumper] | None = None
 
         # sequence of load functions from value to python
         # the length of the result columns
-        self._row_loaders: List[LoadFunc] = []
+        self._row_loaders: list[LoadFunc] = []
 
         # mapping oid -> type sql representation
         self._oid_types: Dict[int, bytes] = {}
@@ -172,7 +171,7 @@ class Transformer(AdaptContext):
         self, params: Sequence[Any], formats: Sequence[PyFormat]
     ) -> Sequence[Buffer | None]:
         nparams = len(params)
-        out: List[Buffer | None] = [None] * nparams
+        out: list[Buffer | None] = [None] * nparams
 
         # If we have dumpers, it means set_dumper_types had been called, in
         # which case self.types and self.formats are set to sequences of the
@@ -297,7 +296,7 @@ class Transformer(AdaptContext):
 
         return dumper
 
-    def load_rows(self, row0: int, row1: int, make_row: RowMaker[Row]) -> List[Row]:
+    def load_rows(self, row0: int, row1: int, make_row: RowMaker[Row]) -> list[Row]:
         res = self._pgresult
         if not res:
             raise e.InterfaceError("result not set")
@@ -309,7 +308,7 @@ class Transformer(AdaptContext):
 
         records = []
         for row in range(row0, row1):
-            record: List[Any] = [None] * self._nfields
+            record: list[Any] = [None] * self._nfields
             for col in range(self._nfields):
                 val = res.get_value(row, col)
                 if val is not None:
@@ -326,7 +325,7 @@ class Transformer(AdaptContext):
         if not 0 <= row < self._ntuples:
             return None
 
-        record: List[Any] = [None] * self._nfields
+        record: list[Any] = [None] * self._nfields
         for col in range(self._nfields):
             val = res.get_value(row, col)
             if val is not None:
index 71a11ed09c5462de89b4fbac3d44e3e64413de71..a1936df8cc8040d8a4530641bea6333ba2f05d9d 100644 (file)
@@ -7,7 +7,7 @@ Utility module to manipulate queries
 from __future__ import annotations
 
 import re
-from typing import Any, Callable, Dict, List, Mapping, Match, NamedTuple
+from typing import Any, Callable, Dict, Mapping, Match, NamedTuple
 from typing import Sequence, Tuple, TYPE_CHECKING
 from functools import lru_cache
 
@@ -50,13 +50,13 @@ class PostgresQuery:
         self.types: Tuple[int, ...] = ()
 
         # The format requested by the user and the ones to really pass Postgres
-        self._want_formats: List[PyFormat] | None = None
+        self._want_formats: list[PyFormat] | None = None
         self.formats: Sequence[pq.Format] | None = None
 
         self._encoding = conn_encoding(transformer.connection)
-        self._parts: List[QueryPart]
+        self._parts: list[QueryPart]
         self.query = b""
-        self._order: List[str] | None = None
+        self._order: list[str] | None = None
 
     def convert(self, query: Query, vars: Params | None) -> None:
         """
@@ -133,7 +133,7 @@ class PostgresQuery:
 
     @staticmethod
     def validate_and_reorder_params(
-        parts: List[QueryPart], vars: Params, order: List[str] | None
+        parts: list[QueryPart], vars: Params, order: list[str] | None
     ) -> Sequence[Any]:
         """
         Verify the compatibility between a query and a set of params.
@@ -169,13 +169,13 @@ class PostgresQuery:
 
 # The type of the _query2pg() and _query2pg_nocache() methods
 _Query2Pg: TypeAlias = Callable[
-    [bytes, str], Tuple[bytes, List[PyFormat], List[str] | None, List[QueryPart]]
+    [bytes, str], Tuple[bytes, list[PyFormat], list[str] | None, list[QueryPart]]
 ]
 
 
 def _query2pg_nocache(
     query: bytes, encoding: str
-) -> Tuple[bytes, List[PyFormat], List[str] | None, List[QueryPart]]:
+) -> Tuple[bytes, list[PyFormat], list[str] | None, list[QueryPart]]:
     """
     Convert Python query and params into something Postgres understands.
 
@@ -187,8 +187,8 @@ def _query2pg_nocache(
       ``parts`` (splits of queries and placeholders).
     """
     parts = _split_query(query, encoding)
-    order: List[str] | None = None
-    chunks: List[bytes] = []
+    order: list[str] | None = None
+    chunks: list[bytes] = []
     formats = []
 
     if isinstance(parts[0].item, int):
@@ -285,19 +285,19 @@ class PostgresClientQuery(PostgresQuery):
 
 
 _Query2PgClient: TypeAlias = Callable[
-    [bytes, str], Tuple[bytes, List[str] | None, List[QueryPart]]
+    [bytes, str], Tuple[bytes, list[str] | None, list[QueryPart]]
 ]
 
 
 def _query2pg_client_nocache(
     query: bytes, encoding: str
-) -> Tuple[bytes, List[str] | None, List[QueryPart]]:
+) -> Tuple[bytes, list[str] | None, list[QueryPart]]:
     """
     Convert Python query and params into a template to perform client-side binding
     """
     parts = _split_query(query, encoding, collapse_double_percent=False)
-    order: List[str] | None = None
-    chunks: List[bytes] = []
+    order: list[str] | None = None
+    chunks: list[bytes] = []
 
     if isinstance(parts[0].item, int):
         for part in parts[:-1]:
@@ -346,8 +346,8 @@ _re_placeholder = re.compile(
 
 def _split_query(
     query: bytes, encoding: str = "ascii", collapse_double_percent: bool = True
-) -> List[QueryPart]:
-    parts: List[Tuple[bytes, Match[bytes] | None]] = []
+) -> list[QueryPart]:
+    parts: list[Tuple[bytes, Match[bytes] | None]] = []
     cur = 0
 
     # pairs [(fragment, match], with the last match None
index 0e6061fc4e09a1f5bb85efaf096f39a87a8e756c..091f88df2a9524be5bcd7dd90f98015ccfcdb2af 100644 (file)
@@ -7,7 +7,7 @@ Protocol objects representing different implementations of the same classes.
 from __future__ import annotations
 
 from typing import Any, Dict, Callable, Generator, Mapping
-from typing import List, Protocol, Sequence, Tuple, TYPE_CHECKING
+from typing import Protocol, Sequence, Tuple, TYPE_CHECKING
 
 from . import pq
 from ._enums import PyFormat as PyFormat
@@ -202,7 +202,7 @@ class Loader(Protocol):
 
 class Transformer(Protocol):
     types: Tuple[int, ...] | None
-    formats: List[pq.Format] | None
+    formats: list[pq.Format] | None
 
     def __init__(self, context: AdaptContext | None = None): ...
 
@@ -243,7 +243,7 @@ class Transformer(Protocol):
 
     def load_rows(
         self, row0: int, row1: int, make_row: "RowMaker[Row]"
-    ) -> List["Row"]: ...
+    ) -> list["Row"]: ...
 
     def load_row(self, row: int, make_row: "RowMaker[Row]") -> "Row" | None: ...
 
index b4f71857dd0dffc4668037debb59fe0585efc7e9..3ad98bffaf7953ddcbaa6c3694f9a40325b628ec 100644 (file)
@@ -12,7 +12,7 @@ from __future__ import annotations
 import logging
 from time import monotonic
 from types import TracebackType
-from typing import Any, Generator, Iterator, List
+from typing import Any, Generator, Iterator
 from typing import Type, cast, overload, TYPE_CHECKING
 from contextlib import contextmanager
 
@@ -469,7 +469,7 @@ class Connection(BaseConnection[Row]):
         with self.lock:
             self.wait(self._tpc_finish_gen("ROLLBACK", xid))
 
-    def tpc_recover(self) -> List[Xid]:
+    def tpc_recover(self) -> list[Xid]:
         self._check_tpc()
         status = self.info.transaction_status
         with self.cursor(row_factory=args_row(Xid._from_record)) as cur:
index 37421579cd128d71aac41a5dfcecbc644f702432..5d4422963baf2940c935e5fea5d3a2c2dc4a9f38 100644 (file)
@@ -9,7 +9,7 @@ from __future__ import annotations
 import logging
 from time import monotonic
 from types import TracebackType
-from typing import Any, AsyncGenerator, AsyncIterator, List
+from typing import Any, AsyncGenerator, AsyncIterator
 from typing import Type, cast, overload, TYPE_CHECKING
 from contextlib import asynccontextmanager
 
@@ -509,7 +509,7 @@ class AsyncConnection(BaseConnection[Row]):
         async with self.lock:
             await self.wait(self._tpc_finish_gen("ROLLBACK", xid))
 
-    async def tpc_recover(self) -> List[Xid]:
+    async def tpc_recover(self) -> list[Xid]:
         self._check_tpc()
         status = self.info.transaction_status
         async with self.cursor(row_factory=args_row(Xid._from_record)) as cur:
index 9ef66b852bd91d6e449e181290f90206ed8f4c66..52415e78c03b32e3ee0e68c6c38ff1147bb46f31 100644 (file)
@@ -10,8 +10,7 @@ Psycopg Cursor object.
 from __future__ import annotations
 
 from types import TracebackType
-from typing import Any, Iterator, Iterable, List, Type
-from typing import TYPE_CHECKING, overload
+from typing import Any, Iterator, Iterable, Type, TYPE_CHECKING, overload
 from contextlib import contextmanager
 
 from . import pq
@@ -181,7 +180,7 @@ class Cursor(BaseCursor["Connection[Any]", Row]):
             self._pos += 1
         return record
 
-    def fetchmany(self, size: int = 0) -> List[Row]:
+    def fetchmany(self, size: int = 0) -> list[Row]:
         """
         Return the next `!size` records from the current recordset.
 
@@ -201,7 +200,7 @@ class Cursor(BaseCursor["Connection[Any]", Row]):
         self._pos += len(records)
         return records
 
-    def fetchall(self) -> List[Row]:
+    def fetchall(self) -> list[Row]:
         """
         Return all the remaining records from the current recordset.
 
index 12c066b6c347bc6591ec65d3275275e8b2a54fba..658da878894895f31b13eca9529902ac03dabe24 100644 (file)
@@ -7,8 +7,7 @@ Psycopg AsyncCursor object.
 from __future__ import annotations
 
 from types import TracebackType
-from typing import Any, AsyncIterator, Iterable, List, Type
-from typing import TYPE_CHECKING, overload
+from typing import Any, AsyncIterator, Iterable, Type, TYPE_CHECKING, overload
 from contextlib import asynccontextmanager
 
 from . import pq
@@ -191,7 +190,7 @@ class AsyncCursor(BaseCursor["AsyncConnection[Any]", Row]):
             self._pos += 1
         return record
 
-    async def fetchmany(self, size: int = 0) -> List[Row]:
+    async def fetchmany(self, size: int = 0) -> list[Row]:
         """
         Return the next `!size` records from the current recordset.
 
@@ -213,7 +212,7 @@ class AsyncCursor(BaseCursor["AsyncConnection[Any]", Row]):
         self._pos += len(records)
         return records
 
-    async def fetchall(self) -> List[Row]:
+    async def fetchall(self) -> list[Row]:
         """
         Return all the remaining records from the current recordset.
 
index b90b478a4cd1159e616d17b39e33cdd5e487bc62..928b781cf8f6c05db9916434f564c98e922f79f1 100644 (file)
@@ -21,8 +21,7 @@ DBAPI-defined Exceptions are defined in the following hierarchy::
 from __future__ import annotations
 
 from dataclasses import dataclass, field, fields
-from typing import Any, Callable, Dict, List, NoReturn, Sequence, Tuple, Type
-from typing import TYPE_CHECKING
+from typing import Any, Callable, Dict, NoReturn, Sequence, Tuple, Type, TYPE_CHECKING
 from asyncio import CancelledError
 
 from .pq.abc import PGconn, PGresult
@@ -45,7 +44,7 @@ class FinishedPGconn:
     raise an `~psycopg.OperationalError`.
     """
 
-    info: List["ConninfoOption"] = field(default_factory=list)
+    info: list[ConninfoOption] = field(default_factory=list)
 
     db: bytes = b""
     user: bytes = b""
index f90addf17ad3e647866f4b00633a6c416d0371c6..d56c2271a5055883ef911c5370ff5669f575c183 100644 (file)
@@ -24,7 +24,6 @@ from __future__ import annotations
 
 import logging
 from time import monotonic
-from typing import List
 
 from . import pq
 from . import errors as e
@@ -122,7 +121,7 @@ def _cancel(cancel_conn: PGcancelConn, *, timeout: float = 0.0) -> PQGenConn[Non
             raise e.InternalError(f"unexpected poll status: {status}")
 
 
-def _execute(pgconn: PGconn) -> PQGen[List[PGresult]]:
+def _execute(pgconn: PGconn) -> PQGen[list[PGresult]]:
     """
     Generator sending a query and returning results without blocking.
 
@@ -165,7 +164,7 @@ def _send(pgconn: PGconn) -> PQGen[None]:
             pgconn.consume_input()
 
 
-def _fetch_many(pgconn: PGconn) -> PQGen[List[PGresult]]:
+def _fetch_many(pgconn: PGconn) -> PQGen[list[PGresult]]:
     """
     Generator retrieving results from the database without blocking.
 
@@ -175,7 +174,7 @@ def _fetch_many(pgconn: PGconn) -> PQGen[List[PGresult]]:
     Return the list of results returned by the database (whether success
     or error).
     """
-    results: List[PGresult] = []
+    results: list[PGresult] = []
     while True:
         res = yield from _fetch(pgconn)
         if not res:
@@ -228,7 +227,7 @@ def _fetch(pgconn: PGconn) -> PQGen[PGresult | None]:
 
 def _pipeline_communicate(
     pgconn: PGconn, commands: Deque[PipelineCommand]
-) -> PQGen[List[List[PGresult]]]:
+) -> PQGen[list[list[PGresult]]]:
     """Generator to send queries from a connection in pipeline mode while also
     receiving results.
 
@@ -246,7 +245,7 @@ def _pipeline_communicate(
             pgconn.consume_input()
             _consume_notifies(pgconn)
 
-            res: List[PGresult] = []
+            res: list[PGresult] = []
             while not pgconn.is_busy():
                 r = pgconn.get_result()
                 if r is None:
@@ -290,7 +289,7 @@ def _consume_notifies(pgconn: PGconn) -> None:
             pgconn.notify_handler(n)
 
 
-def notifies(pgconn: PGconn) -> PQGen[List[pq.PGnotify]]:
+def notifies(pgconn: PGconn) -> PQGen[list[pq.PGnotify]]:
     yield WAIT_R
     pgconn.consume_input()
 
index 6887ee5e3899b6b55fd5f20733141c31cf8171be..650d664635bcb6d5a7604f87f056d45047e7fcfd 100644 (file)
@@ -9,9 +9,11 @@ implementation-dependant but all the implementations share the same interface.
 
 # Copyright (C) 2020 The Psycopg Team
 
+from __future__ import annotations
+
 import os
 import logging
-from typing import Callable, List, Type
+from typing import Callable, Type
 
 from . import abc
 from .misc import ConninfoOption, PGnotify, PGresAttDesc
@@ -59,7 +61,7 @@ def import_from_libpq() -> None:
 
     impl = os.environ.get("PSYCOPG_IMPL", "").lower()
     module = None
-    attempts: List[str] = []
+    attempts: list[str] = []
 
     def handle_error(name: str, e: Exception) -> None:
         if not impl:
index 101ec838462afcd9255ffc3a236fe5d9512586be..27a6d1932edaa1b830d2739251c1662170e6c860 100644 (file)
@@ -11,7 +11,7 @@ import ctypes
 import ctypes.util
 from ctypes import Structure, CFUNCTYPE, POINTER
 from ctypes import c_char, c_char_p, c_int, c_size_t, c_ubyte, c_uint, c_void_p
-from typing import Any, List, NoReturn, Tuple
+from typing import Any, NoReturn, Tuple
 
 from .misc import find_libpq_full_path, version_pretty
 from ..errors import NotSupportedError
@@ -58,11 +58,11 @@ Oid = c_uint
 
 
 class PGconn_struct(Structure):
-    _fields_: List[Tuple[str, type]] = []
+    _fields_: list[Tuple[str, type]] = []
 
 
 class PGresult_struct(Structure):
-    _fields_: List[Tuple[str, type]] = []
+    _fields_: list[Tuple[str, type]] = []
 
 
 class PQconninfoOption_struct(Structure):
@@ -86,11 +86,11 @@ class PGnotify_struct(Structure):
 
 
 class PGcancelConn_struct(Structure):
-    _fields_: List[Tuple[str, type]] = []
+    _fields_: list[Tuple[str, type]] = []
 
 
 class PGcancel_struct(Structure):
-    _fields_: List[Tuple[str, type]] = []
+    _fields_: list[Tuple[str, type]] = []
 
 
 class PGresAttDesc_struct(Structure):
index fadd71e35d29ee388bb30ba5d040227bb6d39a51..257c56a8f9254b38c99941a4456c17ec6b3c74e5 100644 (file)
@@ -6,7 +6,7 @@ Protocol objects to represent objects exposed by different pq implementations.
 
 from __future__ import annotations
 
-from typing import Any, Callable, List, Protocol, Sequence, Tuple, TYPE_CHECKING
+from typing import Any, Callable, Protocol, Sequence, Tuple, TYPE_CHECKING
 
 from ._enums import Format, Trace
 from .._compat import TypeAlias
@@ -33,7 +33,7 @@ class PGconn(Protocol):
     def finish(self) -> None: ...
 
     @property
-    def info(self) -> List["ConninfoOption"]: ...
+    def info(self) -> list["ConninfoOption"]: ...
 
     def reset(self) -> None: ...
 
@@ -271,7 +271,7 @@ class PGresult(Protocol):
     @property
     def oid_value(self) -> int: ...
 
-    def set_attributes(self, descriptions: List["PGresAttDesc"]) -> None: ...
+    def set_attributes(self, descriptions: list["PGresAttDesc"]) -> None: ...
 
 
 class PGcancelConn(Protocol):
@@ -303,13 +303,13 @@ class PGcancel(Protocol):
 
 class Conninfo(Protocol):
     @classmethod
-    def get_defaults(cls) -> List["ConninfoOption"]: ...
+    def get_defaults(cls) -> list["ConninfoOption"]: ...
 
     @classmethod
-    def parse(cls, conninfo: bytes) -> List["ConninfoOption"]: ...
+    def parse(cls, conninfo: bytes) -> list["ConninfoOption"]: ...
 
     @classmethod
-    def _options_from_array(cls, opts: Sequence[Any]) -> List["ConninfoOption"]: ...
+    def _options_from_array(cls, opts: Sequence[Any]) -> list["ConninfoOption"]: ...
 
 
 class Escaping(Protocol):
index fc171e5ba7e6451c45c98bd34bfe1653f9eb681a..7f184fbb863597b02d95787b5b6feb129e10ed15 100644 (file)
@@ -17,7 +17,7 @@ from weakref import ref
 
 from ctypes import Array, POINTER, cast, string_at, create_string_buffer, byref
 from ctypes import addressof, c_char_p, c_int, c_size_t, c_ulong, c_void_p, py_object
-from typing import Any, Callable, List, Sequence, Tuple
+from typing import Any, Callable, Sequence, Tuple
 from typing import cast as t_cast, TYPE_CHECKING
 
 from .. import errors as e
@@ -145,7 +145,7 @@ class PGconn:
         return addressof(self._pgconn_ptr.contents)  # type: ignore[attr-defined]
 
     @property
-    def info(self) -> List["ConninfoOption"]:
+    def info(self) -> list["ConninfoOption"]:
         self._ensure_pgconn()
         opts = impl.PQconninfo(self._pgconn_ptr)
         if not opts:
@@ -914,7 +914,7 @@ class PGresult:
     def oid_value(self) -> int:
         return impl.PQoidValue(self._pgresult_ptr)
 
-    def set_attributes(self, descriptions: List[PGresAttDesc]) -> None:
+    def set_attributes(self, descriptions: list[PGresAttDesc]) -> None:
         structs = [
             impl.PGresAttDesc_struct(*desc) for desc in descriptions  # type: ignore
         ]
@@ -1051,7 +1051,7 @@ class Conninfo:
     """
 
     @classmethod
-    def get_defaults(cls) -> List[ConninfoOption]:
+    def get_defaults(cls) -> list[ConninfoOption]:
         opts = impl.PQconndefaults()
         if not opts:
             raise MemoryError("couldn't allocate connection defaults")
@@ -1061,7 +1061,7 @@ class Conninfo:
             impl.PQconninfoFree(opts)
 
     @classmethod
-    def parse(cls, conninfo: bytes) -> List[ConninfoOption]:
+    def parse(cls, conninfo: bytes) -> list[ConninfoOption]:
         if not isinstance(conninfo, bytes):
             raise TypeError(f"bytes expected, got {type(conninfo)} instead")
 
@@ -1085,7 +1085,7 @@ class Conninfo:
     @classmethod
     def _options_from_array(
         cls, opts: Sequence[impl.PQconninfoOption_struct]
-    ) -> List[ConninfoOption]:
+    ) -> list[ConninfoOption]:
         rv = []
         skws = "keyword envvar compiled val label dispchar".split()
         for opt in opts:
index 25c9383865627d87c676294f0f1656c3f4ea57f0..9ab13fbba828cdb2447db1769c15f84deccab0ba 100644 (file)
@@ -7,7 +7,7 @@ psycopg row factories
 from __future__ import annotations
 
 import functools
-from typing import Any, Callable, Dict, List, NamedTuple, NoReturn
+from typing import Any, Callable, Dict, NamedTuple, NoReturn
 from typing import TYPE_CHECKING, Protocol, Sequence, Tuple, Type
 from collections import namedtuple
 
@@ -241,7 +241,7 @@ def no_result(values: Sequence[Any]) -> NoReturn:
     raise e.InterfaceError("the cursor doesn't have a result")
 
 
-def _get_names(cursor: "BaseCursor[Any, Any]") -> List[str] | None:
+def _get_names(cursor: "BaseCursor[Any, Any]") -> list[str] | None:
     res = cursor.pgresult
     if not res:
         return None
index 76f5ad35554330c33f7a74509b282c37e142b3ab..2f34d3eacda843a32a99833c05094fdcc4c141a5 100644 (file)
@@ -6,8 +6,7 @@ psycopg server-side cursor objects.
 
 from __future__ import annotations
 
-from typing import Any, AsyncIterator, List, Iterable, Iterator
-from typing import TYPE_CHECKING, overload
+from typing import Any, AsyncIterator, Iterable, Iterator, TYPE_CHECKING, overload
 from warnings import warn
 
 from . import pq
@@ -161,7 +160,7 @@ class ServerCursorMixin(BaseCursor[ConnectionType, Row]):
         query = sql.SQL("CLOSE {}").format(sql.Identifier(self._name))
         yield from self._conn._exec_command(query)
 
-    def _fetch_gen(self, num: int | None) -> PQGen[List[Row]]:
+    def _fetch_gen(self, num: int | None) -> PQGen[list[Row]]:
         if self.closed:
             raise e.InterfaceError("the cursor is closed")
         # If we are stealing the cursor, make sure we know its shape
@@ -315,7 +314,7 @@ class ServerCursor(ServerCursorMixin["Connection[Any]", Row], Cursor[Row]):
         else:
             return None
 
-    def fetchmany(self, size: int = 0) -> List[Row]:
+    def fetchmany(self, size: int = 0) -> list[Row]:
         if not size:
             size = self.arraysize
         with self._conn.lock:
@@ -323,7 +322,7 @@ class ServerCursor(ServerCursorMixin["Connection[Any]", Row], Cursor[Row]):
         self._pos += len(recs)
         return recs
 
-    def fetchall(self) -> List[Row]:
+    def fetchall(self) -> list[Row]:
         with self._conn.lock:
             recs = self._conn.wait(self._fetch_gen(None))
         self._pos += len(recs)
@@ -447,7 +446,7 @@ class AsyncServerCursor(
         else:
             return None
 
-    async def fetchmany(self, size: int = 0) -> List[Row]:
+    async def fetchmany(self, size: int = 0) -> list[Row]:
         if not size:
             size = self.arraysize
         async with self._conn.lock:
@@ -455,7 +454,7 @@ class AsyncServerCursor(
         self._pos += len(recs)
         return recs
 
-    async def fetchall(self) -> List[Row]:
+    async def fetchall(self) -> list[Row]:
         async with self._conn.lock:
             recs = await self._conn.wait(self._fetch_gen(None))
         self._pos += len(recs)
index 89647d2f89010de3c48e9aef01247f02733de798..96d518d3768bf972572918115bd29de75165c5b6 100644 (file)
@@ -9,7 +9,7 @@ from __future__ import annotations
 import codecs
 import string
 from abc import ABC, abstractmethod
-from typing import Any, Iterator, Iterable, List, Sequence
+from typing import Any, Iterator, Iterable, Sequence
 
 from .pq import Escaping
 from .abc import AdaptContext
@@ -126,7 +126,7 @@ class Composed(Composable):
     instance).
     """
 
-    _obj: List[Composable]
+    _obj: list[Composable]
 
     def __init__(self, seq: Sequence[Any]):
         seq = [obj if isinstance(obj, Composable) else Literal(obj) for obj in seq]
@@ -245,7 +245,7 @@ class SQL(Composable):
             SELECT * FROM "people" WHERE name = 'O''Rourke'
 
         """
-        rv: List[Composable] = []
+        rv: list[Composable] = []
         autonum: int | None = 0
         # TODO: this is probably not the right way to whitelist pre
         # pyre complains. Will wait for mypy to complain too to fix.
index a795c6d3f82fff1eba33c28980b01361bb1f2ea7..2cae3d4eff5ae5eedd462136b1d5c80fdc65bf16 100644 (file)
@@ -9,7 +9,7 @@ from __future__ import annotations
 import re
 import struct
 from math import prod
-from typing import Any, cast, Callable, List, Pattern, Set, Tuple, Type
+from typing import Any, cast, Callable, Pattern, Set, Tuple, Type
 
 from .. import pq
 from .. import errors as e
@@ -46,7 +46,7 @@ class BaseListDumper(RecursiveDumper):
             sdclass = context.adapters.get_dumper_by_oid(self.element_oid, self.format)
             self.sub_dumper = sdclass(NoneType, context)
 
-    def _find_list_element(self, L: List[Any], format: PyFormat) -> Any:
+    def _find_list_element(self, L: list[Any], format: PyFormat) -> Any:
         """
         Find the first non-null element of an eventually nested list
         """
@@ -84,7 +84,7 @@ class BaseListDumper(RecursiveDumper):
         else:
             return max(imax, -imin - 1)
 
-    def _flatiter(self, L: List[Any], seen: Set[int]) -> Any:
+    def _flatiter(self, L: list[Any], seen: Set[int]) -> Any:
         if id(L) in seen:
             raise e.DataError("cannot dump a recursive list")
 
@@ -115,7 +115,7 @@ class BaseListDumper(RecursiveDumper):
 class ListDumper(BaseListDumper):
     delimiter = b","
 
-    def get_key(self, obj: List[Any], format: PyFormat) -> DumperKey:
+    def get_key(self, obj: list[Any], format: PyFormat) -> DumperKey:
         if self.oid:
             return self.cls
 
@@ -126,7 +126,7 @@ class ListDumper(BaseListDumper):
         sd = self._tx.get_dumper(item, format)
         return (self.cls, sd.get_key(item, format))
 
-    def upgrade(self, obj: List[Any], format: PyFormat) -> "BaseListDumper":
+    def upgrade(self, obj: list[Any], format: PyFormat) -> "BaseListDumper":
         # If we have an oid we don't need to upgrade
         if self.oid:
             return self
@@ -155,11 +155,11 @@ class ListDumper(BaseListDumper):
     # backslash-escaped.
     _re_esc = re.compile(rb'(["\\])')
 
-    def dump(self, obj: List[Any]) -> Buffer | None:
-        tokens: List[Buffer] = []
+    def dump(self, obj: list[Any]) -> Buffer | None:
+        tokens: list[Buffer] = []
         needs_quotes = _get_needs_quotes_regexp(self.delimiter).search
 
-        def dump_list(obj: List[Any]) -> None:
+        def dump_list(obj: list[Any]) -> None:
             if not obj:
                 tokens.append(b"{}")
                 return
@@ -219,7 +219,7 @@ def _get_needs_quotes_regexp(delimiter: bytes) -> Pattern[bytes]:
 class ListBinaryDumper(BaseListDumper):
     format = pq.Format.BINARY
 
-    def get_key(self, obj: List[Any], format: PyFormat) -> DumperKey:
+    def get_key(self, obj: list[Any], format: PyFormat) -> DumperKey:
         if self.oid:
             return self.cls
 
@@ -230,7 +230,7 @@ class ListBinaryDumper(BaseListDumper):
         sd = self._tx.get_dumper(item, format)
         return (self.cls, sd.get_key(item, format))
 
-    def upgrade(self, obj: List[Any], format: PyFormat) -> "BaseListDumper":
+    def upgrade(self, obj: list[Any], format: PyFormat) -> "BaseListDumper":
         # If we have an oid we don't need to upgrade
         if self.oid:
             return self
@@ -247,18 +247,18 @@ class ListBinaryDumper(BaseListDumper):
 
         return dumper
 
-    def dump(self, obj: List[Any]) -> Buffer | None:
+    def dump(self, obj: list[Any]) -> Buffer | None:
         # Postgres won't take unknown for element oid: fall back on text
         sub_oid = self.sub_dumper and self.sub_dumper.oid or TEXT_OID
 
         if not obj:
             return _pack_head(0, 0, sub_oid)
 
-        data: List[Buffer] = [b"", b""]  # placeholders to avoid a resize
-        dims: List[int] = []
+        data: list[Buffer] = [b"", b""]  # placeholders to avoid a resize
+        dims: list[int] = []
         hasnull = 0
 
-        def calc_dims(L: List[Any]) -> None:
+        def calc_dims(L: list[Any]) -> None:
             if isinstance(L, self.cls):
                 if not L:
                     raise e.DataError("lists cannot contain empty lists")
@@ -267,7 +267,7 @@ class ListBinaryDumper(BaseListDumper):
 
         calc_dims(obj)
 
-        def dump_list(L: List[Any], dim: int) -> None:
+        def dump_list(L: list[Any], dim: int) -> None:
             nonlocal hasnull
             if len(L) != dims[dim]:
                 raise e.DataError("nested lists have inconsistent lengths")
@@ -300,7 +300,7 @@ class ArrayLoader(RecursiveLoader):
     delimiter = b","
     base_oid: int
 
-    def load(self, data: Buffer) -> List[Any]:
+    def load(self, data: Buffer) -> list[Any]:
         loader = self._tx.get_loader(self.base_oid, self.format)
         return _load_text(data, loader, self.delimiter)
 
@@ -308,7 +308,7 @@ class ArrayLoader(RecursiveLoader):
 class ArrayBinaryLoader(RecursiveLoader):
     format = pq.Format.BINARY
 
-    def load(self, data: Buffer) -> List[Any]:
+    def load(self, data: Buffer) -> list[Any]:
         return _load_binary(data, self._tx)
 
 
@@ -384,10 +384,10 @@ def _load_text(
     loader: Loader,
     delimiter: bytes = b",",
     __re_unescape: Pattern[bytes] = re.compile(rb"\\(.)"),
-) -> List[Any]:
+) -> list[Any]:
     rv = None
-    stack: List[Any] = []
-    a: List[Any] = []
+    stack: list[Any] = []
+    a: list[Any] = []
     rv = a
     load = loader.load
 
@@ -447,7 +447,7 @@ def _get_array_parse_regexp(delimiter: bytes) -> Pattern[bytes]:
     )
 
 
-def _load_binary(data: Buffer, tx: Transformer) -> List[Any]:
+def _load_binary(data: Buffer, tx: Transformer) -> list[Any]:
     ndims, hasnull, oid = _unpack_head(data)
     load = tx.get_loader(oid, PQ_BINARY).load
 
@@ -458,7 +458,7 @@ def _load_binary(data: Buffer, tx: Transformer) -> List[Any]:
     dims = [_unpack_dim(data, i)[0] for i in range(12, p, 8)]
     nelems = prod(dims)
 
-    out: List[Any] = [None] * nelems
+    out: list[Any] = [None] * nelems
     for i in range(nelems):
         size = unpack_len(data, p)[0]
         p += 4
index 6dd8642c60179ee4514dcd4886b61b90ed7a163b..114d7039a569b87691739d1979003415859ace2a 100644 (file)
@@ -9,7 +9,7 @@ from __future__ import annotations
 import re
 import struct
 from collections import namedtuple
-from typing import Any, Callable, cast, Dict, Iterator, List
+from typing import Any, Callable, cast, Dict, Iterator
 from typing import NamedTuple, Sequence, Tuple, Type, TYPE_CHECKING
 
 from .. import pq
@@ -90,7 +90,7 @@ class SequenceDumper(RecursiveDumper):
         if not obj:
             return start + end
 
-        parts: List[abc.Buffer] = [start]
+        parts: list[abc.Buffer] = [start]
 
         for item in obj:
             if item is None:
@@ -244,7 +244,7 @@ class RecordBinaryLoader(Loader):
 
 class CompositeLoader(RecordLoader):
     factory: Callable[..., Any]
-    fields_types: List[int]
+    fields_types: list[int]
     _types_set = False
 
     def load(self, data: abc.Buffer) -> Any:
index 526c0a688556a2a49ac1e355b73cc4522c89d306..509d617a353bf943fbe713718fc87e9e00512785 100644 (file)
@@ -7,7 +7,7 @@ Dict to hstore adaptation
 from __future__ import annotations
 
 import re
-from typing import Dict, List, Type
+from typing import Dict, Type
 
 from .. import errors as e
 from .. import postgres
@@ -45,7 +45,7 @@ class BaseHstoreDumper(RecursiveDumper):
         if not obj:
             return b""
 
-        tokens: List[str] = []
+        tokens: list[str] = []
 
         def add_token(s: str) -> None:
             tokens.append('"')
index 67d5e97402dcac98ec8a20d69306de70f3f1f746..4cb24a0e09ccdfba4cc9a7b64e6dff5939e8abb5 100644 (file)
@@ -7,7 +7,7 @@ Support for multirange types adaptation.
 from __future__ import annotations
 
 from decimal import Decimal
-from typing import Any, Generic, List, Iterable, MutableSequence
+from typing import Any, Generic, Iterable, MutableSequence
 from typing import Type, overload, TYPE_CHECKING
 from datetime import date, datetime
 
@@ -77,7 +77,7 @@ class Multirange(MutableSequence[Range[T]]):
     """
 
     def __init__(self, items: Iterable[Range[T]] = ()):
-        self._ranges: List[Range[T]] = list(map(self._check_type, items))
+        self._ranges: list[Range[T]] = list(map(self._check_type, items))
 
     def _check_type(self, item: Any) -> Range[Any]:
         if not isinstance(item, Range):
@@ -266,7 +266,7 @@ class MultirangeDumper(BaseMultirangeDumper):
         else:
             dump = fail_dump
 
-        out: List[Buffer] = [b"{"]
+        out: list[Buffer] = [b"{"]
         for r in obj:
             out.append(dump_range_text(r, dump))
             out.append(b",")
@@ -284,7 +284,7 @@ class MultirangeBinaryDumper(BaseMultirangeDumper):
         else:
             dump = fail_dump
 
-        out: List[Buffer] = [pack_len(len(obj))]
+        out: list[Buffer] = [pack_len(len(obj))]
         for r in obj:
             data = dump_range_binary(r, dump)
             out.append(pack_len(len(data)))
index 20b375aa27977812fc7dcb85bc01e8c5eda3a284..775398542f7aa1be9409c5f09bf58bed24bc38e4 100644 (file)
@@ -7,7 +7,7 @@ Support for range types adaptation.
 from __future__ import annotations
 
 import re
-from typing import Any, Dict, Generic, List, Type, Tuple
+from typing import Any, Dict, Generic, Type, Tuple
 from typing import cast, TYPE_CHECKING
 from decimal import Decimal
 from datetime import date, datetime
@@ -370,7 +370,7 @@ def dump_range_text(obj: Range[Any], dump: DumpFunc) -> Buffer:
     if obj.isempty:
         return b"empty"
 
-    parts: List[Buffer] = [b"[" if obj.lower_inc else b"("]
+    parts: list[Buffer] = [b"[" if obj.lower_inc else b"("]
 
     def dump_item(item: Any) -> Buffer:
         ad = dump(item)
index 97bd2af8844173f55317475b7dd9842a229d3bd6..bb7bc48f650a708b4eb9e5cda174a923f130ae74 100644 (file)
@@ -7,14 +7,16 @@ otherwise it only relies on the c files to have been precompiled.
 
 # Copyright (C) 2023 The Psycopg Team
 
+from __future__ import annotations
+
 import os
-from typing import Any, List
+from typing import Any
 
 import tomli
 from setuptools import build_meta
 
 
-def get_requires_for_build_wheel(config_settings: Any = None) -> List[str]:
+def get_requires_for_build_wheel(config_settings: Any = None) -> list[str]:
     if not os.path.exists("psycopg_c/_psycopg.pyx"):
         # Cython files don't exist: we must be in a sdist and we can trust
         # that the .c files we have packaged exist.
@@ -26,7 +28,7 @@ def get_requires_for_build_wheel(config_settings: Any = None) -> List[str]:
     with open("pyproject.toml", "rb") as f:
         pyprj = tomli.load(f)
 
-    rv: List[str] = pyprj["cython-backend"]["cython-requires"]
+    rv: list[str] = pyprj["cython-backend"]["cython-requires"]
     return rv
 
 
index 50834c6b491cabb009f4785aa78d0546050a5d5d..1961b916131079343b812b8b3fc467722e331654 100644 (file)
@@ -7,7 +7,9 @@ information. Will submit a bug.
 
 # Copyright (C) 2020 The Psycopg Team
 
-from typing import Any, List, Sequence, Tuple
+from __future__ import annotations
+
+from typing import Any, Sequence, Tuple
 
 from psycopg import pq, abc, BaseConnection
 from psycopg.rows import Row, RowMaker
@@ -17,7 +19,7 @@ from psycopg._compat import Deque
 
 class Transformer(abc.AdaptContext):
     types: Tuple[int, ...] | None
-    formats: List[pq.Format] | None
+    formats: list[pq.Format] | None
     def __init__(self, context: abc.AdaptContext | None = None): ...
     @classmethod
     def from_context(cls, context: abc.AdaptContext | None) -> "Transformer": ...
@@ -43,7 +45,7 @@ class Transformer(abc.AdaptContext):
     ) -> Sequence[abc.Buffer | None]: ...
     def as_literal(self, obj: Any) -> bytes: ...
     def get_dumper(self, obj: Any, format: PyFormat) -> abc.Dumper: ...
-    def load_rows(self, row0: int, row1: int, make_row: RowMaker[Row]) -> List[Row]: ...
+    def load_rows(self, row0: int, row1: int, make_row: RowMaker[Row]) -> list[Row]: ...
     def load_row(self, row: int, make_row: RowMaker[Row]) -> Row | None: ...
     def load_sequence(self, record: Sequence[abc.Buffer | None]) -> Tuple[Any, ...]: ...
     def get_loader(self, oid: int, format: pq.Format) -> abc.Loader: ...
@@ -53,13 +55,13 @@ def connect(conninfo: str, *, timeout: float = 0.0) -> abc.PQGenConn[PGconn]: ..
 def cancel(
     cancel_conn: PGcancelConn, *, timeout: float = 0.0
 ) -> abc.PQGenConn[None]: ...
-def execute(pgconn: PGconn) -> abc.PQGen[List[PGresult]]: ...
+def execute(pgconn: PGconn) -> abc.PQGen[list[PGresult]]: ...
 def send(pgconn: PGconn) -> abc.PQGen[None]: ...
-def fetch_many(pgconn: PGconn) -> abc.PQGen[List[PGresult]]: ...
+def fetch_many(pgconn: PGconn) -> abc.PQGen[list[PGresult]]: ...
 def fetch(pgconn: PGconn) -> abc.PQGen[PGresult | None]: ...
 def pipeline_communicate(
     pgconn: PGconn, commands: Deque[abc.PipelineCommand]
-) -> abc.PQGen[List[List[PGresult]]]: ...
+) -> abc.PQGen[list[list[PGresult]]]: ...
 def wait_c(
     gen: abc.PQGen[abc.RV], fileno: int, interval: float | None = None
 ) -> abc.RV: ...
@@ -77,5 +79,5 @@ def parse_row_binary(data: abc.Buffer, tx: abc.Transformer) -> Tuple[Any, ...]:
 # Arrays optimization
 def array_load_text(
     data: abc.Buffer, loader: abc.Loader, delimiter: bytes = b","
-) -> List[Any]: ...
-def array_load_binary(data: abc.Buffer, tx: abc.Transformer) -> List[Any]: ...
+) -> list[Any]: ...
+def array_load_binary(data: abc.Buffer, tx: abc.Transformer) -> list[Any]: ...
index df210f698d1ee83fd75d64cf8317335f796cab71..0c8d72e0e4d5cf392b6b476ed422306502206aeb 100644 (file)
@@ -6,7 +6,6 @@ C implementation of generators for the communication protocols with the libpq
 
 from cpython.object cimport PyObject_CallFunctionObjArgs
 
-from typing import List
 from time import monotonic
 
 from psycopg import errors as e
@@ -108,7 +107,7 @@ def cancel(pq.PGcancelConn cancel_conn, *, timeout: float = 0.0) -> PQGenConn[No
             raise e.InternalError(f"unexpected poll status: {status}")
 
 
-def execute(pq.PGconn pgconn) -> PQGen[List[abc.PGresult]]:
+def execute(pq.PGconn pgconn) -> PQGen[list[abc.PGresult]]:
     """
     Generator sending a query and returning results without blocking.
 
@@ -158,7 +157,7 @@ def send(pq.PGconn pgconn) -> PQGen[None]:
                     f"consuming input failed: {error_message(pgconn)}")
 
 
-def fetch_many(pq.PGconn pgconn) -> PQGen[List[PGresult]]:
+def fetch_many(pq.PGconn pgconn) -> PQGen[list[PGresult]]:
     """
     Generator retrieving results from the database without blocking.
 
@@ -247,7 +246,7 @@ def fetch(pq.PGconn pgconn) -> PQGen[PGresult | None]:
 
 def pipeline_communicate(
     pq.PGconn pgconn, commands: Deque[PipelineCommand]
-) -> PQGen[List[List[PGresult]]]:
+) -> PQGen[list[list[PGresult]]]:
     """Generator to send queries from a connection in pipeline mode while also
     receiving results.
 
@@ -277,7 +276,7 @@ def pipeline_communicate(
 
             _consume_notifies(pgconn)
 
-            res: List[PGresult] = []
+            res: list[PGresult] = []
             while True:
                 with nogil:
                     ibres = libpq.PQisBusy(pgconn_ptr)
index c9849551eee4f278d882628d0fcfdf426bd96434..97b6e29783b66cbf79d57098dda9915bb8bba215 100644 (file)
@@ -19,7 +19,7 @@ from cpython.bytes cimport PyBytes_AS_STRING
 from cpython.tuple cimport PyTuple_New, PyTuple_SET_ITEM
 from cpython.object cimport PyObject, PyObject_CallFunctionObjArgs
 
-from typing import Any, Dict, Iterable, List, Sequence, Tuple
+from typing import Any, Dict, Iterable, Sequence, Tuple
 
 from psycopg import errors as e
 from psycopg.pq import Format as PqFormat
@@ -423,7 +423,7 @@ cdef class Transformer:
         self.formats = pqformats
         return out
 
-    def load_rows(self, int row0, int row1, object make_row) -> List[Row]:
+    def load_rows(self, int row0, int row1, object make_row) -> list[Row]:
         if self._pgresult is None:
             raise e.InterfaceError("result not set")
 
index 3443de1baef91a0fbfce92d4baa9ec1173fc9fb0..35fb887d94741039b32e68de6f3b4b44323a3bda 100644 (file)
@@ -9,7 +9,7 @@ from psycopg.pq.misc import ConninfoOption
 
 class Conninfo:
     @classmethod
-    def get_defaults(cls) -> List[ConninfoOption]:
+    def get_defaults(cls) -> list[ConninfoOption]:
         cdef libpq.PQconninfoOption *opts = libpq.PQconndefaults()
         if opts is NULL :
             raise MemoryError("couldn't allocate connection defaults")
@@ -18,7 +18,7 @@ class Conninfo:
         return rv
 
     @classmethod
-    def parse(cls, const char *conninfo) -> List[ConninfoOption]:
+    def parse(cls, const char *conninfo) -> list[ConninfoOption]:
         cdef char *errmsg = NULL
         cdef libpq.PQconninfoOption *opts = libpq.PQconninfoParse(conninfo, &errmsg)
         if opts is NULL:
index 86e6910aa12de0d7003cb7a20a6fd14381bda80e..b66804735cbdcd794d88e64e4cda30c42bca13f5 100644 (file)
@@ -94,7 +94,7 @@ cdef class PGconn:
             return None
 
     @property
-    def info(self) -> List["ConninfoOption"]:
+    def info(self) -> list["ConninfoOption"]:
         _ensure_pgconn(self)
         cdef libpq.PQconninfoOption *opts = libpq.PQconninfo(self._pgconn_ptr)
         if opts is NULL:
index 696d44ff19b8c00ac675533211cc46d932d58fa2..2556896d9d340a4b80401a52c6719745852d8a3c 100644 (file)
@@ -136,7 +136,7 @@ cdef class PGresult:
     def oid_value(self) -> int:
         return libpq.PQoidValue(self._pgresult_ptr)
 
-    def set_attributes(self, descriptions: List[PGresAttDesc]):
+    def set_attributes(self, descriptions: list[PGresAttDesc]):
         cdef Py_ssize_t num = len(descriptions)
         cdef libpq.PGresAttDesc *attrs = <libpq.PGresAttDesc *>PyMem_Malloc(
             num * sizeof(libpq.PGresAttDesc))
index f8ae79d796af7a3f088198983cbea056164da1f7..25010fe60da86495dc3f978f9c480ab8415c76b7 100644 (file)
@@ -14,7 +14,7 @@ import warnings
 from abc import ABC, abstractmethod
 from time import monotonic
 from types import TracebackType
-from typing import Any, Iterator, cast, Dict, Generic, List
+from typing import Any, Iterator, cast, Dict, Generic
 from typing import Type
 from weakref import ref
 from contextlib import contextmanager
@@ -78,7 +78,7 @@ class ConnectionPool(Generic[CT], BasePool):
         self._pool_full_event: Event | None = None
 
         self._sched_runner: Worker | None = None
-        self._workers: List[Worker] = []
+        self._workers: list[Worker] = []
 
         super().__init__(
             conninfo,
index 45000b6ec9a92504a0f0ce86e66d4d59e4e4adbc..f5b3fd22b73b9e2b3e95b39f72f09f12ad931009 100644 (file)
@@ -11,7 +11,7 @@ import warnings
 from abc import ABC, abstractmethod
 from time import monotonic
 from types import TracebackType
-from typing import Any, AsyncIterator, cast, Dict, Generic, List
+from typing import Any, AsyncIterator, cast, Dict, Generic
 from typing import Type
 from weakref import ref
 from contextlib import asynccontextmanager
@@ -77,7 +77,7 @@ class AsyncConnectionPool(Generic[ACT], BasePool):
         self._pool_full_event: AEvent | None = None
 
         self._sched_runner: AWorker | None = None
-        self._workers: List[AWorker] = []
+        self._workers: list[AWorker] = []
 
         super().__init__(
             conninfo,
index 4a5181d63d660cd9bc69878204573e45d09bf555..eff588a7920af152c219aa0711c5b08042f19068 100644 (file)
@@ -20,7 +20,7 @@ from __future__ import annotations
 import logging
 from time import monotonic
 from heapq import heappush, heappop
-from typing import Any, Callable, List
+from typing import Any, Callable
 
 from ._task import Task
 from ._acompat import Lock, Event
@@ -31,7 +31,7 @@ logger = logging.getLogger(__name__)
 class Scheduler:
 
     def __init__(self) -> None:
-        self._queue: List[Task] = []
+        self._queue: list[Task] = []
         self._lock = Lock()
         self._event = Event()
 
index d43ef1d2efc0af2ed4e96f4c7f79783bae65d176..1ba23d47d5e50c601afb468fc77730b599afc9fe 100644 (file)
@@ -17,7 +17,7 @@ from __future__ import annotations
 import logging
 from time import monotonic
 from heapq import heappush, heappop
-from typing import Any, Callable, List
+from typing import Any, Callable
 
 from ._task import Task
 from ._acompat import ALock, AEvent
@@ -27,7 +27,7 @@ logger = logging.getLogger(__name__)
 
 class AsyncScheduler:
     def __init__(self) -> None:
-        self._queue: List[Task] = []
+        self._queue: list[Task] = []
         self._lock = ALock()
         self._event = AEvent()
 
index 56d3859266f333432b4b985ef5b15cf8a4ede422..a161300b1ac8cf1230584a0665d0d08580f32119 100644 (file)
@@ -2,7 +2,9 @@
 Support module for test_connection[_async].py
 """
 
-from typing import Any, List
+from __future__ import annotations
+
+from typing import Any
 from dataclasses import dataclass
 
 import pytest
@@ -29,7 +31,7 @@ def testctx(svcconn):
 class ParamDef:
     name: str
     guc: str
-    values: List[Any]
+    values: list[Any]
     non_default: str
 
 
index c0f463d5f814f4cd00127202efc40882b8e6e73a..95671d2bb7c53bdffd56893bd975051870524d7f 100644 (file)
@@ -5,7 +5,7 @@ Support module for test_cursor[_async].py
 from __future__ import annotations
 
 import re
-from typing import Any, List, Match
+from typing import Any, Match
 
 import pytest
 import psycopg
@@ -49,8 +49,8 @@ def ph(cur: Any, query: str) -> str:
 
 
 def my_row_factory(
-    cursor: psycopg.Cursor[List[str]] | psycopg.AsyncCursor[List[str]],
-) -> RowMaker[List[str]]:
+    cursor: psycopg.Cursor[list[str]] | psycopg.AsyncCursor[list[str]],
+) -> RowMaker[list[str]]:
     if cursor.description is not None:
         titles = [c.name for c in cursor.description]
 
index cc1273f78eb90df9b1df3f6ba2829153e4c359fa..cea5ae775f9a76ebcdd152f8dfcbbb39d30af095 100644 (file)
@@ -1,7 +1,9 @@
+from __future__ import annotations
+
 import asyncio
 import selectors
 import sys
-from typing import Any, Dict, List
+from typing import Any, Dict
 
 import pytest
 
@@ -89,7 +91,7 @@ def anyio_backend(request):
     return backend, options
 
 
-allow_fail_messages: List[str] = []
+allow_fail_messages: list[str] = []
 
 
 def pytest_sessionfinish(session, exitstatus):
index 7821429e9a6a163fb0d8a1e21acc5b0975605459..9da58903fc6dd1f60e0f53c68a05a14bb3ac9310 100644 (file)
@@ -6,7 +6,7 @@ import ipaddress
 from math import isnan
 from uuid import UUID
 from random import choice, random, randrange
-from typing import Any, List, Set, Tuple
+from typing import Any, Set, Tuple
 from decimal import Decimal
 from contextlib import contextmanager, asynccontextmanager
 
@@ -44,7 +44,7 @@ class Faker:
         self.records = []
 
         self._schema = None
-        self._types: List[type] | None = None
+        self._types: list[type] | None = None
         self._types_names = None
         self._makers = {}
         self.table_name = sql.Identifier("fake_table")
@@ -65,7 +65,7 @@ class Faker:
         return [sql.Identifier(f"fld_{i}") for i in range(len(self.schema))]
 
     @property
-    def types(self) -> List[type]:
+    def types(self) -> list[type]:
         if not self._types:
 
             def key(cls: type) -> str:
@@ -76,7 +76,7 @@ class Faker:
         return self._types
 
     @types.setter
-    def types(self, types: List[type]) -> None:
+    def types(self, types: list[type]) -> None:
         self._types = types
 
     @property
@@ -199,7 +199,7 @@ class Faker:
         )
 
     def choose_schema(self, ncols=20):
-        schema: List[Tuple[type, ...] | type] = []
+        schema: list[Tuple[type, ...] | type] = []
         while len(schema) < ncols:
             s = self.make_schema(choice(self.types))
             if s is not None:
@@ -577,7 +577,7 @@ class Faker:
 
             return l1 <= u2 and l2 <= u1
 
-        out: List[Range[Any]] = []
+        out: list[Range[Any]] = []
         for i in range(length):
             r = self.make_Range((Range, spec[1]), **kwargs)
             if r.isempty:
@@ -669,7 +669,7 @@ class Faker:
             return spec[0](empty=True)
 
         while True:
-            bounds: List[Any] = []
+            bounds: list[Any] = []
             while len(bounds) < 2:
                 if random() < no_bound_chance:
                     bounds.append(None)
@@ -779,7 +779,7 @@ class Faker:
         if not length:
             length = randrange(self.str_max_length)
 
-        rv: List[int] = []
+        rv: list[int] = []
         while len(rv) < length:
             c = randrange(1, 128) if random() < 0.5 else randrange(1, 0x110000)
             if not (0xD800 <= c <= 0xDBFF or 0xDC00 <= c <= 0xDFFF):
index 917dfc9193e9c558778034979587cf175a188b7f..0d68dc1fbf9ca5718d6d8fd23d92a15f4b8b1003 100644 (file)
@@ -1,7 +1,9 @@
+from __future__ import annotations
+
 import os
 import sys
 import ctypes
-from typing import Iterator, List, NamedTuple
+from typing import Iterator, NamedTuple
 from tempfile import TemporaryFile
 
 import pytest
@@ -138,4 +140,4 @@ class TraceEntry(NamedTuple):
     direction: str
     length: int
     type: str
-    content: List[bytes]
+    content: list[bytes]
index 9aeed8f5368b45a00ef11eba3538ee1cb5bfd1bc..054d479125231ddd98e47fac067d0ac537f0b8fc 100644 (file)
@@ -1,10 +1,12 @@
 # WARNING: this file is auto-generated by 'async_to_sync.py'
 # from the original file 'test_pool_async.py'
 # DO NOT CHANGE! Change the original file instead.
+from __future__ import annotations
+
 import logging
 import weakref
 from time import time
-from typing import Any, Dict, List, Tuple
+from typing import Any, Dict, Tuple
 
 import pytest
 
@@ -139,7 +141,7 @@ def test_concurrent_filling(dsn, monkeypatch):
     add_orig = pool.ConnectionPool._add_to_pool
     monkeypatch.setattr(pool.ConnectionPool, "_add_to_pool", add_time)
 
-    times: List[float] = []
+    times: list[float] = []
     t0 = time()
 
     with pool.ConnectionPool(dsn, min_size=5, num_workers=2) as p:
@@ -433,7 +435,7 @@ def test_grow(dsn, monkeypatch, min_size, want_times):
 
     with pool.ConnectionPool(dsn, min_size=min_size, max_size=4, num_workers=3) as p:
         p.wait(1.0)
-        results: List[Tuple[int, float]] = []
+        results: list[Tuple[int, float]] = []
         ts = [spawn(worker, args=(i,)) for i in range(len(want_times))]
         gather(*ts)
 
@@ -447,7 +449,7 @@ def test_grow(dsn, monkeypatch, min_size, want_times):
 def test_shrink(dsn, monkeypatch):
     from psycopg_pool.pool import ShrinkPool
 
-    results: List[Tuple[int, int]] = []
+    results: list[Tuple[int, int]] = []
 
     def run_hacked(self, pool):
         n0 = pool._nconns
@@ -654,7 +656,7 @@ def test_resize(dsn):
         with p.connection() as conn:
             conn.execute("select pg_sleep(%s)", [t])
 
-    size: List[int] = []
+    size: list[int] = []
 
     with pool.ConnectionPool(dsn, min_size=2, max_idle=0.2) as p:
         s = spawn(sampler)
index 525905a158b03f62820ffc6374fdf9e73e838f1d..8976bce7d82f6030571659f4f8d304235d2cd6a0 100644 (file)
@@ -1,7 +1,9 @@
+from __future__ import annotations
+
 import logging
 import weakref
 from time import time
-from typing import Any, Dict, List, Tuple
+from typing import Any, Dict, Tuple
 
 import pytest
 
@@ -140,7 +142,7 @@ async def test_concurrent_filling(dsn, monkeypatch):
     add_orig = pool.AsyncConnectionPool._add_to_pool
     monkeypatch.setattr(pool.AsyncConnectionPool, "_add_to_pool", add_time)
 
-    times: List[float] = []
+    times: list[float] = []
     t0 = time()
 
     async with pool.AsyncConnectionPool(dsn, min_size=5, num_workers=2) as p:
@@ -436,7 +438,7 @@ async def test_grow(dsn, monkeypatch, min_size, want_times):
         dsn, min_size=min_size, max_size=4, num_workers=3
     ) as p:
         await p.wait(1.0)
-        results: List[Tuple[int, float]] = []
+        results: list[Tuple[int, float]] = []
         ts = [spawn(worker, args=(i,)) for i in range(len(want_times))]
         await gather(*ts)
 
@@ -450,7 +452,7 @@ async def test_grow(dsn, monkeypatch, min_size, want_times):
 async def test_shrink(dsn, monkeypatch):
     from psycopg_pool.pool_async import ShrinkPool
 
-    results: List[Tuple[int, int]] = []
+    results: list[Tuple[int, int]] = []
 
     async def run_hacked(self, pool):
         n0 = pool._nconns
@@ -656,7 +658,7 @@ async def test_resize(dsn):
         async with p.connection() as conn:
             await conn.execute("select pg_sleep(%s)", [t])
 
-    size: List[int] = []
+    size: list[int] = []
 
     async with pool.AsyncConnectionPool(dsn, min_size=2, max_idle=0.2) as p:
         s = spawn(sampler)
index 2f5baf4e5617fa388794d98d1909ea95e5f3403e..fb994e024cd95267b1c98229d3bb02a0a69baa4f 100644 (file)
@@ -1,9 +1,11 @@
 # WARNING: this file is auto-generated by 'async_to_sync.py'
 # from the original file 'test_pool_common_async.py'
 # DO NOT CHANGE! Change the original file instead.
+from __future__ import annotations
+
 import logging
 from time import time
-from typing import Any, List, Tuple
+from typing import Any, Tuple
 
 import pytest
 
@@ -169,7 +171,7 @@ def test_queue(pool_cls, dsn):
         t1 = time()
         results.append((n, t1 - t0, pid))
 
-    results: List[Tuple[int, float, int]] = []
+    results: list[Tuple[int, float, int]] = []
     with pool_cls(dsn, min_size=min_size(pool_cls, 2), max_size=2) as p:
         p.wait()
         ts = [spawn(worker, args=(i,)) for i in range(6)]
@@ -197,8 +199,8 @@ def test_queue_size(pool_cls, dsn):
         else:
             success.append(True)
 
-    errors: List[Exception] = []
-    success: List[bool] = []
+    errors: list[Exception] = []
+    success: list[bool] = []
 
     with pool_cls(dsn, min_size=min_size(pool_cls), max_size=1, max_waiting=3) as p:
         p.wait()
@@ -235,8 +237,8 @@ def test_queue_timeout(pool_cls, dsn):
             t1 = time()
             results.append((n, t1 - t0, pid))
 
-    results: List[Tuple[int, float, int]] = []
-    errors: List[Tuple[int, float, Exception]] = []
+    results: list[Tuple[int, float, int]] = []
+    errors: list[Tuple[int, float, Exception]] = []
 
     with pool_cls(dsn, min_size=min_size(pool_cls, 2), max_size=2, timeout=0.1) as p:
         ts = [spawn(worker, args=(i,)) for i in range(4)]
@@ -262,7 +264,7 @@ def test_dead_client(pool_cls, dsn):
                 raise
 
     with pool_cls(dsn, min_size=min_size(pool_cls, 2), max_size=2) as p:
-        results: List[int] = []
+        results: list[int] = []
         ts = [
             spawn(worker, args=(i, timeout))
             for i, timeout in enumerate([0.4, 0.4, 0.1, 0.4, 0.4])
@@ -294,8 +296,8 @@ def test_queue_timeout_override(pool_cls, dsn):
             t1 = time()
             results.append((n, t1 - t0, pid))
 
-    results: List[Tuple[int, float, int]] = []
-    errors: List[Tuple[int, float, Exception]] = []
+    results: list[Tuple[int, float, int]] = []
+    errors: list[Tuple[int, float, Exception]] = []
 
     with pool_cls(dsn, min_size=min_size(pool_cls, 2), max_size=2, timeout=0.1) as p:
         ts = [spawn(worker, args=(i,)) for i in range(4)]
@@ -410,7 +412,7 @@ def test_closed_queue(pool_cls, dsn):
 
     with pool_cls(dsn, min_size=min_size(pool_cls), max_size=1) as p:
         p.wait()
-        success: List[str] = []
+        success: list[str] = []
 
         t1 = spawn(w1)
         # Wait until w1 has received a connection
index e566fc85dc2aeb081790b32e089b515b6aaf43ee..141e3e6d728ab30bccb467284b17ab9d09db34fb 100644 (file)
@@ -1,6 +1,8 @@
+from __future__ import annotations
+
 import logging
 from time import time
-from typing import Any, List, Tuple
+from typing import Any, Tuple
 
 import pytest
 
@@ -179,7 +181,7 @@ async def test_queue(pool_cls, dsn):
         t1 = time()
         results.append((n, t1 - t0, pid))
 
-    results: List[Tuple[int, float, int]] = []
+    results: list[Tuple[int, float, int]] = []
     async with pool_cls(dsn, min_size=min_size(pool_cls, 2), max_size=2) as p:
         await p.wait()
         ts = [spawn(worker, args=(i,)) for i in range(6)]
@@ -206,8 +208,8 @@ async def test_queue_size(pool_cls, dsn):
         else:
             success.append(True)
 
-    errors: List[Exception] = []
-    success: List[bool] = []
+    errors: list[Exception] = []
+    success: list[bool] = []
 
     async with pool_cls(
         dsn, min_size=min_size(pool_cls), max_size=1, max_waiting=3
@@ -245,8 +247,8 @@ async def test_queue_timeout(pool_cls, dsn):
             t1 = time()
             results.append((n, t1 - t0, pid))
 
-    results: List[Tuple[int, float, int]] = []
-    errors: List[Tuple[int, float, Exception]] = []
+    results: list[Tuple[int, float, int]] = []
+    errors: list[Tuple[int, float, Exception]] = []
 
     async with pool_cls(
         dsn, min_size=min_size(pool_cls, 2), max_size=2, timeout=0.1
@@ -273,7 +275,7 @@ async def test_dead_client(pool_cls, dsn):
                 raise
 
     async with pool_cls(dsn, min_size=min_size(pool_cls, 2), max_size=2) as p:
-        results: List[int] = []
+        results: list[int] = []
         ts = [
             spawn(worker, args=(i, timeout))
             for i, timeout in enumerate([0.4, 0.4, 0.1, 0.4, 0.4])
@@ -304,8 +306,8 @@ async def test_queue_timeout_override(pool_cls, dsn):
             t1 = time()
             results.append((n, t1 - t0, pid))
 
-    results: List[Tuple[int, float, int]] = []
-    errors: List[Tuple[int, float, Exception]] = []
+    results: list[Tuple[int, float, int]] = []
+    errors: list[Tuple[int, float, Exception]] = []
 
     async with pool_cls(
         dsn, min_size=min_size(pool_cls, 2), max_size=2, timeout=0.1
@@ -421,7 +423,7 @@ async def test_closed_queue(pool_cls, dsn):
 
     async with pool_cls(dsn, min_size=min_size(pool_cls), max_size=1) as p:
         await p.wait()
-        success: List[str] = []
+        success: list[str] = []
 
         t1 = spawn(w1)
         # Wait until w1 has received a connection
index 143e531f9613779955af05433f589ea7d72becd4..89b39d7af36e6d410003dd1b2fb10e2881c8db29 100644 (file)
@@ -1,8 +1,10 @@
 # WARNING: this file is auto-generated by 'async_to_sync.py'
 # from the original file 'test_pool_null_async.py'
 # DO NOT CHANGE! Change the original file instead.
+from __future__ import annotations
+
 import logging
-from typing import Any, Dict, List
+from typing import Any, Dict
 
 import pytest
 from packaging.version import parse as ver  # noqa: F401  # used in skipif
@@ -409,7 +411,7 @@ def test_bad_resize(dsn, min_size, max_size):
 @pytest.mark.timing
 @pytest.mark.crdb_skip("backend pid")
 def test_max_lifetime(dsn):
-    pids: List[int] = []
+    pids: list[int] = []
 
     def worker():
         with p.connection() as conn:
index 5929dcdbc769d144f1be927cb45294c442ea9861..c74acb8fdfd5201179294ad8108d3b0588f3206a 100644 (file)
@@ -1,5 +1,7 @@
+from __future__ import annotations
+
 import logging
-from typing import Any, Dict, List
+from typing import Any, Dict
 
 import pytest
 from packaging.version import parse as ver  # noqa: F401  # used in skipif
@@ -408,7 +410,7 @@ async def test_bad_resize(dsn, min_size, max_size):
 @pytest.mark.timing
 @pytest.mark.crdb_skip("backend pid")
 async def test_max_lifetime(dsn):
-    pids: List[int] = []
+    pids: list[int] = []
 
     async def worker():
         async with p.connection() as conn:
index bf137db61f3c5f20a9fe1a49ec1541cd21492148..77b4960f9a895e249a09b510f91902a40c6a629c 100644 (file)
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import os
 import sys
 import time
@@ -5,7 +7,7 @@ import random
 import asyncio
 import logging
 from enum import Enum
-from typing import Any, Dict, List, Generator
+from typing import Any, Dict, Generator
 from argparse import ArgumentParser, Namespace
 from contextlib import contextmanager
 from concurrent.futures import ThreadPoolExecutor
@@ -25,8 +27,8 @@ class Driver(str, Enum):
     asyncpg = "asyncpg"
 
 
-ids: List[int] = []
-data: List[Dict[str, Any]] = []
+ids: list[int] = []
+data: list[Dict[str, Any]] = []
 
 
 def main() -> None:
index aaddd04387eaea77bb0a9f163aee12fe3295a14a..376f0de268b1fb22f7dffaec01e80d88a2a43bed 100644 (file)
@@ -2,7 +2,7 @@ from __future__ import annotations
 
 import datetime as dt
 from types import ModuleType
-from typing import Any, List
+from typing import Any
 
 import pytest
 
@@ -324,7 +324,7 @@ def test_list_dumper(conn, fmt_out):
     assert dempty.oid == 0
     assert dempty.dump([]) == b"{}"
 
-    L: List[List[Any]] = []
+    L: list[list[Any]] = []
     L.append(L)
     with pytest.raises(psycopg.DataError):
         assert t.get_dumper(L, fmt_in)
index f8266633784431d1619d459e172a24da6238cd8c..7585e71c1b890c1e92ca0a2e4778174033ef0e79 100644 (file)
@@ -10,7 +10,6 @@ import signal
 import threading
 import multiprocessing
 import subprocess as sp
-from typing import List
 
 import pytest
 
@@ -165,7 +164,7 @@ def canceller(conn, errors):
 @pytest.mark.slow
 @pytest.mark.crdb_skip("cancel")
 def test_cancel(conn):
-    errors: List[Exception] = []
+    errors: list[Exception] = []
 
     cur = conn.cursor()
     t = threading.Thread(target=canceller, args=(conn, errors))
@@ -189,7 +188,7 @@ def test_cancel(conn):
 @pytest.mark.slow
 @pytest.mark.crdb_skip("cancel")
 def test_cancel_stream(conn):
-    errors: List[Exception] = []
+    errors: list[Exception] = []
 
     cur = conn.cursor()
     t = threading.Thread(target=canceller, args=(conn, errors))
index bd6247c7d4350b97f5e6c89a4556fd0b462b37ca..65bc2539b71e55644128fa904bce042b9e386ee9 100644 (file)
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 import sys
 import time
 import signal
@@ -6,7 +8,6 @@ import threading
 import subprocess as sp
 from asyncio import create_task
 from asyncio.queues import Queue
-from typing import List
 
 import pytest
 
@@ -74,7 +75,7 @@ async def test_cancel(aconn):
         with pytest.raises(e.QueryCanceled):
             await cur.execute("select pg_sleep(2)")
 
-    errors: List[Exception] = []
+    errors: list[Exception] = []
     workers = [worker(), canceller(aconn, errors)]
 
     t0 = time.time()
@@ -100,7 +101,7 @@ async def test_cancel_stream(aconn):
             async for row in cur.stream("select pg_sleep(2)"):
                 pass
 
-    errors: List[Exception] = []
+    errors: list[Exception] = []
     workers = [worker(), canceller(aconn, errors)]
 
     t0 = time.time()
index 2acf0d747d2a1495b0aa1221fa579c7b78a3908d..cb4fe7e1fc1ee9d543ec46269b7889a05e3a0714 100644 (file)
@@ -1,12 +1,14 @@
 # WARNING: this file is auto-generated by 'async_to_sync.py'
 # from the original file 'test_connection_async.py'
 # DO NOT CHANGE! Change the original file instead.
+from __future__ import annotations
+
 import sys
 import time
 import pytest
 import logging
 import weakref
-from typing import Any, List
+from typing import Any
 
 import psycopg
 from psycopg import pq, errors as e
@@ -721,7 +723,7 @@ def test_set_transaction_param_not_intrans_external(conn, param):
 @skip_async
 @pytest.mark.crdb("skip", reason="transaction isolation")
 def test_set_transaction_param_all_property(conn):
-    params: List[Any] = tx_params[:]
+    params: list[Any] = tx_params[:]
     params[2] = params[2].values[0]
 
     for param in params:
@@ -736,7 +738,7 @@ def test_set_transaction_param_all_property(conn):
 
 @pytest.mark.crdb("skip", reason="transaction isolation")
 def test_set_transaction_param_all(conn):
-    params: List[Any] = tx_params[:]
+    params: list[Any] = tx_params[:]
     params[2] = params[2].values[0]
 
     for param in params:
index f5c355b2581ee61d3dfcb57b5f2593c070741ffa..8a4984af3d59cc9af05765bad54a16d9033cb906 100644 (file)
@@ -1,9 +1,11 @@
+from __future__ import annotations
+
 import sys
 import time
 import pytest
 import logging
 import weakref
-from typing import Any, List
+from typing import Any
 
 import psycopg
 from psycopg import pq, errors as e
@@ -723,7 +725,7 @@ async def test_set_transaction_param_not_intrans_external(aconn, param):
 @skip_async
 @pytest.mark.crdb("skip", reason="transaction isolation")
 def test_set_transaction_param_all_property(conn):
-    params: List[Any] = tx_params[:]
+    params: list[Any] = tx_params[:]
     params[2] = params[2].values[0]
 
     for param in params:
@@ -738,7 +740,7 @@ def test_set_transaction_param_all_property(conn):
 
 @pytest.mark.crdb("skip", reason="transaction isolation")
 async def test_set_transaction_param_all(aconn):
-    params: List[Any] = tx_params[:]
+    params: list[Any] = tx_params[:]
     params[2] = params[2].values[0]
 
     for param in params:
index d5b0d15136e78229a0e3beca406ceb8a1d15cb23..2fdf1f8eda6ecd583f801613c298ae76b3cecf21 100644 (file)
@@ -7,7 +7,7 @@ Tests common to psycopg.Cursor and its subclasses.
 
 import weakref
 import datetime as dt
-from typing import Any, List
+from typing import Any
 from packaging.version import parse as ver
 
 import pytest
@@ -484,7 +484,7 @@ def test_rownumber(conn):
     assert cur.rownumber == 2
     cur.fetchmany(10)
     assert cur.rownumber == 12
-    rns: List[int] = []
+    rns: list[int] = []
     for i in cur:
         assert cur.rownumber
         rns.append(cur.rownumber)
index 840de65ca47c84c7e846fe60c73743993bf0b6ef..0e05a92497e76785673f29586cc7763452d86e4f 100644 (file)
@@ -4,7 +4,7 @@ Tests common to psycopg.AsyncCursor and its subclasses.
 
 import weakref
 import datetime as dt
-from typing import Any, List
+from typing import Any
 from packaging.version import parse as ver
 
 import pytest
@@ -488,7 +488,7 @@ async def test_rownumber(aconn):
     assert cur.rownumber == 2
     await cur.fetchmany(10)
     assert cur.rownumber == 12
-    rns: List[int] = []
+    rns: list[int] = []
     async for i in cur:
         assert cur.rownumber
         rns.append(cur.rownumber)
index 1ab4535cb011adca18a980808dfb7a0832b1badf..0857de45f11c323b7b6c46b44854fe7cce41f53b 100644 (file)
@@ -1,7 +1,5 @@
 from __future__ import annotations
 
-from typing import List
-
 import pytest
 
 import psycopg
@@ -134,7 +132,7 @@ def get_fake_srv_function(monkeypatch):
             ans = fake_hosts[qname, rdtype]
         except KeyError:
             raise DNSException(f"unknown test host: {qname} {rdtype}")
-        rv: List[A | SRV] = []
+        rv: list[A | SRV] = []
 
         if rdtype == "A":
             for entry in ans:
index 78961eea7cb505b4f44c2e028f88070f559dbe02..935813bf80db013d9218ca43a8055a0604990822 100644 (file)
@@ -1,6 +1,7 @@
+from __future__ import annotations
+
 import sys
 import pickle
-from typing import List
 from weakref import ref
 
 import pytest
@@ -50,7 +51,7 @@ def test_diag_right_attr(pgconn, monkeypatch):
     diag = e.Diagnostic(res)
 
     to_check: pq.DiagnosticField
-    checked: List[pq.DiagnosticField] = []
+    checked: list[pq.DiagnosticField] = []
 
     def check_val(self, v):
         nonlocal to_check
index 9bb8bb1afc635797e4b30394125ac68308fa82e6..dce12f42c845029946491eb7bf1b88218c880db2 100644 (file)
@@ -1,7 +1,6 @@
 import time
 from collections import deque
 from functools import partial
-from typing import List
 
 import pytest
 
@@ -81,7 +80,7 @@ def pipeline(pgconn):
 
 
 def _run_pipeline_communicate(pgconn, generators, commands, expected_statuses):
-    actual_statuses: List[pq.ExecStatus] = []
+    actual_statuses: list[pq.ExecStatus] = []
     while len(actual_statuses) != len(expected_statuses):
         if commands:
             gen = generators.pipeline_communicate(pgconn, commands)
index 35bd48c26da7beb8496f2b792d9d300a1e91c74a..2ad397189fdb988eb7884b9ed25df59bc5f9f744 100644 (file)
@@ -304,15 +304,15 @@ curs = {curs}
     [
         (
             "conn.cursor()",
-            "List[Tuple[Any, ...]]",
+            "list[Tuple[Any, ...]]",
         ),
         (
             "conn.cursor(row_factory=rows.dict_row)",
-            "List[Dict[str, Any]]",
+            "list[Dict[str, Any]]",
         ),
         (
             "conn.cursor(row_factory=thing_row)",
-            "List[Thing]",
+            "list[Thing]",
         ),
     ],
 )
@@ -377,7 +377,9 @@ def _test_reveal(stmts, type, mypy):
     stmts = "\n".join(f"    {line}" for line in stmts.splitlines())
 
     src = f"""\
-from typing import Any, Callable, Dict, List, NamedTuple, Sequence, Tuple
+from __future__ import annotations
+
+from typing import Any, Callable, Dict, NamedTuple, Sequence, Tuple
 import psycopg
 from psycopg import rows
 
index 226fca46ba8aa13e2bc3b46394afeeffea42ea48..7831a15ebf3afc00cfeddcd35a28c714ae2636cf 100644 (file)
@@ -1,6 +1,8 @@
+from __future__ import annotations
+
 import gc
 from math import prod
-from typing import List, Any
+from typing import Any
 from decimal import Decimal
 
 import pytest
@@ -306,7 +308,7 @@ def test_load_array_no_comma_separator(conn):
 @pytest.mark.parametrize("fmt_out", pq.Format)
 def test_load_nested_array(conn, fmt_out):
     dims = [3, 4, 5, 6]
-    a: List[Any] = list(range(prod(dims)))
+    a: list[Any] = list(range(prod(dims)))
     for dim in dims[-1:0:-1]:
         a = [a[i : i + dim] for i in range(0, len(a), dim)]
 
index 945979b5691289cf5cfddb7ea5b21efdc10e8739..096cbe9d57102434ea40182f3bef52521f8a803d 100755 (executable)
@@ -14,10 +14,11 @@ with a specified version tag, and then query it using:
     %(prog)s "host=localhost port=11111 user=postgres password=password"
 """
 
+from __future__ import annotations
+
 import re
 import argparse
 import subprocess as sp
-from typing import List
 from pathlib import Path
 
 import psycopg
@@ -89,7 +90,7 @@ def update_crdb_python_oids(conn: Connection) -> None:
     sp.check_call(["black", "-q", fn])
 
 
-def get_version_comment(conn: Connection) -> List[str]:
+def get_version_comment(conn: Connection) -> list[str]:
     if conn.info.vendor == "PostgreSQL":
         version = version_pretty(conn.info.server_version)
     elif conn.info.vendor == "CockroachDB":
@@ -100,7 +101,7 @@ def get_version_comment(conn: Connection) -> List[str]:
     return ["", f"    # Generated from {conn.info.vendor} {version}", ""]
 
 
-def get_py_oids(conn: Connection) -> List[str]:
+def get_py_oids(conn: Connection) -> list[str]:
     lines = []
     for typname, oid in conn.execute(
         """
@@ -134,7 +135,7 @@ typemods = {
 }
 
 
-def get_py_types(conn: Connection) -> List[str]:
+def get_py_types(conn: Connection) -> list[str]:
     # Note: "record" is a pseudotype but still a useful one to have.
     # "pg_lsn" is a documented public type and useful in streaming replication
     lines = []
@@ -175,7 +176,7 @@ order by typname
     return lines
 
 
-def get_py_ranges(conn: Connection) -> List[str]:
+def get_py_ranges(conn: Connection) -> list[str]:
     lines = []
     for typname, oid, typarray, rngsubtype in conn.execute(
         """
@@ -195,7 +196,7 @@ order by typname
     return lines
 
 
-def get_py_multiranges(conn: Connection) -> List[str]:
+def get_py_multiranges(conn: Connection) -> list[str]:
     lines = []
     for typname, oid, typarray, rngtypid, rngsubtype in conn.execute(
         """
@@ -218,7 +219,7 @@ order by typname
     return lines
 
 
-def get_cython_oids(conn: Connection) -> List[str]:
+def get_cython_oids(conn: Connection) -> list[str]:
     lines = []
     for typname, oid in conn.execute(
         """
@@ -237,7 +238,7 @@ order by typname
     return lines
 
 
-def update_file(fn: Path, new: List[str]) -> None:
+def update_file(fn: Path, new: list[str]) -> None:
     with fn.open("r") as f:
         lines = f.read().splitlines()
     istart, iend = [