100 lines
3.9 KiB
Python
100 lines
3.9 KiB
Python
"""
|
|
See the Database class docstring for details on this module
|
|
"""
|
|
|
|
import sqlalchemy.orm
|
|
import sqlalchemy.ext.asyncio
|
|
|
|
from .base import Base
|
|
|
|
|
|
class Database:
|
|
"""
|
|
A class that is a composition of several other classes useful for accessing and manipulating a Postgresql database
|
|
asynchronously.
|
|
|
|
Usage:
|
|
asyncdb must first be initialized with a given postgresql connection url like so:
|
|
>>> db = asyncdb("postgresql://localhost:5432/postgres")
|
|
After asyncdb has been initialized two important objects that are composed into asyncdb become available:
|
|
-> async_engine
|
|
- Relevant for handling the creation and deletion of many tables at once, for example:
|
|
>>> async with self.async_engine.begin() as conn:
|
|
>>> await conn.run_sync(self.Base.metadata.drop_all)
|
|
>>> await conn.run_sync(self.Base.metadata.create_all)
|
|
- See the sqlalchemy documentation for futher details at
|
|
https://docs.sqlalchemy.org/en/14/orm/extensions/asyncio.html#sqlalchemy.ext.asyncio.AsyncEngine
|
|
-> async_session
|
|
- Relevant for properly manipulating rows and columns within the database, for example:
|
|
>>> from sqlalchemy import orm as sqlalchemy_orm
|
|
>>> from sqlalchemy import future as sqlalchemy_future
|
|
>>>
|
|
>>> async with db.async_session() as session:
|
|
>>> async with session.begin():
|
|
>>> session.add_all(
|
|
>>> [
|
|
>>> A(bs=[B(), B()], data="a1"),
|
|
>>> A(bs=[B()], data="a2"),
|
|
>>> A(bs=[B(), B()], data="a3"),
|
|
>>> ]
|
|
>>> )
|
|
>>>
|
|
>>> stmt = sqlalchemy_future.select(A).options(sqlalchemy_orm.selectinload(A.bs))
|
|
>>>
|
|
>>> result = await session.execute(stmt)
|
|
>>> await session.commit()
|
|
- See the sqlalchemy documentation for further details at
|
|
https://docs.sqlalchemy.org/en/14/orm/extensions/asyncio.html#sqlalchemy.ext.asyncio.AsyncConnection
|
|
"""
|
|
|
|
Base = Base
|
|
|
|
def __init__(
|
|
self,
|
|
db_url: str,
|
|
async_session_expire_on_commit: bool = False,
|
|
**engine_kwargs
|
|
):
|
|
"""
|
|
Constructor for the class
|
|
|
|
Args:
|
|
db_url: A string defining a standard postgresql url, for instance: postgresql://localhost:5432/postgres
|
|
async_session_expire_on_commit: A boolean for determining if the given connection via a async
|
|
context manager should close after the session.commit() function is called.
|
|
**engine_kwargs: Arguments that can be passed to sqlalchemy's create_async_engine function
|
|
"""
|
|
self.connection_url = db_url
|
|
self.async_engine = sqlalchemy.ext.asyncio.create_async_engine(
|
|
self.connection_url,
|
|
**engine_kwargs
|
|
)
|
|
self.async_session = sqlalchemy.orm.sessionmaker(
|
|
self.async_engine,
|
|
expire_on_commit=async_session_expire_on_commit,
|
|
class_=sqlalchemy.ext.asyncio.AsyncSession
|
|
)
|
|
|
|
@property
|
|
def connection_url(self) -> str:
|
|
"""
|
|
Getter for self.connection_url
|
|
|
|
Returns:
|
|
The postgresql connection string
|
|
"""
|
|
return self._connection_url
|
|
|
|
@connection_url.setter
|
|
def connection_url(self, url: str):
|
|
"""
|
|
Converts a given typical postgresql string to our asynchronous driver used with sqlalchemy
|
|
|
|
Args:
|
|
url: The given normal postgresql URL
|
|
|
|
Returns:
|
|
Nothing, setter for self.connection_url in the constructor
|
|
"""
|
|
self._connection_url = f"postgresql+asyncpg://{url.split('://')[-1]}"
|