1010import typing
1111import uuid
1212from uuid import UUID
13+ import sqlalchemy
1314from sqlalchemy .ext .asyncio import create_async_engine
1415from contextlib import asynccontextmanager
1516
4142from sqlalchemy .orm import relationship
4243from sqlalchemy .exc import NoResultFound , IntegrityError , OperationalError # noqa: F401
4344
45+ import sqlalchemy_utils
46+
4447LOG = logging .getLogger (__name__ )
4548
4649P = typing .ParamSpec ("P" )
@@ -70,6 +73,10 @@ async def init_engine(db: str, echo=False):
7073 f"Unsupported database dialect: { db } (must be sqlite:// or postgresql://)"
7174 )
7275
76+ if not sqlalchemy_utils .database_exists (db ):
77+ LOG .warning ("Database does not exist, trying to create it..." )
78+ sqlalchemy_utils .create_database (db )
79+
7380 async_engine = create_async_engine (db , echo = echo )
7481 AsyncSessionMaker = async_sessionmaker (async_engine , expire_on_commit = False )
7582
@@ -79,6 +86,12 @@ async def init_engine(db: str, echo=False):
7986 )
8087
8188 async with async_engine .begin () as conn :
89+
90+ if "postgres" in async_engine .url .drivername :
91+ rows = (await conn .execute (sqlalchemy .text ("SELECT datname FROM pg_database" ))).all ()
92+ if async_engine .url .database not in [row [0 ] for row in rows ]:
93+ await conn .execute (sqlalchemy .text (f"CREATE DATABASE { async_engine .url .database } ENCODING 'utf-8" ))
94+
8295 # Creating tables is not transactional in some databases, so we just try
8396 # our luck and if that fails, we sleep a couple of ms and try again.
8497 try :
0 commit comments