From: Daniele Varrazzo Date: Sun, 1 Aug 2021 20:33:44 +0000 (+0200) Subject: Drop AnyCursor from public interface X-Git-Tag: 3.0.dev2~21^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=45f4b3c40720e6917e3cb220a2d6b6534cceef60;p=thirdparty%2Fpsycopg.git Drop AnyCursor from public interface Name repurposed internally for the generic to represent the type of "self" in cursors. --- diff --git a/docs/advanced/rows.rst b/docs/advanced/rows.rst index 5781429c4..01e3d3672 100644 --- a/docs/advanced/rows.rst +++ b/docs/advanced/rows.rst @@ -38,8 +38,6 @@ callable (formally the `~psycopg.rows.RowMaker` protocol) accepting a Note that it's easy to implement an object implementing both `!RowFactory` and `!AsyncRowFactory`: usually, everything you need to implement a row factory is to access `~Cursor.description`, which is provided by both the cursor flavours. -The `psycopg` module also exposes a class `AnyCursor` which you may use if you -want to use the same row factory for both sync and async cursors. `~RowFactory` objects can be implemented as a class, for instance: @@ -90,13 +88,13 @@ The module `psycopg.rows` provides the implementation for a few row factories: .. currentmodule:: psycopg.rows -.. autofunction:: tuple_row(cursor: AnyCursor[TupleRow]) +.. autofunction:: tuple_row .. autodata:: TupleRow -.. autofunction:: dict_row(cursor: AnyCursor[DictRow]) +.. autofunction:: dict_row .. autodata:: DictRow -.. autofunction:: namedtuple_row(cursor: AnyCursor[NamedTuple]) +.. autofunction:: namedtuple_row Use with a static analyzer diff --git a/psycopg/psycopg/__init__.py b/psycopg/psycopg/__init__.py index 5706794f4..6d275db47 100644 --- a/psycopg/psycopg/__init__.py +++ b/psycopg/psycopg/__init__.py @@ -11,7 +11,7 @@ from . import types from . import postgres from .copy import Copy, AsyncCopy from ._enums import IsolationLevel -from .cursor import AnyCursor, AsyncCursor, Cursor +from .cursor import AsyncCursor, Cursor from .errors import Warning, Error, InterfaceError, DatabaseError from .errors import DataError, OperationalError, IntegrityError from .errors import InternalError, ProgrammingError, NotSupportedError @@ -51,7 +51,6 @@ adapters.register_dumper(Binary, BinaryBinaryDumper) # dbapi20 # so that function signatures are consistent with the documentation. __all__ = [ "__version__", - "AnyCursor", "AsyncConnection", "AsyncCopy", "AsyncCursor", diff --git a/psycopg/psycopg/_column.py b/psycopg/psycopg/_column.py index ac0f6f678..4e6a75b04 100644 --- a/psycopg/psycopg/_column.py +++ b/psycopg/psycopg/_column.py @@ -10,7 +10,7 @@ from operator import attrgetter from . import errors as e if TYPE_CHECKING: - from .cursor import AnyCursor + from .cursor import BaseCursor class ColumnData(NamedTuple): @@ -23,7 +23,7 @@ class Column(Sequence[Any]): __module__ = "psycopg" - def __init__(self, cursor: "AnyCursor[Any]", index: int): + def __init__(self, cursor: "BaseCursor[Any, Any]", index: int): res = cursor.pgresult assert res diff --git a/psycopg/psycopg/cursor.py b/psycopg/psycopg/cursor.py index 739fba3b3..df48cd3ac 100644 --- a/psycopg/psycopg/cursor.py +++ b/psycopg/psycopg/cursor.py @@ -28,8 +28,7 @@ from ._preparing import Prepare if TYPE_CHECKING: from .abc import Transformer from .pq.abc import PGconn, PGresult - from .connection import BaseConnection # noqa: F401 - from .connection import Connection, AsyncConnection # noqa: F401 + from .connection import Connection, AsyncConnection execute: Callable[["PGconn"], PQGen[List["PGresult"]]] @@ -452,10 +451,7 @@ class BaseCursor(Generic[ConnectionType, Row]): self._closed = True -AnyCursor = BaseCursor[Any, Row] - - -C = TypeVar("C", bound="BaseCursor[Any, Any]") +AnyCursor = TypeVar("AnyCursor", bound="BaseCursor[Any, Any]") class Cursor(BaseCursor["Connection[Any]", Row]): @@ -468,7 +464,7 @@ class Cursor(BaseCursor["Connection[Any]", Row]): super().__init__(connection) self._row_factory = row_factory - def __enter__(self: C) -> C: + def __enter__(self: AnyCursor) -> AnyCursor: return self def __exit__( @@ -500,12 +496,12 @@ class Cursor(BaseCursor["Connection[Any]", Row]): return self._row_factory(self) def execute( - self: C, + self: AnyCursor, query: Query, params: Optional[Params] = None, *, prepare: Optional[bool] = None, - ) -> C: + ) -> AnyCursor: """ Execute a query or command to the database. """ @@ -642,7 +638,7 @@ class AsyncCursor(BaseCursor["AsyncConnection[Any]", Row]): super().__init__(connection) self._row_factory = row_factory - async def __aenter__(self: C) -> C: + async def __aenter__(self: AnyCursor) -> AnyCursor: return self async def __aexit__( @@ -670,12 +666,12 @@ class AsyncCursor(BaseCursor["AsyncConnection[Any]", Row]): return self._row_factory(self) async def execute( - self: C, + self: AnyCursor, query: Query, params: Optional[Params] = None, *, prepare: Optional[bool] = None, - ) -> C: + ) -> AnyCursor: try: async with self._conn.lock: await self._conn.wait( diff --git a/psycopg/psycopg/rows.py b/psycopg/psycopg/rows.py index 5e4927e7f..21a7912f0 100644 --- a/psycopg/psycopg/rows.py +++ b/psycopg/psycopg/rows.py @@ -7,14 +7,14 @@ psycopg row factories import functools import re from collections import namedtuple -from typing import Any, Callable, Dict, NamedTuple, Sequence, Tuple, Type -from typing import TypeVar, TYPE_CHECKING +from typing import Any, Dict, NamedTuple, Sequence, Tuple, Type, TypeVar +from typing import TYPE_CHECKING from . import errors as e from .compat import Protocol if TYPE_CHECKING: - from .cursor import AnyCursor, Cursor, AsyncCursor + from .cursor import BaseCursor, Cursor, AsyncCursor # Row factories @@ -72,14 +72,13 @@ An alias for the type returned by `tuple_row()` (i.e. a tuple of any content). def tuple_row( - cursor: "AnyCursor[TupleRow]", -) -> Callable[[Sequence[Any]], TupleRow]: + cursor: "BaseCursor[Any, TupleRow]", +) -> RowMaker[TupleRow]: r"""Row factory to represent rows as simple tuples. This is the default factory. - :param cursor: The cursor where the rows are read. - :rtype: `RowMaker`\ [`TupleRow`] + :param cursor: The cursor where to read from. """ # Implementation detail: make sure this is the tuple type itself, not an # equivalent function, because the C code fast-paths on it. @@ -96,15 +95,14 @@ database. def dict_row( - cursor: "AnyCursor[DictRow]", -) -> Callable[[Sequence[Any]], DictRow]: + cursor: "BaseCursor[Any, DictRow]", +) -> RowMaker[DictRow]: r"""Row factory to represent rows as dicts. Note that this is not compatible with the DBAPI, which expects the records to be sequences. - :param cursor: The cursor where the rows are read. - :rtype: `RowMaker`\ [`DictRow`] + :param cursor: The cursor where to read from. """ def make_row(values: Sequence[Any]) -> Dict[str, Any]: @@ -118,12 +116,11 @@ def dict_row( def namedtuple_row( - cursor: "AnyCursor[NamedTuple]", -) -> Callable[[Sequence[Any]], NamedTuple]: + cursor: "BaseCursor[Any, NamedTuple]", +) -> RowMaker[NamedTuple]: r"""Row factory to represent rows as `~collections.namedtuple`. - :param cursor: The cursor where the rows are read. - :rtype: `RowMaker`\ [`NamedTuple`] + :param cursor: The cursor where to read from. """ def make_row(values: Sequence[Any]) -> NamedTuple: diff --git a/psycopg/psycopg/server_cursor.py b/psycopg/psycopg/server_cursor.py index ae58261ed..fc10fbd1c 100644 --- a/psycopg/psycopg/server_cursor.py +++ b/psycopg/psycopg/server_cursor.py @@ -13,11 +13,10 @@ from . import sql from . import errors as e from .abc import ConnectionType, Query, Params, PQGen from .rows import Row, RowFactory, AsyncRowFactory -from .cursor import C, BaseCursor, Cursor, AsyncCursor, execute +from .cursor import AnyCursor, BaseCursor, Cursor, AsyncCursor, execute if TYPE_CHECKING: - from .connection import BaseConnection # noqa: F401 - from .connection import Connection, AsyncConnection # noqa: F401 + from .connection import Connection, AsyncConnection DEFAULT_ITERSIZE = 100 @@ -235,11 +234,11 @@ class ServerCursor(Cursor[Row]): super().close() def execute( - self: C, + self: AnyCursor, query: Query, params: Optional[Params] = None, **kwargs: Any, - ) -> C: + ) -> AnyCursor: """ Open a cursor to execute a query to the database. """ @@ -351,11 +350,11 @@ class AsyncServerCursor(AsyncCursor[Row]): await super().close() async def execute( - self: C, + self: AnyCursor, query: Query, params: Optional[Params] = None, **kwargs: Any, - ) -> C: + ) -> AnyCursor: if kwargs: raise TypeError(f"keyword not supported: {list(kwargs)[0]}") helper = cast(AsyncServerCursor[Row], self)._helper diff --git a/tests/test_typing.py b/tests/test_typing.py index 3ef420673..aa66f6fc0 100644 --- a/tests/test_typing.py +++ b/tests/test_typing.py @@ -284,7 +284,8 @@ def _test_reveal(stmts, type, mypy, tmpdir): stmts = "\n".join(f" {line}" for line in stmts.splitlines()) src = f"""\ -from typing import Any, Callable, Dict, List, NamedTuple, Optional, Sequence, Tuple +from typing import Any, Callable, Dict, List, NamedTuple, Optional, Sequence +from typing import Tuple, Union import psycopg from psycopg import rows @@ -293,7 +294,7 @@ class Thing: self.kwargs = kwargs def thing_row( - cur: psycopg.AnyCursor[Thing], + cur: Union[psycopg.Cursor[Thing], psycopg.AsyncCursor[Thing]], ) -> Callable[[Sequence[Any]], Thing]: assert cur.description names = [d.name for d in cur.description]