diff options
Diffstat (limited to 'test/ext/asyncio/test_session_py3k.py')
| -rw-r--r-- | test/ext/asyncio/test_session_py3k.py | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/test/ext/asyncio/test_session_py3k.py b/test/ext/asyncio/test_session_py3k.py index 36135a43d..a374728f7 100644 --- a/test/ext/asyncio/test_session_py3k.py +++ b/test/ext/asyncio/test_session_py3k.py @@ -1,20 +1,31 @@ +from __future__ import annotations + +from typing import List +from typing import Optional + from sqlalchemy import Column from sqlalchemy import event from sqlalchemy import exc from sqlalchemy import ForeignKey from sqlalchemy import func +from sqlalchemy import Identity from sqlalchemy import inspect from sqlalchemy import Integer from sqlalchemy import select from sqlalchemy import Sequence +from sqlalchemy import String from sqlalchemy import Table from sqlalchemy import testing from sqlalchemy import update from sqlalchemy.ext.asyncio import async_object_session from sqlalchemy.ext.asyncio import async_sessionmaker +from sqlalchemy.ext.asyncio import AsyncAttrs from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import exc as async_exc from sqlalchemy.ext.asyncio.base import ReversibleProxy +from sqlalchemy.orm import DeclarativeBase +from sqlalchemy.orm import Mapped +from sqlalchemy.orm import mapped_column from sqlalchemy.orm import relationship from sqlalchemy.orm import selectinload from sqlalchemy.orm import Session @@ -24,6 +35,7 @@ from sqlalchemy.testing import config from sqlalchemy.testing import engines from sqlalchemy.testing import eq_ from sqlalchemy.testing import expect_raises_message +from sqlalchemy.testing import fixtures from sqlalchemy.testing import is_ from sqlalchemy.testing import is_true from sqlalchemy.testing import mock @@ -45,6 +57,12 @@ class AsyncFixture(_AsyncFixture, _fixtures.FixtureTest): def async_engine(self): return engines.testing_engine(asyncio=True, transfer_staticpool=True) + # TODO: this seems to cause deadlocks in + # OverrideSyncSession for some reason + # @testing.fixture + # def async_engine(self, async_testing_engine): + # return async_testing_engine(transfer_staticpool=True) + @testing.fixture def async_session(self, async_engine): return AsyncSession(async_engine) @@ -1005,3 +1023,103 @@ class OverrideSyncSession(AsyncFixture): is_true(not isinstance(ass.sync_session, _MySession)) is_(ass.sync_session_class, Session) + + +class AsyncAttrsTest( + testing.AssertsExecutionResults, _AsyncFixture, fixtures.TestBase +): + __requires__ = ("async_dialect",) + + @config.fixture + def decl_base(self, metadata): + _md = metadata + + class Base(fixtures.ComparableEntity, AsyncAttrs, DeclarativeBase): + metadata = _md + type_annotation_map = { + str: String().with_variant( + String(50), "mysql", "mariadb", "oracle" + ) + } + + yield Base + Base.registry.dispose() + + @testing.fixture + def async_engine(self, async_testing_engine): + yield async_testing_engine(transfer_staticpool=True) + + @testing.fixture + def ab_fixture(self, decl_base): + class A(decl_base): + __tablename__ = "a" + + id: Mapped[int] = mapped_column(Identity(), primary_key=True) + data: Mapped[Optional[str]] + bs: Mapped[List[B]] = relationship(order_by=lambda: B.id) + + class B(decl_base): + __tablename__ = "b" + id: Mapped[int] = mapped_column(Identity(), primary_key=True) + a_id: Mapped[int] = mapped_column(ForeignKey("a.id")) + data: Mapped[Optional[str]] + + decl_base.metadata.create_all(testing.db) + + return A, B + + @async_test + async def test_lazyloaders(self, async_engine, ab_fixture): + A, B = ab_fixture + + async with AsyncSession(async_engine) as session: + b1, b2, b3 = B(data="b1"), B(data="b2"), B(data="b3") + a1 = A(data="a1", bs=[b1, b2, b3]) + session.add(a1) + + await session.commit() + + assert inspect(a1).expired + + with self.assert_statement_count(async_engine.sync_engine, 1): + eq_(await a1.awaitable_attrs.data, "a1") + + with self.assert_statement_count(async_engine.sync_engine, 1): + eq_(await a1.awaitable_attrs.bs, [b1, b2, b3]) + + # now it's loaded, lazy loading not used anymore + eq_(a1.bs, [b1, b2, b3]) + + @async_test + async def test_it_didnt_load_but_is_ok(self, async_engine, ab_fixture): + A, B = ab_fixture + + async with AsyncSession(async_engine) as session: + b1, b2, b3 = B(data="b1"), B(data="b2"), B(data="b3") + a1 = A(data="a1", bs=[b1, b2, b3]) + session.add(a1) + + await session.commit() + + async with AsyncSession(async_engine) as session: + a1 = ( + await session.scalars(select(A).options(selectinload(A.bs))) + ).one() + + with self.assert_statement_count(async_engine.sync_engine, 0): + eq_(await a1.awaitable_attrs.bs, [b1, b2, b3]) + + @async_test + async def test_the_famous_lazyloader_gotcha( + self, async_engine, ab_fixture + ): + A, B = ab_fixture + + async with AsyncSession(async_engine) as session: + a1 = A(data="a1") + session.add(a1) + + await session.flush() + + with self.assert_statement_count(async_engine.sync_engine, 1): + eq_(await a1.awaitable_attrs.bs, []) |
