from typing import Iterator import sqlalchemy from anydi import Container, Module, Provider, provider from app.adapters.aws.s3 import S3Client from app.adapters.db.base import DB from jinja2sql import Jinja2SQL from app.adapters.opus_clip.client import OpusClipClient, OpusClipClientMock from app.config import Settings, settings import boto3 class AppModule(Module): @provider(scope="singleton") def jinja2sql(self, settings: Settings) -> Jinja2SQL: jinja2sql = Jinja2SQL(searchpath=settings.jinja2sql_template_searchpath) jinja2sql.env.globals.update( # type: ignore { "settings": settings, } ) return jinja2sql @provider(scope="singleton") def db(self, settings: Settings, jinja2sql: Jinja2SQL) -> Iterator[DB]: with DB( url=settings.postgres_url, engine_args={ "echo": settings.postgres_echo, "poolclass": sqlalchemy.pool.QueuePool, "pool_size": settings.postgres_pool_size, "max_overflow": settings.postgres_pool_max_overflow, "pool_recycle": settings.postgres_pool_recycle, "pool_pre_ping": settings.postgres_pool_pre_ping, "pool_reset_on_return": settings.postgres_pool_reset_on_return, "connect_args": settings.postgres_connect_args, }, jinja2sql=jinja2sql, ) as db: yield db @provider(scope="request") def db_session_factory(self, db: DB) -> Iterator[None]: with db.session_factory(): yield @provider(scope="singleton") def opus_clip_client(self, settings: Settings) -> Iterator[OpusClipClient]: with OpusClipClient(api_token=settings.opus_clip_api_token) as opus_client: yield opus_client @provider(scope="singleton") def opus_clip_client_mock(self) -> OpusClipClientMock: return OpusClipClientMock() @provider(scope="singleton") def aws_session(self, settings: Settings) -> boto3.Session: return boto3.Session(region_name=settings.aws_region_name) @provider(scope="singleton") def s3_client(self, settings: Settings, session: boto3.Session) -> S3Client: return S3Client( session=session, region_name=settings.aws_region_name, bucket=settings.assets_bucket_name, ) def setup_container() -> Container: """Configure the application.""" container = Container( providers=[ Provider(call=lambda: settings, scope="singleton", interface=Settings), ], modules=[AppModule], default_scope="singleton", ) return container