Use pydantic instead of dataclasses

This commit is contained in:
2024-02-10 12:59:31 +03:00
parent e89cb04c02
commit 3f957db2eb
9 changed files with 70 additions and 187 deletions

View File

@@ -1,8 +1,7 @@
from ..config import Config
from pydantic import BaseModel, Field
from ..config import GlobalConfig as Config
class ApiMethod:
api_url: str
def __init__(self) -> None:
self.api_url = Config().api_url
class ApiMethod(BaseModel):
api_url: str = Field(Config().api_url)

View File

@@ -1,23 +1,6 @@
from dataclasses import dataclass
from typing import Any
from ._helpers import *
from ._api_model import ApiModel
@dataclass
class Admin:
class Admin(ApiModel):
user_id: int
user_name: str
@staticmethod
def from_dict(obj: Any) -> 'Admin':
assert isinstance(obj, dict)
user_id = int(from_str(obj.get("user_id")))
user_name = from_str(obj.get("user_name"))
return Admin(user_id, user_name)
def to_dict(self) -> dict:
result: dict = {}
result["user_id"] = from_str(str(self.user_id))
result["user_name"] = from_str(self.user_name)
return result

View File

@@ -0,0 +1,12 @@
from typing import Any, Dict
from pydantic import BaseModel
class ApiModel(BaseModel):
@classmethod
def from_dict(cls: 'ApiModel', obj: Dict[str, Any]) -> 'ApiModel':
return cls(**obj)
def to_dict(self, **kwargs: Any) -> Dict[str, Any]:
return self.model_dump(**kwargs)

View File

@@ -1,8 +1,12 @@
from aiogram import Bot, Dispatcher
from pydantic import BaseModel
from handlers.handler import Handler
class Token(BaseModel):
token: str
class NeuroApiBot:
bot: Bot
dp: Dispatcher
@@ -10,14 +14,15 @@ class NeuroApiBot:
_instances = {}
def __init__(self, token: str) -> None:
self.bot = Bot(token)
token_data = Token(token=token)
self.bot = Bot(token_data.token)
self.dp = Dispatcher()
def __new__(cls, token: str) -> 'NeuroApiBot':
assert isinstance(token, str)
if token not in cls._instances:
cls._instances[token] = super(NeuroApiBot, cls).__new__(cls)
return cls._instances[token]
token_data = Token(token=token)
if token_data.token not in cls._instances:
cls._instances[token_data.token] = super(NeuroApiBot, cls).__new__(cls)
return cls._instances[token_data.token]
def include_router(self, *routerClasses: Handler) -> None:
for routerClass in routerClasses:

View File

@@ -1,38 +1,17 @@
from dataclasses import dataclass
from typing import Optional
from typing import List
from uuid import UUID
from ._helpers import *
from pydantic import Field
from ._api_model import ApiModel
from ._singleton import Singleton
@dataclass
class BotSettings(Singleton):
class BotSettings(ApiModel, Singleton):
uuid: UUID
message_times: List[str]
message_times: List[str] = Field([], alias='messageTimes')
channel: str
is_active: bool
is_active: bool = Field(False, alias='isActive')
@staticmethod
def from_dict(obj: Any) -> 'BotSettings':
assert isinstance(obj, dict)
uuid = UUID(obj.get("uuid"))
message_times = from_list(from_str, obj.get("messageTimes"))
channel = from_str(obj.get("channel"))
is_active = from_bool(obj.get("isActive"))
return BotSettings(uuid, message_times, channel, is_active)
def to_dict(self) -> dict:
result: dict = {}
result["uuid"] = str(self.uuid)
result["messageTimes"] = from_list(from_str, self.message_times)
result["channel"] = from_str(self.channel)
result["isActive"] = from_bool(self.is_active)
return result
@staticmethod
def get_active() -> Optional['BotSettings']:
try:
return BotSettings._instances[BotSettings]
except:
return None
def get_text(self):
return f"Канал: {self.channel}\nВремя: {', '.join(self.message_times)}"

View File

@@ -1,47 +0,0 @@
from datetime import datetime
from typing import Any, Callable, List, TypeVar, Type, cast
import dateutil.parser
T = TypeVar("T")
def from_bool(x: Any) -> bool:
assert isinstance(x, bool)
return x
def from_str(x: Any) -> str:
assert isinstance(x, str)
return x
def from_union(fs, x):
for f in fs:
try:
return f(x)
except:
pass
assert False
def from_none(x: Any) -> Any:
assert x is None
return x
def from_list(f: Callable[[Any], T], x: Any) -> List[T]:
assert isinstance(x, list)
return [f(y) for y in x]
def from_datetime(x: Any) -> datetime:
return dateutil.parser.parse(x)
def to_class(c: Type[T], x: Any) -> dict:
assert isinstance(x, c)
return cast(Any, x).to_dict()
def from_int(x: Any) -> int:
assert isinstance(x, int) and not isinstance(x, bool)
return x

