cur = conn.cursor() # type is psycopg.Cursor[tuple[Any, ...]]
- rec = cur.fetchone() # type is Optional[tuple[Any, ...]]
+ rec = cur.fetchone() # type is tuple[Any, ...] | None
recs = cur.fetchall() # type is List[tuple[Any, ...]]
# dcur type is psycopg.Cursor[dict[str, Any]] in both cases
drec = dcur.fetchone()
- # drec type is Optional[dict[str, Any]]
+ # drec type is dict[str, Any] | None
.. _pool-generic:
# reveal_type(conn): Connection[dict[str, Any]]
row = conn.execute("SELECT now()").fetchone()
- # reveal_type(row): Optional[dict[str, Any]]
+ # reveal_type(row): dict[str, Any] | None
print(row) # {"now": datetime.datetime(...)}
# reveal_type(conn): MyConnection
row = conn.execute("SELECT now()").fetchone()
- # reveal_type(row): Optional[dict[str, Any]]
+ # reveal_type(row): dict[str, Any] | None
print(row) # {"now": datetime.datetime(...)}
# Copyright (C) 2020 The Psycopg Team
-from typing import Any, Dict, List, Optional, Type, Union
+from __future__ import annotations
+
+from typing import Any, Dict, List, Type, Union
from typing import cast, TYPE_CHECKING
from . import pq
def __init__(
self,
- template: Optional["AdaptersMap"] = None,
- types: Optional[TypesRegistry] = None,
+ template: "AdaptersMap" | None = None,
+ types: TypesRegistry | None = None,
):
if template:
self._dumpers = template._dumpers.copy()
return self
@property
- def connection(self) -> Optional["BaseConnection[Any]"]:
+ def connection(self) -> "BaseConnection[Any]" | None:
return None
def register_dumper(
)
raise e.ProgrammingError(msg)
- def get_loader(self, oid: int, format: pq.Format) -> Optional[Type["Loader"]]:
+ def get_loader(self, oid: int, format: pq.Format) -> Type["Loader"] | None:
"""
Return the loader class for the given oid and format.
# Copyright (C) 2021 The Psycopg Team
-from typing import Optional
+from __future__ import annotations
from . import pq
-__version__: Optional[str] = None
+__version__: str | None = None
# Note: "c" must the first attempt so that mypy associates the variable the
# right module interface. It will not result Optional, but hey.
# Copyright (C) 2020 The Psycopg Team
-from typing import Any, Optional, Sequence, TYPE_CHECKING
+from __future__ import annotations
+
+from typing import Any, Sequence, TYPE_CHECKING
from operator import attrgetter
if TYPE_CHECKING:
return self._ftype
@property
- def display_size(self) -> Optional[int]:
+ def display_size(self) -> int | None:
"""The field size, for string types such as :sql:`varchar(n)`."""
return self._type.get_display_size(self._fmod) if self._type else None
@property
- def internal_size(self) -> Optional[int]:
+ def internal_size(self) -> int | None:
"""The internal field size for fixed-size types, None otherwise."""
fsize = self._fsize
return fsize if fsize >= 0 else None
@property
- def precision(self) -> Optional[int]:
+ def precision(self) -> int | None:
"""The number of digits for fixed precision types."""
return self._type.get_precision(self._fmod) if self._type else None
@property
- def scale(self) -> Optional[int]:
+ def scale(self) -> int | None:
"""The number of digits after the decimal point if available."""
return self._type.get_scale(self._fmod) if self._type else None
@property
- def null_ok(self) -> Optional[bool]:
+ def null_ok(self) -> bool | None:
"""Always `!None`"""
return None
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
import sys
import logging
from typing import Callable, Generic
-from typing import List, NamedTuple, Optional, Tuple, Union
+from typing import List, NamedTuple, Tuple, Union
from typing import TYPE_CHECKING
from weakref import ref, ReferenceType
from warnings import warn
self._autocommit = False
# None, but set to a copy of the global adapters map as soon as requested.
- self._adapters: Optional[AdaptersMap] = None
+ self._adapters: AdaptersMap | None = None
self._notice_handlers: List[NoticeHandler] = []
self._notify_handlers: List[NotifyHandler] = []
self._closed = False # closed by an explicit close()
self._prepared: PrepareManager = PrepareManager()
- self._tpc: Optional[Tuple[Xid, bool]] = None # xid, prepared
+ self._tpc: Tuple[Xid, bool] | None = None # xid, prepared
wself = ref(self)
pgconn.notice_handler = partial(BaseConnection._notice_handler, wself)
# Attribute is only set if the connection is from a pool so we can tell
# apart a connection in the pool too (when _pool = None)
- self._pool: Optional["BasePool"]
+ self._pool: "BasePool" | None
- self._pipeline: Optional[BasePipeline] = None
+ self._pipeline: BasePipeline | None = None
# Time after which the connection should be closed
self._expire_at: float
- self._isolation_level: Optional[IsolationLevel] = None
- self._read_only: Optional[bool] = None
- self._deferrable: Optional[bool] = None
+ self._isolation_level: IsolationLevel | None = None
+ self._read_only: bool | None = None
+ self._deferrable: bool | None = None
self._begin_statement = b""
def __del__(self) -> None:
self._autocommit = bool(value)
@property
- def isolation_level(self) -> Optional[IsolationLevel]:
+ def isolation_level(self) -> IsolationLevel | None:
"""
The isolation level of the new transactions started on the connection.
"""
return self._isolation_level
@isolation_level.setter
- def isolation_level(self, value: Optional[IsolationLevel]) -> None:
+ def isolation_level(self, value: IsolationLevel | None) -> None:
self._set_isolation_level(value)
- def _set_isolation_level(self, value: Optional[IsolationLevel]) -> None:
+ def _set_isolation_level(self, value: IsolationLevel | None) -> None:
raise NotImplementedError
- def _set_isolation_level_gen(self, value: Optional[IsolationLevel]) -> PQGen[None]:
+ def _set_isolation_level_gen(self, value: IsolationLevel | None) -> PQGen[None]:
yield from self._check_intrans_gen("isolation_level")
self._isolation_level = IsolationLevel(value) if value is not None else None
self._begin_statement = b""
@property
- def read_only(self) -> Optional[bool]:
+ def read_only(self) -> bool | None:
"""
The read-only state of the new transactions started on the connection.
"""
return self._read_only
@read_only.setter
- def read_only(self, value: Optional[bool]) -> None:
+ def read_only(self, value: bool | None) -> None:
self._set_read_only(value)
- def _set_read_only(self, value: Optional[bool]) -> None:
+ def _set_read_only(self, value: bool | None) -> None:
raise NotImplementedError
- def _set_read_only_gen(self, value: Optional[bool]) -> PQGen[None]:
+ def _set_read_only_gen(self, value: bool | None) -> PQGen[None]:
yield from self._check_intrans_gen("read_only")
self._read_only = bool(value) if value is not None else None
self._begin_statement = b""
@property
- def deferrable(self) -> Optional[bool]:
+ def deferrable(self) -> bool | None:
"""
The deferrable state of the new transactions started on the connection.
"""
return self._deferrable
@deferrable.setter
- def deferrable(self, value: Optional[bool]) -> None:
+ def deferrable(self, value: bool | None) -> None:
self._set_deferrable(value)
- def _set_deferrable(self, value: Optional[bool]) -> None:
+ def _set_deferrable(self, value: bool | None) -> None:
raise NotImplementedError
- def _set_deferrable_gen(self, value: Optional[bool]) -> PQGen[None]:
+ def _set_deferrable_gen(self, value: bool | None) -> PQGen[None]:
yield from self._check_intrans_gen("deferrable")
self._deferrable = bool(value) if value is not None else None
self._begin_statement = b""
cb(n)
@property
- def prepare_threshold(self) -> Optional[int]:
+ def prepare_threshold(self) -> int | None:
"""
Number of times a query is executed before it is prepared.
return self._prepared.prepare_threshold
@prepare_threshold.setter
- def prepare_threshold(self, value: Optional[int]) -> None:
+ def prepare_threshold(self, value: int | None) -> None:
self._prepared.prepare_threshold = value
@property
- def prepared_max(self) -> Optional[int]:
+ def prepared_max(self) -> int | None:
"""
Maximum number of prepared statements on the connection.
return rv if rv != sys.maxsize else None
@prepared_max.setter
- def prepared_max(self, value: Optional[int]) -> None:
+ def prepared_max(self, value: int | None) -> None:
if value is None:
value = sys.maxsize
self._prepared.prepared_max = value
def _exec_command(
self, command: Query, result_format: pq.Format = TEXT
- ) -> PQGen[Optional["PGresult"]]:
+ ) -> PQGen["PGresult" | None]:
"""
Generator to send a command and receive the result to the backend.
)
return result
- def _deallocate(self, name: Optional[bytes]) -> PQGen[None]:
+ def _deallocate(self, name: bytes | None) -> PQGen[None]:
"""
Deallocate one, or all, prepared statement in the session.
import struct
from abc import ABC, abstractmethod
from typing import Any, Dict, Generic, List, Match
-from typing import Optional, Sequence, Tuple, Union, TYPE_CHECKING
+from typing import Sequence, Tuple, Union, TYPE_CHECKING
from . import pq
from . import adapt
self,
cursor: "BaseCursor[ConnectionType, Any]",
*,
- binary: Optional[bool] = None,
+ binary: bool | None = None,
):
self.cursor = cursor
self.connection = cursor.connection
self.cursor._rowcount = nrows if nrows is not None else -1
return memoryview(b"")
- def _read_row_gen(self) -> PQGen[Optional[Tuple[Any, ...]]]:
+ def _read_row_gen(self) -> PQGen[Tuple[Any, ...] | None]:
data = yield from self._read_gen()
if not data:
return None
self._row_mode = False # true if the user is using write_row()
@abstractmethod
- def parse_row(self, data: Buffer) -> Optional[Tuple[Any, ...]]: ...
+ def parse_row(self, data: Buffer) -> Tuple[Any, ...] | None: ...
@abstractmethod
def write(self, buffer: Union[Buffer, str]) -> Buffer: ...
super().__init__(transformer)
self._encoding = encoding
- def parse_row(self, data: Buffer) -> Optional[Tuple[Any, ...]]:
+ def parse_row(self, data: Buffer) -> Tuple[Any, ...] | None:
if data:
return parse_row_text(data, self.transformer)
else:
super().__init__(transformer)
self._signature_sent = False
- def parse_row(self, data: Buffer) -> Optional[Tuple[Any, ...]]:
+ def parse_row(self, data: Buffer) -> Tuple[Any, ...] | None:
if not self._signature_sent:
if data[: len(_binary_signature)] != _binary_signature:
raise e.DataError(
def _format_row_text(
- row: Sequence[Any], tx: Transformer, out: Optional[bytearray] = None
+ row: Sequence[Any], tx: Transformer, out: bytearray | None = None
) -> bytearray:
"""Convert a row of objects to the data to send for copy."""
if out is None:
def _format_row_binary(
- row: Sequence[Any], tx: Transformer, out: Optional[bytearray] = None
+ row: Sequence[Any], tx: Transformer, out: bytearray | None = None
) -> bytearray:
"""Convert a row of objects to the data to send for binary copy."""
if out is None:
def _parse_row_binary(data: Buffer, tx: Transformer) -> Tuple[Any, ...]:
- row: List[Optional[Buffer]] = []
+ row: List[Buffer | None] = []
nfields = _unpack_int2(data, 0)[0]
pos = 2
for i in range(nfields):
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
from functools import partial
from typing import Any, Generic, Iterable, List
-from typing import Optional, NoReturn, Sequence, Tuple, Type
+from typing import NoReturn, Sequence, Tuple, Type
from typing import TYPE_CHECKING
from . import pq
self._adapters = adapt.AdaptersMap(connection.adapters)
self.arraysize = 1
self._closed = False
- self._last_query: Optional[Query] = None
+ self._last_query: Query | None = None
self._reset()
def _reset(self, reset_query: bool = True) -> None:
self._results: List["PGresult"] = []
- self.pgresult: Optional["PGresult"] = None
+ self.pgresult: "PGresult" | None = None
self._pos = 0
self._iresult = 0
self._rowcount = -1
- self._query: Optional[PostgresQuery]
+ self._query: PostgresQuery | None
# None if executemany() not executing, True/False according to returning state
- self._execmany_returning: Optional[bool] = None
+ self._execmany_returning: bool | None = None
if reset_query:
self._query = None
return self._closed
@property
- def description(self) -> Optional[List[Column]]:
+ def description(self) -> List[Column] | None:
"""
A list of `Column` objects describing the current resultset.
return self._rowcount
@property
- def rownumber(self) -> Optional[int]:
+ def rownumber(self) -> int | None:
"""Index of the next row to fetch in the current result.
`!None` if there is no result to fetch.
# no-op
pass
- def setoutputsize(self, size: Any, column: Optional[int] = None) -> None:
+ def setoutputsize(self, size: Any, column: int | None = None) -> None:
# no-op
pass
- def nextset(self) -> Optional[bool]:
+ def nextset(self) -> bool | None:
"""
Move to the result set of the next query executed through `executemany()`
or to the next result set if `execute()` returned more than one.
return None
@property
- def statusmessage(self) -> Optional[str]:
+ def statusmessage(self) -> str | None:
"""
The command status tag from the last SQL command executed.
def _execute_gen(
self,
query: Query,
- params: Optional[Params] = None,
+ params: Params | None = None,
*,
- prepare: Optional[bool] = None,
- binary: Optional[bool] = None,
+ prepare: bool | None = None,
+ binary: bool | None = None,
) -> PQGen[None]:
"""Generator implementing `Cursor.execute()`."""
yield from self._start_query(query)
self,
pgq: PostgresQuery,
*,
- prepare: Optional[bool] = None,
- binary: Optional[bool] = None,
+ prepare: bool | None = None,
+ binary: bool | None = None,
) -> PQGen[None]:
# Check if the query is prepared or needs preparing
prep, name = self._get_prepared(pgq, prepare)
self._set_results(results)
def _get_prepared(
- self, pgq: PostgresQuery, prepare: Optional[bool] = None
+ self, pgq: PostgresQuery, prepare: bool | None = None
) -> Tuple[Prepare, bytes]:
return self._conn._prepared.get(pgq, prepare)
def _stream_send_gen(
self,
query: Query,
- params: Optional[Params] = None,
+ params: Params | None = None,
*,
- binary: Optional[bool] = None,
+ binary: bool | None = None,
) -> PQGen[None]:
"""Generator to send the query for `Cursor.stream()`."""
yield from self._start_query(query)
self._last_query = query
yield from send(self._pgconn)
- def _stream_fetchone_gen(self, first: bool) -> PQGen[Optional["PGresult"]]:
+ def _stream_fetchone_gen(self, first: bool) -> PQGen["PGresult" | None]:
res = yield from fetch(self._pgconn)
if res is None:
return None
# Errors, unexpected values
return self._raise_for_result(res)
- def _start_query(self, query: Optional[Query] = None) -> PQGen[None]:
+ def _start_query(self, query: Query | None = None) -> PQGen[None]:
"""Generator to start the processing of a query.
It is implemented as generator because it may send additional queries,
yield from self._conn._start_query()
def _start_copy_gen(
- self, statement: Query, params: Optional[Params] = None
+ self, statement: Query, params: Params | None = None
) -> PQGen[None]:
"""Generator implementing sending a command for `Cursor.copy()."""
query: PostgresQuery,
*,
force_extended: bool = False,
- binary: Optional[bool] = None,
+ binary: bool | None = None,
) -> None:
"""
Implement part of execute() before waiting common to sync and async.
self._pgconn.send_query(query.query)
def _convert_query(
- self, query: Query, params: Optional[Params] = None
+ self, query: Query, params: Params | None = None
) -> PostgresQuery:
pgq = self._query_cls(self._tx)
pgq.convert(query, params)
"unexpected result status from query:" f" {pq.ExecStatus(status).name}"
)
- def _select_current_result(
- self, i: int, format: Optional[pq.Format] = None
- ) -> None:
+ def _select_current_result(self, i: int, format: pq.Format | None = None) -> None:
"""
Select one of the results in the cursor as the active one.
"""
self._pgconn.send_prepare(name, query.query, param_types=query.types)
def _send_query_prepared(
- self, name: bytes, pgq: PostgresQuery, *, binary: Optional[bool] = None
+ self, name: bytes, pgq: PostgresQuery, *, binary: bool | None = None
) -> None:
if binary is None:
fmt = self.format
# Copyright (C) 2021 The Psycopg Team
+from __future__ import annotations
+
import os
import re
import warnings
from random import randint
-from typing import Any, DefaultDict, Dict, List, NamedTuple, Optional, Sequence
+from typing import Any, DefaultDict, Dict, List, NamedTuple, Sequence
from typing import TYPE_CHECKING
from collections import defaultdict
host: str
port: str
totry: bool = False
- target: Optional[str] = None
+ target: str | None = None
class Rfc2782Resolver:
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
import re
import string
import codecs
-from typing import Any, Dict, Optional, TYPE_CHECKING
+from typing import Any, Dict, TYPE_CHECKING
from .pq._enums import ConnStatus
from .errors import NotSupportedError
pg_codecs = {v: k.encode() for k, v in _py_codecs.items()}
-def conn_encoding(conn: "Optional[BaseConnection[Any]]") -> str:
+def conn_encoding(conn: "BaseConnection[Any] | None") -> str:
"""
Return the Python encoding name of a psycopg connection.
# Copyright (C) 2021 The Psycopg Team
+from __future__ import annotations
+
import logging
from types import TracebackType
-from typing import Any, List, Optional, Union, Tuple, Type, TYPE_CHECKING
+from typing import Any, List, Union, Tuple, Type, TYPE_CHECKING
from . import pq
from . import errors as e
PendingResult: TypeAlias = Union[
- None, Tuple["BaseCursor[Any, Any]", Optional[Tuple[Key, Prepare, bytes]]]
+ None, Tuple["BaseCursor[Any, Any]", Tuple[Key, Prepare, bytes] | None]
]
FATAL_ERROR = pq.ExecStatus.FATAL_ERROR
yield from self._sync_gen()
self.level += 1
- def _exit(self, exc: Optional[BaseException]) -> None:
+ def _exit(self, exc: BaseException | None) -> None:
self.level -= 1
if self.level == 0 and self.pgconn.status != BAD:
try:
def __exit__(
self,
- exc_type: Optional[Type[BaseException]],
- exc_val: Optional[BaseException],
- exc_tb: Optional[TracebackType],
+ exc_type: Type[BaseException] | None,
+ exc_val: BaseException | None,
+ exc_tb: TracebackType | None,
) -> None:
try:
with self._conn.lock:
async def __aexit__(
self,
- exc_type: Optional[Type[BaseException]],
- exc_val: Optional[BaseException],
- exc_tb: Optional[TracebackType],
+ exc_type: Type[BaseException] | None,
+ exc_val: BaseException | None,
+ exc_tb: TracebackType | None,
) -> None:
try:
async with self._conn.lock:
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
from enum import IntEnum, auto
-from typing import Optional, Sequence, Tuple, TYPE_CHECKING
+from typing import Sequence, Tuple, TYPE_CHECKING
from collections import OrderedDict
from . import pq
class PrepareManager:
# Number of times a query is executed before it is prepared.
- prepare_threshold: Optional[int] = 5
+ prepare_threshold: int | None = 5
# Maximum number of prepared statements on the connection.
prepared_max: int = 100
# Counter to generate prepared statements names
self._prepared_idx = 0
- self._to_flush = Deque[Optional[bytes]]()
+ self._to_flush = Deque[bytes | None]()
@staticmethod
def key(query: PostgresQuery) -> Key:
return (query.query, query.types)
def get(
- self, query: PostgresQuery, prepare: Optional[bool] = None
+ self, query: PostgresQuery, prepare: bool | None = None
) -> Tuple[Prepare, bytes]:
"""
Check if a query is prepared, tell back whether to prepare it.
def maybe_add_to_cache(
self, query: PostgresQuery, prep: Prepare, name: bytes
- ) -> Optional[Key]:
+ ) -> Key | None:
"""Handle 'query' for possible addition to the cache.
If a new entry has been added, return its key. Return None otherwise
# Copyright (C) 2020 The Psycopg Team
-from typing import Any, Dict, List, Optional, Sequence, Tuple
+from __future__ import annotations
+
+from typing import Any, Dict, List, Sequence, Tuple
from typing import DefaultDict, TYPE_CHECKING
from collections import defaultdict
_oid_dumpers _oid_types _row_dumpers _row_loaders
""".split()
- types: Optional[Tuple[int, ...]]
- formats: Optional[List[pq.Format]]
+ types: Tuple[int, ...] | None
+ formats: List[pq.Format] | None
_adapters: "AdaptersMap"
- _pgresult: Optional["PGresult"]
+ _pgresult: "PGresult" | None
_none_oid: int
- def __init__(self, context: Optional[AdaptContext] = None):
+ def __init__(self, context: AdaptContext | None = None):
self._pgresult = self.types = self.formats = None
# WARNING: don't store context, or you'll create a loop with the Cursor
# mapping fmt, oid -> Dumper instance
# Not often used, so create it only if needed.
- self._oid_dumpers: Optional[Tuple[OidDumperCache, OidDumperCache]]
+ self._oid_dumpers: Tuple[OidDumperCache, OidDumperCache] | None
self._oid_dumpers = None
# mapping fmt, oid -> Loader instance
self._loaders: Tuple[LoaderCache, LoaderCache] = ({}, {})
- self._row_dumpers: Optional[List[abc.Dumper]] = None
+ self._row_dumpers: List[abc.Dumper] | None = None
# sequence of load functions from value to python
# the length of the result columns
self._encoding = ""
@classmethod
- def from_context(cls, context: Optional[AdaptContext]) -> "Transformer":
+ def from_context(cls, context: AdaptContext | None) -> "Transformer":
"""
Return a Transformer from an AdaptContext.
return cls(context)
@property
- def connection(self) -> Optional["BaseConnection[Any]"]:
+ def connection(self) -> "BaseConnection[Any]" | None:
return self._conn
@property
return self._adapters
@property
- def pgresult(self) -> Optional["PGresult"]:
+ def pgresult(self) -> "PGresult" | None:
return self._pgresult
def set_pgresult(
self,
- result: Optional["PGresult"],
+ result: "PGresult" | None,
*,
set_loaders: bool = True,
- format: Optional[pq.Format] = None,
+ format: pq.Format | None = None,
) -> None:
self._pgresult = result
def dump_sequence(
self, params: Sequence[Any], formats: Sequence[PyFormat]
- ) -> Sequence[Optional[Buffer]]:
+ ) -> Sequence[Buffer | None]:
nparams = len(params)
- out: List[Optional[Buffer]] = [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
return records
- def load_row(self, row: int, make_row: RowMaker[Row]) -> Optional[Row]:
+ def load_row(self, row: int, make_row: RowMaker[Row]) -> Row | None:
res = self._pgresult
if not res:
return None
return make_row(record)
- def load_sequence(self, record: Sequence[Optional[Buffer]]) -> Tuple[Any, ...]:
+ def load_sequence(self, record: Sequence[Buffer | None]) -> Tuple[Any, ...]:
if len(self._row_loaders) != len(record):
raise e.ProgrammingError(
f"cannot load sequence of {len(record)} items:"
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
import re
-from typing import Any, Callable, Dict, List, Mapping, Match, NamedTuple, Optional
+from typing import Any, Callable, Dict, List, Mapping, Match, NamedTuple
from typing import Sequence, Tuple, Union, TYPE_CHECKING
from functools import lru_cache
def __init__(self, transformer: "Transformer"):
self._tx = transformer
- self.params: Optional[Sequence[Optional[Buffer]]] = None
+ self.params: Sequence[Buffer | None] | None = None
# these are tuples so they can be used as keys e.g. in prepared stmts
self.types: Tuple[int, ...] = ()
# The format requested by the user and the ones to really pass Postgres
- self._want_formats: Optional[List[PyFormat]] = None
- self.formats: Optional[Sequence[pq.Format]] = 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.query = b""
- self._order: Optional[List[str]] = None
+ self._order: List[str] | None = None
- def convert(self, query: Query, vars: Optional[Params]) -> None:
+ def convert(self, query: Query, vars: Params | None) -> None:
"""
Set up the query and parameters to convert.
self.dump(vars)
- def dump(self, vars: Optional[Params]) -> None:
+ def dump(self, vars: Params | None) -> None:
"""
Process a new set of variables on the query processed by `convert()`.
@staticmethod
def validate_and_reorder_params(
- parts: List[QueryPart], vars: Params, order: Optional[List[str]]
+ parts: List[QueryPart], vars: Params, order: List[str] | None
) -> Sequence[Any]:
"""
Verify the compatibility between a query and a set of params.
# The type of the _query2pg() and _query2pg_nocache() methods
_Query2Pg: TypeAlias = Callable[
- [bytes, str], Tuple[bytes, List[PyFormat], Optional[List[str]], List[QueryPart]]
+ [bytes, str], Tuple[bytes, List[PyFormat], List[str] | None, List[QueryPart]]
]
def _query2pg_nocache(
query: bytes, encoding: str
-) -> Tuple[bytes, List[PyFormat], Optional[List[str]], List[QueryPart]]:
+) -> Tuple[bytes, List[PyFormat], List[str] | None, List[QueryPart]]:
"""
Convert Python query and params into something Postgres understands.
``parts`` (splits of queries and placeholders).
"""
parts = _split_query(query, encoding)
- order: Optional[List[str]] = None
+ order: List[str] | None = None
chunks: List[bytes] = []
formats = []
__slots__ = ("template",)
- def convert(self, query: Query, vars: Optional[Params]) -> None:
+ def convert(self, query: Query, vars: Params | None) -> None:
"""
Set up the query and parameters to convert.
self.dump(vars)
- def dump(self, vars: Optional[Params]) -> None:
+ def dump(self, vars: Params | None) -> None:
"""
Process a new set of variables on the query processed by `convert()`.
_Query2PgClient: TypeAlias = Callable[
- [bytes, str], Tuple[bytes, Optional[List[str]], List[QueryPart]]
+ [bytes, str], Tuple[bytes, List[str] | None, List[QueryPart]]
]
def _query2pg_client_nocache(
query: bytes, encoding: str
-) -> Tuple[bytes, Optional[List[str]], 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: Optional[List[str]] = None
+ order: List[str] | None = None
chunks: List[bytes] = []
if isinstance(parts[0].item, int):
def _split_query(
query: bytes, encoding: str = "ascii", collapse_double_percent: bool = True
) -> List[QueryPart]:
- parts: List[Tuple[bytes, Optional[Match[bytes]]]] = []
+ parts: List[Tuple[bytes, Match[bytes] | None]] = []
cur = 0
# pairs [(fragment, match], with the last match None
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
import struct
-from typing import Callable, cast, Optional, Protocol, Tuple
+from typing import Callable, cast, Protocol, Tuple
from . import errors as e
from .abc import Buffer
class UnpackLen(Protocol):
- def __call__(self, data: Buffer, start: Optional[int]) -> Tuple[int]: ...
+ def __call__(self, data: Buffer, start: int | None) -> Tuple[int]: ...
pack_int2 = cast(PackInt, struct.Struct("!h").pack)
# Copyright (C) 2021 The Psycopg Team
+from __future__ import annotations
+
import re
import datetime as dt
from base64 import b64encode, b64decode
-from typing import Optional, Union
+from typing import Union
from dataclasses import dataclass, replace
_re_xid = re.compile(r"^(\d+)_([^_]*)_([^_]*)$")
"""
- format_id: Optional[int]
+ format_id: int | None
gtrid: str
- bqual: Optional[str]
- prepared: Optional[dt.datetime] = None
- owner: Optional[str] = None
- database: Optional[str] = None
+ bqual: str | None
+ prepared: dt.datetime | None = None
+ owner: str | None = None
+ database: str | None = None
@classmethod
def from_string(cls, s: str) -> "Xid":
return cls.from_parts(format_id, gtrid, bqual)
@classmethod
- def from_parts(
- cls, format_id: Optional[int], gtrid: str, bqual: Optional[str]
- ) -> "Xid":
+ def from_parts(cls, format_id: int | None, gtrid: str, bqual: str | None) -> "Xid":
if format_id is not None:
if bqual is None:
raise TypeError("if format_id is specified, bqual must be too")
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
import logging
-from typing import Dict, Optional, Union
+from typing import Dict, Union
from datetime import timezone, tzinfo
from .pq.abc import PGconn
}
-def get_tzinfo(pgconn: Optional[PGconn]) -> tzinfo:
+def get_tzinfo(pgconn: PGconn | None) -> tzinfo:
"""Return the Python timezone info of the connection's timezone."""
tzname = pgconn.parameter_status(b"TimeZone") if pgconn else None
try:
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
from typing import Any, Dict, Callable, Generator, Mapping
-from typing import List, Optional, Protocol, Sequence, Tuple, Union
+from typing import List, Protocol, Sequence, Tuple, Union
from typing import TYPE_CHECKING
from . import pq
"""
def __call__(
- self, gen: PQGen[RV], fileno: int, interval: Optional[float] = None
+ self, gen: PQGen[RV], fileno: int, interval: float | None = None
) -> RV: ...
# Adaptation types
-DumpFunc: TypeAlias = Callable[[Any], Optional[Buffer]]
+DumpFunc: TypeAlias = Callable[[Any], Buffer | None]
LoadFunc: TypeAlias = Callable[[Buffer], Any]
...
@property
- def connection(self) -> Optional["BaseConnection[Any]"]:
+ def connection(self) -> "BaseConnection[Any]" | None:
"""The connection used by this object, if available.
:rtype: `~psycopg.Connection` or `~psycopg.AsyncConnection` or `!None`
oid: int
"""The oid to pass to the server, if known; 0 otherwise (class attribute)."""
- def __init__(self, cls: type, context: Optional[AdaptContext] = None): ...
+ def __init__(self, cls: type, context: AdaptContext | None = None): ...
- def dump(self, obj: Any) -> Optional[Buffer]:
+ def dump(self, obj: Any) -> Buffer | None:
"""Convert the object `!obj` to PostgreSQL representation.
:param obj: the object to convert.
This is a class attribute.
"""
- def __init__(self, oid: int, context: Optional[AdaptContext] = None): ...
+ def __init__(self, oid: int, context: AdaptContext | None = None): ...
def load(self, data: Buffer) -> Any:
"""
class Transformer(Protocol):
- types: Optional[Tuple[int, ...]]
- formats: Optional[List[pq.Format]]
+ types: Tuple[int, ...] | None
+ formats: List[pq.Format] | None
- def __init__(self, context: Optional[AdaptContext] = None): ...
+ def __init__(self, context: AdaptContext | None = None): ...
@classmethod
- def from_context(cls, context: Optional[AdaptContext]) -> "Transformer": ...
+ def from_context(cls, context: AdaptContext | None) -> "Transformer": ...
@property
- def connection(self) -> Optional["BaseConnection[Any]"]: ...
+ def connection(self) -> "BaseConnection[Any]" | None: ...
@property
def encoding(self) -> str: ...
def adapters(self) -> "AdaptersMap": ...
@property
- def pgresult(self) -> Optional["PGresult"]: ...
+ def pgresult(self) -> "PGresult" | None: ...
def set_pgresult(
self,
- result: Optional["PGresult"],
+ result: "PGresult" | None,
*,
set_loaders: bool = True,
- format: Optional[pq.Format] = None
+ format: pq.Format | None = None,
) -> None: ...
def set_dumper_types(self, types: Sequence[int], format: pq.Format) -> None: ...
def dump_sequence(
self, params: Sequence[Any], formats: Sequence[PyFormat]
- ) -> Sequence[Optional[Buffer]]: ...
+ ) -> Sequence[Buffer | None]: ...
def as_literal(self, obj: Any) -> bytes: ...
self, row0: int, row1: int, make_row: "RowMaker[Row]"
) -> List["Row"]: ...
- def load_row(self, row: int, make_row: "RowMaker[Row]") -> Optional["Row"]: ...
+ def load_row(self, row: int, make_row: "RowMaker[Row]") -> "Row" | None: ...
- def load_sequence(self, record: Sequence[Optional[Buffer]]) -> Tuple[Any, ...]: ...
+ def load_sequence(self, record: Sequence[Buffer | None]) -> Tuple[Any, ...]: ...
def get_loader(self, oid: int, format: pq.Format) -> Loader: ...
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
from abc import ABC, abstractmethod
-from typing import Any, Optional, TYPE_CHECKING
+from typing import Any, TYPE_CHECKING
from . import pq, abc
format: pq.Format = pq.Format.TEXT
"""The format of the data dumped."""
- def __init__(self, cls: type, context: Optional[abc.AdaptContext] = None):
+ def __init__(self, cls: type, context: abc.AdaptContext | None = None):
self.cls = cls
- self.connection: Optional["BaseConnection[Any]"] = (
- context.connection if context else None
- )
+ self.connection: "BaseConnection[Any]" | None
+ self.connection = context.connection if context else None
def __repr__(self) -> str:
return (
)
@abstractmethod
- def dump(self, obj: Any) -> Optional[Buffer]: ...
+ def dump(self, obj: Any) -> Buffer | None: ...
def quote(self, obj: Any) -> Buffer:
"""
format: pq.Format = pq.Format.TEXT
"""The format of the data loaded."""
- def __init__(self, oid: int, context: Optional[abc.AdaptContext] = None):
+ def __init__(self, oid: int, context: abc.AdaptContext | None = None):
self.oid = oid
- self.connection: Optional["BaseConnection[Any]"] = (
- context.connection if context else None
- )
+ self.connection: "BaseConnection[Any]" | None
+ self.connection = context.connection if context else None
@abstractmethod
def load(self, data: Buffer) -> Any:
class RecursiveDumper(Dumper):
"""Dumper with a transformer to help dumping recursive types."""
- def __init__(self, cls: type, context: Optional[abc.AdaptContext] = None):
+ def __init__(self, cls: type, context: abc.AdaptContext | None = None):
super().__init__(cls, context)
self._tx = Transformer.from_context(context)
class RecursiveLoader(Loader):
"""Loader with a transformer to help loading recursive types."""
- def __init__(self, oid: int, context: Optional[abc.AdaptContext] = None):
+ def __init__(self, oid: int, context: abc.AdaptContext | None = None):
super().__init__(oid, context)
self._tx = Transformer.from_context(context)
# Copyright (C) 2022 The Psycopg Team
-from typing import Optional, Tuple, TYPE_CHECKING
+from __future__ import annotations
+
+from typing import Tuple, TYPE_CHECKING
from functools import partial
from ._queries import PostgresQuery, PostgresClientQuery
class ClientCursorMixin(BaseCursor[ConnectionType, Row]):
_query_cls = PostgresClientQuery
- def mogrify(self, query: Query, params: Optional[Params] = None) -> str:
+ def mogrify(self, query: Query, params: Params | None = None) -> str:
"""
Return the query and parameters merged.
query: PostgresQuery,
*,
force_extended: bool = False,
- binary: Optional[bool] = None,
+ binary: bool | None = None,
) -> None:
if binary is None:
fmt = self.format
self._pgconn.send_query(query.query)
def _get_prepared(
- self, pgq: PostgresQuery, prepare: Optional[bool] = None
+ self, pgq: PostgresQuery, prepare: bool | None = None
) -> Tuple[Prepare, bytes]:
return (Prepare.NO, b"")
import logging
from time import monotonic
from types import TracebackType
-from typing import Any, Generator, Iterator, List, Optional
+from typing import Any, Generator, Iterator, List
from typing import Type, Union, cast, overload, TYPE_CHECKING
from contextlib import contextmanager
cursor_factory: Type[Cursor[Row]]
server_cursor_factory: Type[ServerCursor[Row]]
row_factory: RowFactory[Row]
- _pipeline: Optional[Pipeline]
+ _pipeline: Pipeline | None
def __init__(
self,
conninfo: str = "",
*,
autocommit: bool = False,
- prepare_threshold: Optional[int] = 5,
- context: Optional[AdaptContext] = None,
- row_factory: Optional[RowFactory[Row]] = None,
- cursor_factory: Optional[Type[Cursor[Row]]] = None,
+ prepare_threshold: int | None = 5,
+ context: AdaptContext | None = None,
+ row_factory: RowFactory[Row] | None = None,
+ cursor_factory: Type[Cursor[Row]] | None = None,
**kwargs: ConnParam,
) -> Self:
"""
def __exit__(
self,
- exc_type: Optional[Type[BaseException]],
- exc_val: Optional[BaseException],
- exc_tb: Optional[TracebackType],
+ exc_type: Type[BaseException] | None,
+ exc_val: BaseException | None,
+ exc_tb: TracebackType | None,
) -> None:
if self.closed:
return
name: str,
*,
binary: bool = False,
- scrollable: Optional[bool] = None,
+ scrollable: bool | None = None,
withhold: bool = False,
) -> ServerCursor[Row]: ...
*,
binary: bool = False,
row_factory: RowFactory[CursorRow],
- scrollable: Optional[bool] = None,
+ scrollable: bool | None = None,
withhold: bool = False,
) -> ServerCursor[CursorRow]: ...
name: str = "",
*,
binary: bool = False,
- row_factory: Optional[RowFactory[Any]] = None,
- scrollable: Optional[bool] = None,
+ row_factory: RowFactory[Any] | None = None,
+ scrollable: bool | None = None,
withhold: bool = False,
) -> Union[Cursor[Any], ServerCursor[Any]]:
"""
def execute(
self,
query: Query,
- params: Optional[Params] = None,
+ params: Params | None = None,
*,
- prepare: Optional[bool] = None,
+ prepare: bool | None = None,
binary: bool = False,
) -> Cursor[Row]:
"""Execute a query and return a cursor to read its results."""
@contextmanager
def transaction(
- self, savepoint_name: Optional[str] = None, force_rollback: bool = False
+ self, savepoint_name: str | None = None, force_rollback: bool = False
) -> Iterator[Transaction]:
"""
Start a context block with a new transaction or nested transaction.
yield tx
def notifies(
- self, *, timeout: Optional[float] = None, stop_after: Optional[int] = None
+ self, *, timeout: float | None = None, stop_after: int | None = None
) -> Generator[Notify, None, None]:
"""
Yield `Notify` objects as soon as they are received from the database.
assert pipeline is self._pipeline
self._pipeline = None
- def wait(self, gen: PQGen[RV], interval: Optional[float] = _WAIT_INTERVAL) -> RV:
+ def wait(self, gen: PQGen[RV], interval: float | None = _WAIT_INTERVAL) -> RV:
"""
Consume a generator operating on the connection.
with self.lock:
self.wait(self._set_autocommit_gen(value))
- def _set_isolation_level(self, value: Optional[IsolationLevel]) -> None:
+ def _set_isolation_level(self, value: IsolationLevel | None) -> None:
self.set_isolation_level(value)
- def set_isolation_level(self, value: Optional[IsolationLevel]) -> None:
+ def set_isolation_level(self, value: IsolationLevel | None) -> None:
"""Method version of the `~Connection.isolation_level` setter."""
with self.lock:
self.wait(self._set_isolation_level_gen(value))
- def _set_read_only(self, value: Optional[bool]) -> None:
+ def _set_read_only(self, value: bool | None) -> None:
self.set_read_only(value)
- def set_read_only(self, value: Optional[bool]) -> None:
+ def set_read_only(self, value: bool | None) -> None:
"""Method version of the `~Connection.read_only` setter."""
with self.lock:
self.wait(self._set_read_only_gen(value))
- def _set_deferrable(self, value: Optional[bool]) -> None:
+ def _set_deferrable(self, value: bool | None) -> None:
self.set_deferrable(value)
- def set_deferrable(self, value: Optional[bool]) -> None:
+ def set_deferrable(self, value: bool | None) -> None:
"""Method version of the `~Connection.deferrable` setter."""
with self.lock:
self.wait(self._set_deferrable_gen(value))
import logging
from time import monotonic
from types import TracebackType
-from typing import Any, AsyncGenerator, AsyncIterator, List, Optional
+from typing import Any, AsyncGenerator, AsyncIterator, List
from typing import Type, Union, cast, overload, TYPE_CHECKING
from contextlib import asynccontextmanager
cursor_factory: Type[AsyncCursor[Row]]
server_cursor_factory: Type[AsyncServerCursor[Row]]
row_factory: AsyncRowFactory[Row]
- _pipeline: Optional[AsyncPipeline]
+ _pipeline: AsyncPipeline | None
def __init__(
self,
conninfo: str = "",
*,
autocommit: bool = False,
- prepare_threshold: Optional[int] = 5,
- context: Optional[AdaptContext] = None,
- row_factory: Optional[AsyncRowFactory[Row]] = None,
- cursor_factory: Optional[Type[AsyncCursor[Row]]] = None,
+ prepare_threshold: int | None = 5,
+ context: AdaptContext | None = None,
+ row_factory: AsyncRowFactory[Row] | None = None,
+ cursor_factory: Type[AsyncCursor[Row]] | None = None,
**kwargs: ConnParam,
) -> Self:
"""
async def __aexit__(
self,
- exc_type: Optional[Type[BaseException]],
- exc_val: Optional[BaseException],
- exc_tb: Optional[TracebackType],
+ exc_type: Type[BaseException] | None,
+ exc_val: BaseException | None,
+ exc_tb: TracebackType | None,
) -> None:
if self.closed:
return
name: str,
*,
binary: bool = False,
- scrollable: Optional[bool] = None,
+ scrollable: bool | None = None,
withhold: bool = False,
) -> AsyncServerCursor[Row]: ...
*,
binary: bool = False,
row_factory: AsyncRowFactory[CursorRow],
- scrollable: Optional[bool] = None,
+ scrollable: bool | None = None,
withhold: bool = False,
) -> AsyncServerCursor[CursorRow]: ...
name: str = "",
*,
binary: bool = False,
- row_factory: Optional[AsyncRowFactory[Any]] = None,
- scrollable: Optional[bool] = None,
+ row_factory: AsyncRowFactory[Any] | None = None,
+ scrollable: bool | None = None,
withhold: bool = False,
) -> Union[AsyncCursor[Any], AsyncServerCursor[Any]]:
"""
async def execute(
self,
query: Query,
- params: Optional[Params] = None,
+ params: Params | None = None,
*,
- prepare: Optional[bool] = None,
+ prepare: bool | None = None,
binary: bool = False,
) -> AsyncCursor[Row]:
"""Execute a query and return a cursor to read its results."""
@asynccontextmanager
async def transaction(
- self, savepoint_name: Optional[str] = None, force_rollback: bool = False
+ self, savepoint_name: str | None = None, force_rollback: bool = False
) -> AsyncIterator[AsyncTransaction]:
"""
Start a context block with a new transaction or nested transaction.
yield tx
async def notifies(
- self, *, timeout: Optional[float] = None, stop_after: Optional[int] = None
+ self, *, timeout: float | None = None, stop_after: int | None = None
) -> AsyncGenerator[Notify, None]:
"""
Yield `Notify` objects as soon as they are received from the database.
assert pipeline is self._pipeline
self._pipeline = None
- async def wait(
- self, gen: PQGen[RV], interval: Optional[float] = _WAIT_INTERVAL
- ) -> RV:
+ async def wait(self, gen: PQGen[RV], interval: float | None = _WAIT_INTERVAL) -> RV:
"""
Consume a generator operating on the connection.
async with self.lock:
await self.wait(self._set_autocommit_gen(value))
- def _set_isolation_level(self, value: Optional[IsolationLevel]) -> None:
+ def _set_isolation_level(self, value: IsolationLevel | None) -> None:
if True: # ASYNC
self._no_set_async("isolation_level")
else:
self.set_isolation_level(value)
- async def set_isolation_level(self, value: Optional[IsolationLevel]) -> None:
+ async def set_isolation_level(self, value: IsolationLevel | None) -> None:
"""Method version of the `~Connection.isolation_level` setter."""
async with self.lock:
await self.wait(self._set_isolation_level_gen(value))
- def _set_read_only(self, value: Optional[bool]) -> None:
+ def _set_read_only(self, value: bool | None) -> None:
if True: # ASYNC
self._no_set_async("read_only")
else:
self.set_read_only(value)
- async def set_read_only(self, value: Optional[bool]) -> None:
+ async def set_read_only(self, value: bool | None) -> None:
"""Method version of the `~Connection.read_only` setter."""
async with self.lock:
await self.wait(self._set_read_only_gen(value))
- def _set_deferrable(self, value: Optional[bool]) -> None:
+ def _set_deferrable(self, value: bool | None) -> None:
if True: # ASYNC
self._no_set_async("deferrable")
else:
self.set_deferrable(value)
- async def set_deferrable(self, value: Optional[bool]) -> None:
+ async def set_deferrable(self, value: bool | None) -> None:
"""Method version of the `~Connection.deferrable` setter."""
async with self.lock:
await self.wait(self._set_deferrable_gen(value))
# Copyright (C) 2022 The Psycopg Team
+from __future__ import annotations
+
import re
-from typing import Any, Optional, Union, TYPE_CHECKING
+from typing import Any, Union, TYPE_CHECKING
from .. import errors as e
from ..rows import Row
class _CrdbConnectionMixin:
- _adapters: Optional[AdaptersMap]
+ _adapters: AdaptersMap | None
pgconn: "PGconn"
@classmethod
return ver
@classmethod
- def parse_crdb_version(self, sver: str) -> Optional[int]:
+ def parse_crdb_version(self, sver: str) -> int | None:
m = re.search(r"\bv(\d+)\.(\d+)\.(\d+)", sver)
if not m:
return None
from __future__ import annotations
from types import TracebackType
-from typing import Any, Iterator, Iterable, List, Optional, Type
+from typing import Any, Iterator, Iterable, List, Type
from typing import TYPE_CHECKING, overload
from contextlib import contextmanager
): ...
def __init__(
- self,
- connection: Connection[Any],
- *,
- row_factory: Optional[RowFactory[Row]] = None,
+ self, connection: Connection[Any], *, row_factory: RowFactory[Row] | None = None
):
super().__init__(connection)
self._row_factory = row_factory or connection.row_factory
def __exit__(
self,
- exc_type: Optional[Type[BaseException]],
- exc_val: Optional[BaseException],
- exc_tb: Optional[TracebackType],
+ exc_type: Type[BaseException] | None,
+ exc_val: BaseException | None,
+ exc_tb: TracebackType | None,
) -> None:
self.close()
def execute(
self,
query: Query,
- params: Optional[Params] = None,
+ params: Params | None = None,
*,
- prepare: Optional[bool] = None,
- binary: Optional[bool] = None,
+ prepare: bool | None = None,
+ binary: bool | None = None,
) -> Self:
"""
Execute a query or command to the database.
raise ex.with_traceback(None)
def stream(
- self,
- query: Query,
- params: Optional[Params] = None,
- *,
- binary: Optional[bool] = None,
+ self, query: Query, params: Params | None = None, *, binary: bool | None = None
) -> Iterator[Row]:
"""
Iterate row-by-row on a result from the database.
except Exception:
pass
- def fetchone(self) -> Optional[Row]:
+ def fetchone(self) -> Row | None:
"""
Return the next record from the current recordset.
Return `!None` the recordset is finished.
- :rtype: Optional[Row], with Row defined by `row_factory`
+ :rtype: Row | None, with Row defined by `row_factory`
"""
self._fetch_pipeline()
self._check_result_for_fetch()
self._fetch_pipeline()
self._check_result_for_fetch()
- def load(pos: int) -> Optional[Row]:
+ def load(pos: int) -> Row | None:
return self._tx.load_row(pos, self._make_row)
while True:
def copy(
self,
statement: Query,
- params: Optional[Params] = None,
+ params: Params | None = None,
*,
- writer: Optional[Writer] = None,
+ writer: Writer | None = None,
) -> Iterator[Copy]:
"""
Initiate a :sql:`COPY` operation and return an object to manage it.
from __future__ import annotations
from types import TracebackType
-from typing import Any, AsyncIterator, Iterable, List, Optional, Type
+from typing import Any, AsyncIterator, Iterable, List, Type
from typing import TYPE_CHECKING, overload
from contextlib import asynccontextmanager
self,
connection: AsyncConnection[Any],
*,
- row_factory: Optional[AsyncRowFactory[Row]] = None,
+ row_factory: AsyncRowFactory[Row] | None = None,
):
super().__init__(connection)
self._row_factory = row_factory or connection.row_factory
async def __aexit__(
self,
- exc_type: Optional[Type[BaseException]],
- exc_val: Optional[BaseException],
- exc_tb: Optional[TracebackType],
+ exc_type: Type[BaseException] | None,
+ exc_val: BaseException | None,
+ exc_tb: TracebackType | None,
) -> None:
await self.close()
async def execute(
self,
query: Query,
- params: Optional[Params] = None,
+ params: Params | None = None,
*,
- prepare: Optional[bool] = None,
- binary: Optional[bool] = None,
+ prepare: bool | None = None,
+ binary: bool | None = None,
) -> Self:
"""
Execute a query or command to the database.
raise ex.with_traceback(None)
async def stream(
- self,
- query: Query,
- params: Optional[Params] = None,
- *,
- binary: Optional[bool] = None,
+ self, query: Query, params: Params | None = None, *, binary: bool | None = None
) -> AsyncIterator[Row]:
"""
Iterate row-by-row on a result from the database.
except Exception:
pass
- async def fetchone(self) -> Optional[Row]:
+ async def fetchone(self) -> Row | None:
"""
Return the next record from the current recordset.
Return `!None` the recordset is finished.
- :rtype: Optional[Row], with Row defined by `row_factory`
+ :rtype: Row | None, with Row defined by `row_factory`
"""
await self._fetch_pipeline()
self._check_result_for_fetch()
await self._fetch_pipeline()
self._check_result_for_fetch()
- def load(pos: int) -> Optional[Row]:
+ def load(pos: int) -> Row | None:
return self._tx.load_row(pos, self._make_row)
while True:
async def copy(
self,
statement: Query,
- params: Optional[Params] = None,
+ params: Params | None = None,
*,
- writer: Optional[AsyncWriter] = None,
+ writer: AsyncWriter | None = None,
) -> AsyncIterator[AsyncCopy]:
"""
Initiate a :sql:`COPY` operation and return an object to manage it.
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
import time
import datetime as dt
from math import floor
-from typing import Any, Optional, Sequence, Union
+from typing import Any, Sequence, Union
from . import _oids
from .abc import AdaptContext, Buffer
class BinaryBinaryDumper(BytesBinaryDumper):
- def dump(self, obj: Union[Buffer, Binary]) -> Optional[Buffer]:
+ def dump(self, obj: Union[Buffer, Binary]) -> Buffer | None:
if isinstance(obj, Binary):
return super().dump(obj.obj)
else:
class BinaryTextDumper(BytesDumper):
- def dump(self, obj: Union[Buffer, Binary]) -> Optional[Buffer]:
+ def dump(self, obj: Union[Buffer, Binary]) -> Buffer | None:
if isinstance(obj, Binary):
return super().dump(obj.obj)
else:
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
from dataclasses import dataclass, field, fields
-from typing import Any, Callable, Dict, List, NoReturn, Optional, Sequence, Tuple, Type
+from typing import Any, Callable, Dict, List, NoReturn, Sequence, Tuple, Type
from typing import Union, TYPE_CHECKING
from asyncio import CancelledError
if TYPE_CHECKING:
from .pq.misc import PGnotify, ConninfoOption
-ErrorInfo: TypeAlias = Union[None, PGresult, Dict[int, Optional[bytes]]]
+ErrorInfo: TypeAlias = Union[None, PGresult, Dict[int, bytes | None]]
_sqlcodes: Dict[str, "Type[Error]"] = {}
nonblocking: int = 0
- notice_handler: Optional[Callable[["PGresult"], None]] = None
- notify_handler: Optional[Callable[["PGnotify"], None]] = None
+ notice_handler: Callable[["PGresult"], None] | None = None
+ notify_handler: Callable[["PGnotify"], None] | None = None
@staticmethod
def _raise() -> NoReturn:
__module__ = "psycopg"
- sqlstate: Optional[str] = None
+ sqlstate: str | None = None
def __init__(
self,
*args: Sequence[Any],
info: ErrorInfo = None,
encoding: str = "utf-8",
- pgconn: Optional[PGconn] = None,
+ pgconn: PGconn | None = None,
):
super().__init__(*args)
self._info = info
self.sqlstate = self.diag.sqlstate
@property
- def pgconn(self) -> Optional[PGconn]:
+ def pgconn(self) -> PGconn | None:
"""The connection object, if the error was raised from a connection attempt.
- :rtype: Optional[psycopg.pq.PGconn]
+ :rtype: psycopg.pq.PGconn | None
"""
return self._pgconn if self._pgconn else None
@property
- def pgresult(self) -> Optional[PGresult]:
+ def pgresult(self) -> PGresult | None:
"""The result object, if the exception was raised after a failed query.
- :rtype: Optional[psycopg.pq.PGresult]
+ :rtype: psycopg.pq.PGresult | None
"""
return self._info if _is_pgresult(self._info) else None
__module__ = "psycopg"
- def __init_subclass__(cls, code: Optional[str] = None, name: Optional[str] = None):
+ def __init_subclass__(cls, code: str | None = None, name: str | None = None):
if code:
_sqlcodes[code] = cls
cls.sqlstate = code
self._encoding = encoding
@property
- def severity(self) -> Optional[str]:
+ def severity(self) -> str | None:
return self._error_message(DiagnosticField.SEVERITY)
@property
- def severity_nonlocalized(self) -> Optional[str]:
+ def severity_nonlocalized(self) -> str | None:
return self._error_message(DiagnosticField.SEVERITY_NONLOCALIZED)
@property
- def sqlstate(self) -> Optional[str]:
+ def sqlstate(self) -> str | None:
return self._error_message(DiagnosticField.SQLSTATE)
@property
- def message_primary(self) -> Optional[str]:
+ def message_primary(self) -> str | None:
return self._error_message(DiagnosticField.MESSAGE_PRIMARY)
@property
- def message_detail(self) -> Optional[str]:
+ def message_detail(self) -> str | None:
return self._error_message(DiagnosticField.MESSAGE_DETAIL)
@property
- def message_hint(self) -> Optional[str]:
+ def message_hint(self) -> str | None:
return self._error_message(DiagnosticField.MESSAGE_HINT)
@property
- def statement_position(self) -> Optional[str]:
+ def statement_position(self) -> str | None:
return self._error_message(DiagnosticField.STATEMENT_POSITION)
@property
- def internal_position(self) -> Optional[str]:
+ def internal_position(self) -> str | None:
return self._error_message(DiagnosticField.INTERNAL_POSITION)
@property
- def internal_query(self) -> Optional[str]:
+ def internal_query(self) -> str | None:
return self._error_message(DiagnosticField.INTERNAL_QUERY)
@property
- def context(self) -> Optional[str]:
+ def context(self) -> str | None:
return self._error_message(DiagnosticField.CONTEXT)
@property
- def schema_name(self) -> Optional[str]:
+ def schema_name(self) -> str | None:
return self._error_message(DiagnosticField.SCHEMA_NAME)
@property
- def table_name(self) -> Optional[str]:
+ def table_name(self) -> str | None:
return self._error_message(DiagnosticField.TABLE_NAME)
@property
- def column_name(self) -> Optional[str]:
+ def column_name(self) -> str | None:
return self._error_message(DiagnosticField.COLUMN_NAME)
@property
- def datatype_name(self) -> Optional[str]:
+ def datatype_name(self) -> str | None:
return self._error_message(DiagnosticField.DATATYPE_NAME)
@property
- def constraint_name(self) -> Optional[str]:
+ def constraint_name(self) -> str | None:
return self._error_message(DiagnosticField.CONSTRAINT_NAME)
@property
- def source_file(self) -> Optional[str]:
+ def source_file(self) -> str | None:
return self._error_message(DiagnosticField.SOURCE_FILE)
@property
- def source_line(self) -> Optional[str]:
+ def source_line(self) -> str | None:
return self._error_message(DiagnosticField.SOURCE_LINE)
@property
- def source_function(self) -> Optional[str]:
+ def source_function(self) -> str | None:
return self._error_message(DiagnosticField.SOURCE_FUNCTION)
- def _error_message(self, field: DiagnosticField) -> Optional[str]:
+ def _error_message(self, field: DiagnosticField) -> str | None:
if self._info:
if isinstance(self._info, dict):
val = self._info.get(field)
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
import logging
from time import monotonic
-from typing import List, Optional, Union
+from typing import List, Union
from . import pq
from . import errors as e
return results
-def _fetch(pgconn: PGconn) -> PQGen[Optional[PGresult]]:
+def _fetch(pgconn: PGconn) -> PQGen[PGresult | None]:
"""
Generator retrieving a single result from the database without blocking.
break
-def copy_end(pgconn: PGconn, error: Optional[bytes]) -> PQGen[PGresult]:
+def copy_end(pgconn: PGconn, error: bytes | None) -> PQGen[PGresult]:
# Retry enqueuing end copy message until successful
while pgconn.put_copy_end(error) == 0:
while True:
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
import sys
import ctypes
import ctypes.util
if narg is not None:
return "bytes"
else:
- return "Optional[bytes]"
+ return "bytes | None"
elif t.__name__ in (
"LP_PGconn_struct",
"LP_PGcancel_struct",
):
if narg is not None:
- return f"Optional[{t.__name__[3:]}]"
+ return f"{t.__name__[3:]} | None"
else:
return str(t.__name__[3:])
# Copyright (C) 2020 The Psycopg Team
-from typing import Any, Callable, Optional, Sequence
+from typing import Any, Callable, Sequence
from ctypes import Array, pointer, _Pointer
from ctypes import c_char, c_char_p, c_int, c_ubyte, c_uint, c_ulong
typlen: int
atttypmod: int
-def PQhostaddr(arg1: Optional[PGconn_struct]) -> bytes: ...
-def PQerrorMessage(arg1: Optional[PGconn_struct]) -> bytes: ...
-def PQresultErrorMessage(arg1: Optional[PGresult_struct]) -> bytes: ...
+def PQhostaddr(arg1: PGconn_struct | None) -> bytes: ...
+def PQerrorMessage(arg1: PGconn_struct | None) -> bytes: ...
+def PQresultErrorMessage(arg1: PGresult_struct | None) -> bytes: ...
def PQexecPrepared(
- arg1: Optional[PGconn_struct],
+ arg1: PGconn_struct | None,
arg2: bytes,
arg3: int,
- arg4: Optional[Array[c_char_p]],
- arg5: Optional[Array[c_int]],
- arg6: Optional[Array[c_int]],
+ arg4: Array[c_char_p] | None,
+ arg5: Array[c_int] | None,
+ arg6: Array[c_int] | None,
arg7: int,
) -> PGresult_struct: ...
def PQprepare(
- arg1: Optional[PGconn_struct],
+ arg1: PGconn_struct | None,
arg2: bytes,
arg3: bytes,
arg4: int,
- arg5: Optional[Array[c_uint]],
+ arg5: Array[c_uint] | None,
) -> PGresult_struct: ...
def PQgetvalue(
- arg1: Optional[PGresult_struct], arg2: int, arg3: int
+ arg1: PGresult_struct | None, arg2: int, arg3: int
) -> _Pointer[c_char]: ...
-def PQcmdTuples(arg1: Optional[PGresult_struct]) -> bytes: ...
+def PQcmdTuples(arg1: PGresult_struct | None) -> bytes: ...
def PQescapeStringConn(
- arg1: Optional[PGconn_struct],
+ arg1: PGconn_struct | None,
arg2: c_char_p,
arg3: bytes,
arg4: int,
) -> int: ...
def PQescapeString(arg1: c_char_p, arg2: bytes, arg3: int) -> int: ...
def PQsendPrepare(
- arg1: Optional[PGconn_struct],
+ arg1: PGconn_struct | None,
arg2: bytes,
arg3: bytes,
arg4: int,
- arg5: Optional[Array[c_uint]],
+ arg5: Array[c_uint] | None,
) -> int: ...
def PQsendQueryPrepared(
- arg1: Optional[PGconn_struct],
+ arg1: PGconn_struct | None,
arg2: bytes,
arg3: int,
- arg4: Optional[Array[c_char_p]],
- arg5: Optional[Array[c_int]],
- arg6: Optional[Array[c_int]],
+ arg4: Array[c_char_p] | None,
+ arg5: Array[c_int] | None,
+ arg6: Array[c_int] | None,
arg7: int,
) -> int: ...
-def PQcancelCreate(arg1: Optional[PGconn_struct]) -> PGcancelConn_struct: ...
-def PQcancelBlocking(arg1: Optional[PGcancelConn_struct]) -> int: ...
-def PQcancelStart(arg1: Optional[PGcancelConn_struct]) -> int: ...
-def PQcancelPoll(arg1: Optional[PGcancelConn_struct]) -> int: ...
-def PQcancelStatus(arg1: Optional[PGcancelConn_struct]) -> int: ...
-def PQcancelSocket(arg1: Optional[PGcancelConn_struct]) -> int: ...
-def PQcancelErrorMessage(arg1: Optional[PGcancelConn_struct]) -> bytes: ...
-def PQcancelReset(arg1: Optional[PGcancelConn_struct]) -> None: ...
-def PQcancelFinish(arg1: Optional[PGcancelConn_struct]) -> None: ...
-def PQcancel(arg1: Optional[PGcancel_struct], arg2: c_char_p, arg3: int) -> int: ...
+def PQcancelCreate(arg1: PGconn_struct | None) -> PGcancelConn_struct: ...
+def PQcancelBlocking(arg1: PGcancelConn_struct | None) -> int: ...
+def PQcancelStart(arg1: PGcancelConn_struct | None) -> int: ...
+def PQcancelPoll(arg1: PGcancelConn_struct | None) -> int: ...
+def PQcancelStatus(arg1: PGcancelConn_struct | None) -> int: ...
+def PQcancelSocket(arg1: PGcancelConn_struct | None) -> int: ...
+def PQcancelErrorMessage(arg1: PGcancelConn_struct | None) -> bytes: ...
+def PQcancelReset(arg1: PGcancelConn_struct | None) -> None: ...
+def PQcancelFinish(arg1: PGcancelConn_struct | None) -> None: ...
+def PQcancel(arg1: PGcancel_struct | None, arg2: c_char_p, arg3: int) -> int: ...
def PQsetNoticeReceiver(
arg1: PGconn_struct, arg2: Callable[[Any], PGresult_struct], arg3: Any
) -> Callable[[Any], PGresult_struct]: ...
# Type argument "psycopg.pq._pq_ctypes.PGnotify_struct" of "pointer" must be
# a subtype of "ctypes._CData"
def PQnotifies(
- arg1: Optional[PGconn_struct],
-) -> Optional[_Pointer[PGnotify_struct]]: ... # type: ignore
-def PQputCopyEnd(arg1: Optional[PGconn_struct], arg2: Optional[bytes]) -> int: ...
+ arg1: PGconn_struct | None,
+) -> _Pointer[PGnotify_struct] | None: ... # type: ignore
+def PQputCopyEnd(arg1: PGconn_struct | None, arg2: bytes | None) -> int: ...
# Arg 2 is a _Pointer, reported as _CArgObject by mypy
-def PQgetCopyData(arg1: Optional[PGconn_struct], arg2: Any, arg3: int) -> int: ...
+def PQgetCopyData(arg1: PGconn_struct | None, arg2: Any, arg3: int) -> int: ...
def PQsetResultAttrs(
- arg1: Optional[PGresult_struct],
+ arg1: PGresult_struct | None,
arg2: int,
arg3: Array[PGresAttDesc_struct], # type: ignore
) -> int: ...
def PQtrace(
- arg1: Optional[PGconn_struct],
+ arg1: PGconn_struct | None,
arg2: _Pointer[FILE], # type: ignore[type-var]
) -> None: ...
-def PQsetTraceFlags(arg1: Optional[PGconn_struct], arg2: int) -> None: ...
+def PQsetTraceFlags(arg1: PGconn_struct | None, arg2: int) -> None: ...
def PQencryptPasswordConn(
- arg1: Optional[PGconn_struct],
+ arg1: PGconn_struct | None,
arg2: bytes,
arg3: bytes,
- arg4: Optional[bytes],
+ arg4: bytes | None,
) -> bytes: ...
-def PQpipelineStatus(pgconn: Optional[PGconn_struct]) -> int: ...
-def PQenterPipelineMode(pgconn: Optional[PGconn_struct]) -> int: ...
-def PQexitPipelineMode(pgconn: Optional[PGconn_struct]) -> int: ...
-def PQpipelineSync(pgconn: Optional[PGconn_struct]) -> int: ...
-def PQsendFlushRequest(pgconn: Optional[PGconn_struct]) -> int: ...
+def PQpipelineStatus(pgconn: PGconn_struct | None) -> int: ...
+def PQenterPipelineMode(pgconn: PGconn_struct | None) -> int: ...
+def PQexitPipelineMode(pgconn: PGconn_struct | None) -> int: ...
+def PQpipelineSync(pgconn: PGconn_struct | None) -> int: ...
+def PQsendFlushRequest(pgconn: PGconn_struct | None) -> int: ...
+
+# Autogenerated section.
+# In order to refresh, run:
+# python -m psycopg.pq._pq_ctypes
# fmt: off
# autogenerated: start
def PQlibVersion() -> int: ...
def PQconnectdb(arg1: bytes) -> PGconn_struct: ...
def PQconnectStart(arg1: bytes) -> PGconn_struct: ...
-def PQconnectPoll(arg1: Optional[PGconn_struct]) -> int: ...
+def PQconnectPoll(arg1: PGconn_struct | None) -> int: ...
def PQconndefaults() -> Sequence[PQconninfoOption_struct]: ...
def PQconninfoFree(arg1: Sequence[PQconninfoOption_struct]) -> None: ...
-def PQconninfo(arg1: Optional[PGconn_struct]) -> Sequence[PQconninfoOption_struct]: ...
+def PQconninfo(arg1: PGconn_struct | None) -> Sequence[PQconninfoOption_struct]: ...
def PQconninfoParse(arg1: bytes, arg2: _Pointer[c_char_p]) -> Sequence[PQconninfoOption_struct]: ...
-def PQfinish(arg1: Optional[PGconn_struct]) -> None: ...
-def PQreset(arg1: Optional[PGconn_struct]) -> None: ...
-def PQresetStart(arg1: Optional[PGconn_struct]) -> int: ...
-def PQresetPoll(arg1: Optional[PGconn_struct]) -> int: ...
+def PQfinish(arg1: PGconn_struct | None) -> None: ...
+def PQreset(arg1: PGconn_struct | None) -> None: ...
+def PQresetStart(arg1: PGconn_struct | None) -> int: ...
+def PQresetPoll(arg1: PGconn_struct | None) -> int: ...
def PQping(arg1: bytes) -> int: ...
-def PQdb(arg1: Optional[PGconn_struct]) -> Optional[bytes]: ...
-def PQuser(arg1: Optional[PGconn_struct]) -> Optional[bytes]: ...
-def PQpass(arg1: Optional[PGconn_struct]) -> Optional[bytes]: ...
-def PQhost(arg1: Optional[PGconn_struct]) -> Optional[bytes]: ...
-def PQport(arg1: Optional[PGconn_struct]) -> Optional[bytes]: ...
-def PQtty(arg1: Optional[PGconn_struct]) -> Optional[bytes]: ...
-def PQoptions(arg1: Optional[PGconn_struct]) -> Optional[bytes]: ...
-def PQstatus(arg1: Optional[PGconn_struct]) -> int: ...
-def PQtransactionStatus(arg1: Optional[PGconn_struct]) -> int: ...
-def PQparameterStatus(arg1: Optional[PGconn_struct], arg2: bytes) -> Optional[bytes]: ...
-def PQprotocolVersion(arg1: Optional[PGconn_struct]) -> int: ...
-def PQserverVersion(arg1: Optional[PGconn_struct]) -> int: ...
-def PQsocket(arg1: Optional[PGconn_struct]) -> int: ...
-def PQbackendPID(arg1: Optional[PGconn_struct]) -> int: ...
-def PQconnectionNeedsPassword(arg1: Optional[PGconn_struct]) -> int: ...
-def PQconnectionUsedPassword(arg1: Optional[PGconn_struct]) -> int: ...
-def PQsslInUse(arg1: Optional[PGconn_struct]) -> int: ...
-def PQexec(arg1: Optional[PGconn_struct], arg2: bytes) -> PGresult_struct: ...
-def PQexecParams(arg1: Optional[PGconn_struct], arg2: bytes, arg3: int, arg4: _Pointer[c_uint], arg5: _Pointer[c_char_p], arg6: _Pointer[c_int], arg7: _Pointer[c_int], arg8: int) -> PGresult_struct: ...
-def PQdescribePrepared(arg1: Optional[PGconn_struct], arg2: bytes) -> PGresult_struct: ...
-def PQdescribePortal(arg1: Optional[PGconn_struct], arg2: bytes) -> PGresult_struct: ...
-def PQclosePrepared(arg1: Optional[PGconn_struct], arg2: bytes) -> PGresult_struct: ...
-def PQclosePortal(arg1: Optional[PGconn_struct], arg2: bytes) -> PGresult_struct: ...
-def PQresultStatus(arg1: Optional[PGresult_struct]) -> int: ...
-def PQresultErrorField(arg1: Optional[PGresult_struct], arg2: int) -> Optional[bytes]: ...
-def PQclear(arg1: Optional[PGresult_struct]) -> None: ...
-def PQntuples(arg1: Optional[PGresult_struct]) -> int: ...
-def PQnfields(arg1: Optional[PGresult_struct]) -> int: ...
-def PQfname(arg1: Optional[PGresult_struct], arg2: int) -> Optional[bytes]: ...
-def PQftable(arg1: Optional[PGresult_struct], arg2: int) -> int: ...
-def PQftablecol(arg1: Optional[PGresult_struct], arg2: int) -> int: ...
-def PQfformat(arg1: Optional[PGresult_struct], arg2: int) -> int: ...
-def PQftype(arg1: Optional[PGresult_struct], arg2: int) -> int: ...
-def PQfmod(arg1: Optional[PGresult_struct], arg2: int) -> int: ...
-def PQfsize(arg1: Optional[PGresult_struct], arg2: int) -> int: ...
-def PQbinaryTuples(arg1: Optional[PGresult_struct]) -> int: ...
-def PQgetisnull(arg1: Optional[PGresult_struct], arg2: int, arg3: int) -> int: ...
-def PQgetlength(arg1: Optional[PGresult_struct], arg2: int, arg3: int) -> int: ...
-def PQnparams(arg1: Optional[PGresult_struct]) -> int: ...
-def PQparamtype(arg1: Optional[PGresult_struct], arg2: int) -> int: ...
-def PQcmdStatus(arg1: Optional[PGresult_struct]) -> Optional[bytes]: ...
-def PQoidValue(arg1: Optional[PGresult_struct]) -> int: ...
-def PQescapeLiteral(arg1: Optional[PGconn_struct], arg2: bytes, arg3: int) -> Optional[bytes]: ...
-def PQescapeIdentifier(arg1: Optional[PGconn_struct], arg2: bytes, arg3: int) -> Optional[bytes]: ...
-def PQescapeByteaConn(arg1: Optional[PGconn_struct], arg2: bytes, arg3: int, arg4: _Pointer[c_ulong]) -> _Pointer[c_ubyte]: ...
+def PQdb(arg1: PGconn_struct | None) -> bytes | None: ...
+def PQuser(arg1: PGconn_struct | None) -> bytes | None: ...
+def PQpass(arg1: PGconn_struct | None) -> bytes | None: ...
+def PQhost(arg1: PGconn_struct | None) -> bytes | None: ...
+def PQport(arg1: PGconn_struct | None) -> bytes | None: ...
+def PQtty(arg1: PGconn_struct | None) -> bytes | None: ...
+def PQoptions(arg1: PGconn_struct | None) -> bytes | None: ...
+def PQstatus(arg1: PGconn_struct | None) -> int: ...
+def PQtransactionStatus(arg1: PGconn_struct | None) -> int: ...
+def PQparameterStatus(arg1: PGconn_struct | None, arg2: bytes) -> bytes | None: ...
+def PQprotocolVersion(arg1: PGconn_struct | None) -> int: ...
+def PQserverVersion(arg1: PGconn_struct | None) -> int: ...
+def PQsocket(arg1: PGconn_struct | None) -> int: ...
+def PQbackendPID(arg1: PGconn_struct | None) -> int: ...
+def PQconnectionNeedsPassword(arg1: PGconn_struct | None) -> int: ...
+def PQconnectionUsedPassword(arg1: PGconn_struct | None) -> int: ...
+def PQsslInUse(arg1: PGconn_struct | None) -> int: ...
+def PQexec(arg1: PGconn_struct | None, arg2: bytes) -> PGresult_struct: ...
+def PQexecParams(arg1: PGconn_struct | None, arg2: bytes, arg3: int, arg4: _Pointer[c_uint], arg5: _Pointer[c_char_p], arg6: _Pointer[c_int], arg7: _Pointer[c_int], arg8: int) -> PGresult_struct: ...
+def PQdescribePrepared(arg1: PGconn_struct | None, arg2: bytes) -> PGresult_struct: ...
+def PQdescribePortal(arg1: PGconn_struct | None, arg2: bytes) -> PGresult_struct: ...
+def PQclosePrepared(arg1: PGconn_struct | None, arg2: bytes) -> PGresult_struct: ...
+def PQclosePortal(arg1: PGconn_struct | None, arg2: bytes) -> PGresult_struct: ...
+def PQresultStatus(arg1: PGresult_struct | None) -> int: ...
+def PQresultErrorField(arg1: PGresult_struct | None, arg2: int) -> bytes | None: ...
+def PQclear(arg1: PGresult_struct | None) -> None: ...
+def PQntuples(arg1: PGresult_struct | None) -> int: ...
+def PQnfields(arg1: PGresult_struct | None) -> int: ...
+def PQfname(arg1: PGresult_struct | None, arg2: int) -> bytes | None: ...
+def PQftable(arg1: PGresult_struct | None, arg2: int) -> int: ...
+def PQftablecol(arg1: PGresult_struct | None, arg2: int) -> int: ...
+def PQfformat(arg1: PGresult_struct | None, arg2: int) -> int: ...
+def PQftype(arg1: PGresult_struct | None, arg2: int) -> int: ...
+def PQfmod(arg1: PGresult_struct | None, arg2: int) -> int: ...
+def PQfsize(arg1: PGresult_struct | None, arg2: int) -> int: ...
+def PQbinaryTuples(arg1: PGresult_struct | None) -> int: ...
+def PQgetisnull(arg1: PGresult_struct | None, arg2: int, arg3: int) -> int: ...
+def PQgetlength(arg1: PGresult_struct | None, arg2: int, arg3: int) -> int: ...
+def PQnparams(arg1: PGresult_struct | None) -> int: ...
+def PQparamtype(arg1: PGresult_struct | None, arg2: int) -> int: ...
+def PQcmdStatus(arg1: PGresult_struct | None) -> bytes | None: ...
+def PQoidValue(arg1: PGresult_struct | None) -> int: ...
+def PQescapeLiteral(arg1: PGconn_struct | None, arg2: bytes, arg3: int) -> bytes | None: ...
+def PQescapeIdentifier(arg1: PGconn_struct | None, arg2: bytes, arg3: int) -> bytes | None: ...
+def PQescapeByteaConn(arg1: PGconn_struct | None, arg2: bytes, arg3: int, arg4: _Pointer[c_ulong]) -> _Pointer[c_ubyte]: ...
def PQescapeBytea(arg1: bytes, arg2: int, arg3: _Pointer[c_ulong]) -> _Pointer[c_ubyte]: ...
def PQunescapeBytea(arg1: bytes, arg2: _Pointer[c_ulong]) -> _Pointer[c_ubyte]: ...
-def PQsendQuery(arg1: Optional[PGconn_struct], arg2: bytes) -> int: ...
-def PQsendQueryParams(arg1: Optional[PGconn_struct], arg2: bytes, arg3: int, arg4: _Pointer[c_uint], arg5: _Pointer[c_char_p], arg6: _Pointer[c_int], arg7: _Pointer[c_int], arg8: int) -> int: ...
-def PQsendDescribePrepared(arg1: Optional[PGconn_struct], arg2: bytes) -> int: ...
-def PQsendDescribePortal(arg1: Optional[PGconn_struct], arg2: bytes) -> int: ...
-def PQsendClosePrepared(arg1: Optional[PGconn_struct], arg2: bytes) -> int: ...
-def PQsendClosePortal(arg1: Optional[PGconn_struct], arg2: bytes) -> int: ...
-def PQgetResult(arg1: Optional[PGconn_struct]) -> PGresult_struct: ...
-def PQconsumeInput(arg1: Optional[PGconn_struct]) -> int: ...
-def PQisBusy(arg1: Optional[PGconn_struct]) -> int: ...
-def PQsetnonblocking(arg1: Optional[PGconn_struct], arg2: int) -> int: ...
-def PQisnonblocking(arg1: Optional[PGconn_struct]) -> int: ...
-def PQflush(arg1: Optional[PGconn_struct]) -> int: ...
-def PQsetSingleRowMode(arg1: Optional[PGconn_struct]) -> int: ...
-def PQsetChunkedRowsMode(arg1: Optional[PGconn_struct], arg2: int) -> int: ...
-def PQgetCancel(arg1: Optional[PGconn_struct]) -> PGcancel_struct: ...
-def PQfreeCancel(arg1: Optional[PGcancel_struct]) -> None: ...
-def PQputCopyData(arg1: Optional[PGconn_struct], arg2: bytes, arg3: int) -> int: ...
-def PQuntrace(arg1: Optional[PGconn_struct]) -> None: ...
+def PQsendQuery(arg1: PGconn_struct | None, arg2: bytes) -> int: ...
+def PQsendQueryParams(arg1: PGconn_struct | None, arg2: bytes, arg3: int, arg4: _Pointer[c_uint], arg5: _Pointer[c_char_p], arg6: _Pointer[c_int], arg7: _Pointer[c_int], arg8: int) -> int: ...
+def PQsendDescribePrepared(arg1: PGconn_struct | None, arg2: bytes) -> int: ...
+def PQsendDescribePortal(arg1: PGconn_struct | None, arg2: bytes) -> int: ...
+def PQsendClosePrepared(arg1: PGconn_struct | None, arg2: bytes) -> int: ...
+def PQsendClosePortal(arg1: PGconn_struct | None, arg2: bytes) -> int: ...
+def PQgetResult(arg1: PGconn_struct | None) -> PGresult_struct: ...
+def PQconsumeInput(arg1: PGconn_struct | None) -> int: ...
+def PQisBusy(arg1: PGconn_struct | None) -> int: ...
+def PQsetnonblocking(arg1: PGconn_struct | None, arg2: int) -> int: ...
+def PQisnonblocking(arg1: PGconn_struct | None) -> int: ...
+def PQflush(arg1: PGconn_struct | None) -> int: ...
+def PQsetSingleRowMode(arg1: PGconn_struct | None) -> int: ...
+def PQsetChunkedRowsMode(arg1: PGconn_struct | None, arg2: int) -> int: ...
+def PQgetCancel(arg1: PGconn_struct | None) -> PGcancel_struct: ...
+def PQfreeCancel(arg1: PGcancel_struct | None) -> None: ...
+def PQputCopyData(arg1: PGconn_struct | None, arg2: bytes, arg3: int) -> int: ...
+def PQuntrace(arg1: PGconn_struct | None) -> None: ...
def PQfreemem(arg1: Any) -> None: ...
-def PQchangePassword(arg1: Optional[PGconn_struct], arg2: bytes, arg3: bytes) -> PGresult_struct: ...
-def PQmakeEmptyPGresult(arg1: Optional[PGconn_struct], arg2: int) -> PGresult_struct: ...
+def PQchangePassword(arg1: PGconn_struct | None, arg2: bytes, arg3: bytes) -> PGresult_struct: ...
+def PQmakeEmptyPGresult(arg1: PGconn_struct | None, arg2: int) -> PGresult_struct: ...
def PQinitOpenSSL(arg1: int, arg2: int) -> None: ...
# autogenerated: end
# fmt: on
# Copyright (C) 2020 The Psycopg Team
-from typing import Any, Callable, List, Optional, Protocol, Sequence, Tuple
+from __future__ import annotations
+
+from typing import Any, Callable, List, Protocol, Sequence, Tuple
from typing import Union, TYPE_CHECKING
from ._enums import Format, Trace
class PGconn(Protocol):
- notice_handler: Optional[Callable[["PGresult"], None]]
- notify_handler: Optional[Callable[["PGnotify"], None]]
+ notice_handler: Callable[["PGresult"], None] | None
+ notify_handler: Callable[["PGnotify"], None] | None
@classmethod
def connect(cls, conninfo: bytes) -> "PGconn": ...
@property
def transaction_status(self) -> int: ...
- def parameter_status(self, name: bytes) -> Optional[bytes]: ...
+ def parameter_status(self, name: bytes) -> bytes | None: ...
@property
def error_message(self) -> bytes: ...
def exec_params(
self,
command: bytes,
- param_values: Optional[Sequence[Optional[Buffer]]],
- param_types: Optional[Sequence[int]] = None,
- param_formats: Optional[Sequence[int]] = None,
+ param_values: Sequence[Buffer | None] | None,
+ param_types: Sequence[int] | None = None,
+ param_formats: Sequence[int] | None = None,
result_format: int = Format.TEXT,
) -> "PGresult": ...
def send_query_params(
self,
command: bytes,
- param_values: Optional[Sequence[Optional[Buffer]]],
- param_types: Optional[Sequence[int]] = None,
- param_formats: Optional[Sequence[int]] = None,
+ param_values: Sequence[Buffer | None] | None,
+ param_types: Sequence[int] | None = None,
+ param_formats: Sequence[int] | None = None,
result_format: int = Format.TEXT,
) -> None: ...
self,
name: bytes,
command: bytes,
- param_types: Optional[Sequence[int]] = None,
+ param_types: Sequence[int] | None = None,
) -> None: ...
def send_query_prepared(
self,
name: bytes,
- param_values: Optional[Sequence[Optional[Buffer]]],
- param_formats: Optional[Sequence[int]] = None,
+ param_values: Sequence[Buffer | None] | None,
+ param_formats: Sequence[int] | None = None,
result_format: int = Format.TEXT,
) -> None: ...
self,
name: bytes,
command: bytes,
- param_types: Optional[Sequence[int]] = None,
+ param_types: Sequence[int] | None = None,
) -> "PGresult": ...
def exec_prepared(
self,
name: bytes,
- param_values: Optional[Sequence[Buffer]],
- param_formats: Optional[Sequence[int]] = None,
+ param_values: Sequence[Buffer] | None,
+ param_formats: Sequence[int] | None = None,
result_format: int = 0,
) -> "PGresult": ...
def send_close_portal(self, name: bytes) -> None: ...
- def get_result(self) -> Optional["PGresult"]: ...
+ def get_result(self) -> "PGresult" | None: ...
def consume_input(self) -> None: ...
def get_cancel(self) -> "PGcancel": ...
- def notifies(self) -> Optional["PGnotify"]: ...
+ def notifies(self) -> "PGnotify" | None: ...
def put_copy_data(self, buffer: Buffer) -> int: ...
- def put_copy_end(self, error: Optional[bytes] = None) -> int: ...
+ def put_copy_end(self, error: bytes | None = None) -> int: ...
def get_copy_data(self, async_: int) -> Tuple[int, memoryview]: ...
def untrace(self) -> None: ...
def encrypt_password(
- self, passwd: bytes, user: bytes, algorithm: Optional[bytes] = None
+ self, passwd: bytes, user: bytes, algorithm: bytes | None = None
) -> bytes: ...
def change_password(self, user: bytes, passwd: bytes) -> None: ...
@property
def error_message(self) -> bytes: ...
- def error_field(self, fieldcode: int) -> Optional[bytes]: ...
+ def error_field(self, fieldcode: int) -> bytes | None: ...
@property
def ntuples(self) -> int: ...
@property
def nfields(self) -> int: ...
- def fname(self, column_number: int) -> Optional[bytes]: ...
+ def fname(self, column_number: int) -> bytes | None: ...
def ftable(self, column_number: int) -> int: ...
@property
def binary_tuples(self) -> int: ...
- def get_value(self, row_number: int, column_number: int) -> Optional[bytes]: ...
+ def get_value(self, row_number: int, column_number: int) -> bytes | None: ...
@property
def nparams(self) -> int: ...
def param_type(self, param_number: int) -> int: ...
@property
- def command_status(self) -> Optional[bytes]: ...
+ def command_status(self) -> bytes | None: ...
@property
- def command_tuples(self) -> Optional[int]: ...
+ def command_tuples(self) -> int | None: ...
@property
def oid_value(self) -> int: ...
class Escaping(Protocol):
- def __init__(self, conn: Optional[PGconn] = None): ...
+ def __init__(self, conn: PGconn | None = None): ...
def escape_literal(self, data: Buffer) -> bytes: ...
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
import re
import os
import sys
import logging
import ctypes.util
-from typing import cast, NamedTuple, Optional, Union
+from typing import cast, NamedTuple, Union
from .abc import PGconn, PGresult
from ._enums import ConnStatus, TransactionStatus, PipelineStatus
class ConninfoOption(NamedTuple):
keyword: bytes
- envvar: Optional[bytes]
- compiled: Optional[bytes]
- val: Optional[bytes]
+ envvar: bytes | None
+ compiled: bytes | None
+ val: bytes | None
label: bytes
dispchar: bytes
dispsize: int
@cache
-def find_libpq_full_path() -> Optional[str]:
+def find_libpq_full_path() -> str | None:
if sys.platform == "win32":
libname = ctypes.util.find_library("libpq.dll")
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
import sys
import logging
from os import getpid
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, Optional, Sequence, Tuple
+from typing import Any, Callable, List, Sequence, Tuple
from typing import cast as t_cast, TYPE_CHECKING
from .. import errors as e
)
def __init__(self, pgconn_ptr: impl.PGconn_struct):
- self._pgconn_ptr: Optional[impl.PGconn_struct] = pgconn_ptr
- self.notice_handler: Optional[Callable[["abc.PGresult"], None]] = None
- self.notify_handler: Optional[Callable[[PGnotify], None]] = None
+ self._pgconn_ptr: impl.PGconn_struct | None = pgconn_ptr
+ self.notice_handler: Callable[["abc.PGresult"], None] | None = None
+ self.notify_handler: Callable[[PGnotify], None] | None = None
# Keep alive for the lifetime of PGconn
self._self_ptr = py_object(ref(self))
PQfinish(p)
@property
- def pgconn_ptr(self) -> Optional[int]:
+ def pgconn_ptr(self) -> int | None:
"""The pointer to the underlying `!PGconn` structure, as integer.
`!None` if the connection is closed.
def transaction_status(self) -> int:
return impl.PQtransactionStatus(self._pgconn_ptr)
- def parameter_status(self, name: bytes) -> Optional[bytes]:
+ def parameter_status(self, name: bytes) -> bytes | None:
self._ensure_pgconn()
return impl.PQparameterStatus(self._pgconn_ptr, name)
def exec_params(
self,
command: bytes,
- param_values: Optional[Sequence[Optional["abc.Buffer"]]],
- param_types: Optional[Sequence[int]] = None,
- param_formats: Optional[Sequence[int]] = None,
+ param_values: Sequence["abc.Buffer" | None] | None,
+ param_types: Sequence[int] | None = None,
+ param_formats: Sequence[int] | None = None,
result_format: int = Format.TEXT,
) -> "PGresult":
args = self._query_params_args(
def send_query_params(
self,
command: bytes,
- param_values: Optional[Sequence[Optional["abc.Buffer"]]],
- param_types: Optional[Sequence[int]] = None,
- param_formats: Optional[Sequence[int]] = None,
+ param_values: Sequence["abc.Buffer" | None] | None,
+ param_types: Sequence[int] | None = None,
+ param_formats: Sequence[int] | None = None,
result_format: int = Format.TEXT,
) -> None:
args = self._query_params_args(
self,
name: bytes,
command: bytes,
- param_types: Optional[Sequence[int]] = None,
+ param_types: Sequence[int] | None = None,
) -> None:
- atypes: Optional[Array[impl.Oid]]
+ atypes: Array[impl.Oid] | None
if not param_types:
nparams = 0
atypes = None
def send_query_prepared(
self,
name: bytes,
- param_values: Optional[Sequence[Optional["abc.Buffer"]]],
- param_formats: Optional[Sequence[int]] = None,
+ param_values: Sequence["abc.Buffer" | None] | None,
+ param_formats: Sequence[int] | None = None,
result_format: int = Format.TEXT,
) -> None:
# repurpose this function with a cheeky replacement of query with name,
def _query_params_args(
self,
command: bytes,
- param_values: Optional[Sequence[Optional["abc.Buffer"]]],
- param_types: Optional[Sequence[int]] = None,
- param_formats: Optional[Sequence[int]] = None,
+ param_values: Sequence["abc.Buffer" | None] | None,
+ param_types: Sequence[int] | None = None,
+ param_formats: Sequence[int] | None = None,
result_format: int = Format.TEXT,
) -> Any:
if not isinstance(command, bytes):
raise TypeError(f"bytes expected, got {type(command)} instead")
- aparams: Optional[Array[c_char_p]]
- alenghts: Optional[Array[c_int]]
+ aparams: Array[c_char_p] | None
+ alenghts: Array[c_int] | None
if param_values:
nparams = len(param_values)
aparams = (c_char_p * nparams)(
nparams = 0
aparams = alenghts = None
- atypes: Optional[Array[impl.Oid]]
+ atypes: Array[impl.Oid] | None
if not param_types:
atypes = None
else:
self,
name: bytes,
command: bytes,
- param_types: Optional[Sequence[int]] = None,
+ param_types: Sequence[int] | None = None,
) -> "PGresult":
if not isinstance(name, bytes):
raise TypeError(f"'name' must be bytes, got {type(name)} instead")
def exec_prepared(
self,
name: bytes,
- param_values: Optional[Sequence["abc.Buffer"]],
- param_formats: Optional[Sequence[int]] = None,
+ param_values: Sequence["abc.Buffer"] | None,
+ param_formats: Sequence[int] | None = None,
result_format: int = 0,
) -> "PGresult":
if not isinstance(name, bytes):
raise TypeError(f"'name' must be bytes, got {type(name)} instead")
- aparams: Optional[Array[c_char_p]]
- alenghts: Optional[Array[c_int]]
+ aparams: Array[c_char_p] | None
+ alenghts: Array[c_int] | None
if param_values:
nparams = len(param_values)
aparams = (c_char_p * nparams)(
f"sending close portal failed: {error_message(self)}"
)
- def get_result(self) -> Optional["PGresult"]:
+ def get_result(self) -> "PGresult" | None:
rv = impl.PQgetResult(self._pgconn_ptr)
return PGresult(rv) if rv else None
raise e.OperationalError("couldn't create cancel object")
return PGcancel(rv)
- def notifies(self) -> Optional[PGnotify]:
+ def notifies(self) -> PGnotify | None:
ptr = impl.PQnotifies(self._pgconn_ptr)
if ptr:
c = ptr.contents
raise e.OperationalError(f"sending copy data failed: {error_message(self)}")
return rv
- def put_copy_end(self, error: Optional[bytes] = None) -> int:
+ def put_copy_end(self, error: bytes | None = None) -> int:
rv = impl.PQputCopyEnd(self._pgconn_ptr, error)
if rv < 0:
raise e.OperationalError(f"sending copy end failed: {error_message(self)}")
impl.PQuntrace(self._pgconn_ptr)
def encrypt_password(
- self, passwd: bytes, user: bytes, algorithm: Optional[bytes] = None
+ self, passwd: bytes, user: bytes, algorithm: bytes | None = None
) -> bytes:
"""
Return the encrypted form of a PostgreSQL password.
if impl.PQsendFlushRequest(self._pgconn_ptr) == 0:
raise e.OperationalError(f"flush request failed: {error_message(self)}")
- def _call_bytes(
- self, func: Callable[[impl.PGconn_struct], Optional[bytes]]
- ) -> bytes:
+ def _call_bytes(self, func: Callable[[impl.PGconn_struct], bytes | None]) -> bytes:
"""
Call one of the pgconn libpq functions returning a bytes pointer.
"""
__slots__ = ("_pgresult_ptr",)
def __init__(self, pgresult_ptr: impl.PGresult_struct):
- self._pgresult_ptr: Optional[impl.PGresult_struct] = pgresult_ptr
+ self._pgresult_ptr: impl.PGresult_struct | None = pgresult_ptr
def __del__(self) -> None:
self.clear()
PQclear(p)
@property
- def pgresult_ptr(self) -> Optional[int]:
+ def pgresult_ptr(self) -> int | None:
"""The pointer to the underlying `!PGresult` structure, as integer.
`!None` if the result was cleared.
def error_message(self) -> bytes:
return impl.PQresultErrorMessage(self._pgresult_ptr)
- def error_field(self, fieldcode: int) -> Optional[bytes]:
+ def error_field(self, fieldcode: int) -> bytes | None:
return impl.PQresultErrorField(self._pgresult_ptr, fieldcode)
@property
def nfields(self) -> int:
return impl.PQnfields(self._pgresult_ptr)
- def fname(self, column_number: int) -> Optional[bytes]:
+ def fname(self, column_number: int) -> bytes | None:
return impl.PQfname(self._pgresult_ptr, column_number)
def ftable(self, column_number: int) -> int:
def binary_tuples(self) -> int:
return impl.PQbinaryTuples(self._pgresult_ptr)
- def get_value(self, row_number: int, column_number: int) -> Optional[bytes]:
+ def get_value(self, row_number: int, column_number: int) -> bytes | None:
length: int = impl.PQgetlength(self._pgresult_ptr, row_number, column_number)
if length:
v = impl.PQgetvalue(self._pgresult_ptr, row_number, column_number)
return impl.PQparamtype(self._pgresult_ptr, param_number)
@property
- def command_status(self) -> Optional[bytes]:
+ def command_status(self) -> bytes | None:
return impl.PQcmdStatus(self._pgresult_ptr)
@property
- def command_tuples(self) -> Optional[int]:
+ def command_tuples(self) -> int | None:
rv = impl.PQcmdTuples(self._pgresult_ptr)
return int(rv) if rv else None
__slots__ = ("pgcancelconn_ptr",)
def __init__(self, pgcancelconn_ptr: impl.PGcancelConn_struct):
- self.pgcancelconn_ptr: Optional[impl.PGcancelConn_struct] = pgcancelconn_ptr
+ self.pgcancelconn_ptr: impl.PGcancelConn_struct | None = pgcancelconn_ptr
def __del__(self) -> None:
self.finish()
__slots__ = ("pgcancel_ptr",)
def __init__(self, pgcancel_ptr: impl.PGcancel_struct):
- self.pgcancel_ptr: Optional[impl.PGcancel_struct] = pgcancel_ptr
+ self.pgcancel_ptr: impl.PGcancel_struct | None = pgcancel_ptr
def __del__(self) -> None:
self.free()
Utility object to escape strings for SQL interpolation.
"""
- def __init__(self, conn: Optional[PGconn] = None):
+ def __init__(self, conn: PGconn | None = None):
self.conn = conn
def escape_literal(self, data: "abc.Buffer") -> bytes:
# Copyright (C) 2023 The Psycopg Team
-from typing import Optional, TYPE_CHECKING
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
from .abc import ConnectionType, Query, Params
from .sql import Composable
class PostgresRawQuery(PostgresQuery):
- def convert(self, query: Query, vars: Optional[Params]) -> None:
+ def convert(self, query: Query, vars: Params | None) -> None:
if isinstance(query, str):
bquery = query.encode(self._encoding)
elif isinstance(query, Composable):
self._want_formats = self._order = None
self.dump(vars)
- def dump(self, vars: Optional[Params]) -> None:
+ def dump(self, vars: Params | None) -> None:
if vars is not None:
if not PostgresQuery.is_params_sequence(vars):
raise TypeError("raw queries require a sequence of parameters")
# Copyright (C) 2021 The Psycopg Team
+from __future__ import annotations
+
import functools
-from typing import Any, Callable, Dict, List, Optional, NamedTuple, NoReturn
+from typing import Any, Callable, Dict, List, NamedTuple, NoReturn
from typing import TYPE_CHECKING, Protocol, Sequence, Tuple, Type
from collections import namedtuple
raise e.InterfaceError("the cursor doesn't have a result")
-def _get_names(cursor: "BaseCursor[Any, Any]") -> Optional[List[str]]:
+def _get_names(cursor: "BaseCursor[Any, Any]") -> List[str] | None:
res = cursor.pgresult
if not res:
return None
]
-def _get_nfields(res: "PGresult") -> Optional[int]:
+def _get_nfields(res: "PGresult") -> int | None:
"""
Return the number of columns in a result, if it returns tuples else None
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
from typing import Any, AsyncIterator, List, Iterable, Iterator
-from typing import Optional, TYPE_CHECKING, overload
+from typing import TYPE_CHECKING, overload
from warnings import warn
from . import pq
def __init__(
self,
name: str,
- scrollable: Optional[bool],
+ scrollable: bool | None,
withhold: bool,
):
self._name = name
return self._name
@property
- def scrollable(self) -> Optional[bool]:
+ def scrollable(self) -> bool | None:
"""
Whether the cursor is scrollable or not.
return self._withhold
@property
- def rownumber(self) -> Optional[int]:
+ def rownumber(self) -> int | None:
"""Index of the next row to fetch in the current result.
`!None` if there is no result to fetch.
def _declare_gen(
self,
query: Query,
- params: Optional[Params] = None,
- binary: Optional[bool] = None,
+ params: Params | None = None,
+ binary: bool | None = None,
) -> PQGen[None]:
"""Generator implementing `ServerCursor.execute()`."""
query = sql.SQL("CLOSE {}").format(sql.Identifier(self._name))
yield from self._conn._exec_command(query)
- def _fetch_gen(self, num: Optional[int]) -> 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
connection: "Connection[Row]",
name: str,
*,
- scrollable: Optional[bool] = None,
+ scrollable: bool | None = None,
withhold: bool = False,
): ...
name: str,
*,
row_factory: RowFactory[Row],
- scrollable: Optional[bool] = None,
+ scrollable: bool | None = None,
withhold: bool = False,
): ...
connection: "Connection[Any]",
name: str,
*,
- row_factory: Optional[RowFactory[Row]] = None,
- scrollable: Optional[bool] = None,
+ row_factory: RowFactory[Row] | None = None,
+ scrollable: bool | None = None,
withhold: bool = False,
):
Cursor.__init__(
def execute(
self,
query: Query,
- params: Optional[Params] = None,
+ params: Params | None = None,
*,
- binary: Optional[bool] = None,
+ binary: bool | None = None,
**kwargs: Any,
) -> Self:
"""
"""Method not implemented for server-side cursors."""
raise e.NotSupportedError("executemany not supported on server-side cursors")
- def fetchone(self) -> Optional[Row]:
+ def fetchone(self) -> Row | None:
with self._conn.lock:
recs = self._conn.wait(self._fetch_gen(1))
if recs:
connection: "AsyncConnection[Row]",
name: str,
*,
- scrollable: Optional[bool] = None,
+ scrollable: bool | None = None,
withhold: bool = False,
): ...
name: str,
*,
row_factory: AsyncRowFactory[Row],
- scrollable: Optional[bool] = None,
+ scrollable: bool | None = None,
withhold: bool = False,
): ...
connection: "AsyncConnection[Any]",
name: str,
*,
- row_factory: Optional[AsyncRowFactory[Row]] = None,
- scrollable: Optional[bool] = None,
+ row_factory: AsyncRowFactory[Row] | None = None,
+ scrollable: bool | None = None,
withhold: bool = False,
):
AsyncCursor.__init__(
async def execute(
self,
query: Query,
- params: Optional[Params] = None,
+ params: Params | None = None,
*,
- binary: Optional[bool] = None,
+ binary: bool | None = None,
**kwargs: Any,
) -> Self:
if kwargs:
) -> None:
raise e.NotSupportedError("executemany not supported on server-side cursors")
- async def fetchone(self) -> Optional[Row]:
+ async def fetchone(self) -> Row | None:
async with self._conn.lock:
recs = await self._conn.wait(self._fetch_gen(1))
if recs:
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
import codecs
import string
from abc import ABC, abstractmethod
-from typing import Any, Iterator, Iterable, List, Optional, Sequence, Union
+from typing import Any, Iterator, Iterable, List, Sequence, Union
from .pq import Escaping
from .abc import AdaptContext
from ._transformer import Transformer
-def quote(obj: Any, context: Optional[AdaptContext] = None) -> str:
+def quote(obj: Any, context: AdaptContext | None = None) -> str:
"""
Adapt a Python object to a quoted SQL string.
return f"{self.__class__.__name__}({self._obj!r})"
@abstractmethod
- def as_bytes(self, context: Optional[AdaptContext] = None) -> bytes:
+ def as_bytes(self, context: AdaptContext | None = None) -> bytes:
"""
Return the value of the object as bytes.
"""
raise NotImplementedError
- def as_string(self, context: Optional[AdaptContext] = None) -> str:
+ def as_string(self, context: AdaptContext | None = None) -> str:
"""
Return the value of the object as string.
seq = [obj if isinstance(obj, Composable) else Literal(obj) for obj in seq]
super().__init__(seq)
- def as_bytes(self, context: Optional[AdaptContext] = None) -> bytes:
+ def as_bytes(self, context: AdaptContext | None = None) -> bytes:
return b"".join(obj.as_bytes(context) for obj in self._obj)
def __iter__(self) -> Iterator[Composable]:
if not isinstance(obj, str):
raise TypeError(f"SQL values must be strings, got {obj!r} instead")
- def as_string(self, context: Optional[AdaptContext] = None) -> str:
+ def as_string(self, context: AdaptContext | None = None) -> str:
return self._obj
- def as_bytes(self, context: Optional[AdaptContext] = None) -> bytes:
+ def as_bytes(self, context: AdaptContext | None = None) -> bytes:
conn = context.connection if context else None
enc = conn_encoding(conn)
return self._obj.encode(enc)
"""
rv: List[Composable] = []
- autonum: Optional[int] = 0
+ 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.
pre: LiteralString
def __repr__(self) -> str:
return f"{self.__class__.__name__}({', '.join(map(repr, self._obj))})"
- def as_bytes(self, context: Optional[AdaptContext] = None) -> bytes:
+ def as_bytes(self, context: AdaptContext | None = None) -> bytes:
conn = context.connection if context else None
if conn:
esc = Escaping(conn.pgconn)
"""
- def as_bytes(self, context: Optional[AdaptContext] = None) -> bytes:
+ def as_bytes(self, context: AdaptContext | None = None) -> bytes:
tx = Transformer.from_context(context)
return tx.as_literal(self._obj)
return f"{self.__class__.__name__}({', '.join(parts)})"
- def as_string(self, context: Optional[AdaptContext] = None) -> str:
+ def as_string(self, context: AdaptContext | None = None) -> str:
code = self._format.value
return f"%({self._obj}){code}" if self._obj else f"%{code}"
- def as_bytes(self, context: Optional[AdaptContext] = None) -> bytes:
+ def as_bytes(self, context: AdaptContext | None = None) -> bytes:
conn = context.connection if context else None
enc = conn_encoding(conn)
return self.as_string(context).encode(enc)
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
import logging
from types import TracebackType
-from typing import Generic, Iterator, Optional, Type, Union, TYPE_CHECKING
+from typing import Generic, Iterator, Type, Union, TYPE_CHECKING
from . import pq
from . import sql
def __init__(
self,
connection: ConnectionType,
- savepoint_name: Optional[str] = None,
+ savepoint_name: str | None = None,
force_rollback: bool = False,
):
self._conn = connection
self._stack_index = -1
@property
- def savepoint_name(self) -> Optional[str]:
+ def savepoint_name(self) -> str | None:
"""
The name of the savepoint; `!None` if handling the main transaction.
"""
def _exit_gen(
self,
- exc_type: Optional[Type[BaseException]],
- exc_val: Optional[BaseException],
- exc_tb: Optional[TracebackType],
+ exc_type: Type[BaseException] | None,
+ exc_val: BaseException | None,
+ exc_tb: TracebackType | None,
) -> PQGen[bool]:
if not exc_val and not self.force_rollback:
yield from self._commit_gen()
for command in self._get_commit_commands():
yield from self._conn._exec_command(command)
- def _rollback_gen(self, exc_val: Optional[BaseException]) -> PQGen[bool]:
+ def _rollback_gen(self, exc_val: BaseException | None) -> PQGen[bool]:
if isinstance(exc_val, Rollback):
logger.debug(f"{self._conn}: Explicit rollback from: ", exc_info=True)
self._stack_index = self._conn._num_transactions
self._conn._num_transactions += 1
- def _pop_savepoint(self, action: str) -> Optional[Exception]:
+ def _pop_savepoint(self, action: str) -> Exception | None:
"""
Pop the transaction from the connection transactions stack.
def __exit__(
self,
- exc_type: Optional[Type[BaseException]],
- exc_val: Optional[BaseException],
- exc_tb: Optional[TracebackType],
+ exc_type: Type[BaseException] | None,
+ exc_val: BaseException | None,
+ exc_tb: TracebackType | None,
) -> bool:
if self.pgconn.status == OK:
with self._conn.lock:
async def __aexit__(
self,
- exc_type: Optional[Type[BaseException]],
- exc_val: Optional[BaseException],
- exc_tb: Optional[TracebackType],
+ exc_type: Type[BaseException] | None,
+ exc_val: BaseException | None,
+ exc_tb: TracebackType | None,
) -> bool:
if self.pgconn.status == OK:
async with self._conn.lock:
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
import re
import struct
from math import prod
-from typing import Any, cast, Callable, List, Optional, Pattern, Set, Tuple, Type
+from typing import Any, cast, Callable, List, Pattern, Set, Tuple, Type
from .. import pq
from .. import errors as e
class BaseListDumper(RecursiveDumper):
element_oid = INVALID_OID
- def __init__(self, cls: type, context: Optional[AdaptContext] = None):
+ def __init__(self, cls: type, context: AdaptContext | None = None):
if cls is NoneType:
cls = list
super().__init__(cls, context)
- self.sub_dumper: Optional[Dumper] = None
+ self.sub_dumper: Dumper | None = None
if self.element_oid and context:
sdclass = context.adapters.get_dumper_by_oid(self.element_oid, self.format)
self.sub_dumper = sdclass(NoneType, context)
# backslash-escaped.
_re_esc = re.compile(rb'(["\\])')
- def dump(self, obj: List[Any]) -> Optional[Buffer]:
+ def dump(self, obj: List[Any]) -> Buffer | None:
tokens: List[Buffer] = []
needs_quotes = _get_needs_quotes_regexp(self.delimiter).search
return b"".join(tokens)
- def _dump_item(self, item: Any) -> Optional[Buffer]:
+ def _dump_item(self, item: Any) -> Buffer | None:
if self.sub_dumper:
return self.sub_dumper.dump(item)
else:
return dumper
- def dump(self, obj: List[Any]) -> Optional[Buffer]:
+ 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
return _load_binary(data, self._tx)
-def register_array(info: TypeInfo, context: Optional[AdaptContext] = None) -> None:
+def register_array(info: TypeInfo, context: AdaptContext | None = None) -> None:
if not info.array_oid:
raise ValueError(f"the type info {info} doesn't describe an array")
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
from .. import _oids
-from typing import Optional
from ..pq import Format
from ..abc import AdaptContext
from ..adapt import Buffer, Dumper, Loader
class BoolDumper(Dumper):
oid = _oids.BOOL_OID
- def dump(self, obj: bool) -> Optional[Buffer]:
+ def dump(self, obj: bool) -> Buffer | None:
return b"t" if obj else b"f"
def quote(self, obj: bool) -> Buffer:
format = Format.BINARY
oid = _oids.BOOL_OID
- def dump(self, obj: bool) -> Optional[Buffer]:
+ def dump(self, obj: bool) -> Buffer | None:
return b"\x01" if obj else b"\x00"
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
import re
import struct
from collections import namedtuple
-from typing import Any, Callable, cast, Dict, Iterator, List, Optional
+from typing import Any, Callable, cast, Dict, Iterator, List
from typing import NamedTuple, Sequence, Tuple, Type, TYPE_CHECKING
from .. import pq
self.field_names = field_names
self.field_types = field_types
# Will be set by register() if the `factory` is a type
- self.python_type: Optional[type] = None
+ self.python_type: type | None = None
@classmethod
def _get_info_query(cls, conn: "BaseConnection[Any]") -> abc.Query:
# Should be this, but it doesn't work
# oid = _oids.RECORD_OID
- def dump(self, obj: Tuple[Any, ...]) -> Optional[Buffer]:
+ def dump(self, obj: Tuple[Any, ...]) -> Buffer | None:
return self._dump_sequence(obj, b"(", b")", b",")
# Subclasses must set this info
_field_types: Tuple[int, ...]
- def __init__(self, cls: type, context: Optional[abc.AdaptContext] = None):
+ def __init__(self, cls: type, context: abc.AdaptContext | None = None):
super().__init__(cls, context)
# Note: this class is not a RecursiveDumper because it would use the
nfields = len(self._field_types)
self._formats = (PyFormat.from_pq(self.format),) * nfields
- def dump(self, obj: Tuple[Any, ...]) -> Optional[Buffer]:
+ def dump(self, obj: Tuple[Any, ...]) -> Buffer | None:
out = bytearray(pack_len(len(obj)))
adapted = self._tx.dump_sequence(obj, self._formats)
for i in range(len(obj)):
class BaseCompositeLoader(Loader):
- def __init__(self, oid: int, context: Optional[abc.AdaptContext] = None):
+ def __init__(self, oid: int, context: abc.AdaptContext | None = None):
super().__init__(oid, context)
self._tx = Transformer(context)
- def _parse_record(self, data: abc.Buffer) -> Iterator[Optional[bytes]]:
+ def _parse_record(self, data: abc.Buffer) -> Iterator[bytes | None]:
"""
Split a non-empty representation of a composite type into components.
class RecordBinaryLoader(Loader):
format = pq.Format.BINARY
- def __init__(self, oid: int, context: Optional[abc.AdaptContext] = None):
+ def __init__(self, oid: int, context: abc.AdaptContext | None = None):
super().__init__(oid, context)
self._ctx = context
# Cache a transformer for each sequence of oid found.
def register_composite(
info: CompositeInfo,
- context: Optional[abc.AdaptContext] = None,
- factory: Optional[Callable[..., Any]] = None,
+ context: abc.AdaptContext | None = None,
+ factory: Callable[..., Any] | None = None,
) -> None:
"""Register the adapters to load and dump a composite type.
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
import re
import struct
from datetime import date, datetime, time, timedelta, timezone
-from typing import Any, Callable, cast, Optional, Tuple, TYPE_CHECKING
+from typing import Any, Callable, cast, Tuple, TYPE_CHECKING
from .. import _oids
from ..pq import Format
class DateDumper(Dumper):
oid = _oids.DATE_OID
- def dump(self, obj: date) -> Optional[Buffer]:
+ def dump(self, obj: date) -> Buffer | None:
# NOTE: whatever the PostgreSQL DateStyle input format (DMY, MDY, YMD)
# the YYYY-MM-DD is always understood correctly.
return str(obj).encode()
format = Format.BINARY
oid = _oids.DATE_OID
- def dump(self, obj: date) -> Optional[Buffer]:
+ def dump(self, obj: date) -> Buffer | None:
days = obj.toordinal() - _pg_date_epoch_days
return pack_int4(days)
class _BaseTimeTextDumper(_BaseTimeDumper):
- def dump(self, obj: time) -> Optional[Buffer]:
+ def dump(self, obj: time) -> Buffer | None:
return str(obj).encode()
class TimeTzDumper(_BaseTimeTextDumper):
oid = _oids.TIMETZ_OID
- def dump(self, obj: time) -> Optional[Buffer]:
+ def dump(self, obj: time) -> Buffer | None:
self._get_offset(obj)
return super().dump(obj)
format = Format.BINARY
oid = _oids.TIME_OID
- def dump(self, obj: time) -> Optional[Buffer]:
+ def dump(self, obj: time) -> Buffer | None:
us = obj.microsecond + 1_000_000 * (
obj.second + 60 * (obj.minute + 60 * obj.hour)
)
format = Format.BINARY
oid = _oids.TIMETZ_OID
- def dump(self, obj: time) -> Optional[Buffer]:
+ def dump(self, obj: time) -> Buffer | None:
us = obj.microsecond + 1_000_000 * (
obj.second + 60 * (obj.minute + 60 * obj.hour)
)
class _BaseDatetimeTextDumper(_BaseDatetimeDumper):
- def dump(self, obj: datetime) -> Optional[Buffer]:
+ def dump(self, obj: datetime) -> Buffer | None:
# NOTE: whatever the PostgreSQL DateStyle input format (DMY, MDY, YMD)
# the YYYY-MM-DD is always understood correctly.
return str(obj).encode()
format = Format.BINARY
oid = _oids.TIMESTAMPTZ_OID
- def dump(self, obj: datetime) -> Optional[Buffer]:
+ def dump(self, obj: datetime) -> Buffer | None:
delta = obj - _pg_datetimetz_epoch
micros = delta.microseconds + 1_000_000 * (86_400 * delta.days + delta.seconds)
return pack_int8(micros)
format = Format.BINARY
oid = _oids.TIMESTAMP_OID
- def dump(self, obj: datetime) -> Optional[Buffer]:
+ def dump(self, obj: datetime) -> Buffer | None:
delta = obj - _pg_datetime_epoch
micros = delta.microseconds + 1_000_000 * (86_400 * delta.days + delta.seconds)
return pack_int8(micros)
class TimedeltaDumper(Dumper):
oid = _oids.INTERVAL_OID
- def __init__(self, cls: type, context: Optional[AdaptContext] = None):
+ def __init__(self, cls: type, context: AdaptContext | None = None):
super().__init__(cls, context)
if _get_intervalstyle(self.connection) == b"sql_standard":
self._dump_method = self._dump_sql
else:
self._dump_method = self._dump_any
- def dump(self, obj: timedelta) -> Optional[Buffer]:
+ def dump(self, obj: timedelta) -> Buffer | None:
return self._dump_method(self, obj)
@staticmethod
format = Format.BINARY
oid = _oids.INTERVAL_OID
- def dump(self, obj: timedelta) -> Optional[Buffer]:
+ def dump(self, obj: timedelta) -> Buffer | None:
micros = 1_000_000 * obj.seconds + obj.microseconds
return _pack_interval(micros, obj.days, 0)
_ORDER_DMY = 1
_ORDER_MDY = 2
- def __init__(self, oid: int, context: Optional[AdaptContext] = None):
+ def __init__(self, oid: int, context: AdaptContext | None = None):
super().__init__(oid, context)
ds = _get_datestyle(self.connection)
if ds.startswith(b"I"): # ISO
_ORDER_PGDM = 3
_ORDER_PGMD = 4
- def __init__(self, oid: int, context: Optional[AdaptContext] = None):
+ def __init__(self, oid: int, context: AdaptContext | None = None):
super().__init__(oid, context)
ds = _get_datestyle(self.connection)
"""
)
- def __init__(self, oid: int, context: Optional[AdaptContext] = None):
+ def __init__(self, oid: int, context: AdaptContext | None = None):
super().__init__(oid, context)
self._timezone = get_tzinfo(self.connection.pgconn if self.connection else None)
class TimestamptzBinaryLoader(Loader):
format = Format.BINARY
- def __init__(self, oid: int, context: Optional[AdaptContext] = None):
+ def __init__(self, oid: int, context: AdaptContext | None = None):
super().__init__(oid, context)
self._timezone = get_tzinfo(self.connection.pgconn if self.connection else None)
re.VERBOSE,
)
- def __init__(self, oid: int, context: Optional[AdaptContext] = None):
+ def __init__(self, oid: int, context: AdaptContext | None = None):
super().__init__(oid, context)
if _get_intervalstyle(self.connection) == b"postgres":
self._load_method = self._load_postgres
raise DataError(f"can't parse interval: {e}") from None
-def _get_datestyle(conn: Optional["BaseConnection[Any]"]) -> bytes:
+def _get_datestyle(conn: "BaseConnection[Any]" | None) -> bytes:
if conn:
ds = conn.pgconn.parameter_status(b"DateStyle")
if ds:
return b"ISO, DMY"
-def _get_intervalstyle(conn: Optional["BaseConnection[Any]"]) -> bytes:
+def _get_intervalstyle(conn: "BaseConnection[Any]" | None) -> bytes:
if conn:
ints = conn.pgconn.parameter_status(b"IntervalStyle")
if ints:
def _get_timestamp_load_error(
- conn: Optional["BaseConnection[Any]"], data: Buffer, ex: Optional[Exception] = None
+ conn: "BaseConnection[Any]" | None, data: Buffer, ex: Exception | None = None
) -> Exception:
s = bytes(data).decode("utf8", "replace")
Adapters for the enum type.
"""
+from __future__ import annotations
+
from enum import Enum
-from typing import Any, Dict, Generic, Optional, Mapping, Sequence
+from typing import Any, Dict, Generic, Mapping, Sequence
from typing import Tuple, Type, Union, cast, TYPE_CHECKING
from .. import sql
super().__init__(name, oid, array_oid)
self.labels = labels
# Will be set by register_enum()
- self.enum: Optional[Type[Enum]] = None
+ self.enum: Type[Enum] | None = None
@classmethod
def _get_info_query(cls, conn: "BaseConnection[Any]") -> Query:
enum: Type[E]
_dump_map: EnumDumpMap[E]
- def dump(self, value: E) -> Optional[Buffer]:
+ def dump(self, value: E) -> Buffer | None:
return self._dump_map[value]
Dumper for a generic Enum class
"""
- def __init__(self, cls: type, context: Optional[AdaptContext] = None):
+ def __init__(self, cls: type, context: AdaptContext | None = None):
super().__init__(cls, context)
self._encoding = conn_encoding(self.connection)
- def dump(self, value: E) -> Optional[Buffer]:
+ def dump(self, value: E) -> Buffer | None:
return value.name.encode(self._encoding)
def register_enum(
info: EnumInfo,
- context: Optional[AdaptContext] = None,
- enum: Optional[Type[E]] = None,
+ context: AdaptContext | None = None,
+ enum: Type[E] | None = None,
*,
mapping: EnumMapping[E] = None,
) -> None:
info: EnumInfo,
enum: Type[E],
mapping: EnumMapping[E],
- context: Optional[AdaptContext],
+ context: AdaptContext | None,
) -> _HEnumLoadMap[E]:
enc = conn_encoding(context.connection if context else None)
rv = []
info: EnumInfo,
enum: Type[E],
mapping: EnumMapping[E],
- context: Optional[AdaptContext],
+ context: AdaptContext | None,
) -> _HEnumDumpMap[E]:
enc = conn_encoding(context.connection if context else None)
rv = []
# Copyright (C) 2021 The Psycopg Team
+from __future__ import annotations
+
import re
-from typing import Dict, List, Optional, Type
+from typing import Dict, List, Type
from .. import errors as e
from .. import postgres
)
-Hstore: TypeAlias = Dict[str, Optional[str]]
+Hstore: TypeAlias = Dict[str, str | None]
class BaseHstoreDumper(RecursiveDumper):
- def dump(self, obj: Hstore) -> Optional[Buffer]:
+ def dump(self, obj: Hstore) -> Buffer | None:
if not obj:
return b""
return rv
-def register_hstore(info: TypeInfo, context: Optional[AdaptContext] = None) -> None:
+def register_hstore(info: TypeInfo, context: AdaptContext | None = None) -> None:
"""Register the adapters to load and dump hstore.
:param info: The object with the information about the hstore type.
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
import json
-from typing import Any, Callable, Dict, Optional, Tuple, Type, Union
+from typing import Any, Callable, Dict, Tuple, Type, Union
from .. import abc
from .. import _oids
def set_json_dumps(
- dumps: JsonDumpsFunction, context: Optional[abc.AdaptContext] = None
+ dumps: JsonDumpsFunction, context: abc.AdaptContext | None = None
) -> None:
"""
Set the JSON serialisation function to store JSON objects in the database.
def set_json_loads(
- loads: JsonLoadsFunction, context: Optional[abc.AdaptContext] = None
+ loads: JsonLoadsFunction, context: abc.AdaptContext | None = None
) -> None:
"""
Set the JSON parsing function to fetch JSON objects from the database.
class _JsonWrapper:
__slots__ = ("obj", "dumps")
- def __init__(self, obj: Any, dumps: Optional[JsonDumpsFunction] = None):
+ def __init__(self, obj: Any, dumps: JsonDumpsFunction | None = None):
self.obj = obj
self.dumps = dumps
# set_json_dumps) or by a subclass.
_dumps: JsonDumpsFunction = json.dumps
- def __init__(self, cls: type, context: Optional[abc.AdaptContext] = None):
+ def __init__(self, cls: type, context: abc.AdaptContext | None = None):
super().__init__(cls, context)
self.dumps = self.__class__._dumps
- def dump(self, obj: Any) -> Optional[Buffer]:
+ def dump(self, obj: Any) -> Buffer | None:
if isinstance(obj, _JsonWrapper):
dumps = obj.dumps or self.dumps
obj = obj.obj
format = Format.BINARY
oid = _oids.JSONB_OID
- def dump(self, obj: Any) -> Optional[Buffer]:
+ def dump(self, obj: Any) -> Buffer | None:
obj_bytes = super().dump(obj)
if obj_bytes is not None:
return b"\x01" + obj_bytes
# set_json_loads) or by a subclass.
_loads: JsonLoadsFunction = json.loads
- def __init__(self, oid: int, context: Optional[abc.AdaptContext] = None):
+ def __init__(self, oid: int, context: abc.AdaptContext | None = None):
super().__init__(oid, context)
self.loads = self.__class__._loads
# Copyright (C) 2021 The Psycopg Team
+from __future__ import annotations
+
from decimal import Decimal
from typing import Any, Generic, List, Iterable, MutableSequence
-from typing import Optional, Type, Union, overload, TYPE_CHECKING
+from typing import Type, Union, overload, TYPE_CHECKING
from datetime import date, datetime
from .. import sql
class BaseMultirangeDumper(RecursiveDumper):
- def __init__(self, cls: type, context: Optional[AdaptContext] = None):
+ def __init__(self, cls: type, context: AdaptContext | None = None):
super().__init__(cls, context)
- self.sub_dumper: Optional[Dumper] = None
+ self.sub_dumper: Dumper | None = None
self._adapt_format = PyFormat.from_pq(self.format)
def get_key(self, obj: Multirange[Any], format: PyFormat) -> DumperKey:
The dumper can upgrade to one specific for a different range type.
"""
- def dump(self, obj: Multirange[Any]) -> Optional[Buffer]:
+ def dump(self, obj: Multirange[Any]) -> Buffer | None:
if not obj:
return b"{}"
class MultirangeBinaryDumper(BaseMultirangeDumper):
format = Format.BINARY
- def dump(self, obj: Multirange[Any]) -> Optional[Buffer]:
+ def dump(self, obj: Multirange[Any]) -> Buffer | None:
item = self._get_item(obj)
if item is not None:
dump = self._tx.get_dumper(item, self._adapt_format).dump
class BaseMultirangeLoader(RecursiveLoader, Generic[T]):
subtype_oid: int
- def __init__(self, oid: int, context: Optional[AdaptContext] = None):
+ def __init__(self, oid: int, context: AdaptContext | None = None):
super().__init__(oid, context)
self._load = self._tx.get_loader(self.subtype_oid, format=self.format).load
def register_multirange(
- info: MultirangeInfo, context: Optional[AdaptContext] = None
+ info: MultirangeInfo, context: AdaptContext | None = None
) -> None:
"""Register the adapters to load and dump a multirange type.
# Copyright (C) 2020 The Psycopg Team
-from typing import Callable, Optional, Type, Union, TYPE_CHECKING
+from __future__ import annotations
+
+from typing import Callable, Type, Union, TYPE_CHECKING
from .. import _oids
from ..pq import Format
class InterfaceDumper(Dumper):
oid = _oids.INET_OID
- def dump(self, obj: Interface) -> Optional[Buffer]:
+ def dump(self, obj: Interface) -> Buffer | None:
return str(obj).encode()
class NetworkDumper(Dumper):
oid = _oids.CIDR_OID
- def dump(self, obj: Network) -> Optional[Buffer]:
+ def dump(self, obj: Network) -> Buffer | None:
return str(obj).encode()
class AddressBinaryDumper(_AIBinaryDumper):
- def dump(self, obj: Address) -> Optional[Buffer]:
+ def dump(self, obj: Address) -> Buffer | None:
packed = obj.packed
family = PGSQL_AF_INET if obj.version == 4 else PGSQL_AF_INET6
head = bytes((family, obj.max_prefixlen, 0, len(packed)))
class InterfaceBinaryDumper(_AIBinaryDumper):
- def dump(self, obj: Interface) -> Optional[Buffer]:
+ def dump(self, obj: Interface) -> Buffer | None:
packed = obj.packed
family = PGSQL_AF_INET if obj.version == 4 else PGSQL_AF_INET6
head = bytes((family, obj.network.prefixlen, 0, len(packed)))
Used when looking up by oid.
"""
- def __init__(self, cls: type, context: Optional[AdaptContext] = None):
+ def __init__(self, cls: type, context: AdaptContext | None = None):
super().__init__(cls, context)
self._ensure_module()
- def dump(self, obj: Union[Address, Interface]) -> Optional[Buffer]:
+ def dump(self, obj: Union[Address, Interface]) -> Buffer | None:
packed = obj.packed
family = PGSQL_AF_INET if obj.version == 4 else PGSQL_AF_INET6
if isinstance(obj, (IPv4Interface, IPv6Interface)):
format = Format.BINARY
oid = _oids.CIDR_OID
- def dump(self, obj: Network) -> Optional[Buffer]:
+ def dump(self, obj: Network) -> Buffer | None:
packed = obj.network_address.packed
family = PGSQL_AF_INET if obj.version == 4 else PGSQL_AF_INET6
head = bytes((family, obj.prefixlen, 1, len(packed)))
class _LazyIpaddressLoader(Loader, _LazyIpaddress):
- def __init__(self, oid: int, context: Optional[AdaptContext] = None):
+ def __init__(self, oid: int, context: AdaptContext | None = None):
super().__init__(oid, context)
self._ensure_module()
# Copyright (C) 2020 The Psycopg Team
-from typing import Optional
+from __future__ import annotations
from ..abc import AdaptContext, NoneType, Buffer
from ..adapt import Dumper
quote(), so it can be used in sql composition.
"""
- def dump(self, obj: None) -> Optional[Buffer]:
+ def dump(self, obj: None) -> Buffer | None:
raise NotImplementedError("NULL is passed to Postgres in other ways")
def quote(self, obj: None) -> Buffer:
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
import sys
import struct
from abc import ABC, abstractmethod
from math import log
-from typing import Any, Callable, DefaultDict, Dict, Optional, Tuple, Union
+from typing import Any, Callable, DefaultDict, Dict, Tuple, Union
from typing import cast, TYPE_CHECKING
from decimal import Decimal, DefaultContext, Context
class _IntDumper(Dumper):
- def dump(self, obj: Any) -> Optional[Buffer]:
+ def dump(self, obj: Any) -> Buffer | None:
return str(obj).encode()
def quote(self, obj: Any) -> Buffer:
class _IntOrSubclassDumper(_IntDumper):
- def dump(self, obj: Any) -> Optional[Buffer]:
+ def dump(self, obj: Any) -> Buffer | None:
t = type(obj)
# Convert to int in order to dump IntEnum or numpy.integer correctly
if t is not int:
class _SpecialValuesDumper(Dumper):
_special: Dict[bytes, bytes] = {}
- def dump(self, obj: Any) -> Optional[Buffer]:
+ def dump(self, obj: Any) -> Buffer | None:
return str(obj).encode()
def quote(self, obj: Any) -> Buffer:
format = Format.BINARY
oid = _oids.FLOAT8_OID
- def dump(self, obj: float) -> Optional[Buffer]:
+ def dump(self, obj: float) -> Buffer | None:
return pack_float8(obj)
class Float4BinaryDumper(FloatBinaryDumper):
oid = _oids.FLOAT4_OID
- def dump(self, obj: float) -> Optional[Buffer]:
+ def dump(self, obj: float) -> Buffer | None:
return pack_float4(obj)
class DecimalDumper(_SpecialValuesDumper):
oid = _oids.NUMERIC_OID
- def dump(self, obj: Decimal) -> Optional[Buffer]:
+ def dump(self, obj: Decimal) -> Buffer | None:
return dump_decimal_to_text(obj)
_special = {
class IntDumper(Dumper):
- def dump(self, obj: Any) -> Optional[Buffer]:
+ def dump(self, obj: Any) -> Buffer | None:
raise TypeError(
f"{type(self).__name__} is a dispatcher to other dumpers:"
" dump() is not supposed to be called"
class Int2BinaryDumper(Int2Dumper):
format = Format.BINARY
- def dump(self, obj: int) -> Optional[Buffer]:
+ def dump(self, obj: int) -> Buffer | None:
return pack_int2(obj)
class Int4BinaryDumper(Int4Dumper):
format = Format.BINARY
- def dump(self, obj: int) -> Optional[Buffer]:
+ def dump(self, obj: int) -> Buffer | None:
return pack_int4(obj)
class Int8BinaryDumper(Int8Dumper):
format = Format.BINARY
- def dump(self, obj: int) -> Optional[Buffer]:
+ def dump(self, obj: int) -> Buffer | None:
return pack_int8(obj)
class IntNumericBinaryDumper(IntNumericDumper):
format = Format.BINARY
- def dump(self, obj: int) -> Optional[Buffer]:
+ def dump(self, obj: int) -> Buffer | None:
return dump_int_to_numeric_binary(obj)
class OidBinaryDumper(OidDumper):
format = Format.BINARY
- def dump(self, obj: int) -> Optional[Buffer]:
+ def dump(self, obj: int) -> Buffer | None:
return pack_uint4(obj)
format = Format.BINARY
oid = _oids.NUMERIC_OID
- def dump(self, obj: Decimal) -> Optional[Buffer]:
+ def dump(self, obj: Decimal) -> Buffer | None:
return dump_decimal_to_numeric_binary(obj)
# If numpy is available, the dumped object might be a numpy integer too
int_classes: Union[type, Tuple[type, ...]] = ()
- def __init__(self, cls: type, context: Optional[AdaptContext] = None):
+ def __init__(self, cls: type, context: AdaptContext | None = None):
super().__init__(cls, context)
# Verify if numpy is available. If it is, we might have to dump
_MixedNumericDumper.int_classes = int
@abstractmethod
- def dump(
- self, obj: Union[Decimal, int, "numpy.integer[Any]"]
- ) -> Optional[Buffer]: ...
+ def dump(self, obj: Union[Decimal, int, "numpy.integer[Any]"]) -> Buffer | None: ...
class NumericDumper(_MixedNumericDumper):
- def dump(self, obj: Union[Decimal, int, "numpy.integer[Any]"]) -> Optional[Buffer]:
+ def dump(self, obj: Union[Decimal, int, "numpy.integer[Any]"]) -> Buffer | None:
if isinstance(obj, self.int_classes):
return str(obj).encode()
elif isinstance(obj, Decimal):
class NumericBinaryDumper(_MixedNumericDumper):
format = Format.BINARY
- def dump(self, obj: Union[Decimal, int, "numpy.integer[Any]"]) -> Optional[Buffer]:
+ def dump(self, obj: Union[Decimal, int, "numpy.integer[Any]"]) -> Buffer | None:
if type(obj) is int:
return dump_int_to_numeric_binary(obj)
elif isinstance(obj, Decimal):
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
+
import re
-from typing import Any, Dict, Generic, List, Optional, Type, Tuple
+from typing import Any, Dict, Generic, List, Type, Tuple
from typing import cast, TYPE_CHECKING
from decimal import Decimal
from datetime import date, datetime
def __init__(
self,
- lower: Optional[T] = None,
- upper: Optional[T] = None,
+ lower: T | None = None,
+ upper: T | None = None,
bounds: str = "[)",
empty: bool = False,
):
return "".join(items)
@property
- def lower(self) -> Optional[T]:
+ def lower(self) -> T | None:
"""The lower bound of the range. `!None` if empty or unbound."""
return self._lower
@property
- def upper(self) -> Optional[T]:
+ def upper(self) -> T | None:
"""The upper bound of the range. `!None` if empty or unbound."""
return self._upper
class BaseRangeDumper(RecursiveDumper):
- def __init__(self, cls: type, context: Optional[AdaptContext] = None):
+ def __init__(self, cls: type, context: AdaptContext | None = None):
super().__init__(cls, context)
- self.sub_dumper: Optional[Dumper] = None
+ self.sub_dumper: Dumper | None = None
self._adapt_format = PyFormat.from_pq(self.format)
def get_key(self, obj: Range[Any], format: PyFormat) -> DumperKey:
The dumper can upgrade to one specific for a different range type.
"""
- def dump(self, obj: Range[Any]) -> Optional[Buffer]:
+ def dump(self, obj: Range[Any]) -> Buffer | None:
item = self._get_item(obj)
if item is not None:
dump = self._tx.get_dumper(item, self._adapt_format).dump
class RangeBinaryDumper(BaseRangeDumper):
format = Format.BINARY
- def dump(self, obj: Range[Any]) -> Optional[Buffer]:
+ def dump(self, obj: Range[Any]) -> Buffer | None:
item = self._get_item(obj)
if item is not None:
dump = self._tx.get_dumper(item, self._adapt_format).dump
subtype_oid: int
- def __init__(self, oid: int, context: Optional[AdaptContext] = None):
+ def __init__(self, oid: int, context: AdaptContext | None = None):
super().__init__(oid, context)
self._load = self._tx.get_loader(self.subtype_oid, format=self.format).load
return Range(min, max, lb + ub)
-def register_range(info: RangeInfo, context: Optional[AdaptContext] = None) -> None:
+def register_range(info: RangeInfo, context: AdaptContext | None = None) -> None:
"""Register the adapters to load and dump a range type.
:param info: The object with the information about the range to register.
Adapters for PostGIS geometries
"""
-from typing import Optional, Type
+from __future__ import annotations
+
+from typing import Type
from .. import postgres
from ..abc import AdaptContext, Buffer
from .._compat import cache
from .._typeinfo import TypeInfo
-
try:
from shapely.wkb import loads, dumps
from shapely.geometry.base import BaseGeometry
class BaseGeometryBinaryDumper(Dumper):
format = Format.BINARY
- def dump(self, obj: "BaseGeometry") -> Optional[Buffer]:
+ def dump(self, obj: "BaseGeometry") -> Buffer | None:
return dumps(obj) # type: ignore
class BaseGeometryDumper(Dumper):
- def dump(self, obj: "BaseGeometry") -> Optional[Buffer]:
+ def dump(self, obj: "BaseGeometry") -> Buffer | None:
return dumps(obj, hex=True).encode() # type: ignore
-def register_shapely(info: TypeInfo, context: Optional[AdaptContext] = None) -> None:
+def register_shapely(info: TypeInfo, context: AdaptContext | None = None) -> None:
"""Register Shapely dumper and loaders."""
# A friendly error warning instead of an AttributeError in case fetch()
# Copyright (C) 2020 The Psycopg Team
-from typing import Optional, Union, TYPE_CHECKING
+from __future__ import annotations
+
+from typing import Union, TYPE_CHECKING
from .. import _oids
from ..pq import Format, Escaping
class _BaseStrDumper(Dumper):
- def __init__(self, cls: type, context: Optional[AdaptContext] = None):
+ def __init__(self, cls: type, context: AdaptContext | None = None):
super().__init__(cls, context)
enc = conn_encoding(self.connection)
self._encoding = enc if enc != "ascii" else "utf-8"
format = Format.BINARY
- def dump(self, obj: str) -> Optional[Buffer]:
+ def dump(self, obj: str) -> Buffer | None:
# the server will raise DataError subclass if the string contains 0x00
return obj.encode(self._encoding)
Subclasses shall specify the oids of real types (text, varchar, name...).
"""
- def dump(self, obj: str) -> Optional[Buffer]:
+ def dump(self, obj: str) -> Buffer | None:
if "\x00" in obj:
raise DataError("PostgreSQL text fields cannot contain NUL (0x00) bytes")
else:
class TextLoader(Loader):
- def __init__(self, oid: int, context: Optional[AdaptContext] = None):
+ def __init__(self, oid: int, context: AdaptContext | None = None):
super().__init__(oid, context)
enc = conn_encoding(self.connection)
self._encoding = enc if enc != "ascii" else ""
oid = _oids.BYTEA_OID
_qprefix = b""
- def __init__(self, cls: type, context: Optional[AdaptContext] = None):
+ def __init__(self, cls: type, context: AdaptContext | None = None):
super().__init__(cls, context)
self._esc = Escaping(self.connection.pgconn if self.connection else None)
- def dump(self, obj: Buffer) -> Optional[Buffer]:
+ def dump(self, obj: Buffer) -> Buffer | None:
return self._esc.escape_bytea(obj)
def quote(self, obj: Buffer) -> Buffer:
format = Format.BINARY
oid = _oids.BYTEA_OID
- def dump(self, obj: Buffer) -> Optional[Buffer]:
+ def dump(self, obj: Buffer) -> Buffer | None:
return obj
class ByteaLoader(Loader):
_escaping: "EscapingProto"
- def __init__(self, oid: int, context: Optional[AdaptContext] = None):
+ def __init__(self, oid: int, context: AdaptContext | None = None):
super().__init__(oid, context)
if not hasattr(self.__class__, "_escaping"):
self.__class__._escaping = Escaping()
# Copyright (C) 2020 The Psycopg Team
-from typing import Callable, Optional, TYPE_CHECKING
+from __future__ import annotations
+
+from typing import Callable, TYPE_CHECKING
from .. import _oids
from ..pq import Format
class UUIDDumper(Dumper):
oid = _oids.UUID_OID
- def dump(self, obj: "uuid.UUID") -> Optional[Buffer]:
+ def dump(self, obj: "uuid.UUID") -> Buffer | None:
return obj.hex.encode()
class UUIDBinaryDumper(UUIDDumper):
format = Format.BINARY
- def dump(self, obj: "uuid.UUID") -> Optional[Buffer]:
+ def dump(self, obj: "uuid.UUID") -> Buffer | None:
return obj.bytes
class UUIDLoader(Loader):
- def __init__(self, oid: int, context: Optional[AdaptContext] = None):
+ def __init__(self, oid: int, context: AdaptContext | None = None):
super().__init__(oid, context)
global UUID
if UUID is None:
# Copyright (C) 2020 The Psycopg Team
+from __future__ import annotations
import os
import sys
import select
import logging
import selectors
-from typing import Optional
from asyncio import get_event_loop, wait_for, Event, TimeoutError
from selectors import DefaultSelector
logger = logging.getLogger(__name__)
-def wait_selector(gen: PQGen[RV], fileno: int, interval: Optional[float] = None) -> RV:
+def wait_selector(gen: PQGen[RV], fileno: int, interval: float | None = None) -> RV:
"""
Wait for a generator using the best strategy available.
return rv
-def wait_conn(gen: PQGenConn[RV], interval: Optional[float] = None) -> RV:
+def wait_conn(gen: PQGenConn[RV], interval: float | None = None) -> RV:
"""
Wait for a connection generator using the best strategy available.
return rv
-async def wait_async(
- gen: PQGen[RV], fileno: int, interval: Optional[float] = None
-) -> RV:
+async def wait_async(gen: PQGen[RV], fileno: int, interval: float | None = None) -> RV:
"""
Coroutine waiting for a generator to complete.
return rv
-async def wait_conn_async(gen: PQGenConn[RV], interval: Optional[float] = None) -> RV:
+async def wait_conn_async(gen: PQGenConn[RV], interval: float | None = None) -> RV:
"""
Coroutine waiting for a connection generator to complete.
# Specialised implementation of wait functions.
-def wait_select(gen: PQGen[RV], fileno: int, interval: Optional[float] = None) -> RV:
+def wait_select(gen: PQGen[RV], fileno: int, interval: float | None = None) -> RV:
"""
Wait for a generator using select where supported.
_epoll_evmasks = {}
-def wait_epoll(gen: PQGen[RV], fileno: int, interval: Optional[float] = None) -> RV:
+def wait_epoll(gen: PQGen[RV], fileno: int, interval: float | None = None) -> RV:
"""
Wait for a generator using epoll where supported.
_poll_evmasks = {}
-def wait_poll(gen: PQGen[RV], fileno: int, interval: Optional[float] = None) -> RV:
+def wait_poll(gen: PQGen[RV], fileno: int, interval: float | None = None) -> RV:
"""
Wait for a generator using poll where supported.
# Copyright (C) 2020 The Psycopg Team
-from typing import Any, List, Optional, Sequence, Tuple
+from typing import Any, List, Sequence, Tuple
from psycopg import pq, abc, BaseConnection
from psycopg.rows import Row, RowMaker
from psycopg._compat import Deque
class Transformer(abc.AdaptContext):
- types: Optional[Tuple[int, ...]]
- formats: Optional[List[pq.Format]]
- def __init__(self, context: Optional[abc.AdaptContext] = None): ...
+ types: Tuple[int, ...] | None
+ formats: List[pq.Format] | None
+ def __init__(self, context: abc.AdaptContext | None = None): ...
@classmethod
- def from_context(cls, context: Optional[abc.AdaptContext]) -> "Transformer": ...
+ def from_context(cls, context: abc.AdaptContext | None) -> "Transformer": ...
@property
- def connection(self) -> Optional[BaseConnection[Any]]: ...
+ def connection(self) -> BaseConnection[Any] | None: ...
@property
def encoding(self) -> str: ...
@property
def adapters(self) -> AdaptersMap: ...
@property
- def pgresult(self) -> Optional[PGresult]: ...
+ def pgresult(self) -> PGresult | None: ...
def set_pgresult(
self,
- result: Optional["PGresult"],
+ result: "PGresult" | None,
*,
set_loaders: bool = True,
- format: Optional[pq.Format] = None,
+ format: pq.Format | None = None,
) -> None: ...
def set_dumper_types(self, types: Sequence[int], format: pq.Format) -> None: ...
def set_loader_types(self, types: Sequence[int], format: pq.Format) -> None: ...
def dump_sequence(
self, params: Sequence[Any], formats: Sequence[PyFormat]
- ) -> Sequence[Optional[abc.Buffer]]: ...
+ ) -> 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_row(self, row: int, make_row: RowMaker[Row]) -> Optional[Row]: ...
- def load_sequence(
- self, record: Sequence[Optional[abc.Buffer]]
- ) -> Tuple[Any, ...]: ...
+ 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: ...
# Generators
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(pgconn: PGconn) -> abc.PQGen[Optional[PGresult]]: ...
+def fetch(pgconn: PGconn) -> abc.PQGen[PGresult | None]: ...
def pipeline_communicate(
pgconn: PGconn, commands: Deque[abc.PipelineCommand]
) -> abc.PQGen[List[List[PGresult]]]: ...
def wait_c(
- gen: abc.PQGen[abc.RV], fileno: int, interval: Optional[float] = None
+ gen: abc.PQGen[abc.RV], fileno: int, interval: float | None = None
) -> abc.RV: ...
# Copy support
def format_row_text(
- row: Sequence[Any], tx: abc.Transformer, out: Optional[bytearray] = None
+ row: Sequence[Any], tx: abc.Transformer, out: bytearray | None = None
) -> bytearray: ...
def format_row_binary(
- row: Sequence[Any], tx: abc.Transformer, out: Optional[bytearray] = None
+ row: Sequence[Any], tx: abc.Transformer, out: bytearray | None = None
) -> bytearray: ...
def parse_row_text(data: abc.Buffer, tx: abc.Transformer) -> Tuple[Any, ...]: ...
def parse_row_binary(data: abc.Buffer, tx: abc.Transformer) -> Tuple[Any, ...]: ...
oid = oids.INVALID_OID
- def __cinit__(self, cls, context: Optional[AdaptContext] = None):
+ def __cinit__(self, cls, context: AdaptContext | None = None):
self.cls = cls
conn = context.connection if context is not None else None
self._pgconn = conn.pgconn if conn is not None else None
"""
raise NotImplementedError()
- def dump(self, obj) -> Optional[Buffer]:
+ def dump(self, obj) -> Buffer | None:
"""Return the Postgres representation of *obj* as Python array of bytes"""
cdef rv = PyByteArray_FromStringAndSize("", 0)
cdef Py_ssize_t length = self.cdump(obj, rv, 0)
cdef public libpq.Oid oid
cdef pq.PGconn _pgconn
- def __cinit__(self, libpq.Oid oid, context: Optional[AdaptContext] = None):
+ def __cinit__(self, libpq.Oid oid, context: AdaptContext | None = None):
self.oid = oid
conn = context.connection if context is not None else None
self._pgconn = conn.pgconn if conn is not None else None
cdef Transformer _tx
- def __cinit__(self, oid: int, context: Optional[AdaptContext] = None):
+ def __cinit__(self, oid: int, context: AdaptContext | None = None):
self._tx = Transformer.from_context(context)
return results
-def fetch(pq.PGconn pgconn) -> PQGen[Optional[PGresult]]:
+def fetch(pq.PGconn pgconn) -> PQGen[PGresult | None]:
"""
Generator retrieving a single result from the database without blocking.
from cpython.tuple cimport PyTuple_New, PyTuple_SET_ITEM
from cpython.object cimport PyObject, PyObject_CallFunctionObjArgs
-from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple
+from typing import Any, Dict, Iterable, List, Sequence, Tuple
from psycopg import errors as e
from psycopg.pq import Format as PqFormat
cdef dict _oid_types
- def __cinit__(self, context: Optional["AdaptContext"] = None):
+ def __cinit__(self, context: "AdaptContext" | None = None):
if context is not None:
self.adapters = context.adapters
self.connection = context.connection
self._none_oid = -1
@classmethod
- def from_context(cls, context: Optional["AdaptContext"]):
+ def from_context(cls, context: "AdaptContext" | None):
"""
Return a Transformer from an AdaptContext.
return self._encoding
@property
- def pgresult(self) -> Optional[PGresult]:
+ def pgresult(self) -> PGresult | None:
return self._pgresult
cpdef set_pgresult(
Py_DECREF(<object>brecord)
return records
- def load_row(self, int row, object make_row) -> Optional[Row]:
+ def load_row(self, int row, object make_row) -> Row | None:
if self._pgresult is None:
return None
make_row, <PyObject *>record, NULL)
return record
- cpdef object load_sequence(self, record: Sequence[Optional[Buffer]]):
+ cpdef object load_sequence(self, record: Sequence[Buffer | None]):
cdef Py_ssize_t nfields = len(record)
out = PyTuple_New(nfields)
cdef PyObject *loader # borrowed RowLoader
self._pgconn_ptr = NULL
@property
- def pgconn_ptr(self) -> Optional[int]:
+ def pgconn_ptr(self) -> int | None:
if self._pgconn_ptr:
return <long long><void *>self._pgconn_ptr
else:
def transaction_status(self) -> int:
return libpq.PQtransactionStatus(self._pgconn_ptr)
- def parameter_status(self, const char *name) -> Optional[bytes]:
+ def parameter_status(self, const char *name) -> bytes | None:
_ensure_pgconn(self)
cdef const char *rv = libpq.PQparameterStatus(self._pgconn_ptr, name)
if rv is not NULL:
def exec_params(
self,
const char *command,
- param_values: Optional[Sequence[Optional[bytes]]],
- param_types: Optional[Sequence[int]] = None,
- param_formats: Optional[Sequence[int]] = None,
+ param_values: Sequence[bytes | None] | None,
+ param_types: Sequence[int] | None = None,
+ param_formats: Sequence[int] | None = None,
int result_format = PqFormat.TEXT,
) -> PGresult:
_ensure_pgconn(self)
def send_query_params(
self,
const char *command,
- param_values: Optional[Sequence[Optional[bytes]]],
- param_types: Optional[Sequence[int]] = None,
- param_formats: Optional[Sequence[int]] = None,
+ param_values: Sequence[bytes | None] | None,
+ param_types: Sequence[int] | None = None,
+ param_formats: Sequence[int] | None = None,
int result_format = PqFormat.TEXT,
) -> None:
_ensure_pgconn(self)
self,
const char *name,
const char *command,
- param_types: Optional[Sequence[int]] = None,
+ param_types: Sequence[int] | None = None,
) -> None:
_ensure_pgconn(self)
def send_query_prepared(
self,
const char *name,
- param_values: Optional[Sequence[Optional[bytes]]],
- param_formats: Optional[Sequence[int]] = None,
+ param_values: Sequence[bytes | None] | None,
+ param_formats: Sequence[int] | None = None,
int result_format = PqFormat.TEXT,
) -> None:
_ensure_pgconn(self)
self,
const char *name,
const char *command,
- param_types: Optional[Sequence[int]] = None,
+ param_types: Sequence[int] | None = None,
) -> PGresult:
_ensure_pgconn(self)
def exec_prepared(
self,
const char *name,
- param_values: Optional[Sequence[bytes]],
- param_formats: Optional[Sequence[int]] = None,
+ param_values: Sequence[bytes] | None,
+ param_formats: Sequence[int] | None = None,
int result_format = PqFormat.TEXT,
) -> PGresult:
_ensure_pgconn(self)
f"sending close prepared failed: {error_message(self)}"
)
- def get_result(self) -> Optional["PGresult"]:
+ def get_result(self) -> "PGresult" | None:
cdef libpq.PGresult *pgresult = libpq.PQgetResult(self._pgconn_ptr)
if pgresult is NULL:
return None
raise e.OperationalError(f"sending copy data failed: {error_message(self)}")
return rv
- def put_copy_end(self, error: Optional[bytes] = None) -> int:
+ def put_copy_end(self, error: bytes | None = None) -> int:
cdef int rv
cdef const char *cerr = NULL
if error is not None:
cdef (Py_ssize_t, libpq.Oid *, char * const*, int *, int *) _query_params_args(
- list param_values: Optional[Sequence[Optional[bytes]]],
- param_types: Optional[Sequence[int]],
- list param_formats: Optional[Sequence[int]],
+ list param_values: Sequence[bytes | None] | None,
+ param_types: Sequence[int] | None,
+ list param_formats: Sequence[int] | None,
) except *:
cdef int i
self._pgresult_ptr = NULL
@property
- def pgresult_ptr(self) -> Optional[int]:
+ def pgresult_ptr(self) -> int | None:
if self._pgresult_ptr:
return <long long><void *>self._pgresult_ptr
else:
def error_message(self) -> bytes:
return libpq.PQresultErrorMessage(self._pgresult_ptr)
- def error_field(self, int fieldcode) -> Optional[bytes]:
+ def error_field(self, int fieldcode) -> bytes | None:
cdef char * rv = libpq.PQresultErrorField(self._pgresult_ptr, fieldcode)
if rv is not NULL:
return rv
def nfields(self) -> int:
return libpq.PQnfields(self._pgresult_ptr)
- def fname(self, int column_number) -> Optional[bytes]:
+ def fname(self, int column_number) -> bytes | None:
cdef char *rv = libpq.PQfname(self._pgresult_ptr, column_number)
if rv is not NULL:
return rv
def binary_tuples(self) -> int:
return libpq.PQbinaryTuples(self._pgresult_ptr)
- def get_value(self, int row_number, int column_number) -> Optional[bytes]:
+ def get_value(self, int row_number, int column_number) -> bytes | None:
cdef int crow = row_number
cdef int ccol = column_number
cdef int length = libpq.PQgetlength(self._pgresult_ptr, crow, ccol)
return libpq.PQparamtype(self._pgresult_ptr, param_number)
@property
- def command_status(self) -> Optional[bytes]:
+ def command_status(self) -> bytes | None:
cdef char *rv = libpq.PQcmdStatus(self._pgresult_ptr)
if rv is not NULL:
return rv
return None
@property
- def command_tuples(self) -> Optional[int]:
+ def command_tuples(self) -> int | None:
cdef char *rv = libpq.PQcmdTuples(self._pgresult_ptr)
if rv is NULL:
return None
return 1
- def quote(self, obj: bool) -> Optional[Buffer]:
+ def quote(self, obj: bool) -> Buffer | None:
if obj is True:
return b"true"
elif obj is False:
oid = oids.INTERVAL_OID
cdef int _style
- def __cinit__(self, cls, context: Optional[AdaptContext] = None):
+ def __cinit__(self, cls, context: AdaptContext | None = None):
cdef const char *ds = _get_intervalstyle(self._pgconn)
if ds[0] == b's': # sql_standard
format = PQ_TEXT
cdef int _order
- def __cinit__(self, oid: int, context: Optional[AdaptContext] = None):
+ def __cinit__(self, oid: int, context: AdaptContext | None = None):
cdef const char *ds = _get_datestyle(self._pgconn)
if ds[0] == b'I': # ISO
format = PQ_TEXT
cdef int _order
- def __cinit__(self, oid: int, context: Optional[AdaptContext] = None):
+ def __cinit__(self, oid: int, context: AdaptContext | None = None):
cdef const char *ds = _get_datestyle(self._pgconn)
if ds[0] == b'I': # ISO
cdef class _BaseTimestamptzLoader(CLoader):
cdef object _time_zone
- def __cinit__(self, oid: int, context: Optional[AdaptContext] = None):
+ def __cinit__(self, oid: int, context: AdaptContext | None = None):
self._time_zone = _timezone_from_connection(self._pgconn)
format = PQ_TEXT
cdef int _order
- def __cinit__(self, oid: int, context: Optional[AdaptContext] = None):
+ def __cinit__(self, oid: int, context: AdaptContext | None = None):
cdef const char *ds = _get_datestyle(self._pgconn)
if ds[0] == b'I': # ISO
format = PQ_TEXT
cdef int _style
- def __cinit__(self, oid: int, context: Optional[AdaptContext] = None):
+ def __cinit__(self, oid: int, context: AdaptContext | None = None):
cdef const char *ds = _get_intervalstyle(self._pgconn)
if ds[0] == b'p' and ds[8] == 0: # postgres
cdef object _get_timestamp_load_error(
- pq.PGconn pgconn, const char *data, ex: Optional[Exception] = None
+ pq.PGconn pgconn, const char *data, ex: Exception | None = None
):
s = bytes(data).decode("utf8", "replace")
cdef Py_ssize_t cdump(self, obj, bytearray rv, Py_ssize_t offset) except -1:
return dump_int_to_text(obj, rv, offset)
- def quote(self, obj) -> Optional[Buffer]:
+ def quote(self, obj) -> Buffer | None:
cdef Py_ssize_t length
rv = PyByteArray_FromStringAndSize("", 0)
PyMem_Free(out)
return length
- def quote(self, obj) -> Optional[Buffer]:
+ def quote(self, obj) -> Buffer | None:
value = bytes(self.dump(obj))
cdef PyObject *ptr = PyDict_GetItem(_special_float, value)
if ptr != NULL:
cdef Py_ssize_t cdump(self, obj, bytearray rv, Py_ssize_t offset) except -1:
return dump_decimal_to_text(obj, rv, offset)
- def quote(self, obj) -> Optional[Buffer]:
+ def quote(self, obj) -> Buffer | None:
value = bytes(self.dump(obj))
cdef PyObject *ptr = PyDict_GetItem(_special_decimal, value)
if ptr != NULL:
oid = oids.NUMERIC_OID
- def __cinit__(self, cls, context: Optional[AdaptContext] = None):
+ def __cinit__(self, cls, context: AdaptContext | None = None):
global _int_classes
if _int_classes is None:
cdef char *encoding
cdef bytes _bytes_encoding # needed to keep `encoding` alive
- def __cinit__(self, cls, context: Optional[AdaptContext] = None):
+ def __cinit__(self, cls, context: AdaptContext | None = None):
self.is_utf8 = 0
self.encoding = "utf-8"
cdef char *encoding
cdef bytes _bytes_encoding # needed to keep `encoding` alive
- def __cinit__(self, oid: int, context: Optional[AdaptContext] = None):
+ def __cinit__(self, oid: int, context: AdaptContext | None = None):
self.is_utf8 = 0
self.encoding = "utf-8"
# Copyright (C) 2023 The Psycopg Team
-from typing import Any, Callable, Optional
+from __future__ import annotations
+
+from typing import Any, Callable
from dataclasses import dataclass, field
@dataclass(order=True)
class Task:
time: float
- action: Optional[Callable[[], Any]] = field(compare=False)
+ action: Callable[[], Any] | None = field(compare=False)
# Copyright (C) 2021 The Psycopg Team
+from __future__ import annotations
+
from time import monotonic
from random import random
-from typing import Any, Dict, Optional, Tuple, TYPE_CHECKING
+from typing import Any, Dict, Tuple, TYPE_CHECKING
from psycopg import errors as e
self,
conninfo: str = "",
*,
- kwargs: Optional[Dict[str, Any]],
+ kwargs: Dict[str, Any] | None,
min_size: int,
- max_size: Optional[int],
- name: Optional[str],
+ max_size: int | None,
+ name: str | None,
timeout: float,
max_waiting: int,
max_lifetime: float,
"""`!True` if the pool is closed."""
return self._closed
- def _check_size(self, min_size: int, max_size: Optional[int]) -> Tuple[int, int]:
+ def _check_size(self, min_size: int, max_size: int | None) -> Tuple[int, int]:
if max_size is None:
max_size = min_size
from __future__ import annotations
import logging
-from typing import Any, cast, Dict, Optional, Type
+from typing import Any, cast, Dict, Type
from psycopg import Connection
from psycopg.pq import TransactionStatus
conninfo: str = "",
*,
connection_class: Type[CT] = cast(Type[CT], Connection),
- kwargs: Optional[Dict[str, Any]] = None,
+ kwargs: Dict[str, Any] | None = None,
min_size: int = 0,
- max_size: Optional[int] = None,
+ max_size: int | None = None,
open: bool | None = None,
- configure: Optional[ConnectionCB[CT]] = None,
- check: Optional[ConnectionCB[CT]] = None,
- reset: Optional[ConnectionCB[CT]] = None,
- name: Optional[str] = None,
+ configure: ConnectionCB[CT] | None = None,
+ check: ConnectionCB[CT] | None = None,
+ reset: ConnectionCB[CT] | None = None,
+ name: str | None = None,
timeout: float = 30.0,
max_waiting: int = 0,
max_lifetime: float = 60 * 60.0,
max_idle: float = 10 * 60.0,
reconnect_timeout: float = 5 * 60.0,
- reconnect_failed: Optional[ConnectFailedCB] = None,
+ reconnect_failed: ConnectFailedCB | None = None,
num_workers: int = 3,
): # Note: min_size default value changed to 0.
logger.info("pool %r is ready to use", self.name)
- def _get_ready_connection(self, timeout: Optional[float]) -> Optional[CT]:
+ def _get_ready_connection(self, timeout: float | None) -> CT | None:
if timeout is not None and timeout <= 0.0:
raise PoolTimeout()
- conn: Optional[CT] = None
+ conn: CT | None = None
if self.max_size == 0 or self._nconns < self.max_size:
# Create a new connection for the client
try:
self._nconns -= 1
return True
- def resize(self, min_size: int, max_size: Optional[int] = None) -> None:
+ def resize(self, min_size: int, max_size: int | None = None) -> None:
"""Change the size of the pool during runtime.
Only *max_size* can be changed; *min_size* must remain 0.
from __future__ import annotations
import logging
-from typing import Any, cast, Dict, Optional, Type
+from typing import Any, cast, Dict, Type
from psycopg import AsyncConnection
from psycopg.pq import TransactionStatus
conninfo: str = "",
*,
connection_class: Type[ACT] = cast(Type[ACT], AsyncConnection),
- kwargs: Optional[Dict[str, Any]] = None,
+ kwargs: Dict[str, Any] | None = None,
min_size: int = 0, # Note: min_size default value changed to 0.
- max_size: Optional[int] = None,
+ max_size: int | None = None,
open: bool | None = None,
- configure: Optional[AsyncConnectionCB[ACT]] = None,
- check: Optional[AsyncConnectionCB[ACT]] = None,
- reset: Optional[AsyncConnectionCB[ACT]] = None,
- name: Optional[str] = None,
+ configure: AsyncConnectionCB[ACT] | None = None,
+ check: AsyncConnectionCB[ACT] | None = None,
+ reset: AsyncConnectionCB[ACT] | None = None,
+ name: str | None = None,
timeout: float = 30.0,
max_waiting: int = 0,
max_lifetime: float = 60 * 60.0,
max_idle: float = 10 * 60.0,
reconnect_timeout: float = 5 * 60.0,
- reconnect_failed: Optional[AsyncConnectFailedCB] = None,
+ reconnect_failed: AsyncConnectFailedCB | None = None,
num_workers: int = 3,
):
super().__init__(
logger.info("pool %r is ready to use", self.name)
- async def _get_ready_connection(self, timeout: Optional[float]) -> Optional[ACT]:
+ async def _get_ready_connection(self, timeout: float | None) -> ACT | None:
if timeout is not None and timeout <= 0.0:
raise PoolTimeout()
- conn: Optional[ACT] = None
+ conn: ACT | None = None
if self.max_size == 0 or self._nconns < self.max_size:
# Create a new connection for the client
try:
self._nconns -= 1
return True
- async def resize(self, min_size: int, max_size: Optional[int] = None) -> None:
+ async def resize(self, min_size: int, max_size: int | None = None) -> None:
"""Change the size of the pool during runtime.
Only *max_size* can be changed; *min_size* must remain 0.
from time import monotonic
from types import TracebackType
from typing import Any, Iterator, cast, Dict, Generic, List
-from typing import Optional, Type
+from typing import Type
from weakref import ref
from contextlib import contextmanager
conninfo: str = "",
*,
connection_class: Type[CT] = cast(Type[CT], Connection),
- kwargs: Optional[Dict[str, Any]] = None,
+ kwargs: Dict[str, Any] | None = None,
min_size: int = 4,
- max_size: Optional[int] = None,
+ max_size: int | None = None,
open: bool | None = None,
- configure: Optional[ConnectionCB[CT]] = None,
- check: Optional[ConnectionCB[CT]] = None,
- reset: Optional[ConnectionCB[CT]] = None,
- name: Optional[str] = None,
+ configure: ConnectionCB[CT] | None = None,
+ check: ConnectionCB[CT] | None = None,
+ reset: ConnectionCB[CT] | None = None,
+ name: str | None = None,
timeout: float = 30.0,
max_waiting: int = 0,
max_lifetime: float = 60 * 60.0,
max_idle: float = 10 * 60.0,
reconnect_timeout: float = 5 * 60.0,
- reconnect_failed: Optional[ConnectFailedCB] = None,
+ reconnect_failed: ConnectFailedCB | None = None,
num_workers: int = 3,
):
self.connection_class = connection_class
self._waiting = Deque[WaitingClient[CT]]()
# to notify that the pool is full
- self._pool_full_event: Optional[Event] = None
+ self._pool_full_event: Event | None = None
- self._sched_runner: Optional[Worker] = None
+ self._sched_runner: Worker | None = None
self._workers: List[Worker] = []
super().__init__(
logger.info("pool %r is ready to use", self.name)
@contextmanager
- def connection(self, timeout: Optional[float] = None) -> Iterator[CT]:
+ def connection(self, timeout: float | None = None) -> Iterator[CT]:
"""Context manager to obtain a connection from the pool.
Return the connection immediately if available, otherwise wait up to
t1 = monotonic()
self._stats[self._USAGE_MS] += int(1000.0 * (t1 - t0))
- def getconn(self, timeout: Optional[float] = None) -> CT:
+ def getconn(self, timeout: float | None = None) -> CT:
"""Obtain a connection from the pool.
You should preferably use `connection()`. Use this function only if
conn._pool = self
return conn
- def _get_ready_connection(self, timeout: Optional[float]) -> Optional[CT]:
+ def _get_ready_connection(self, timeout: float | None) -> CT | None:
"""Return a connection, if the client deserves one."""
if timeout is not None and timeout <= 0.0:
raise PoolTimeout()
- conn: Optional[CT] = None
+ conn: CT | None = None
if self._pool:
# Take a connection ready out of the pool
conn = self._pool.popleft()
def __exit__(
self,
- exc_type: Optional[Type[BaseException]],
- exc_val: Optional[BaseException],
- exc_tb: Optional[TracebackType],
+ exc_type: Type[BaseException] | None,
+ exc_val: BaseException | None,
+ exc_tb: TracebackType | None,
) -> None:
self.close()
- def resize(self, min_size: int, max_size: Optional[int] = None) -> None:
+ def resize(self, min_size: int, max_size: int | None = None) -> None:
"""Change the size of the pool during runtime."""
min_size, max_size = self._check_size(min_size, max_size)
"task run %s failed: %s: %s", task, ex.__class__.__name__, ex
)
- def _connect(self, timeout: Optional[float] = None) -> CT:
+ def _connect(self, timeout: float | None = None) -> CT:
"""Return a new connection configured for the pool."""
self._stats[self._CONNECTIONS_NUM] += 1
kwargs = self.kwargs
return conn
def _add_connection(
- self, attempt: Optional[AttemptWithBackoff], growing: bool = False
+ self, attempt: AttemptWithBackoff | None, growing: bool = False
) -> None:
"""Try to connect and add the connection to the pool.
conn.close()
def _shrink_pool(self) -> None:
- to_close: Optional[CT] = None
+ to_close: CT | None = None
with self._lock:
# Reset the min number of connections used
__slots__ = ("conn", "error", "_cond")
def __init__(self) -> None:
- self.conn: Optional[CT] = None
- self.error: Optional[BaseException] = None
+ self.conn: CT | None = None
+ self.error: BaseException | None = None
# The WaitingClient behaves in a way similar to an Event, but we need
# to notify reliably the flagger that the waiter has "accepted" the
def __init__(
self,
pool: ConnectionPool[Any],
- attempt: Optional[AttemptWithBackoff] = None,
+ attempt: AttemptWithBackoff | None = None,
growing: bool = False,
):
super().__init__(pool)
from time import monotonic
from types import TracebackType
from typing import Any, AsyncIterator, cast, Dict, Generic, List
-from typing import Optional, Type
+from typing import Type
from weakref import ref
from contextlib import asynccontextmanager
conninfo: str = "",
*,
connection_class: Type[ACT] = cast(Type[ACT], AsyncConnection),
- kwargs: Optional[Dict[str, Any]] = None,
+ kwargs: Dict[str, Any] | None = None,
min_size: int = 4,
- max_size: Optional[int] = None,
+ max_size: int | None = None,
open: bool | None = None,
- configure: Optional[AsyncConnectionCB[ACT]] = None,
- check: Optional[AsyncConnectionCB[ACT]] = None,
- reset: Optional[AsyncConnectionCB[ACT]] = None,
- name: Optional[str] = None,
+ configure: AsyncConnectionCB[ACT] | None = None,
+ check: AsyncConnectionCB[ACT] | None = None,
+ reset: AsyncConnectionCB[ACT] | None = None,
+ name: str | None = None,
timeout: float = 30.0,
max_waiting: int = 0,
max_lifetime: float = 60 * 60.0,
max_idle: float = 10 * 60.0,
reconnect_timeout: float = 5 * 60.0,
- reconnect_failed: Optional[AsyncConnectFailedCB] = None,
+ reconnect_failed: AsyncConnectFailedCB | None = None,
num_workers: int = 3,
):
self.connection_class = connection_class
self._waiting = Deque[WaitingClient[ACT]]()
# to notify that the pool is full
- self._pool_full_event: Optional[AEvent] = None
+ self._pool_full_event: AEvent | None = None
- self._sched_runner: Optional[AWorker] = None
+ self._sched_runner: AWorker | None = None
self._workers: List[AWorker] = []
super().__init__(
logger.info("pool %r is ready to use", self.name)
@asynccontextmanager
- async def connection(self, timeout: Optional[float] = None) -> AsyncIterator[ACT]:
+ async def connection(self, timeout: float | None = None) -> AsyncIterator[ACT]:
"""Context manager to obtain a connection from the pool.
Return the connection immediately if available, otherwise wait up to
t1 = monotonic()
self._stats[self._USAGE_MS] += int(1000.0 * (t1 - t0))
- async def getconn(self, timeout: Optional[float] = None) -> ACT:
+ async def getconn(self, timeout: float | None = None) -> ACT:
"""Obtain a connection from the pool.
You should preferably use `connection()`. Use this function only if
conn._pool = self
return conn
- async def _get_ready_connection(self, timeout: Optional[float]) -> Optional[ACT]:
+ async def _get_ready_connection(self, timeout: float | None) -> ACT | None:
"""Return a connection, if the client deserves one."""
if timeout is not None and timeout <= 0.0:
raise PoolTimeout()
- conn: Optional[ACT] = None
+ conn: ACT | None = None
if self._pool:
# Take a connection ready out of the pool
conn = self._pool.popleft()
async def __aexit__(
self,
- exc_type: Optional[Type[BaseException]],
- exc_val: Optional[BaseException],
- exc_tb: Optional[TracebackType],
+ exc_type: Type[BaseException] | None,
+ exc_val: BaseException | None,
+ exc_tb: TracebackType | None,
) -> None:
await self.close()
- async def resize(self, min_size: int, max_size: Optional[int] = None) -> None:
+ async def resize(self, min_size: int, max_size: int | None = None) -> None:
"""Change the size of the pool during runtime."""
min_size, max_size = self._check_size(min_size, max_size)
"task run %s failed: %s: %s", task, ex.__class__.__name__, ex
)
- async def _connect(self, timeout: Optional[float] = None) -> ACT:
+ async def _connect(self, timeout: float | None = None) -> ACT:
"""Return a new connection configured for the pool."""
self._stats[self._CONNECTIONS_NUM] += 1
kwargs = self.kwargs
return conn
async def _add_connection(
- self, attempt: Optional[AttemptWithBackoff], growing: bool = False
+ self, attempt: AttemptWithBackoff | None, growing: bool = False
) -> None:
"""Try to connect and add the connection to the pool.
await conn.close()
async def _shrink_pool(self) -> None:
- to_close: Optional[ACT] = None
+ to_close: ACT | None = None
async with self._lock:
# Reset the min number of connections used
__slots__ = ("conn", "error", "_cond")
def __init__(self) -> None:
- self.conn: Optional[ACT] = None
- self.error: Optional[BaseException] = None
+ self.conn: ACT | None = None
+ self.error: BaseException | None = None
# The WaitingClient behaves in a way similar to an Event, but we need
# to notify reliably the flagger that the waiter has "accepted" the
def __init__(
self,
pool: AsyncConnectionPool[Any],
- attempt: Optional[AttemptWithBackoff] = None,
+ attempt: AttemptWithBackoff | None = None,
growing: bool = False,
):
super().__init__(pool)
# Copyright (C) 2021 The Psycopg Team
+from __future__ import annotations
+
import logging
from time import monotonic
from heapq import heappush, heappop
-from typing import Any, Callable, List, Optional
+from typing import Any, Callable, List
from ._task import Task
from ._acompat import Lock, Event
EMPTY_QUEUE_TIMEOUT = 600.0
- def enter(self, delay: float, action: Optional[Callable[[], Any]]) -> Task:
+ def enter(self, delay: float, action: Callable[[], Any] | None) -> Task:
"""Enter a new task in the queue delayed in the future.
Schedule a `!None` to stop the execution.
time = monotonic() + delay
return self.enterabs(time, action)
- def enterabs(self, time: float, action: Optional[Callable[[], Any]]) -> Task:
+ def enterabs(self, time: float, action: Callable[[], Any] | None) -> Task:
"""Enter a new task in the queue at an absolute time.
Schedule a `!None` to stop the execution.
# Copyright (C) 2021 The Psycopg Team
+from __future__ import annotations
+
import logging
from time import monotonic
from heapq import heappush, heappop
-from typing import Any, Callable, List, Optional
+from typing import Any, Callable, List
from ._task import Task
from ._acompat import ALock, AEvent
EMPTY_QUEUE_TIMEOUT = 600.0
- async def enter(self, delay: float, action: Optional[Callable[[], Any]]) -> Task:
+ async def enter(self, delay: float, action: Callable[[], Any] | None) -> Task:
"""Enter a new task in the queue delayed in the future.
Schedule a `!None` to stop the execution.
time = monotonic() + delay
return await self.enterabs(time, action)
- async def enterabs(self, time: float, action: Optional[Callable[[], Any]]) -> Task:
+ async def enterabs(self, time: float, action: Callable[[], Any] | None) -> Task:
"""Enter a new task in the queue at an absolute time.
Schedule a `!None` to stop the execution.
-from typing import Optional
+from __future__ import annotations
from psycopg import pq
from psycopg.abc import Dumper, Loader, AdaptContext, PyFormat, Buffer
format = pq.Format.TEXT
oid = 25 # text
- def __init__(self, cls: type, context: Optional[AdaptContext] = None):
+ def __init__(self, cls: type, context: AdaptContext | None = None):
self._cls = cls
def dump(self, obj: str) -> bytes:
class MyTextLoader:
format = pq.Format.TEXT
- def __init__(self, oid: int, context: Optional[AdaptContext] = None):
+ def __init__(self, oid: int, context: AdaptContext | None = None):
pass
def load(self, data: Buffer) -> str:
-from typing import Optional
+from __future__ import annotations
import pytest
is_crdb = CrdbConnection.is_crdb
-def crdb_skip_message(reason: Optional[str]) -> str:
+def crdb_skip_message(reason: str | None) -> str:
msg = ""
if reason:
msg = reason
+from __future__ import annotations
+
import io
import os
import sys
import pytest
import logging
from contextlib import contextmanager
-from typing import Optional
import psycopg
from psycopg import pq
# Set by warm_up_database() the first time the dsn fixture is used
pg_version: int
-crdb_version: Optional[int]
+crdb_version: int | None
def pytest_addoption(parser):
+from __future__ import annotations
+
import datetime as dt
import importlib
import ipaddress
from math import isnan
from uuid import UUID
from random import choice, random, randrange
-from typing import Any, List, Optional, Set, Tuple, Union
+from typing import Any, List, Set, Tuple, Union
from decimal import Decimal
from contextlib import contextmanager, asynccontextmanager
self.records = []
self._schema = None
- self._types: Optional[List[type]] = None
+ self._types: List[type] | None = None
self._types_names = None
self._makers = {}
self.table_name = sql.Identifier("fake_table")
happens when the output buffer is full.
"""
+from __future__ import annotations
+
import argparse
import asyncio
import logging
from contextlib import contextmanager
from functools import partial
-from typing import Any, Iterator, Optional, Sequence, Tuple
+from typing import Any, Iterator, Sequence, Tuple
from psycopg import AsyncConnection, Connection
from psycopg import pq, waiting
self._logger = logger
def log_notice(result: pq.abc.PGresult) -> None:
- def get_field(field: DiagnosticField) -> Optional[str]:
+ def get_field(field: DiagnosticField) -> str | None:
value = result.error_field(field)
return value.decode("utf-8", "replace") if value else None
def send_query_params(
self,
command: bytes,
- param_values: Optional[Sequence[Optional[bytes]]],
- param_types: Optional[Sequence[int]] = None,
- param_formats: Optional[Sequence[int]] = None,
+ param_values: Sequence[bytes | None] | None,
+ param_types: Sequence[int] | None = None,
+ param_formats: Sequence[int] | None = None,
result_format: int = Format.TEXT,
) -> None:
self._pgconn.send_query_params(
def send_query_prepared(
self,
name: bytes,
- param_values: Optional[Sequence[Optional[bytes]]],
- param_formats: Optional[Sequence[int]] = None,
+ param_values: Sequence[bytes | None] | None,
+ param_formats: Sequence[int] | None = None,
result_format: int = Format.TEXT,
) -> None:
self._pgconn.send_query_prepared(
self,
name: bytes,
command: bytes,
- param_types: Optional[Sequence[int]] = None,
+ param_types: Sequence[int] | None = None,
) -> None:
self._pgconn.send_prepare(name, command, param_types)
self._logger.info("prepare %s as '%s'", command.decode(), name.decode())
- def get_result(self) -> Optional[pq.abc.PGresult]:
+ def get_result(self) -> pq.abc.PGresult | None:
r = self._pgconn.get_result()
if r is not None:
self._logger.info("got %s result", pq.ExecStatus(r.status).name)
+from __future__ import annotations
+
import datetime as dt
from types import ModuleType
-from typing import Any, List, Optional
+from typing import Any, List
import pytest
class StrNoneDumper(StrDumper):
- def dump(self, obj: str) -> Optional[Buffer]:
+ def dump(self, obj: str) -> Buffer | None:
return super().dump(obj) if obj else None
class StrNoneBinaryDumper(StrBinaryDumper):
- def dump(self, obj: str) -> Optional[Buffer]:
+ def dump(self, obj: str) -> Buffer | None:
return super().dump(obj) if obj else None
+from __future__ import annotations
+
import os
import pytest
[
(
"conn.cursor()",
- "Optional[Tuple[Any, ...]]",
+ "Tuple[Any, ...] | None",
),
(
"conn.cursor(row_factory=rows.dict_row)",
- "Optional[Dict[str, Any]]",
+ "Dict[str, Any] | None",
),
(
"conn.cursor(row_factory=thing_row)",
- "Optional[Thing]",
+ "Thing | None",
),
],
)
def _test_reveal(stmts, type, mypy):
- ignore = "" if type.startswith("Optional") else "# type: ignore[assignment]"
+ ignore = "" if type.endswith("| None") else "# type: ignore[assignment]"
stmts = "\n".join(f" {line}" for line in stmts.splitlines())
src = f"""\
-from typing import Any, Callable, Dict, List, NamedTuple, Optional, Sequence
+from typing import Any, Callable, Dict, List, NamedTuple, Sequence
from typing import Tuple, Union
import psycopg
from psycopg import rows
+from __future__ import annotations
+
import enum
from math import isnan, isinf, exp
-from typing import Optional
from decimal import Decimal
import pytest
Base: type = Int8Dumper if fmt_in == PyFormat.TEXT else Int8BinaryDumper
class MyDumper(Base): # type: ignore
- def dump(self, obj: int) -> Optional[Buffer]:
+ def dump(self, obj: int) -> Buffer | None:
if not obj:
return None
else:
from __future__ import annotations
from dataclasses import dataclass
-from typing import Any, Callable, Dict, Optional, Sequence, Tuple, Union
+from typing import Any, Callable, Dict, Sequence, Tuple, Union
from psycopg import Connection, Cursor, ServerCursor, connect, rows
from psycopg import AsyncConnection, AsyncCursor, AsyncServerCursor
cur1: Cursor[Any]
cur1 = conn.cursor()
- r1: Optional[Any]
+ r1: Any | None
r1 = cur1.fetchone()
r1 is not None
cur2: Cursor[int]
- r2: Optional[int]
+ r2: int | None
with conn.cursor(row_factory=int_row_factory) as cur2:
cur2.execute("select 1")
r2 = cur2.fetchone()
cur1: AsyncCursor[Any]
cur1 = conn.cursor()
- r1: Optional[Any]
+ r1: Any | None
r1 = await cur1.fetchone()
r1 is not None
cur2: AsyncCursor[int]
- r2: Optional[int]
+ r2: int | None
async with conn.cursor(row_factory=int_row_factory) as cur2:
await cur2.execute("select 1")
r2 = await cur2.fetchone()
"""
conn1: Connection[int]
cur1: Cursor[int]
- r1: Optional[int]
+ r1: int | None
conn1 = connect(row_factory=int_row_factory)
cur1 = conn1.execute("select 1")
r1 = cur1.fetchone()
conn2: Connection[Person]
cur2: Cursor[Person]
- r2: Optional[Person]
+ r2: Person | None
conn2 = connect(row_factory=Person.row_factory)
cur2 = conn2.execute("select * from persons")
r2 = cur2.fetchone()
cur2.execute("select 2")
cur3: Cursor[Tuple[Any, ...]]
- r3: Optional[Tuple[Any, ...]]
+ r3: Tuple[Any, ...] | None
conn3 = connect()
cur3 = conn3.execute("select 3")
with conn3.cursor() as cur3:
"""
conn1: AsyncConnection[int]
cur1: AsyncCursor[int]
- r1: Optional[int]
+ r1: int | None
conn1 = await AsyncConnection.connect(row_factory=int_row_factory)
cur1 = await conn1.execute("select 1")
r1 = await cur1.fetchone()
conn2: AsyncConnection[Person]
cur2: AsyncCursor[Person]
- r2: Optional[Person]
+ r2: Person | None
conn2 = await AsyncConnection.connect(row_factory=Person.row_factory)
cur2 = await conn2.execute("select * from persons")
r2 = await cur2.fetchone()
await cur2.execute("select 2")
cur3: AsyncCursor[Tuple[Any, ...]]
- r3: Optional[Tuple[Any, ...]]
+ r3: Tuple[Any, ...] | None
conn3 = await AsyncConnection.connect()
cur3 = await conn3.execute("select 3")
async with conn3.cursor() as cur3:
+from __future__ import annotations
+
import re
import sys
import operator
-from typing import Callable, Optional, Tuple
+from typing import Callable, Tuple
from contextlib import contextmanager
self,
*,
skip: bool = False,
- op: Optional[str] = None,
+ op: str | None = None,
version_tuple: Tuple[int, ...] = (),
whose: str = "(wanted)",
postgres_rule: bool = False,
skip=skip, op=op, version_tuple=version_tuple, postgres_rule=postgres_rule
)
- def get_skip_message(self, version: Optional[int]) -> Optional[str]:
+ def get_skip_message(self, version: int | None) -> str | None:
got_tuple = self._parse_int_version(version)
- msg: Optional[str] = None
+ msg: str | None = None
if self.skip:
if got_tuple:
if not self.version_tuple:
op = getattr(operator, self._OP_NAMES[self.op])
return op(got_tuple, version_tuple)
- def _parse_int_version(self, version: Optional[int]) -> Tuple[int, ...]:
+ def _parse_int_version(self, version: int | None) -> Tuple[int, ...]:
if version is None:
return ()
version, ver_fix = divmod(version, 100)