from dataclasses import dataclass, fields from typing import Optional, List from DataClassJson import DataClassJson from modules.shared.DatabaseAbstraction import Cursor types = {bool: 'INTEGER', int: 'INTEGER', float: 'REAL', str: "TEXT", Optional[bool]: 'INTEGER', Optional[int]: 'INTEGER', Optional[float]: 'REAL', Optional[str]: "TEXT", } @dataclass class DataClassDatabase(DataClassJson): _main_entity: bool = None _table_name: str = None pass def __post_init__(self): super().__post_init__() @classmethod def get_create_sqls(cls, table_name = None): result: list[str] = list() result.append(f'CREATE TABLE IF NOT EXISTS {table_name} (fk TEXT NOT NULL, pk TEXT NOT NULL, PRIMARY KEY(pk, fk));') tmp_instance = cls() if not table_name: table_name = tmp_instance._table_name excluded_fields = {f.name for f in fields(DataClassDatabase)} all_fields = [f for f in fields(cls) if f.name not in excluded_fields and not f.name.startswith('_')] for field in all_fields: if field.name in tmp_instance._forwarding: inner_type: type = tmp_instance._forwarding[field.name] try: result.extend(inner_type.get_create_sqls()) except Exception as e: raise RuntimeError('invalid forwarding type') from e elif field.type in { list, Optional[list], Optional[List] }: result.append(f'CREATE TABLE IF NOT EXISTS {table_name}_{field.name} (fk TEXT NOT NULL, data TEXT NOT NULL);') else: result.append(f'ALTER TABLE {table_name} ADD COLUMN {field.name} {types.get(field.type, 'TEXT')};') return result @classmethod def create(cls, cur: Cursor): for sql in cls.get_create_sqls(): cur.execute(sql) if __name__ == '__main__': @dataclass class ModelStats(DataClassDatabase): downloadCount: Optional[int] = None favoriteCount: Optional[int] = None thumbsUpCount: Optional[int] = None thumbsDownCount: Optional[int] = None commentCount: Optional[int] = None ratingCount: Optional[int] = None rating: Optional[int] = None def __post_init__(self): super().__post_init__() self._forwarding = {} @dataclass class Model(DataClassDatabase): id: Optional[int] = None name: Optional[str] = None description: Optional[str] = None allowNoCredit: Optional[bool] = None allowCommercialUse: Optional[list] = None allowDerivatives: Optional[bool] = None allowDifferentLicense: Optional[bool] = None type: Optional[str] = None minor: Optional[bool] = None sfwOnly: Optional[bool] = None poi: Optional[bool] = None nsfw: Optional[bool] = None nsfwLevel: Optional[int] = None availability: Optional[str] = None cosmetic: Optional[str] = None supportsGeneration: Optional[bool] = None stats: Optional[ModelStats] = None def __post_init__(self): super().__post_init__() self._forwarding = { 'stats': ModelStats, } self._key_field = 'id' self._table_name = 'gagaga' for s in Model.get_create_sqls(): print(s)