mirror of
https://gitlab.com/MoonTestUse1/AdministrationItDepartmens.git
synced 2025-08-14 00:25:46 +02:00
Проверка 09.02.2025
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# ext/asyncio/session.py
|
||||
# Copyright (C) 2020-2024 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2020-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
@@ -38,6 +38,9 @@ from ...orm import Session
|
||||
from ...orm import SessionTransaction
|
||||
from ...orm import state as _instance_state
|
||||
from ...util.concurrency import greenlet_spawn
|
||||
from ...util.typing import Concatenate
|
||||
from ...util.typing import ParamSpec
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .engine import AsyncConnection
|
||||
@@ -71,6 +74,7 @@ if TYPE_CHECKING:
|
||||
|
||||
_AsyncSessionBind = Union["AsyncEngine", "AsyncConnection"]
|
||||
|
||||
_P = ParamSpec("_P")
|
||||
_T = TypeVar("_T", bound=Any)
|
||||
|
||||
|
||||
@@ -332,9 +336,12 @@ class AsyncSession(ReversibleProxy[Session]):
|
||||
)
|
||||
|
||||
async def run_sync(
|
||||
self, fn: Callable[..., _T], *arg: Any, **kw: Any
|
||||
self,
|
||||
fn: Callable[Concatenate[Session, _P], _T],
|
||||
*arg: _P.args,
|
||||
**kw: _P.kwargs,
|
||||
) -> _T:
|
||||
"""Invoke the given synchronous (i.e. not async) callable,
|
||||
'''Invoke the given synchronous (i.e. not async) callable,
|
||||
passing a synchronous-style :class:`_orm.Session` as the first
|
||||
argument.
|
||||
|
||||
@@ -344,25 +351,27 @@ class AsyncSession(ReversibleProxy[Session]):
|
||||
E.g.::
|
||||
|
||||
def some_business_method(session: Session, param: str) -> str:
|
||||
'''A synchronous function that does not require awaiting
|
||||
"""A synchronous function that does not require awaiting
|
||||
|
||||
:param session: a SQLAlchemy Session, used synchronously
|
||||
|
||||
:return: an optional return value is supported
|
||||
|
||||
'''
|
||||
"""
|
||||
session.add(MyObject(param=param))
|
||||
session.flush()
|
||||
return "success"
|
||||
|
||||
|
||||
async def do_something_async(async_engine: AsyncEngine) -> None:
|
||||
'''an async function that uses awaiting'''
|
||||
"""an async function that uses awaiting"""
|
||||
|
||||
with AsyncSession(async_engine) as async_session:
|
||||
# run some_business_method() with a sync-style
|
||||
# Session, proxied into an awaitable
|
||||
return_code = await async_session.run_sync(some_business_method, param="param1")
|
||||
return_code = await async_session.run_sync(
|
||||
some_business_method, param="param1"
|
||||
)
|
||||
print(return_code)
|
||||
|
||||
This method maintains the asyncio event loop all the way through
|
||||
@@ -384,9 +393,11 @@ class AsyncSession(ReversibleProxy[Session]):
|
||||
:meth:`.AsyncConnection.run_sync`
|
||||
|
||||
:ref:`session_run_sync`
|
||||
""" # noqa: E501
|
||||
''' # noqa: E501
|
||||
|
||||
return await greenlet_spawn(fn, self.sync_session, *arg, **kw)
|
||||
return await greenlet_spawn(
|
||||
fn, self.sync_session, *arg, _require_await=False, **kw
|
||||
)
|
||||
|
||||
@overload
|
||||
async def execute(
|
||||
@@ -868,28 +879,28 @@ class AsyncSession(ReversibleProxy[Session]):
|
||||
|
||||
# construct async engines w/ async drivers
|
||||
engines = {
|
||||
'leader':create_async_engine("sqlite+aiosqlite:///leader.db"),
|
||||
'other':create_async_engine("sqlite+aiosqlite:///other.db"),
|
||||
'follower1':create_async_engine("sqlite+aiosqlite:///follower1.db"),
|
||||
'follower2':create_async_engine("sqlite+aiosqlite:///follower2.db"),
|
||||
"leader": create_async_engine("sqlite+aiosqlite:///leader.db"),
|
||||
"other": create_async_engine("sqlite+aiosqlite:///other.db"),
|
||||
"follower1": create_async_engine("sqlite+aiosqlite:///follower1.db"),
|
||||
"follower2": create_async_engine("sqlite+aiosqlite:///follower2.db"),
|
||||
}
|
||||
|
||||
|
||||
class RoutingSession(Session):
|
||||
def get_bind(self, mapper=None, clause=None, **kw):
|
||||
# within get_bind(), return sync engines
|
||||
if mapper and issubclass(mapper.class_, MyOtherClass):
|
||||
return engines['other'].sync_engine
|
||||
return engines["other"].sync_engine
|
||||
elif self._flushing or isinstance(clause, (Update, Delete)):
|
||||
return engines['leader'].sync_engine
|
||||
return engines["leader"].sync_engine
|
||||
else:
|
||||
return engines[
|
||||
random.choice(['follower1','follower2'])
|
||||
random.choice(["follower1", "follower2"])
|
||||
].sync_engine
|
||||
|
||||
|
||||
# apply to AsyncSession using sync_session_class
|
||||
AsyncSessionMaker = async_sessionmaker(
|
||||
sync_session_class=RoutingSession
|
||||
)
|
||||
AsyncSessionMaker = async_sessionmaker(sync_session_class=RoutingSession)
|
||||
|
||||
The :meth:`_orm.Session.get_bind` method is called in a non-asyncio,
|
||||
implicitly non-blocking context in the same manner as ORM event hooks
|
||||
@@ -945,7 +956,7 @@ class AsyncSession(ReversibleProxy[Session]):
|
||||
object is entered::
|
||||
|
||||
async with async_session.begin():
|
||||
# .. ORM transaction is begun
|
||||
... # ORM transaction is begun
|
||||
|
||||
Note that database IO will not normally occur when the session-level
|
||||
transaction is begun, as database transactions begin on an
|
||||
@@ -1298,7 +1309,7 @@ class AsyncSession(ReversibleProxy[Session]):
|
||||
|
||||
This method retrieves the history for each instrumented
|
||||
attribute on the instance and performs a comparison of the current
|
||||
value to its previously committed value, if any.
|
||||
value to its previously flushed or committed value, if any.
|
||||
|
||||
It is in effect a more expensive and accurate
|
||||
version of checking for the given instance in the
|
||||
@@ -1622,16 +1633,22 @@ class async_sessionmaker(Generic[_AS]):
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy.ext.asyncio import async_sessionmaker
|
||||
|
||||
async def run_some_sql(async_session: async_sessionmaker[AsyncSession]) -> None:
|
||||
|
||||
async def run_some_sql(
|
||||
async_session: async_sessionmaker[AsyncSession],
|
||||
) -> None:
|
||||
async with async_session() as session:
|
||||
session.add(SomeObject(data="object"))
|
||||
session.add(SomeOtherObject(name="other object"))
|
||||
await session.commit()
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
# an AsyncEngine, which the AsyncSession will use for connection
|
||||
# resources
|
||||
engine = create_async_engine('postgresql+asyncpg://scott:tiger@localhost/')
|
||||
engine = create_async_engine(
|
||||
"postgresql+asyncpg://scott:tiger@localhost/"
|
||||
)
|
||||
|
||||
# create a reusable factory for new AsyncSession instances
|
||||
async_session = async_sessionmaker(engine)
|
||||
@@ -1730,7 +1747,6 @@ class async_sessionmaker(Generic[_AS]):
|
||||
|
||||
# commits transaction, closes session
|
||||
|
||||
|
||||
"""
|
||||
|
||||
session = self()
|
||||
@@ -1763,7 +1779,7 @@ class async_sessionmaker(Generic[_AS]):
|
||||
|
||||
AsyncSession = async_sessionmaker(some_engine)
|
||||
|
||||
AsyncSession.configure(bind=create_async_engine('sqlite+aiosqlite://'))
|
||||
AsyncSession.configure(bind=create_async_engine("sqlite+aiosqlite://"))
|
||||
""" # noqa E501
|
||||
|
||||
self.kw.update(new_kw)
|
||||
@@ -1854,7 +1870,7 @@ class AsyncSessionTransaction(
|
||||
) -> AsyncSessionTransaction:
|
||||
self.sync_transaction = self._assign_proxied(
|
||||
await greenlet_spawn(
|
||||
self.session.sync_session.begin_nested # type: ignore
|
||||
self.session.sync_session.begin_nested
|
||||
if self.nested
|
||||
else self.session.sync_session.begin
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user