This commit is contained in:
2025-05-22 20:25:38 +02:00
parent 09f6750c2b
commit ce03fbf12f
529 changed files with 3353 additions and 3312 deletions

View File

@@ -1047,7 +1047,7 @@ class AssociationProxyInstance(SQLORMOperations[_T]):
target_assoc = self._unwrap_target_assoc_proxy
if target_assoc is not None:
inner = target_assoc._criterion_exists( # type: ignore
inner = target_assoc._criterion_exists(
criterion=criterion, **kwargs
)
return self._comparator._criterion_exists(inner)
@@ -1961,7 +1961,7 @@ class _AssociationSet(_AssociationSingleItem[_T], MutableSet[_T]):
return set(self).symmetric_difference(__s)
def __xor__(self, s: AbstractSet[_S]) -> MutableSet[Union[_T, _S]]:
return self.symmetric_difference(s) # type: ignore
return self.symmetric_difference(s)
def symmetric_difference_update(self, other: Iterable[Any]) -> None:
want, have = self.symmetric_difference(other), set(self)

View File

@@ -22,3 +22,4 @@ from .session import async_sessionmaker as async_sessionmaker
from .session import AsyncAttrs as AsyncAttrs
from .session import AsyncSession as AsyncSession
from .session import AsyncSessionTransaction as AsyncSessionTransaction
from .session import close_all_sessions as close_all_sessions

View File

@@ -58,9 +58,7 @@ class ReversibleProxy(Generic[_PT]):
)
proxy_ref = weakref.ref(
self,
functools.partial( # type: ignore
ReversibleProxy._target_gced, target_ref
),
functools.partial(ReversibleProxy._target_gced, target_ref),
)
ReversibleProxy._proxy_objects[target_ref] = proxy_ref
@@ -70,7 +68,7 @@ class ReversibleProxy(Generic[_PT]):
def _target_gced(
cls,
ref: weakref.ref[_PT],
proxy_ref: Optional[weakref.ref[Self]] = None,
proxy_ref: Optional[weakref.ref[Self]] = None, # noqa: U100
) -> None:
cls._proxy_objects.pop(ref, None)
@@ -124,7 +122,7 @@ class StartableContext(Awaitable[_T_co], abc.ABC):
return self.start().__await__()
async def __aenter__(self) -> _T_co:
return await self.start(is_ctxmanager=True) # type: ignore
return await self.start(is_ctxmanager=True)
@abc.abstractmethod
async def __aexit__(

View File

@@ -257,7 +257,9 @@ class AsyncConnection(
AsyncEngine._retrieve_proxy_for_target(target.engine), target
)
async def start(self, is_ctxmanager: bool = False) -> AsyncConnection:
async def start(
self, is_ctxmanager: bool = False # noqa: U100
) -> AsyncConnection:
"""Start this :class:`_asyncio.AsyncConnection` object's context
outside of using a Python ``with:`` block.
@@ -1442,7 +1444,9 @@ def _get_sync_engine_or_connection(
@inspection._inspects(AsyncConnection)
def _no_insp_for_async_conn_yet(subject: AsyncConnection) -> NoReturn:
def _no_insp_for_async_conn_yet(
subject: AsyncConnection, # noqa: U100
) -> NoReturn:
raise exc.NoInspectionAvailable(
"Inspection on an AsyncConnection is currently not supported. "
"Please use ``run_sync`` to pass a callable where it's possible "
@@ -1452,7 +1456,9 @@ def _no_insp_for_async_conn_yet(subject: AsyncConnection) -> NoReturn:
@inspection._inspects(AsyncEngine)
def _no_insp_for_async_engine_xyet(subject: AsyncEngine) -> NoReturn:
def _no_insp_for_async_engine_xyet(
subject: AsyncEngine, # noqa: U100
) -> NoReturn:
raise exc.NoInspectionAvailable(
"Inspection on an AsyncEngine is currently not supported. "
"Please obtain a connection then use ``conn.run_sync`` to pass a "

View File

@@ -60,7 +60,7 @@ class AsyncCommon(FilterResult[_R]):
.. versionadded:: 2.0.0b3
"""
return self._real_result.closed # type: ignore
return self._real_result.closed
class AsyncResult(_WithKeys, AsyncCommon[Row[_TP]]):

View File

@@ -77,6 +77,7 @@ _T = TypeVar("_T", bound=Any)
"begin",
"begin_nested",
"close",
"reset",
"commit",
"connection",
"delete",
@@ -94,6 +95,8 @@ _T = TypeVar("_T", bound=Any)
"rollback",
"scalar",
"scalars",
"get",
"get_one",
"stream",
"stream_scalars",
],
@@ -108,6 +111,7 @@ _T = TypeVar("_T", bound=Any)
"no_autoflush",
"info",
],
use_intermediate_variable=["get"],
)
class async_scoped_session(Generic[_AS]):
"""Provides scoped management of :class:`.AsyncSession` objects.
@@ -213,49 +217,6 @@ class async_scoped_session(Generic[_AS]):
await self.registry().close()
self.registry.clear()
async def get(
self,
entity: _EntityBindKey[_O],
ident: _PKIdentityArgument,
*,
options: Optional[Sequence[ORMOption]] = None,
populate_existing: bool = False,
with_for_update: ForUpdateParameter = None,
identity_token: Optional[Any] = None,
execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
) -> Optional[_O]:
r"""Return an instance based on the given primary key identifier,
or ``None`` if not found.
.. container:: class_bases
Proxied for the :class:`_asyncio.AsyncSession` class on
behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
.. seealso::
:meth:`_orm.Session.get` - main documentation for get
""" # noqa: E501
# this was proxied but Mypy is requiring the return type to be
# clarified
# work around:
# https://github.com/python/typing/discussions/1143
return_value = await self._proxied.get(
entity,
ident,
options=options,
populate_existing=populate_existing,
with_for_update=with_for_update,
identity_token=identity_token,
execution_options=execution_options,
)
return return_value
# START PROXY METHODS async_scoped_session
# code within this block is **programmatically,
@@ -433,6 +394,12 @@ class async_scoped_session(Generic[_AS]):
For a general description of ORM begin nested, see
:meth:`_orm.Session.begin_nested`.
.. seealso::
:ref:`aiosqlite_serializable` - special workarounds required
with the SQLite asyncio driver in order for SAVEPOINT to work
correctly.
""" # noqa: E501
@@ -447,34 +414,45 @@ class async_scoped_session(Generic[_AS]):
Proxied for the :class:`_asyncio.AsyncSession` class on
behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
This expunges all ORM objects associated with this
:class:`_asyncio.AsyncSession`, ends any transaction in progress and
:term:`releases` any :class:`_asyncio.AsyncConnection` objects which
this :class:`_asyncio.AsyncSession` itself has checked out from
associated :class:`_asyncio.AsyncEngine` objects. The operation then
leaves the :class:`_asyncio.AsyncSession` in a state which it may be
used again.
.. tip::
The :meth:`_asyncio.AsyncSession.close` method **does not prevent
the Session from being used again**. The
:class:`_asyncio.AsyncSession` itself does not actually have a
distinct "closed" state; it merely means the
:class:`_asyncio.AsyncSession` will release all database
connections and ORM objects.
.. seealso::
:meth:`_orm.Session.close` - main documentation for
"close"
:ref:`session_closing` - detail on the semantics of
:meth:`_asyncio.AsyncSession.close`
:meth:`_asyncio.AsyncSession.close` and
:meth:`_asyncio.AsyncSession.reset`.
""" # noqa: E501
return await self._proxied.close()
async def reset(self) -> None:
r"""Close out the transactional resources and ORM objects used by this
:class:`_orm.Session`, resetting the session to its initial state.
.. container:: class_bases
Proxied for the :class:`_asyncio.AsyncSession` class on
behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
.. versionadded:: 2.0.22
.. seealso::
:meth:`_orm.Session.reset` - main documentation for
"reset"
:ref:`session_closing` - detail on the semantics of
:meth:`_asyncio.AsyncSession.close` and
:meth:`_asyncio.AsyncSession.reset`.
""" # noqa: E501
return await self._proxied.reset()
async def commit(self) -> None:
r"""Commit the current transaction in progress.
@@ -483,6 +461,11 @@ class async_scoped_session(Generic[_AS]):
Proxied for the :class:`_asyncio.AsyncSession` class on
behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
.. seealso::
:meth:`_orm.Session.commit` - main documentation for
"commit"
""" # noqa: E501
return await self._proxied.commit()
@@ -1014,6 +997,11 @@ class async_scoped_session(Generic[_AS]):
Proxied for the :class:`_asyncio.AsyncSession` class on
behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
.. seealso::
:meth:`_orm.Session.rollback` - main documentation for
"rollback"
""" # noqa: E501
return await self._proxied.rollback()
@@ -1137,6 +1125,85 @@ class async_scoped_session(Generic[_AS]):
**kw,
)
async def get(
self,
entity: _EntityBindKey[_O],
ident: _PKIdentityArgument,
*,
options: Optional[Sequence[ORMOption]] = None,
populate_existing: bool = False,
with_for_update: ForUpdateParameter = None,
identity_token: Optional[Any] = None,
execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
) -> Union[_O, None]:
r"""Return an instance based on the given primary key identifier,
or ``None`` if not found.
.. container:: class_bases
Proxied for the :class:`_asyncio.AsyncSession` class on
behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
.. seealso::
:meth:`_orm.Session.get` - main documentation for get
""" # noqa: E501
result = await self._proxied.get(
entity,
ident,
options=options,
populate_existing=populate_existing,
with_for_update=with_for_update,
identity_token=identity_token,
execution_options=execution_options,
)
return result
async def get_one(
self,
entity: _EntityBindKey[_O],
ident: _PKIdentityArgument,
*,
options: Optional[Sequence[ORMOption]] = None,
populate_existing: bool = False,
with_for_update: ForUpdateParameter = None,
identity_token: Optional[Any] = None,
execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
) -> _O:
r"""Return an instance based on the given primary key identifier,
or raise an exception if not found.
.. container:: class_bases
Proxied for the :class:`_asyncio.AsyncSession` class on
behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
Raises ``sqlalchemy.orm.exc.NoResultFound`` if the query selects
no rows.
..versionadded: 2.0.22
.. seealso::
:meth:`_orm.Session.get_one` - main documentation for get_one
""" # noqa: E501
return await self._proxied.get_one(
entity,
ident,
options=options,
populate_existing=populate_existing,
with_for_update=with_for_update,
identity_token=identity_token,
execution_options=execution_options,
)
@overload
async def stream(
self,
@@ -1483,7 +1550,7 @@ class async_scoped_session(Generic[_AS]):
return self._proxied.info
@classmethod
async def close_all(self) -> None:
async def close_all(cls) -> None:
r"""Close all :class:`_asyncio.AsyncSession` sessions.
.. container:: class_bases
@@ -1491,6 +1558,8 @@ class async_scoped_session(Generic[_AS]):
Proxied for the :class:`_asyncio.AsyncSession` class on
behalf of the :class:`_asyncio.scoping.async_scoped_session` class.
.. deprecated:: 2.0 The :meth:`.AsyncSession.close_all` method is deprecated and will be removed in a future release. Please refer to :func:`_asyncio.close_all_sessions`.
""" # noqa: E501
return await AsyncSession.close_all()

View File

@@ -32,6 +32,7 @@ from .result import _ensure_sync_result
from .result import AsyncResult
from .result import AsyncScalarResult
from ... import util
from ...orm import close_all_sessions as _sync_close_all_sessions
from ...orm import object_session
from ...orm import Session
from ...orm import SessionTransaction
@@ -509,7 +510,7 @@ class AsyncSession(ReversibleProxy[Session]):
else:
execution_options = _EXECUTE_OPTIONS
result = await greenlet_spawn(
return await greenlet_spawn(
self.sync_session.scalar,
statement,
params=params,
@@ -517,7 +518,6 @@ class AsyncSession(ReversibleProxy[Session]):
bind_arguments=bind_arguments,
**kw,
)
return result
@overload
async def scalars(
@@ -588,7 +588,7 @@ class AsyncSession(ReversibleProxy[Session]):
with_for_update: ForUpdateParameter = None,
identity_token: Optional[Any] = None,
execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
) -> Optional[_O]:
) -> Union[_O, None]:
"""Return an instance based on the given primary key identifier,
or ``None`` if not found.
@@ -599,9 +599,7 @@ class AsyncSession(ReversibleProxy[Session]):
"""
# result_obj = self.sync_session.get(entity, ident)
result_obj = await greenlet_spawn(
return await greenlet_spawn(
cast("Callable[..., _O]", self.sync_session.get),
entity,
ident,
@@ -609,8 +607,44 @@ class AsyncSession(ReversibleProxy[Session]):
populate_existing=populate_existing,
with_for_update=with_for_update,
identity_token=identity_token,
execution_options=execution_options,
)
async def get_one(
self,
entity: _EntityBindKey[_O],
ident: _PKIdentityArgument,
*,
options: Optional[Sequence[ORMOption]] = None,
populate_existing: bool = False,
with_for_update: ForUpdateParameter = None,
identity_token: Optional[Any] = None,
execution_options: OrmExecuteOptionsParameter = util.EMPTY_DICT,
) -> _O:
"""Return an instance based on the given primary key identifier,
or raise an exception if not found.
Raises ``sqlalchemy.orm.exc.NoResultFound`` if the query selects
no rows.
..versionadded: 2.0.22
.. seealso::
:meth:`_orm.Session.get_one` - main documentation for get_one
"""
return await greenlet_spawn(
cast("Callable[..., _O]", self.sync_session.get_one),
entity,
ident,
options=options,
populate_existing=populate_existing,
with_for_update=with_for_update,
identity_token=identity_token,
execution_options=execution_options,
)
return result_obj
@overload
async def stream(
@@ -946,48 +980,70 @@ class AsyncSession(ReversibleProxy[Session]):
For a general description of ORM begin nested, see
:meth:`_orm.Session.begin_nested`.
.. seealso::
:ref:`aiosqlite_serializable` - special workarounds required
with the SQLite asyncio driver in order for SAVEPOINT to work
correctly.
"""
return AsyncSessionTransaction(self, nested=True)
async def rollback(self) -> None:
"""Rollback the current transaction in progress."""
"""Rollback the current transaction in progress.
.. seealso::
:meth:`_orm.Session.rollback` - main documentation for
"rollback"
"""
await greenlet_spawn(self.sync_session.rollback)
async def commit(self) -> None:
"""Commit the current transaction in progress."""
"""Commit the current transaction in progress.
.. seealso::
:meth:`_orm.Session.commit` - main documentation for
"commit"
"""
await greenlet_spawn(self.sync_session.commit)
async def close(self) -> None:
"""Close out the transactional resources and ORM objects used by this
:class:`_asyncio.AsyncSession`.
This expunges all ORM objects associated with this
:class:`_asyncio.AsyncSession`, ends any transaction in progress and
:term:`releases` any :class:`_asyncio.AsyncConnection` objects which
this :class:`_asyncio.AsyncSession` itself has checked out from
associated :class:`_asyncio.AsyncEngine` objects. The operation then
leaves the :class:`_asyncio.AsyncSession` in a state which it may be
used again.
.. tip::
The :meth:`_asyncio.AsyncSession.close` method **does not prevent
the Session from being used again**. The
:class:`_asyncio.AsyncSession` itself does not actually have a
distinct "closed" state; it merely means the
:class:`_asyncio.AsyncSession` will release all database
connections and ORM objects.
.. seealso::
:meth:`_orm.Session.close` - main documentation for
"close"
:ref:`session_closing` - detail on the semantics of
:meth:`_asyncio.AsyncSession.close`
:meth:`_asyncio.AsyncSession.close` and
:meth:`_asyncio.AsyncSession.reset`.
"""
await greenlet_spawn(self.sync_session.close)
async def reset(self) -> None:
"""Close out the transactional resources and ORM objects used by this
:class:`_orm.Session`, resetting the session to its initial state.
.. versionadded:: 2.0.22
.. seealso::
:meth:`_orm.Session.reset` - main documentation for
"reset"
:ref:`session_closing` - detail on the semantics of
:meth:`_asyncio.AsyncSession.close` and
:meth:`_asyncio.AsyncSession.reset`.
"""
await greenlet_spawn(self.sync_session.reset)
async def aclose(self) -> None:
"""A synonym for :meth:`_asyncio.AsyncSession.close`.
@@ -1008,9 +1064,15 @@ class AsyncSession(ReversibleProxy[Session]):
await greenlet_spawn(self.sync_session.invalidate)
@classmethod
async def close_all(self) -> None:
@util.deprecated(
"2.0",
"The :meth:`.AsyncSession.close_all` method is deprecated and will be "
"removed in a future release. Please refer to "
":func:`_asyncio.close_all_sessions`.",
)
async def close_all(cls) -> None:
"""Close all :class:`_asyncio.AsyncSession` sessions."""
await greenlet_spawn(self.sync_session.close_all)
await close_all_sessions()
async def __aenter__(self: _AS) -> _AS:
return self
@@ -1862,4 +1924,17 @@ def async_session(session: Session) -> Optional[AsyncSession]:
return AsyncSession._retrieve_proxy_for_target(session, regenerate=False)
async def close_all_sessions() -> None:
"""Close all :class:`_asyncio.AsyncSession` sessions.
.. versionadded:: 2.0.23
.. seealso::
:func:`.session.close_all_sessions`
"""
await greenlet_spawn(_sync_close_all_sessions)
_instance_state._async_provider = async_session # type: ignore

View File

@@ -200,7 +200,7 @@ Using ``inplace`` to create pep-484 compliant hybrid properties
In the previous section, a :class:`.hybrid_property` decorator is illustrated
which includes two separate method-level functions being decorated, both
to produce a single object attribute referred towards as ``Interval.radius``.
to produce a single object attribute referenced as ``Interval.radius``.
There are actually several different modifiers we can use for
:class:`.hybrid_property` including :meth:`.hybrid_property.expression`,
:meth:`.hybrid_property.setter` and :meth:`.hybrid_property.update_expression`.
@@ -927,10 +927,10 @@ class _HybridDeleterType(Protocol[_T_co]):
...
class _HybridExprCallableType(Protocol[_T]):
class _HybridExprCallableType(Protocol[_T_co]):
def __call__(
s, cls: Any
) -> Union[_HasClauseElement, SQLColumnExpression[_T]]:
) -> Union[_HasClauseElement, SQLColumnExpression[_T_co]]:
...
@@ -1516,7 +1516,7 @@ class ExprComparator(Comparator[_T]):
def operate(
self, op: OperatorType, *other: Any, **kwargs: Any
) -> ColumnElement[Any]:
return op(self.expression, *other, **kwargs) # type: ignore
return op(self.expression, *other, **kwargs)
def reverse_operate(
self, op: OperatorType, other: Any, **kwargs: Any

View File

@@ -34,24 +34,23 @@ from mypy.types import UnboundType
from ... import util
COLUMN: int = util.symbol("COLUMN") # type: ignore
RELATIONSHIP: int = util.symbol("RELATIONSHIP") # type: ignore
REGISTRY: int = util.symbol("REGISTRY") # type: ignore
COLUMN_PROPERTY: int = util.symbol("COLUMN_PROPERTY") # type: ignore
TYPEENGINE: int = util.symbol("TYPEENGNE") # type: ignore
MAPPED: int = util.symbol("MAPPED") # type: ignore
DECLARATIVE_BASE: int = util.symbol("DECLARATIVE_BASE") # type: ignore
DECLARATIVE_META: int = util.symbol("DECLARATIVE_META") # type: ignore
MAPPED_DECORATOR: int = util.symbol("MAPPED_DECORATOR") # type: ignore
COLUMN_PROPERTY: int = util.symbol("COLUMN_PROPERTY") # type: ignore
SYNONYM_PROPERTY: int = util.symbol("SYNONYM_PROPERTY") # type: ignore
COMPOSITE_PROPERTY: int = util.symbol("COMPOSITE_PROPERTY") # type: ignore
DECLARED_ATTR: int = util.symbol("DECLARED_ATTR") # type: ignore
MAPPER_PROPERTY: int = util.symbol("MAPPER_PROPERTY") # type: ignore
AS_DECLARATIVE: int = util.symbol("AS_DECLARATIVE") # type: ignore
AS_DECLARATIVE_BASE: int = util.symbol("AS_DECLARATIVE_BASE") # type: ignore
DECLARATIVE_MIXIN: int = util.symbol("DECLARATIVE_MIXIN") # type: ignore
QUERY_EXPRESSION: int = util.symbol("QUERY_EXPRESSION") # type: ignore
COLUMN: int = util.symbol("COLUMN")
RELATIONSHIP: int = util.symbol("RELATIONSHIP")
REGISTRY: int = util.symbol("REGISTRY")
COLUMN_PROPERTY: int = util.symbol("COLUMN_PROPERTY")
TYPEENGINE: int = util.symbol("TYPEENGNE")
MAPPED: int = util.symbol("MAPPED")
DECLARATIVE_BASE: int = util.symbol("DECLARATIVE_BASE")
DECLARATIVE_META: int = util.symbol("DECLARATIVE_META")
MAPPED_DECORATOR: int = util.symbol("MAPPED_DECORATOR")
SYNONYM_PROPERTY: int = util.symbol("SYNONYM_PROPERTY")
COMPOSITE_PROPERTY: int = util.symbol("COMPOSITE_PROPERTY")
DECLARED_ATTR: int = util.symbol("DECLARED_ATTR")
MAPPER_PROPERTY: int = util.symbol("MAPPER_PROPERTY")
AS_DECLARATIVE: int = util.symbol("AS_DECLARATIVE")
AS_DECLARATIVE_BASE: int = util.symbol("AS_DECLARATIVE_BASE")
DECLARATIVE_MIXIN: int = util.symbol("DECLARATIVE_MIXIN")
QUERY_EXPRESSION: int = util.symbol("QUERY_EXPRESSION")
# names that must succeed with mypy.api.named_type
NAMED_TYPE_BUILTINS_OBJECT = "builtins.object"

View File

@@ -173,7 +173,7 @@ def get_mapped_attributes(
def format_type(typ_: Type, options: Options) -> str:
if mypy_14:
return _mypy_format_type(typ_, options) # type: ignore
return _mypy_format_type(typ_, options)
else:
return _mypy_format_type(typ_) # type: ignore