My app is structured as shown below.
app/
├── backend/
│ └── main.py
├── models/
│ └── my_model.py
└── utils/
└── enums.py
main.py
instantiates a config dict, containing key prefix
, from a yaml file which is needed in enums.py
to generate schema names at runtime.
utils/enums.py:
def create_schema_names(prefix: str) -> Type[Enum]:
class SchemaNames(str, Enum):
RAW = prefix + "_RAW"
STAGING = prefix + "_STAGING"
TRANSFORMED = prefix + "_TRANSFORMED"
return SchemaNames
I want to use SchemaNames
in my SQLAlchemy models in my_model.py
to specify the schema for each model: __table_args__ = {"schema": SchemaNames.RAW.value}
.
Problem:
Importing SchemaNames
in my_model.py
leads to circular dependencies because the config is defined in main.py
.
I want to avoid using global variables by exporting SchemaNames
globally.
How can I dynamically create the SchemaNames
enum based on the runtime config and use it in SQLAlchemy models without causing circular dependencies or relying on global exports? What best practice approach is there for this?
Edit: main.py
is structured as follows:
from fastapi import FastAPI
from app.api import register_api_1
# in register_api_2 function my_model.py is imported so that data in it from the DB can be read.
from app.api import register_api_2
def make_config() -> ConfigClass:
# parses config from yaml file
return my_config
def create_app(config: ConfigClass) -> FastAPI:
app = FastAPI()
register_api_1(app, config)
register_api_2(app)
return app
def main():
config = make_config()
app = create_app(config)
uvicorn.run(
app,
host=config.webserver.host,
port=config.webserver.port,
log_config=config.log_config,
)
def __name__ == "__main__":
main()
as suggested by M.O., I ended up placing make_config()
in a settings.py
file and importing the config from there wherever needed. This resolved the circular dependency issue and also made the app structure less convoluted.
Any suggestions are, of course, welcomed.