refactor: refactor for modern layout
- split frontend and backend. - update backend with modern Python dev strategies.
This commit is contained in:
130
backend/config.py
Normal file
130
backend/config.py
Normal file
@@ -0,0 +1,130 @@
|
||||
import tomllib
|
||||
from dataclasses import dataclass
|
||||
from enum import StrEnum
|
||||
from typing import Optional
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class DatabaseDriver(StrEnum):
|
||||
SQLITE = "sqlite"
|
||||
MYSQL = "mysql"
|
||||
|
||||
@staticmethod
|
||||
def from_raw(raw: dict):
|
||||
return DatabaseDriver(raw["driver"])
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class SqliteDatabaseConfig:
|
||||
path: str
|
||||
"""Database path"""
|
||||
|
||||
@staticmethod
|
||||
def from_raw(raw: dict):
|
||||
return SqliteDatabaseConfig(raw["path"])
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class MysqlDatabaseConfig:
|
||||
host: str
|
||||
"""Database host"""
|
||||
port: int
|
||||
"""Database port"""
|
||||
user: str
|
||||
"""Database user"""
|
||||
password: str
|
||||
"""Database password"""
|
||||
database: str
|
||||
"""Database name"""
|
||||
|
||||
@staticmethod
|
||||
def from_raw(raw: dict):
|
||||
return MysqlDatabaseConfig(
|
||||
raw["host"], raw["port"], raw["user"], raw["password"], raw["database"]
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class DatabaseConfig:
|
||||
driver: DatabaseDriver
|
||||
"""Database driver"""
|
||||
config: SqliteDatabaseConfig | MysqlDatabaseConfig
|
||||
"""Database config"""
|
||||
|
||||
@staticmethod
|
||||
def from_raw(raw: dict):
|
||||
if raw["driver"] == DatabaseDriver.SQLITE:
|
||||
return DatabaseConfig(
|
||||
DatabaseDriver.SQLITE, SqliteDatabaseConfig.from_raw(raw["config"])
|
||||
)
|
||||
elif raw["driver"] == DatabaseDriver.MYSQL:
|
||||
return DatabaseConfig(
|
||||
DatabaseDriver.MYSQL, MysqlDatabaseConfig.from_raw(raw["config"])
|
||||
)
|
||||
else:
|
||||
raise ValueError("Invalid database driver")
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class WebConfig:
|
||||
port: int
|
||||
"""Web server port"""
|
||||
|
||||
@staticmethod
|
||||
def from_raw(raw: dict):
|
||||
return WebConfig(raw["port"])
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class OthersConfig:
|
||||
debug: bool
|
||||
"""Whether enable debug mode"""
|
||||
auto_token_clean_duration: int
|
||||
"""Auto token clean duration"""
|
||||
|
||||
@staticmethod
|
||||
def from_raw(raw: dict):
|
||||
return OthersConfig(raw["debug"], raw["auto-token-clean-duration"])
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Config:
|
||||
database: DatabaseConfig
|
||||
web: WebConfig
|
||||
others: OthersConfig
|
||||
|
||||
@staticmethod
|
||||
def from_raw(raw: dict):
|
||||
return Config(
|
||||
database=DatabaseConfig.from_raw(raw["database"]),
|
||||
web=WebConfig.from_raw(raw["web"]),
|
||||
others=OthersConfig.from_raw(raw["others"]),
|
||||
)
|
||||
|
||||
|
||||
_CONFIG: Optional[Config] = None
|
||||
|
||||
|
||||
def setup_config(p: Path) -> None:
|
||||
"""
|
||||
Setup config by given path.
|
||||
|
||||
Raise exception if config file is invalid.
|
||||
"""
|
||||
with open(p, "rb") as f:
|
||||
raw = tomllib.load(f)
|
||||
|
||||
global _CONFIG
|
||||
_CONFIG = Config.from_raw(raw)
|
||||
|
||||
|
||||
def get_config() -> Config:
|
||||
"""
|
||||
Get config instance.
|
||||
|
||||
Raises RuntimeError if config is not loaded.
|
||||
"""
|
||||
if _CONFIG is None:
|
||||
raise RuntimeError("Config is not loaded. Call setup_config() first.")
|
||||
else:
|
||||
return _CONFIG
|
||||
Reference in New Issue
Block a user