| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- """
- File with environment variables and general configuration logic.
- `SECRET_KEY`, `ENVIRONMENT` etc. map to env variables with the same names.
- Pydantic priority ordering:
- 1. (Most important, will overwrite everything) - environment variables
- 2. `.env` file in root folder of project
- 3. Default values
- For project name, version, description we use pyproject.toml
- For the rest, we use file `.env` (gitignored), see `.env.example`
- `DEFAULT_SQLALCHEMY_DATABASE_URI` and `TEST_SQLALCHEMY_DATABASE_URI`:
- Both are ment to be validated at the runtime, do not change unless you know
- what are you doing. All the two validators do is to build full URI (TCP protocol)
- to databases to avoid typo bugs.
- See https://pydantic-docs.helpmanual.io/usage/settings/
- Note, complex types like lists are read as json-encoded strings.
- """
- import tomllib
- from pathlib import Path
- from typing import Literal
- from pydantic import AnyHttpUrl, BaseSettings, EmailStr, PostgresDsn, validator
- PROJECT_DIR = Path(__file__).parent.parent.parent
- with open(f"{PROJECT_DIR}/pyproject.toml", "rb") as f:
- PYPROJECT_CONTENT = tomllib.load(f)["tool"]["poetry"]
- class Settings(BaseSettings):
- # CORE SETTINGS
- SECRET_KEY: str
- ENVIRONMENT: Literal["DEV", "PYTEST", "STG", "PRD"] = "DEV"
- SECURITY_BCRYPT_ROUNDS: int = 12
- ACCESS_TOKEN_EXPIRE_MINUTES: int = 11520 # 8 days
- REFRESH_TOKEN_EXPIRE_MINUTES: int = 40320 # 28 days
- BACKEND_CORS_ORIGINS: list[AnyHttpUrl] = []
- ALLOWED_HOSTS: list[str] = ["localhost", "127.0.0.1"]
- # PROJECT NAME, VERSION AND DESCRIPTION
- PROJECT_NAME: str = PYPROJECT_CONTENT["name"]
- VERSION: str = PYPROJECT_CONTENT["version"]
- DESCRIPTION: str = PYPROJECT_CONTENT["description"]
- # POSTGRESQL DEFAULT DATABASE
- DEFAULT_DATABASE_HOSTNAME: str
- DEFAULT_DATABASE_USER: str
- DEFAULT_DATABASE_PASSWORD: str
- DEFAULT_DATABASE_PORT: str
- DEFAULT_DATABASE_DB: str
- DEFAULT_SQLALCHEMY_DATABASE_URI: str = ""
- # POSTGRESQL TEST DATABASE
- TEST_DATABASE_HOSTNAME: str = "postgres"
- TEST_DATABASE_USER: str = "postgres"
- TEST_DATABASE_PASSWORD: str = "postgres"
- TEST_DATABASE_PORT: str = "5432"
- TEST_DATABASE_DB: str = "postgres"
- TEST_SQLALCHEMY_DATABASE_URI: str = ""
- # FIRST SUPERUSER
- FIRST_SUPERUSER_EMAIL: EmailStr
- FIRST_SUPERUSER_PASSWORD: str
- @validator("DEFAULT_SQLALCHEMY_DATABASE_URI")
- def _assemble_default_db_connection(cls, v: str, values: dict[str, str]) -> str:
- return PostgresDsn.build(
- scheme="postgresql+asyncpg",
- user=values["DEFAULT_DATABASE_USER"],
- password=values["DEFAULT_DATABASE_PASSWORD"],
- host=values["DEFAULT_DATABASE_HOSTNAME"],
- port=values["DEFAULT_DATABASE_PORT"],
- path=f"/{values['DEFAULT_DATABASE_DB']}",
- )
- @validator("TEST_SQLALCHEMY_DATABASE_URI")
- def _assemble_test_db_connection(cls, v: str, values: dict[str, str]) -> str:
- return PostgresDsn.build(
- scheme="postgresql+asyncpg",
- user=values["TEST_DATABASE_USER"],
- password=values["TEST_DATABASE_PASSWORD"],
- host=values["TEST_DATABASE_HOSTNAME"],
- port=values["TEST_DATABASE_PORT"],
- path=f"/{values['TEST_DATABASE_DB']}",
- )
- class Config:
- env_file = f"{PROJECT_DIR}/.env"
- case_sensitive = True
- settings: Settings = Settings() # type: ignore
|