PoC: Bot instance inside method shortcuts using pydantic Validation Context (#1210)

* PoC: Mount objects to the Bot instance, bind shortcuts to configured instance

* Fixe docstring of the bind method

* Pass Bot instance explicitly to the URLInputFile

* Added tests

* Added changelog

* Refactor aiogram client and update tests

Refactored base.py to improve code readability by separating response_type operation from model_validate(). Also, adjusted the parameters in URLInputFile() within test_input_file.py for better test coverage. Updated input_file.py to streamline read method and avoid unnecessary instantiation of Bot class. Lastly, adjusted typing in methods/base.py to enhance code clarity.

* Update changelog
This commit is contained in:
Alex Root Junior 2023-07-11 23:17:26 +03:00 committed by GitHub
parent c39a803747
commit a7b92bb050
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 228 additions and 111 deletions

View file

@ -1,11 +1,22 @@
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, Any, Dict, Generator, Generic, Optional, TypeVar
from typing import (
TYPE_CHECKING,
Any,
ClassVar,
Dict,
Generator,
Generic,
Optional,
TypeVar,
)
from pydantic import BaseModel, ConfigDict
from pydantic.functional_validators import model_validator
from aiogram.client.context_controller import BotContextController
from ..types import InputFile, ResponseParameters
from ..types.base import UNSET_TYPE
@ -32,7 +43,7 @@ class Response(BaseModel, Generic[TelegramType]):
parameters: Optional[ResponseParameters] = None
class TelegramMethod(BaseModel, Generic[TelegramType], ABC):
class TelegramMethod(BotContextController, BaseModel, Generic[TelegramType], ABC):
model_config = ConfigDict(
extra="allow",
populate_by_name=True,
@ -40,6 +51,7 @@ class TelegramMethod(BaseModel, Generic[TelegramType], ABC):
)
@model_validator(mode="before")
@classmethod
def remove_unset(cls, values: Dict[str, Any]) -> Dict[str, Any]:
"""
Remove UNSET before fields validation.
@ -51,25 +63,31 @@ class TelegramMethod(BaseModel, Generic[TelegramType], ABC):
"""
return {k: v for k, v in values.items() if not isinstance(v, UNSET_TYPE)}
@property
@abstractmethod
def __returning__(self) -> type: # pragma: no cover
pass
if TYPE_CHECKING:
__returning__: ClassVar[type]
__api_method__: ClassVar[str]
else:
@property
@abstractmethod
def __api_method__(self) -> str:
pass
@property
@abstractmethod
def __returning__(self) -> type:
pass
def build_response(self, data: Dict[str, Any]) -> Response[TelegramType]:
# noinspection PyTypeChecker
return Response[self.__returning__](**data) # type: ignore
@property
@abstractmethod
def __api_method__(self) -> str:
pass
async def emit(self, bot: Bot) -> TelegramType:
return await bot(self)
def __await__(self) -> Generator[Any, None, TelegramType]:
from aiogram.client.bot import Bot
bot = Bot.get_current(no_error=False)
bot = self._bot
if not bot:
raise RuntimeError(
"This method is not mounted to a any bot instance, please call it explicilty "
"with bot instance `await bot(method)`\n"
"or mount method to a bot instance `method.as_(bot)` "
"and then call it `await method()`"
)
return self.emit(bot).__await__()