From: Daniele Varrazzo Date: Thu, 30 May 2024 01:03:57 +0000 (+0200) Subject: refactor: drop use of typing.List X-Git-Tag: 3.2.0~19^2~7 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0c3d31c1c977525e87272b13484d003e1886da5f;p=thirdparty%2Fpsycopg.git refactor: drop use of typing.List --- diff --git a/psycopg/psycopg/_adapters_map.py b/psycopg/psycopg/_adapters_map.py index 28b63956b..70a5586b0 100644 --- a/psycopg/psycopg/_adapters_map.py +++ b/psycopg/psycopg/_adapters_map.py @@ -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] = {} diff --git a/psycopg/psycopg/_connection_base.py b/psycopg/psycopg/_connection_base.py index 923040862..98eda8a74 100644 --- a/psycopg/psycopg/_connection_base.py +++ b/psycopg/psycopg/_connection_base.py @@ -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 diff --git a/psycopg/psycopg/_copy_base.py b/psycopg/psycopg/_copy_base.py index 60b455cca..3f1ddabe4 100644 --- a/psycopg/psycopg/_copy_base.py +++ b/psycopg/psycopg/_copy_base.py @@ -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): diff --git a/psycopg/psycopg/_cursor_base.py b/psycopg/psycopg/_cursor_base.py index 587b82190..6e02586bd 100644 --- a/psycopg/psycopg/_cursor_base.py +++ b/psycopg/psycopg/_cursor_base.py @@ -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 diff --git a/psycopg/psycopg/_dns.py b/psycopg/psycopg/_dns.py index 0701de482..612d4cfab 100644 --- a/psycopg/psycopg/_dns.py +++ b/psycopg/psycopg/_dns.py @@ -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) diff --git a/psycopg/psycopg/_pipeline.py b/psycopg/psycopg/_pipeline.py index 72dfe9111..09be343bb 100644 --- a/psycopg/psycopg/_pipeline.py +++ b/psycopg/psycopg/_pipeline.py @@ -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. diff --git a/psycopg/psycopg/_py_transformer.py b/psycopg/psycopg/_py_transformer.py index 6c3b8550e..f8726c949 100644 --- a/psycopg/psycopg/_py_transformer.py +++ b/psycopg/psycopg/_py_transformer.py @@ -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: diff --git a/psycopg/psycopg/_queries.py b/psycopg/psycopg/_queries.py index 71a11ed09..a1936df8c 100644 --- a/psycopg/psycopg/_queries.py +++ b/psycopg/psycopg/_queries.py @@ -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 diff --git a/psycopg/psycopg/abc.py b/psycopg/psycopg/abc.py index 0e6061fc4..091f88df2 100644 --- a/psycopg/psycopg/abc.py +++ b/psycopg/psycopg/abc.py @@ -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: ... diff --git a/psycopg/psycopg/connection.py b/psycopg/psycopg/connection.py index b4f71857d..3ad98bffa 100644 --- a/psycopg/psycopg/connection.py +++ b/psycopg/psycopg/connection.py @@ -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: diff --git a/psycopg/psycopg/connection_async.py b/psycopg/psycopg/connection_async.py index 37421579c..5d4422963 100644 --- a/psycopg/psycopg/connection_async.py +++ b/psycopg/psycopg/connection_async.py @@ -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: diff --git a/psycopg/psycopg/cursor.py b/psycopg/psycopg/cursor.py index 9ef66b852..52415e78c 100644 --- a/psycopg/psycopg/cursor.py +++ b/psycopg/psycopg/cursor.py @@ -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. diff --git a/psycopg/psycopg/cursor_async.py b/psycopg/psycopg/cursor_async.py index 12c066b6c..658da8788 100644 --- a/psycopg/psycopg/cursor_async.py +++ b/psycopg/psycopg/cursor_async.py @@ -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. diff --git a/psycopg/psycopg/errors.py b/psycopg/psycopg/errors.py index b90b478a4..928b781cf 100644 --- a/psycopg/psycopg/errors.py +++ b/psycopg/psycopg/errors.py @@ -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"" diff --git a/psycopg/psycopg/generators.py b/psycopg/psycopg/generators.py index f90addf17..d56c2271a 100644 --- a/psycopg/psycopg/generators.py +++ b/psycopg/psycopg/generators.py @@ -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() diff --git a/psycopg/psycopg/pq/__init__.py b/psycopg/psycopg/pq/__init__.py index 6887ee5e3..650d66463 100644 --- a/psycopg/psycopg/pq/__init__.py +++ b/psycopg/psycopg/pq/__init__.py @@ -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: diff --git a/psycopg/psycopg/pq/_pq_ctypes.py b/psycopg/psycopg/pq/_pq_ctypes.py index 101ec8384..27a6d1932 100644 --- a/psycopg/psycopg/pq/_pq_ctypes.py +++ b/psycopg/psycopg/pq/_pq_ctypes.py @@ -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): diff --git a/psycopg/psycopg/pq/abc.py b/psycopg/psycopg/pq/abc.py index fadd71e35..257c56a8f 100644 --- a/psycopg/psycopg/pq/abc.py +++ b/psycopg/psycopg/pq/abc.py @@ -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): diff --git a/psycopg/psycopg/pq/pq_ctypes.py b/psycopg/psycopg/pq/pq_ctypes.py index fc171e5ba..7f184fbb8 100644 --- a/psycopg/psycopg/pq/pq_ctypes.py +++ b/psycopg/psycopg/pq/pq_ctypes.py @@ -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: diff --git a/psycopg/psycopg/rows.py b/psycopg/psycopg/rows.py index 25c938386..9ab13fbba 100644 --- a/psycopg/psycopg/rows.py +++ b/psycopg/psycopg/rows.py @@ -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 diff --git a/psycopg/psycopg/server_cursor.py b/psycopg/psycopg/server_cursor.py index 76f5ad355..2f34d3eac 100644 --- a/psycopg/psycopg/server_cursor.py +++ b/psycopg/psycopg/server_cursor.py @@ -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) diff --git a/psycopg/psycopg/sql.py b/psycopg/psycopg/sql.py index 89647d2f8..96d518d37 100644 --- a/psycopg/psycopg/sql.py +++ b/psycopg/psycopg/sql.py @@ -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. diff --git a/psycopg/psycopg/types/array.py b/psycopg/psycopg/types/array.py index a795c6d3f..2cae3d4ef 100644 --- a/psycopg/psycopg/types/array.py +++ b/psycopg/psycopg/types/array.py @@ -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 diff --git a/psycopg/psycopg/types/composite.py b/psycopg/psycopg/types/composite.py index 6dd8642c6..114d7039a 100644 --- a/psycopg/psycopg/types/composite.py +++ b/psycopg/psycopg/types/composite.py @@ -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: diff --git a/psycopg/psycopg/types/hstore.py b/psycopg/psycopg/types/hstore.py index 526c0a688..509d617a3 100644 --- a/psycopg/psycopg/types/hstore.py +++ b/psycopg/psycopg/types/hstore.py @@ -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('"') diff --git a/psycopg/psycopg/types/multirange.py b/psycopg/psycopg/types/multirange.py index 67d5e9740..4cb24a0e0 100644 --- a/psycopg/psycopg/types/multirange.py +++ b/psycopg/psycopg/types/multirange.py @@ -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))) diff --git a/psycopg/psycopg/types/range.py b/psycopg/psycopg/types/range.py index 20b375aa2..775398542 100644 --- a/psycopg/psycopg/types/range.py +++ b/psycopg/psycopg/types/range.py @@ -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) diff --git a/psycopg_c/build_backend/cython_backend.py b/psycopg_c/build_backend/cython_backend.py index 97bd2af88..bb7bc48f6 100644 --- a/psycopg_c/build_backend/cython_backend.py +++ b/psycopg_c/build_backend/cython_backend.py @@ -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 diff --git a/psycopg_c/psycopg_c/_psycopg.pyi b/psycopg_c/psycopg_c/_psycopg.pyi index 50834c6b4..1961b9161 100644 --- a/psycopg_c/psycopg_c/_psycopg.pyi +++ b/psycopg_c/psycopg_c/_psycopg.pyi @@ -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]: ... diff --git a/psycopg_c/psycopg_c/_psycopg/generators.pyx b/psycopg_c/psycopg_c/_psycopg/generators.pyx index df210f698..0c8d72e0e 100644 --- a/psycopg_c/psycopg_c/_psycopg/generators.pyx +++ b/psycopg_c/psycopg_c/_psycopg/generators.pyx @@ -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) diff --git a/psycopg_c/psycopg_c/_psycopg/transform.pyx b/psycopg_c/psycopg_c/_psycopg/transform.pyx index c9849551e..97b6e2978 100644 --- a/psycopg_c/psycopg_c/_psycopg/transform.pyx +++ b/psycopg_c/psycopg_c/_psycopg/transform.pyx @@ -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") diff --git a/psycopg_c/psycopg_c/pq/conninfo.pyx b/psycopg_c/psycopg_c/pq/conninfo.pyx index 3443de1ba..35fb887d9 100644 --- a/psycopg_c/psycopg_c/pq/conninfo.pyx +++ b/psycopg_c/psycopg_c/pq/conninfo.pyx @@ -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: diff --git a/psycopg_c/psycopg_c/pq/pgconn.pyx b/psycopg_c/psycopg_c/pq/pgconn.pyx index 86e6910aa..b66804735 100644 --- a/psycopg_c/psycopg_c/pq/pgconn.pyx +++ b/psycopg_c/psycopg_c/pq/pgconn.pyx @@ -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: diff --git a/psycopg_c/psycopg_c/pq/pgresult.pyx b/psycopg_c/psycopg_c/pq/pgresult.pyx index 696d44ff1..2556896d9 100644 --- a/psycopg_c/psycopg_c/pq/pgresult.pyx +++ b/psycopg_c/psycopg_c/pq/pgresult.pyx @@ -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 = PyMem_Malloc( num * sizeof(libpq.PGresAttDesc)) diff --git a/psycopg_pool/psycopg_pool/pool.py b/psycopg_pool/psycopg_pool/pool.py index f8ae79d79..25010fe60 100644 --- a/psycopg_pool/psycopg_pool/pool.py +++ b/psycopg_pool/psycopg_pool/pool.py @@ -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, diff --git a/psycopg_pool/psycopg_pool/pool_async.py b/psycopg_pool/psycopg_pool/pool_async.py index 45000b6ec..f5b3fd22b 100644 --- a/psycopg_pool/psycopg_pool/pool_async.py +++ b/psycopg_pool/psycopg_pool/pool_async.py @@ -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, diff --git a/psycopg_pool/psycopg_pool/sched.py b/psycopg_pool/psycopg_pool/sched.py index 4a5181d63..eff588a79 100644 --- a/psycopg_pool/psycopg_pool/sched.py +++ b/psycopg_pool/psycopg_pool/sched.py @@ -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() diff --git a/psycopg_pool/psycopg_pool/sched_async.py b/psycopg_pool/psycopg_pool/sched_async.py index d43ef1d2e..1ba23d47d 100644 --- a/psycopg_pool/psycopg_pool/sched_async.py +++ b/psycopg_pool/psycopg_pool/sched_async.py @@ -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() diff --git a/tests/_test_connection.py b/tests/_test_connection.py index 56d385926..a161300b1 100644 --- a/tests/_test_connection.py +++ b/tests/_test_connection.py @@ -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 diff --git a/tests/_test_cursor.py b/tests/_test_cursor.py index c0f463d5f..95671d2bb 100644 --- a/tests/_test_cursor.py +++ b/tests/_test_cursor.py @@ -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] diff --git a/tests/conftest.py b/tests/conftest.py index cc1273f78..cea5ae775 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -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): diff --git a/tests/fix_faker.py b/tests/fix_faker.py index 7821429e9..9da58903f 100644 --- a/tests/fix_faker.py +++ b/tests/fix_faker.py @@ -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): diff --git a/tests/fix_pq.py b/tests/fix_pq.py index 917dfc919..0d68dc1fb 100644 --- a/tests/fix_pq.py +++ b/tests/fix_pq.py @@ -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] diff --git a/tests/pool/test_pool.py b/tests/pool/test_pool.py index 9aeed8f53..054d47912 100644 --- a/tests/pool/test_pool.py +++ b/tests/pool/test_pool.py @@ -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) diff --git a/tests/pool/test_pool_async.py b/tests/pool/test_pool_async.py index 525905a15..8976bce7d 100644 --- a/tests/pool/test_pool_async.py +++ b/tests/pool/test_pool_async.py @@ -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) diff --git a/tests/pool/test_pool_common.py b/tests/pool/test_pool_common.py index 2f5baf4e5..fb994e024 100644 --- a/tests/pool/test_pool_common.py +++ b/tests/pool/test_pool_common.py @@ -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 diff --git a/tests/pool/test_pool_common_async.py b/tests/pool/test_pool_common_async.py index e566fc85d..141e3e6d7 100644 --- a/tests/pool/test_pool_common_async.py +++ b/tests/pool/test_pool_common_async.py @@ -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 diff --git a/tests/pool/test_pool_null.py b/tests/pool/test_pool_null.py index 143e531f9..89b39d7af 100644 --- a/tests/pool/test_pool_null.py +++ b/tests/pool/test_pool_null.py @@ -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: diff --git a/tests/pool/test_pool_null_async.py b/tests/pool/test_pool_null_async.py index 5929dcdbc..c74acb8fd 100644 --- a/tests/pool/test_pool_null_async.py +++ b/tests/pool/test_pool_null_async.py @@ -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: diff --git a/tests/scripts/bench-411.py b/tests/scripts/bench-411.py index bf137db61..77b4960f9 100644 --- a/tests/scripts/bench-411.py +++ b/tests/scripts/bench-411.py @@ -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: diff --git a/tests/test_adapt.py b/tests/test_adapt.py index aaddd0438..376f0de26 100644 --- a/tests/test_adapt.py +++ b/tests/test_adapt.py @@ -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) diff --git a/tests/test_concurrency.py b/tests/test_concurrency.py index f82666337..7585e71c1 100644 --- a/tests/test_concurrency.py +++ b/tests/test_concurrency.py @@ -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)) diff --git a/tests/test_concurrency_async.py b/tests/test_concurrency_async.py index bd6247c7d..65bc2539b 100644 --- a/tests/test_concurrency_async.py +++ b/tests/test_concurrency_async.py @@ -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() diff --git a/tests/test_connection.py b/tests/test_connection.py index 2acf0d747..cb4fe7e1f 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -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: diff --git a/tests/test_connection_async.py b/tests/test_connection_async.py index f5c355b25..8a4984af3 100644 --- a/tests/test_connection_async.py +++ b/tests/test_connection_async.py @@ -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: diff --git a/tests/test_cursor_common.py b/tests/test_cursor_common.py index d5b0d1513..2fdf1f8ed 100644 --- a/tests/test_cursor_common.py +++ b/tests/test_cursor_common.py @@ -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) diff --git a/tests/test_cursor_common_async.py b/tests/test_cursor_common_async.py index 840de65ca..0e05a9249 100644 --- a/tests/test_cursor_common_async.py +++ b/tests/test_cursor_common_async.py @@ -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) diff --git a/tests/test_dns_srv.py b/tests/test_dns_srv.py index 1ab4535cb..0857de45f 100644 --- a/tests/test_dns_srv.py +++ b/tests/test_dns_srv.py @@ -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: diff --git a/tests/test_errors.py b/tests/test_errors.py index 78961eea7..935813bf8 100644 --- a/tests/test_errors.py +++ b/tests/test_errors.py @@ -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 diff --git a/tests/test_generators.py b/tests/test_generators.py index 9bb8bb1af..dce12f42c 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -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) diff --git a/tests/test_typing.py b/tests/test_typing.py index 35bd48c26..2ad397189 100644 --- a/tests/test_typing.py +++ b/tests/test_typing.py @@ -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 diff --git a/tests/types/test_array.py b/tests/types/test_array.py index 226fca46b..7831a15eb 100644 --- a/tests/types/test_array.py +++ b/tests/types/test_array.py @@ -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)] diff --git a/tools/update_oids.py b/tools/update_oids.py index 945979b56..096cbe9d5 100755 --- a/tools/update_oids.py +++ b/tools/update_oids.py @@ -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 = [