View File

@@ -1,28 +1,10 @@
from dataclasses import dataclass
from uuid import UUID
from ._helpers import *
from ._api_model import ApiModel
@dataclass
class Image:
class Image(ApiModel):
message_id: int
file_id: str
has_spoiler: bool
post_uuid: UUID
@staticmethod
def from_dict(obj: Any) -> 'Image':
assert isinstance(obj, dict)
message_id = from_int(obj.get("message_id"))
file_id = from_str(obj.get("file_id"))
has_spoiler = from_bool(obj.get("has_spoiler"))
post_uuid = UUID(obj.get("post_uuid"))
return Image(message_id, file_id, has_spoiler, post_uuid)
def to_dict(self) -> dict:
result: dict = {}
result["message_id"] = from_int(self.message_id)
result["file_id"] = from_str(self.file_id)
result["has_spoiler"] = from_bool(self.has_spoiler)
result["post_uuid"] = str(self.post_uuid)
return result

View File

@@ -1,59 +1,34 @@
import json
from dataclasses import dataclass
from datetime import datetime
from typing import Any, List, Optional
from typing import Any, Dict, List, Optional
from uuid import UUID
from aiogram.types import MessageEntity
from pydantic import Field
from ._helpers import *
from ._api_model import ApiModel
from ._image import Image
def to_message_dict_class(x: Any) -> dict:
assert isinstance(x, MessageEntity)
return cast(MessageEntity, x).model_dump()
@dataclass
class Post:
class Post(ApiModel):
uuid: UUID
posted: bool
text: str
media_group_id: int | str
timestamp: datetime
from_user_id: int
images: Optional[List[Image]] = None
message_entities: Optional[List[MessageEntity]] = None
images: Optional[List[Image]] = Field(None)
message_entities: Optional[List[MessageEntity]] = Field(None)
@staticmethod
def from_dict(obj: Any) -> 'Post':
assert isinstance(obj, dict)
uuid = UUID(obj.get("uuid"))
posted = from_bool(obj.get("posted"))
text = from_str(obj.get("text"))
media_group_id = from_str(obj.get("media_group_id")) if obj.get(
"media_group_id") is not None else 'None'
timestamp = from_datetime(obj.get("timestamp"))
from_user_id = int(from_str(obj.get("from_user_id")))
images = from_union([lambda x: from_list(
Image.from_dict, x), from_none], obj.get("images"))
@classmethod
def from_dict(cls: 'Post', obj: Dict[str, Any]) -> 'Post':
mes_ent = json.loads(obj.get('message_entities', '[]'))
message_entities = from_list(MessageEntity.model_validate, mes_ent)
return Post(uuid, posted, text, media_group_id, timestamp, from_user_id, images, message_entities)
obj['message_entities'] = mes_ent
return cls(**obj)
def to_dict(self) -> dict:
result: dict = {}
result["uuid"] = str(self.uuid)
result["posted"] = from_bool(self.posted)
result["text"] = from_str(self.text)
result["media_group_id"] = from_str(str(self.media_group_id))
result["timestamp"] = self.timestamp.isoformat()
result["from_user_id"] = from_str(str(self.from_user_id))
if self.images is not None:
result["images"] = from_union([lambda x: from_list(
lambda x: to_class(Image, x), x), from_none], self.images)
if self.message_entities is not None:
result['message_entities'] = from_union([lambda x: from_list(
lambda x: to_message_dict_class(x), x), from_none], self.message_entities)
return result
obj = super().to_dict()
obj['message_entities'] = json.dumps(obj['message_entities'])
obj['media_group_id'] = str(obj['media_group_id'])
return obj

View File

@@ -1,22 +1,17 @@
from dataclasses import dataclass
from typing import Any
from ._helpers import *
import json
from typing import Optional
from pydantic import Field
from ._api_model import ApiModel
@dataclass
class User:
class User(ApiModel):
id: int
username: str
@staticmethod
def from_dict(obj: Any) -> 'User':
assert isinstance(obj, dict)
id = int(from_str(obj.get("id")))
username = from_str(obj.get("username"))
return User(id, username)
username: str = Field(..., alias='user_name')
banned: Optional[bool] = Field(None)
def to_dict(self) -> dict:
result: dict = {}
result["id"] = from_str(str(self.id))
result["username"] = from_str(self.username)
return result
obj = super().to_dict(exclude_unset=True)
obj['id'] = str(obj['id'])
return obj