Skip to content

Commit

Permalink
Merge branch 'release/0.19.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
ri-gilfanov committed Jul 1, 2021
2 parents 573d9ff + f1eb960 commit ad5b2a2
Show file tree
Hide file tree
Showing 13 changed files with 148 additions and 121 deletions.
17 changes: 8 additions & 9 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,7 @@ Copy and paste this code in a file and run:
from aiohttp import web
from sqlalchemy import orm
import aiohttp_sqlalchemy
from aiohttp_sqlalchemy import sa_session
import aiohttp_sqlalchemy as ahsa
metadata = sa.MetaData()
Base = orm.declarative_base(metadata=metadata)
Expand All @@ -91,11 +90,11 @@ Copy and paste this code in a file and run:
async def main(request):
db_session = sa_session(request)
sa_session = ahsa.get_session(request)
async with db_session.begin():
db_session.add(MyModel())
result = await db_session.execute(sa.select(MyModel))
async with sa_session.begin():
sa_session.add(MyModel())
result = await sa_session.execute(sa.select(MyModel))
result = result.scalars()
data = {
Expand All @@ -108,10 +107,10 @@ Copy and paste this code in a file and run:
async def app_factory():
app = web.Application()
aiohttp_sqlalchemy.setup(app, [
aiohttp_sqlalchemy.bind('sqlite+aiosqlite:///'),
ahsa.setup(app, [
ahsa.bind('sqlite+aiosqlite:///'),
])
await aiohttp_sqlalchemy.init_db(app, metadata)
await ahsa.init_db(app, metadata)
app.add_routes([web.get('/', main)])
return app
Expand Down
10 changes: 7 additions & 3 deletions aiohttp_sqlalchemy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
from aiohttp_sqlalchemy.middlewares import sa_middleware
from aiohttp_sqlalchemy.typedefs import TBind, TBinds, TSessionFactory, TTarget
from aiohttp_sqlalchemy.utils import (
get_session,
get_session_factory,
init_db,
sa_init_db,
sa_session,
Expand All @@ -33,7 +35,7 @@
SAView,
)

__version__ = '0.18.1'
__version__ = '0.19.0'

__all__ = [
'SA_DEFAULT_KEY',
Expand All @@ -44,18 +46,20 @@
'SAModelMixin',
'SAModelView',
'bind',
'get_session',
'get_session_factory',
'init_db',
'sa_decorator',
'sa_middleware',
'sa_session',
'sa_session_factory',
'setup',
# Synonyms
'DEFAULT_KEY',
'SAAbstractView',
'SAView',
'sa_bind',
'sa_init_db',
'sa_session',
'sa_session_factory',
]


Expand Down
3 changes: 2 additions & 1 deletion aiohttp_sqlalchemy/typedefs.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from typing import Awaitable, Callable, Iterable, Tuple, Union
from typing import Awaitable, Callable, Iterable, Optional, Tuple, Union

from aiohttp.web import StreamResponse
from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession

THandler = Callable[..., Awaitable[StreamResponse]]
THandlerWrapper = Callable[..., THandler]
TSessionFactory = Callable[..., AsyncSession]
TOptSessionFactory = Optional[TSessionFactory]

TTarget = Union[str, AsyncEngine, TSessionFactory]
TBind = Tuple[TSessionFactory, str, bool]
Expand Down
27 changes: 18 additions & 9 deletions aiohttp_sqlalchemy/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from sqlalchemy.ext.asyncio import AsyncSession

from aiohttp_sqlalchemy.constants import SA_DEFAULT_KEY
from aiohttp_sqlalchemy.typedefs import TSessionFactory
from aiohttp_sqlalchemy.typedefs import TOptSessionFactory


async def init_db(
Expand All @@ -19,13 +19,14 @@ async def init_db(
:param metadata: ...
:param key: key of SQLAlchemy binding.
"""
session_factory = sa_session_factory(app, key)
async with session_factory() as session:
async with session.bind.begin() as connection:
await connection.run_sync(metadata.create_all)
session_factory = get_session_factory(app, key)
if callable(session_factory):
async with session_factory() as session:
async with session.bind.begin() as connection:
await connection.run_sync(metadata.create_all)


def sa_session(
def get_session(
request: Request,
key: str = SA_DEFAULT_KEY,
) -> AsyncSession:
Expand All @@ -45,17 +46,25 @@ def sa_session(
return session


def sa_session_factory(
def get_session_factory(
source: Union[Request, Application],
key: str = SA_DEFAULT_KEY,
) -> TSessionFactory:
) -> TOptSessionFactory:
"""Return callable object which returns an `AsyncSession` instance.
:param source: AIOHTTP request object or your AIOHTTP application.
:param key: key of SQLAlchemy binding.
"""
return cast(TSessionFactory, getattr(source, "app", source).get(key))
if isinstance(source, Request):
return cast(TOptSessionFactory, source.config_dict.get(key))
elif isinstance(source, Application):
return cast(TOptSessionFactory, source.get(key))
raise TypeError(
'Arg `source` must be `Application` or `Request` from `aiohttp.web`.'
)


# Synonyms
sa_init_db = init_db
sa_session = get_session
sa_session_factory = get_session_factory
4 changes: 2 additions & 2 deletions aiohttp_sqlalchemy/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from sqlalchemy.ext.asyncio import AsyncSession

from aiohttp_sqlalchemy.constants import SA_DEFAULT_KEY
from aiohttp_sqlalchemy.utils import sa_session
from aiohttp_sqlalchemy.utils import get_session


class SAMixin(AbstractView, metaclass=ABCMeta):
Expand All @@ -19,7 +19,7 @@ def sa_session(self, key: Optional[str] = None) -> AsyncSession:
:param key: key of SQLAlchemy binding.
"""
return sa_session(self.request, key or self.sa_session_key)
return get_session(self.request, key or self.sa_session_key)


class SAModelMixin(SAMixin, metaclass=ABCMeta):
Expand Down
49 changes: 24 additions & 25 deletions docs/advansed.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ Multiple session factories in application
-----------------------------------------
.. code-block:: python
import aiohttp_sqlalchemy
import aiohttp_sqlalchemy as ahsa
postgresql_url = 'postgresql+asyncpg://user:password@host/database'
mysql_url = 'mysql+aiomysql://user:password@host/database'
sqlite_url = 'sqlite+aiosqlite:///path/to/file.sqlite3'
aiohttp_sqlalchemy.setup(app, [
aiohttp_sqlalchemy.bind(postgresql_url),
aiohttp_sqlalchemy.bind(mysql_url, 'sa_second'),
aiohttp_sqlalchemy.bind(sqlite_url, 'sa_third'),
ahsa.setup(app, [
ahsa.bind(postgresql_url),
ahsa.bind(mysql_url, 'sa_second'),
ahsa.bind(sqlite_url, 'sa_third'),
])
Expand All @@ -37,37 +37,36 @@ use a ``sa_decorator(key)``. For example:

.. code-block:: python
from aiohttp_sqlalchemy import sa_decorator
import aiohttp_sqlalchemy as ahsa
@sa_decorator('sa_specific')
@ahsa.sa_decorator('sa_specific')
async def specific_handler(request):
specific_db_session = sa_session(request, 'sa_specific')
specific_db_session = ahsa.get_session(request, 'sa_specific')
async with specific_db_session.begin():
# some your code
aiohttp_sqlalchemy.setup(app, [
aiohttp_sqlalchemy.bind(specific_db_url, 'sa_specific', middleware=False),
ahsa.setup(app, [
ahsa.bind(specific_db_url, 'sa_specific', middleware=False),
])
You can combine the use of decorators with the use of middlewares. For example:

.. code-block:: python
from aiohttp_sqlalchemy import sa_decorator
import aiohttp_sqlalchemy as ahsa
async def simple_handler(request):
main_db_session = sa_session(request)
main_db_session = ahsa.get_session(request)
async with main_db_session.begin():
# some your code
@sa_decorator('sa_specific')
@ahsa.sa_decorator('sa_specific')
async def specific_handler(request):
main_db_session = sa_session(request)
specific_db_session = sa_session(request, 'sa_specific')
main_db_session = ahsa.get_session(request)
specific_db_session = ahsa.get_session(request, 'sa_specific')
async with main_db_session.begin():
# some your code
Expand All @@ -76,9 +75,9 @@ You can combine the use of decorators with the use of middlewares. For example:
# some your code
aiohttp_sqlalchemy.setup(app, [
aiohttp_sqlalchemy.bind(main_db_url),
aiohttp_sqlalchemy.bind(specific_db_url, 'sa_specific', middleware=False),
ahsa.setup(app, [
ahsa.bind(main_db_url),
ahsa.bind(specific_db_url, 'sa_specific', middleware=False),
])
app.add_routes([
web.get('/simple', simple_handler),
Expand All @@ -90,30 +89,30 @@ You can apply ``sa_decorator(key)`` with class based views. For example:
.. code-block:: python
from aiohttp import web
from aiohttp_sqlalchemy import SABaseView, sa_decorator
import aiohttp_sqlalchemy as ahsa
SPECIFIC_DB_KEY = 'sa_specific'
SPECIFIC_DB_URL = 'sqlite+aiosqlite:///'
class SpecificHandler(SABaseView):
class SpecificHandler(ahsa.SABaseView):
@property
def specific_session(self):
return self.sa_session(SPECIFIC_DB_KEY)
@sa_decorator(SPECIFIC_DB_KEY)
@ahsa.sa_decorator(SPECIFIC_DB_KEY)
async def get(self):
async with self.specific_session.begin():
# some your code
@sa_decorator(SPECIFIC_DB_KEY)
@ahsa.sa_decorator(SPECIFIC_DB_KEY)
async def post(self):
async with self.specific_session.begin():
# some your code
aiohttp_sqlalchemy.setup(app, [
aiohttp_sqlalchemy.bind(SPECIFIC_DB_URL, SPECIFIC_DB_KEY, middleware=False),
ahsa.setup(app, [
ahsa.bind(SPECIFIC_DB_URL, SPECIFIC_DB_KEY, middleware=False),
])
app.add_routes([web.view('/', SpecificHandler)])
31 changes: 15 additions & 16 deletions docs/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ Copy and paste this code in a file and run:
from aiohttp import web
from sqlalchemy import orm
import aiohttp_sqlalchemy
from aiohttp_sqlalchemy import sa_session
import aiohttp_sqlalchemy as ahsa
metadata = sa.MetaData()
Base = orm.declarative_base(metadata=metadata)
Expand All @@ -33,11 +32,11 @@ Copy and paste this code in a file and run:
async def main(request):
db_session = sa_session(request)
sa_session = ahsa.get_session(request)
async with db_session.begin():
db_session.add(MyModel())
result = await db_session.execute(sa.select(MyModel))
async with sa_session.begin():
sa_session.add(MyModel())
result = await sa_session.execute(sa.select(MyModel))
result = result.scalars()
data = {
Expand All @@ -50,10 +49,10 @@ Copy and paste this code in a file and run:
async def app_factory():
app = web.Application()
aiohttp_sqlalchemy.setup(app, [
aiohttp_sqlalchemy.bind('sqlite+aiosqlite:///'),
ahsa.setup(app, [
ahsa.bind('sqlite+aiosqlite:///'),
])
await aiohttp_sqlalchemy.init_db(app, metadata)
await ahsa.init_db(app, metadata)
app.add_routes([web.get('/', main)])
return app
Expand All @@ -73,15 +72,15 @@ More control in configuration
-----------------------------
.. code-block:: python
import aiohttp_sqlalchemy
import aiohttp_sqlalchemy as ahsa
from sqlalchemy import orm
url = 'sqlite+aiosqlite:///'
engine = create_async_engine(url, echo=True)
Session = orm.sessionmaker(main_engine, AsyncSession, expire_on_commit=False)
aiohttp_sqlalchemy.setup(app, [
aiohttp_sqlalchemy.bind(Session),
ahsa.setup(app, [
ahsa.bind(Session),
])
Expand All @@ -90,18 +89,18 @@ Class based views
.. code-block:: python
from aiohttp import web
from aiohttp_sqlalchemy import SABaseView
import aiohttp_sqlalchemy as ahsa
class MyClassBasedView(SABaseView):
class MyClassBasedView(ahsa.SABaseView):
async def get(self):
db_session = self.sa_session()
async with db_session.begin():
# some your code
aiohttp_sqlalchemy.setup(app, [
aiohttp_sqlalchemy.bind(MainSession),
ahsa.setup(app, [
ahsa.bind(MainSession),
])
app.add_routes([web.view('/', MyClassBasedView)])
4 changes: 2 additions & 2 deletions docs/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Main user functionality

.. autofunction:: aiohttp_sqlalchemy.sa_init_db

.. autofunction:: aiohttp_sqlalchemy.sa_session
.. autofunction:: aiohttp_sqlalchemy.get_session

Class based views
-----------------
Expand All @@ -31,4 +31,4 @@ Additional functionality

.. autofunction:: aiohttp_sqlalchemy.sa_middleware

.. autofunction:: aiohttp_sqlalchemy.sa_session_factory
.. autofunction:: aiohttp_sqlalchemy.get_session_factory

0 comments on commit ad5b2a2

Please sign in to comment.