import os from pathlib import Path from typing import Optional, List, Union import pydantic import yaml from pydantic import BaseModel def build_path(path: Union[Path, str], path_is_absolute: bool = False) -> Path: """ This function build Path instance from arguments and returns it. :param path: path :param path_is_absolute: if True, use path as absolute :return: Path instance """ if not path_is_absolute: return Path(os.getcwd()) / path if isinstance(path, str): return Path(path) return path def load_yaml(path: Union[Path, str] = None, path_is_absolute: bool = False): """ This method loads from YAML file to properties of self instance. Why doesn't load when __init__ is to make the following requirements compatible: 1. Access config as global 2. Independent on config for development or use config for unit testing when unit testing """ if path is None: path = 'config.yml' built_path = build_path(path, path_is_absolute) dictionary_config = yaml.full_load(built_path.read_text(encoding="UTF-8")) return dictionary_config class Modules: MIDDLEWARE: list = [] ROUTES: list = [] class AuthConf: AUTH_ACCESS_TOKEN_EXPIRE_MINUTES: int AUTH_REFRESH_TOKEN_EXPIRE_MINUTES: int AUTH_ALGORITHM: str AUTH_SECRET_KEY: str class MongoConf: MONGO_URL: str MONGO_DB: str AUTH_DB: str PROD_MONGO_URL: str PROD_MONGO_DB: str PROD_AUTH_DB: str class LinkerConf: LINKER_URL: str class DatabaseConfig(BaseModel): url: str db: str version: Optional[float] username: Optional[str] password: Optional[str] class DatabaseModeConfig(BaseModel): dev: Optional[DatabaseConfig] production: Optional[DatabaseConfig] class DependencyConfig(BaseModel): middleware: Optional[List[str]] routes: Optional[List[str]] class AuthConfig(BaseModel): secret_key: Optional[str] algorithm: Optional[str] access_token_expire_minutes: Optional[int] refresh_token_expire_minutes: Optional[int] url: Optional[str] cache_prefix_key: Optional[str] cache_ttl: Optional[int] = 360 class ServerConfig(BaseModel): base_api_doc_url: Optional[str] is_prod: Optional[bool] api_logo: Optional[str] = 'https://scm.hacoupian.net/resource/img/logo.svg' prefix_url: Optional[str] port: Optional[int] class CeleryTask(BaseModel): broker: Optional[str] backend: Optional[str] autodiscover_tasks: Optional[List[str]] class CorsConfig(BaseModel): origins: Optional[List[str]] allow_headers: Optional[List[str]] = ['*'] allow_credentials: Optional[bool] = True allow_methods: Optional[List[str]] = ['*'] class CoreConfig(pydantic.BaseModel): cors: Optional[CorsConfig] server: Optional[ServerConfig] auth: Optional[AuthConfig] dependency: Optional[DependencyConfig] database: dict[str, Union[DatabaseConfig, DatabaseModeConfig]] static_files: dict[str, str] = dict() celery: Optional[CeleryTask] class Config: arbitrary_types_allowed = False # def load_modules_config(self): # # import dynamic routes in the modules # for i in self.dependency.routes: # if os.path.exists(Path(f'{i}/.env')): # values = dotenv_values(f'{i}/.env') # self.extra_conf = dict(self.extra_conf, **dict(values))