add SQLAlchemy.create_all()

This commit is contained in:
Yusur 2025-08-08 07:58:17 +02:00
parent 1ab0982dc3
commit 5bdf13b104
3 changed files with 21 additions and 7 deletions

View file

@ -3,7 +3,8 @@
## 0.5.0 ## 0.5.0
+ `sqlalchemy`: add `unbound_fk()`, `bound_fk()` + `sqlalchemy`: add `unbound_fk()`, `bound_fk()`
+ Add `sqlalchemy_async` module with `SQLAlchemy()` + Add `sqlalchemy_async` module with `SQLAlchemy()` async database binding.
* Supports being used as an async context manager
+ Add `timed_cache()`, `TimedDict()`, `none_pass()`, `twocolon_list()`, `quote_css_string()`, `must_be()` + Add `timed_cache()`, `TimedDict()`, `none_pass()`, `twocolon_list()`, `quote_css_string()`, `must_be()`
+ Add module `calendar` with `want_*` date type conversion utilities and `age_and_days()` + Add module `calendar` with `want_*` date type conversion utilities and `age_and_days()`
+ Move obsolete stuff to `obsolete` package (includes configparse 0.3 as of now) + Move obsolete stuff to `obsolete` package (includes configparse 0.3 as of now)

View file

@ -62,7 +62,7 @@ class SassAsyncMiddleware(_MiddlewareFactory):
## WSGI path — is it valid for ASGI as well?? ## WSGI path — is it valid for ASGI as well??
asgi_path = f'/{manifest.wsgi_path.strip('/')}/' asgi_path = f'/{manifest.wsgi_path.strip('/')}/'
pkg_dir = self.package_dir[pkgname] pkg_dir = self.package_dir[pkgname]
self.paths.append((asgi_path, package_dir, manifest)) self.paths.append((asgi_path, pkg_dir, manifest))
async def __call__(self, /, scope: ASGIScope, receive: ASGIReceive, send: ASGISend): async def __call__(self, /, scope: ASGIScope, receive: ASGIReceive, send: ASGISend):
path: str = scope.get('path') path: str = scope.get('path')

View file

@ -19,7 +19,7 @@ from __future__ import annotations
from sqlalchemy import Engine, Select, func, select from sqlalchemy import Engine, Select, func, select
from sqlalchemy.orm import DeclarativeBase, lazyload from sqlalchemy.orm import DeclarativeBase, lazyload
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, create_async_engine
from flask_sqlalchemy.pagination import Pagination from flask_sqlalchemy.pagination import Pagination
from suou.exceptions import NotFoundError from suou.exceptions import NotFoundError
@ -32,7 +32,7 @@ class SQLAlchemy:
NEW 0.5.0 NEW 0.5.0
""" """
base: DeclarativeBase base: DeclarativeBase
engine: Engine engine: AsyncEngine
_sessions: list[AsyncSession] _sessions: list[AsyncSession]
NotFound = NotFoundError NotFound = NotFoundError
@ -42,9 +42,11 @@ class SQLAlchemy:
self._sessions = [] self._sessions = []
def bind(self, url: str): def bind(self, url: str):
self.engine = create_async_engine(url) self.engine = create_async_engine(url)
async def begin(self) -> AsyncSession: def _ensure_engine(self):
if self.engine is None: if self.engine is None:
raise RuntimeError('database is not connected') raise RuntimeError('database is not connected')
async def begin(self) -> AsyncSession:
self._ensure_engine()
## XXX is it accurate? ## XXX is it accurate?
s = AsyncSession(self.engine) s = AsyncSession(self.engine)
self._sessions.append(s) self._sessions.append(s)
@ -64,7 +66,7 @@ class SQLAlchemy:
max_per_page: int | None = None, error_out: bool = True, max_per_page: int | None = None, error_out: bool = True,
count: bool = True) -> AsyncSelectPagination: count: bool = True) -> AsyncSelectPagination:
""" """
... Return a pagination. Analogous to flask_sqlalchemy.SQLAlchemy.paginate().
""" """
async with self as session: async with self as session:
return AsyncSelectPagination( return AsyncSelectPagination(
@ -74,11 +76,22 @@ class SQLAlchemy:
per_page=per_page, max_per_page=max_per_page, per_page=per_page, max_per_page=max_per_page,
error_out=self.NotFound if error_out else None, count=count error_out=self.NotFound if error_out else None, count=count
) )
async def create_all(self, *, checkfirst = True):
"""
Initialize database
"""
self._ensure_engine()
self.base.metadata.create_all(
self.engine, checkfirst=checkfirst
)
class AsyncSelectPagination(Pagination): class AsyncSelectPagination(Pagination):
""" """
flask_sqlalchemy.SelectPagination but asynchronous flask_sqlalchemy.SelectPagination but asynchronous.
Pagination is not part of the public API, therefore expect that it may break
""" """
async def _query_items(self) -> list: async def _query_items(self) -> list: