Add ORM base class; make Postgresql mandatory; add dependencies

This commit is contained in:
Daniil Fajnberg 2022-07-01 10:46:48 +02:00
parent eb08e5a674
commit 71f9db6c0d
7 changed files with 45 additions and 16 deletions

View File

@ -1,4 +1,6 @@
Pydantic
FastAPI
SQLAlchemy[asyncio]
Alembic
Alembic
SQLAlchemy-Utils
python-slugify

View File

@ -27,6 +27,8 @@ install_requires =
FastAPI
SQLAlchemy[asyncio]
Alembic
SQLAlchemy-Utils
python-slugify
[options.extras_require]
srv =

View File

@ -1,9 +0,0 @@
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import declarative_base, sessionmaker
from compub.settings import settings
engine = create_async_engine(settings.db_uri, future=True)
LocalAsyncSession = sessionmaker(engine, expire_on_commit=False, class_=AsyncSession)
ORMBase = declarative_base()

View File

@ -0,0 +1 @@
from .base import LocalAsyncSession, ORMBase, engine

31
src/compub/db/base.py Normal file
View File

@ -0,0 +1,31 @@
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import declarative_base, sessionmaker
from sqlalchemy.sql.functions import now as db_now
from sqlalchemy.sql.schema import Column
from sqlalchemy.sql.sqltypes import TIMESTAMP
from compub.exceptions import NoDatabaseConfigured
from compub.settings import settings
if settings.db_uri is None:
raise NoDatabaseConfigured
engine = create_async_engine(settings.db_uri, future=True)
LocalAsyncSession = sessionmaker(engine, expire_on_commit=False, class_=AsyncSession)
ORMBase = declarative_base()
class AbstractBase(ORMBase):
__abstract__ = True
NON_REPR_FIELDS = ['id', 'date_created', 'date_updated']
date_created = Column(TIMESTAMP(timezone=False), server_default=db_now())
date_updated = Column(TIMESTAMP(timezone=False), server_default=db_now(), onupdate=db_now())
def __repr__(self) -> str:
# Exclude non-representative fields:
fields = (name for name in self.__mapper__.columns.keys() if name not in self.NON_REPR_FIELDS)
# Exclude NULL value fields:
attrs = ', '.join(f"{name}={repr(getattr(self, name))}" for name in fields if getattr(self, name) is not None)
return f"{self.__class__.__name__}({attrs})"

6
src/compub/exceptions.py Normal file
View File

@ -0,0 +1,6 @@
class ConfigError(Exception):
pass
class NoDatabaseConfigured(ConfigError):
pass

View File

@ -3,7 +3,7 @@ import logging.config
from pathlib import Path
from typing import Any, Callable, ClassVar
from pydantic import BaseModel, BaseSettings, AnyUrl, validator
from pydantic import BaseModel, BaseSettings, PostgresDsn, validator
from pydantic.env_settings import SettingsSourceCallable
from yaml import safe_load
@ -70,10 +70,6 @@ def _yaml_config_settings_source(settings_obj: AbstractBaseSettings) -> dict[str
return config
class DBUri(AnyUrl):
host_required = False
class ServerSettings(BaseModel):
host: str = '127.0.0.1'
port: int = 9009
@ -81,7 +77,7 @@ class ServerSettings(BaseModel):
class Settings(AbstractBaseSettings):
db_uri: DBUri = 'sqlite+aiosqlite:///:memory:'
db_uri: PostgresDsn | None = None
server: ServerSettings = ServerSettings()
log_config: dict | Path | None = None