Dev 3.x i18n & improvements (#696)

* Added base code and make code improvements
* Auto-exclude coverage for `if TYPE_CHECKING:`
* Fixed current coverage
* Cover I18n module
* Update pipeline
* Fixed annotations
* Added docs
* Move exceptions
* Added tests for KeyboardBuilder and initial docs
* Remove help generator (removed from sources tree, requires rewrite)
* Added patch-notes #698, #699, #700, #701, #702, #703
This commit is contained in:
Alex Root Junior 2021-09-22 00:52:38 +03:00 committed by GitHub
parent 5bd1162f57
commit e4046095d7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
223 changed files with 1909 additions and 1121 deletions

View file

@ -0,0 +1,5 @@
[report]
exclude_lines =
pragma: no cover
if TYPE_CHECKING:
@abstractmethod

View file

@ -12,7 +12,6 @@ jobs:
build: build:
strategy: strategy:
max-parallel: 9 max-parallel: 9
fail-fast: true
matrix: matrix:
os: os:
- ubuntu-latest - ubuntu-latest
@ -38,10 +37,12 @@ jobs:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- name: Install and configure Poetry - name: Install and configure Poetry
uses: snok/install-poetry@v1.1.4 uses: snok/install-poetry@v1
with: with:
version: 1.1.8
virtualenvs-create: true virtualenvs-create: true
virtualenvs-in-project: true virtualenvs-in-project: true
installer-parallel: true
- name: Setup redis - name: Setup redis
if: ${{ matrix.os != 'windows-latest' }} if: ${{ matrix.os != 'windows-latest' }}
@ -59,7 +60,7 @@ jobs:
- name: Project dependencies - name: Project dependencies
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true' if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
run: | run: |
poetry install --no-interaction poetry install --no-interaction -E fast -E redis -E proxy -E i18n -E docs
- name: Lint code - name: Lint code
run: | run: |

3
CHANGES/698.feature Normal file
View file

@ -0,0 +1,3 @@
Added support of local Bot API server files downloading
When Local API is enabled files can be downloaded via `bot.download`/`bot.download_file` methods.

1
CHANGES/699.misc Normal file
View file

@ -0,0 +1 @@
Covered by tests and docs KeyboardBuilder util

4
CHANGES/700.misc Normal file
View file

@ -0,0 +1,4 @@
**Breaking!!!**. Refactored and renamed exceptions.
- Exceptions module was moved from :code:`aiogram.utils.exceptions` to :code:`aiogram.exceptions`
- Added prefix `Telegram` for all error classes

1
CHANGES/701.feature Normal file
View file

@ -0,0 +1 @@
Implemented I18n & L10n support

1
CHANGES/702.misc Normal file
View file

@ -0,0 +1 @@
Replaced all :code:`pragma: no cover` marks via global :code:`.coveragerc` config

4
CHANGES/703.misc Normal file
View file

@ -0,0 +1,4 @@
Updated dependencies.
**Breaking for framework developers**
Now all optional dependencies should be installed as extra: `poetry install -E fast -E redis -E proxy -E i18n -E docs`

View file

@ -47,7 +47,7 @@ help:
.PHONY: install .PHONY: install
install: install:
poetry install poetry install -E fast -E redis -E proxy -E i18n -E docs
$(py) pre-commit install $(py) pre-commit install
.PHONY: clean .PHONY: clean

View file

@ -231,6 +231,14 @@ class Bot(ContextInstanceMixin["Bot"]):
async for chunk in stream: async for chunk in stream:
await f.write(chunk) await f.write(chunk)
@classmethod
async def __aiofiles_reader(
cls, file: str, chunk_size: int = 65536
) -> AsyncGenerator[bytes, None]:
async with aiofiles.open(file, "rb") as f:
while chunk := await f.read(chunk_size):
yield chunk
async def download_file( async def download_file(
self, self,
file_path: str, file_path: str,
@ -254,15 +262,26 @@ class Bot(ContextInstanceMixin["Bot"]):
if destination is None: if destination is None:
destination = io.BytesIO() destination = io.BytesIO()
url = self.session.api.file_url(self.__token, file_path) close_stream = False
stream = self.session.stream_content(url=url, timeout=timeout, chunk_size=chunk_size) if self.session.api.is_local:
stream = self.__aiofiles_reader(
if isinstance(destination, (str, pathlib.Path)): self.session.api.wrap_local_file(file_path), chunk_size=chunk_size
return await self.__download_file(destination=destination, stream=stream)
else:
return await self.__download_file_binary_io(
destination=destination, seek=seek, stream=stream
) )
close_stream = True
else:
url = self.session.api.file_url(self.__token, file_path)
stream = self.session.stream_content(url=url, timeout=timeout, chunk_size=chunk_size)
try:
if isinstance(destination, (str, pathlib.Path)):
return await self.__download_file(destination=destination, stream=stream)
else:
return await self.__download_file_binary_io(
destination=destination, seek=seek, stream=stream
)
finally:
if close_stream:
await stream.aclose()
async def download( async def download(
self, self,

View file

@ -19,11 +19,11 @@ from aiohttp import BasicAuth, ClientError, ClientSession, FormData, TCPConnecto
from aiogram.methods import Request, TelegramMethod from aiogram.methods import Request, TelegramMethod
from ...exceptions import TelegramNetworkError
from ...methods.base import TelegramType from ...methods.base import TelegramType
from ...utils.exceptions.network import NetworkError
from .base import UNSET, BaseSession from .base import UNSET, BaseSession
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..bot import Bot from ..bot import Bot
_ProxyBasic = Union[str, Tuple[str, BasicAuth]] _ProxyBasic = Union[str, Tuple[str, BasicAuth]]
@ -147,9 +147,9 @@ class AiohttpSession(BaseSession):
) as resp: ) as resp:
raw_result = await resp.text() raw_result = await resp.text()
except asyncio.TimeoutError: except asyncio.TimeoutError:
raise NetworkError(method=call, message="Request timeout error") raise TelegramNetworkError(method=call, message="Request timeout error")
except ClientError as e: except ClientError as e:
raise NetworkError(method=call, message=f"{type(e).__name__}: {e}") raise TelegramNetworkError(method=call, message=f"{type(e).__name__}: {e}")
response = self.check_response(method=call, status_code=resp.status, content=raw_result) response = self.check_response(method=call, status_code=resp.status, content=raw_result)
return cast(TelegramType, response.result) return cast(TelegramType, response.result)

View file

@ -20,22 +20,27 @@ from typing import (
cast, cast,
) )
from aiogram.utils.exceptions.base import TelegramAPIError from aiogram.exceptions import (
RestartingTelegram,
TelegramAPIError,
TelegramBadRequest,
TelegramConflictError,
TelegramEntityTooLarge,
TelegramForbiddenError,
TelegramMigrateToChat,
TelegramNotFound,
TelegramRetryAfter,
TelegramServerError,
TelegramUnauthorizedError,
)
from aiogram.utils.helper import Default from aiogram.utils.helper import Default
from ...methods import Response, TelegramMethod from ...methods import Response, TelegramMethod
from ...methods.base import TelegramType from ...methods.base import TelegramType
from ...types import UNSET, TelegramObject from ...types import UNSET, TelegramObject
from ...utils.exceptions.bad_request import BadRequest
from ...utils.exceptions.conflict import ConflictError
from ...utils.exceptions.network import EntityTooLarge
from ...utils.exceptions.not_found import NotFound
from ...utils.exceptions.server import RestartingTelegram, ServerError
from ...utils.exceptions.special import MigrateToChat, RetryAfter
from ...utils.exceptions.unauthorized import UnauthorizedError
from ..telegram import PRODUCTION, TelegramAPIServer from ..telegram import PRODUCTION, TelegramAPIServer
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..bot import Bot from ..bot import Bot
_JsonLoads = Callable[..., Any] _JsonLoads = Callable[..., Any]
@ -44,7 +49,7 @@ NextRequestMiddlewareType = Callable[
["Bot", TelegramMethod[TelegramObject]], Awaitable[Response[TelegramObject]] ["Bot", TelegramMethod[TelegramObject]], Awaitable[Response[TelegramObject]]
] ]
RequestMiddlewareType = Callable[ RequestMiddlewareType = Callable[
["Bot", TelegramMethod[TelegramType], NextRequestMiddlewareType], [NextRequestMiddlewareType, "Bot", TelegramMethod[TelegramType]],
Awaitable[Response[TelegramType]], Awaitable[Response[TelegramType]],
] ]
@ -79,29 +84,31 @@ class BaseSession(abc.ABC):
if parameters := response.parameters: if parameters := response.parameters:
if parameters.retry_after: if parameters.retry_after:
raise RetryAfter( raise TelegramRetryAfter(
method=method, message=description, retry_after=parameters.retry_after method=method, message=description, retry_after=parameters.retry_after
) )
if parameters.migrate_to_chat_id: if parameters.migrate_to_chat_id:
raise MigrateToChat( raise TelegramMigrateToChat(
method=method, method=method,
message=description, message=description,
migrate_to_chat_id=parameters.migrate_to_chat_id, migrate_to_chat_id=parameters.migrate_to_chat_id,
) )
if status_code == HTTPStatus.BAD_REQUEST: if status_code == HTTPStatus.BAD_REQUEST:
raise BadRequest(method=method, message=description) raise TelegramBadRequest(method=method, message=description)
if status_code == HTTPStatus.NOT_FOUND: if status_code == HTTPStatus.NOT_FOUND:
raise NotFound(method=method, message=description) raise TelegramNotFound(method=method, message=description)
if status_code == HTTPStatus.CONFLICT: if status_code == HTTPStatus.CONFLICT:
raise ConflictError(method=method, message=description) raise TelegramConflictError(method=method, message=description)
if status_code in (HTTPStatus.UNAUTHORIZED, HTTPStatus.FORBIDDEN): if status_code == HTTPStatus.UNAUTHORIZED:
raise UnauthorizedError(method=method, message=description) raise TelegramUnauthorizedError(method=method, message=description)
if status_code == HTTPStatus.FORBIDDEN:
raise TelegramForbiddenError(method=method, message=description)
if status_code == HTTPStatus.REQUEST_ENTITY_TOO_LARGE: if status_code == HTTPStatus.REQUEST_ENTITY_TOO_LARGE:
raise EntityTooLarge(method=method, message=description) raise TelegramEntityTooLarge(method=method, message=description)
if status_code >= HTTPStatus.INTERNAL_SERVER_ERROR: if status_code >= HTTPStatus.INTERNAL_SERVER_ERROR:
if "restart" in description: if "restart" in description:
raise RestartingTelegram(method=method, message=description) raise RestartingTelegram(method=method, message=description)
raise ServerError(method=method, message=description) raise TelegramServerError(method=method, message=description)
raise TelegramAPIError( raise TelegramAPIError(
method=method, method=method,

View file

@ -1,4 +1,10 @@
from dataclasses import dataclass from dataclasses import dataclass
from typing import Any, Protocol
class WrapLocalFileCallbackCallbackProtocol(Protocol): # pragma: no cover
def __call__(self, value: str) -> str:
pass
@dataclass(frozen=True) @dataclass(frozen=True)
@ -8,8 +14,13 @@ class TelegramAPIServer:
""" """
base: str base: str
"""Base URL"""
file: str file: str
"""Files URL"""
is_local: bool = False is_local: bool = False
"""Mark this server is in `local mode <https://core.telegram.org/bots/api#using-a-local-bot-api-server>`_."""
wrap_local_file: WrapLocalFileCallbackCallbackProtocol = lambda v: v
"""Callback to wrap files path in local mode"""
def api_url(self, token: str, method: str) -> str: def api_url(self, token: str, method: str) -> str:
""" """
@ -32,19 +43,18 @@ class TelegramAPIServer:
return self.file.format(token=token, path=path) return self.file.format(token=token, path=path)
@classmethod @classmethod
def from_base(cls, base: str, is_local: bool = False) -> "TelegramAPIServer": def from_base(cls, base: str, **kwargs: Any) -> "TelegramAPIServer":
""" """
Use this method to auto-generate TelegramAPIServer instance from base URL Use this method to auto-generate TelegramAPIServer instance from base URL
:param base: Base URL :param base: Base URL
:param is_local: Mark this server is in `local mode <https://core.telegram.org/bots/api#using-a-local-bot-api-server>`_.
:return: instance of :class:`TelegramAPIServer` :return: instance of :class:`TelegramAPIServer`
""" """
base = base.rstrip("/") base = base.rstrip("/")
return cls( return cls(
base=f"{base}/bot{{token}}/{{method}}", base=f"{base}/bot{{token}}/{{method}}",
file=f"{base}/file/bot{{token}}/{{path}}", file=f"{base}/file/bot{{token}}/{{path}}",
is_local=is_local, **kwargs,
) )

View file

@ -8,13 +8,11 @@ from typing import Any, AsyncGenerator, Dict, List, Optional, Union
from .. import loggers from .. import loggers
from ..client.bot import Bot from ..client.bot import Bot
from ..exceptions import TelegramAPIError, TelegramNetworkError, TelegramServerError
from ..methods import GetUpdates, TelegramMethod from ..methods import GetUpdates, TelegramMethod
from ..types import Update, User from ..types import Update, User
from ..types.update import UpdateTypeLookupError from ..types.update import UpdateTypeLookupError
from ..utils.backoff import Backoff, BackoffConfig from ..utils.backoff import Backoff, BackoffConfig
from ..utils.exceptions.base import TelegramAPIError
from ..utils.exceptions.network import NetworkError
from ..utils.exceptions.server import ServerError
from .event.bases import UNHANDLED, SkipHandler from .event.bases import UNHANDLED, SkipHandler
from .event.telegram import TelegramEventObserver from .event.telegram import TelegramEventObserver
from .fsm.middleware import FSMContextMiddleware from .fsm.middleware import FSMContextMiddleware
@ -149,7 +147,7 @@ class Dispatcher(Router):
while True: while True:
try: try:
updates = await bot(get_updates, **kwargs) updates = await bot(get_updates, **kwargs)
except (NetworkError, ServerError) as e: except (TelegramNetworkError, TelegramServerError) as e:
# In cases when Telegram Bot API was inaccessible don't need to stop polling process # In cases when Telegram Bot API was inaccessible don't need to stop polling process
# because some of developers can't make auto-restarting of the script # because some of developers can't make auto-restarting of the script
loggers.dispatcher.error("Failed to fetch updates - %s: %s", type(e).__name__, e) loggers.dispatcher.error("Failed to fetch updates - %s: %s", type(e).__name__, e)
@ -331,7 +329,7 @@ class Dispatcher(Router):
try: try:
try: try:
await waiter await waiter
except CancelledError: # pragma: nocover except CancelledError: # pragma: no cover
process_updates.remove_done_callback(release_waiter) process_updates.remove_done_callback(release_waiter)
process_updates.cancel() process_updates.cancel()
raise raise

View file

@ -1,14 +1,19 @@
from __future__ import annotations from __future__ import annotations
from typing import Any, Awaitable, Callable, Dict, NoReturn, Optional, Union from typing import Any, Awaitable, Callable, Dict, NoReturn, Optional, TypeVar, Union
from unittest.mock import sentinel from unittest.mock import sentinel
from ...types import TelegramObject from ...types import TelegramObject
from ..middlewares.base import BaseMiddleware from ..middlewares.base import BaseMiddleware
NextMiddlewareType = Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]] MiddlewareEventType = TypeVar("MiddlewareEventType", bound=TelegramObject)
NextMiddlewareType = Callable[[MiddlewareEventType, Dict[str, Any]], Awaitable[Any]]
MiddlewareType = Union[ MiddlewareType = Union[
BaseMiddleware, Callable[[NextMiddlewareType, TelegramObject, Dict[str, Any]], Awaitable[Any]] BaseMiddleware,
Callable[
[NextMiddlewareType[MiddlewareEventType], MiddlewareEventType, Dict[str, Any]],
Awaitable[Any],
],
] ]
UNHANDLED = sentinel.UNHANDLED UNHANDLED = sentinel.UNHANDLED

View file

@ -8,10 +8,17 @@ from pydantic import ValidationError
from ...types import TelegramObject from ...types import TelegramObject
from ..filters.base import BaseFilter from ..filters.base import BaseFilter
from .bases import REJECTED, UNHANDLED, MiddlewareType, NextMiddlewareType, SkipHandler from .bases import (
REJECTED,
UNHANDLED,
MiddlewareEventType,
MiddlewareType,
NextMiddlewareType,
SkipHandler,
)
from .handler import CallbackType, FilterObject, FilterType, HandlerObject, HandlerType from .handler import CallbackType, FilterObject, FilterType, HandlerObject, HandlerType
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from aiogram.dispatcher.router import Router from aiogram.dispatcher.router import Router
@ -29,8 +36,8 @@ class TelegramEventObserver:
self.handlers: List[HandlerObject] = [] self.handlers: List[HandlerObject] = []
self.filters: List[Type[BaseFilter]] = [] self.filters: List[Type[BaseFilter]] = []
self.outer_middlewares: List[MiddlewareType] = [] self.outer_middlewares: List[MiddlewareType[TelegramObject]] = []
self.middlewares: List[MiddlewareType] = [] self.middlewares: List[MiddlewareType[TelegramObject]] = []
# Re-used filters check method from already implemented handler object # Re-used filters check method from already implemented handler object
# with dummy callback which never will be used # with dummy callback which never will be used
@ -78,7 +85,7 @@ class TelegramEventObserver:
yield filter_ yield filter_
registry.append(filter_) registry.append(filter_)
def _resolve_middlewares(self, *, outer: bool = False) -> List[MiddlewareType]: def _resolve_middlewares(self, *, outer: bool = False) -> List[MiddlewareType[TelegramObject]]:
""" """
Get all middlewares in a tree Get all middlewares in a tree
:param *: :param *:
@ -137,8 +144,8 @@ class TelegramEventObserver:
@classmethod @classmethod
def _wrap_middleware( def _wrap_middleware(
cls, middlewares: List[MiddlewareType], handler: HandlerType cls, middlewares: List[MiddlewareType[MiddlewareEventType]], handler: HandlerType
) -> NextMiddlewareType: ) -> NextMiddlewareType[MiddlewareEventType]:
@functools.wraps(handler) @functools.wraps(handler)
def mapper(event: TelegramObject, kwargs: Dict[str, Any]) -> Any: def mapper(event: TelegramObject, kwargs: Dict[str, Any]) -> Any:
return handler(event, **kwargs) return handler(event, **kwargs)
@ -194,8 +201,11 @@ class TelegramEventObserver:
def middleware( def middleware(
self, self,
middleware: Optional[MiddlewareType] = None, middleware: Optional[MiddlewareType[TelegramObject]] = None,
) -> Union[Callable[[MiddlewareType], MiddlewareType], MiddlewareType]: ) -> Union[
Callable[[MiddlewareType[TelegramObject]], MiddlewareType[TelegramObject]],
MiddlewareType[TelegramObject],
]:
""" """
Decorator for registering inner middlewares Decorator for registering inner middlewares
@ -215,7 +225,7 @@ class TelegramEventObserver:
<event>.middleware(my_middleware) # via method <event>.middleware(my_middleware) # via method
""" """
def wrapper(m: MiddlewareType) -> MiddlewareType: def wrapper(m: MiddlewareType[TelegramObject]) -> MiddlewareType[TelegramObject]:
self.middlewares.append(m) self.middlewares.append(m)
return m return m
@ -225,8 +235,11 @@ class TelegramEventObserver:
def outer_middleware( def outer_middleware(
self, self,
middleware: Optional[MiddlewareType] = None, middleware: Optional[MiddlewareType[TelegramObject]] = None,
) -> Union[Callable[[MiddlewareType], MiddlewareType], MiddlewareType]: ) -> Union[
Callable[[MiddlewareType[TelegramObject]], MiddlewareType[TelegramObject]],
MiddlewareType[TelegramObject],
]:
""" """
Decorator for registering outer middlewares Decorator for registering outer middlewares
@ -246,7 +259,7 @@ class TelegramEventObserver:
<event>.outer_middleware(my_middleware) # via method <event>.outer_middleware(my_middleware) # via method
""" """
def wrapper(m: MiddlewareType) -> MiddlewareType: def wrapper(m: MiddlewareType[TelegramObject]) -> MiddlewareType[TelegramObject]:
self.outer_middlewares.append(m) self.outer_middlewares.append(m)
return m return m

View file

@ -4,6 +4,7 @@ from .base import BaseFilter
from .command import Command, CommandObject from .command import Command, CommandObject
from .content_types import ContentTypesFilter from .content_types import ContentTypesFilter
from .exception import ExceptionMessageFilter, ExceptionTypeFilter from .exception import ExceptionMessageFilter, ExceptionTypeFilter
from .state import StateFilter
from .text import Text from .text import Text
__all__ = ( __all__ = (
@ -15,21 +16,46 @@ __all__ = (
"ContentTypesFilter", "ContentTypesFilter",
"ExceptionMessageFilter", "ExceptionMessageFilter",
"ExceptionTypeFilter", "ExceptionTypeFilter",
"StateFilter",
) )
BUILTIN_FILTERS: Dict[str, Tuple[Type[BaseFilter], ...]] = { BUILTIN_FILTERS: Dict[str, Tuple[Type[BaseFilter], ...]] = {
"message": (Text, Command, ContentTypesFilter), "message": (
"edited_message": (Text, Command, ContentTypesFilter), Text,
"channel_post": (Text, ContentTypesFilter), Command,
"edited_channel_post": (Text, ContentTypesFilter), ContentTypesFilter,
"inline_query": (Text,), StateFilter,
"chosen_inline_result": (), ),
"callback_query": (Text,), "edited_message": (
"shipping_query": (), Text,
"pre_checkout_query": (), Command,
"poll": (), ContentTypesFilter,
"poll_answer": (), StateFilter,
"my_chat_member": (), ),
"chat_member": (), "channel_post": (
Text,
ContentTypesFilter,
StateFilter,
),
"edited_channel_post": (
Text,
ContentTypesFilter,
StateFilter,
),
"inline_query": (
Text,
StateFilter,
),
"chosen_inline_result": (StateFilter,),
"callback_query": (
Text,
StateFilter,
),
"shipping_query": (StateFilter,),
"pre_checkout_query": (StateFilter,),
"poll": (StateFilter,),
"poll_answer": (StateFilter,),
"my_chat_member": (StateFilter,),
"chat_member": (StateFilter,),
"error": (ExceptionMessageFilter, ExceptionTypeFilter), "error": (ExceptionMessageFilter, ExceptionTypeFilter),
} }

View file

@ -14,7 +14,7 @@ class BaseFilter(ABC, BaseModel):
the validators based on class attributes and custom validator. the validators based on class attributes and custom validator.
""" """
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
# This checking type-hint is needed because mypy checks validity of overrides and raises: # This checking type-hint is needed because mypy checks validity of overrides and raises:
# error: Signature of "__call__" incompatible with supertype "BaseFilter" [override] # error: Signature of "__call__" incompatible with supertype "BaseFilter" [override]
# https://mypy.readthedocs.io/en/latest/error_code_list.html#check-validity-of-overrides-override # https://mypy.readthedocs.io/en/latest/error_code_list.html#check-validity-of-overrides-override

View file

@ -22,7 +22,7 @@ class CallbackDataException(Exception):
class CallbackData(BaseModel): class CallbackData(BaseModel):
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
sep: str sep: str
prefix: str prefix: str

View file

@ -0,0 +1,47 @@
from inspect import isclass
from typing import Any, Dict, Optional, Sequence, Type, Union, cast, no_type_check
from pydantic import validator
from aiogram.dispatcher.filters import BaseFilter
from aiogram.dispatcher.fsm.state import State, StatesGroup
from aiogram.types import TelegramObject
StateType = Union[str, None, State, StatesGroup, Type[StatesGroup]]
class StateFilter(BaseFilter):
"""
State filter
"""
state: Union[StateType, Sequence[StateType]]
class Config:
arbitrary_types_allowed = True
@validator("state", always=True)
@no_type_check # issubclass breaks things
def _validate_state(cls, v: Union[StateType, Sequence[StateType]]) -> Sequence[StateType]:
if (
isinstance(v, (str, State, StatesGroup))
or (isclass(v) and issubclass(v, StatesGroup))
or v is None
):
return [v]
return v
async def __call__(
self, obj: Union[TelegramObject], raw_state: Optional[str] = None
) -> Union[bool, Dict[str, Any]]:
allowed_states = cast(Sequence[StateType], self.state)
for allowed_state in allowed_states:
if isinstance(allowed_state, str) or allowed_state is None:
if allowed_state == "*":
return True
return raw_state == allowed_state
elif isinstance(allowed_state, (State, StatesGroup)):
return allowed_state(event=obj, raw_state=raw_state)
elif isclass(allowed_state) and issubclass(allowed_state, StatesGroup):
return allowed_state()(event=obj, raw_state=raw_state)
return False

View file

@ -1,11 +1,14 @@
from typing import Any, Dict, Optional, Sequence, Union from typing import TYPE_CHECKING, Any, Dict, Optional, Sequence, Union
from pydantic import root_validator from pydantic import root_validator
from aiogram.dispatcher.filters import BaseFilter from aiogram.dispatcher.filters import BaseFilter
from aiogram.types import CallbackQuery, InlineQuery, Message, Poll from aiogram.types import CallbackQuery, InlineQuery, Message, Poll
TextType = str if TYPE_CHECKING:
from aiogram.utils.i18n.lazy_proxy import LazyProxy
TextType = Union[str, "LazyProxy"]
class Text(BaseFilter): class Text(BaseFilter):
@ -35,6 +38,9 @@ class Text(BaseFilter):
text_ignore_case: bool = False text_ignore_case: bool = False
"""Ignore case when checks""" """Ignore case when checks"""
class Config:
arbitrary_types_allowed = True
@root_validator @root_validator
def _validate_constraints(cls, values: Dict[str, Any]) -> Dict[str, Any]: def _validate_constraints(cls, values: Dict[str, Any]) -> Dict[str, Any]:
# Validate that only one text filter type is presented # Validate that only one text filter type is presented

View file

@ -5,10 +5,10 @@ from aiogram.dispatcher.fsm.context import FSMContext
from aiogram.dispatcher.fsm.storage.base import BaseStorage from aiogram.dispatcher.fsm.storage.base import BaseStorage
from aiogram.dispatcher.fsm.strategy import FSMStrategy, apply_strategy from aiogram.dispatcher.fsm.strategy import FSMStrategy, apply_strategy
from aiogram.dispatcher.middlewares.base import BaseMiddleware from aiogram.dispatcher.middlewares.base import BaseMiddleware
from aiogram.types import Update from aiogram.types import TelegramObject
class FSMContextMiddleware(BaseMiddleware[Update]): class FSMContextMiddleware(BaseMiddleware):
def __init__( def __init__(
self, self,
storage: BaseStorage, storage: BaseStorage,
@ -21,8 +21,8 @@ class FSMContextMiddleware(BaseMiddleware[Update]):
async def __call__( async def __call__(
self, self,
handler: Callable[[Update, Dict[str, Any]], Awaitable[Any]], handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]],
event: Update, event: TelegramObject,
data: Dict[str, Any], data: Dict[str, Any],
) -> Any: ) -> Any:
bot: Bot = cast(Bot, data["bot"]) bot: Bot = cast(Bot, data["bot"])

View file

@ -129,8 +129,8 @@ class StatesGroup(metaclass=StatesGroupMeta):
return cls return cls
return cls.__parent__.get_root() return cls.__parent__.get_root()
def __call__(cls, event: TelegramObject, raw_state: Optional[str] = None) -> bool: def __call__(self, event: TelegramObject, raw_state: Optional[str] = None) -> bool:
return raw_state in type(cls).__all_states_names__ return raw_state in type(self).__all_states_names__
def __str__(self) -> str: def __str__(self) -> str:
return f"StatesGroup {type(self).__full_group_name__}" return f"StatesGroup {type(self).__full_group_name__}"

View file

@ -8,7 +8,7 @@ T = TypeVar("T")
class BaseHandlerMixin(Generic[T]): class BaseHandlerMixin(Generic[T]):
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
event: T event: T
data: Dict[str, Any] data: Dict[str, Any]

View file

@ -1,10 +1,12 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import Any, Awaitable, Callable, Dict, Generic, TypeVar from typing import Any, Awaitable, Callable, Dict, TypeVar
from aiogram.types import TelegramObject
T = TypeVar("T") T = TypeVar("T")
class BaseMiddleware(ABC, Generic[T]): class BaseMiddleware(ABC):
""" """
Generic middleware class Generic middleware class
""" """
@ -12,8 +14,8 @@ class BaseMiddleware(ABC, Generic[T]):
@abstractmethod @abstractmethod
async def __call__( async def __call__(
self, self,
handler: Callable[[T, Dict[str, Any]], Awaitable[Any]], handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]],
event: T, event: TelegramObject,
data: Dict[str, Any], data: Dict[str, Any],
) -> Any: # pragma: no cover ) -> Any: # pragma: no cover
""" """

View file

@ -2,22 +2,22 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Any, Awaitable, Callable, Dict from typing import TYPE_CHECKING, Any, Awaitable, Callable, Dict
from ...types import Update from ...types import TelegramObject
from ..event.bases import UNHANDLED, CancelHandler, SkipHandler from ..event.bases import UNHANDLED, CancelHandler, SkipHandler
from .base import BaseMiddleware from .base import BaseMiddleware
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..router import Router from ..router import Router
class ErrorsMiddleware(BaseMiddleware[Update]): class ErrorsMiddleware(BaseMiddleware):
def __init__(self, router: Router): def __init__(self, router: Router):
self.router = router self.router = router
async def __call__( async def __call__(
self, self,
handler: Callable[[Any, Dict[str, Any]], Awaitable[Any]], handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]],
event: Any, event: TelegramObject,
data: Dict[str, Any], data: Dict[str, Any],
) -> Any: ) -> Any:
try: try:

View file

@ -2,16 +2,18 @@ from contextlib import contextmanager
from typing import Any, Awaitable, Callable, Dict, Iterator, Optional, Tuple from typing import Any, Awaitable, Callable, Dict, Iterator, Optional, Tuple
from aiogram.dispatcher.middlewares.base import BaseMiddleware from aiogram.dispatcher.middlewares.base import BaseMiddleware
from aiogram.types import Chat, Update, User from aiogram.types import Chat, TelegramObject, Update, User
class UserContextMiddleware(BaseMiddleware[Update]): class UserContextMiddleware(BaseMiddleware):
async def __call__( async def __call__(
self, self,
handler: Callable[[Update, Dict[str, Any]], Awaitable[Any]], handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]],
event: Update, event: TelegramObject,
data: Dict[str, Any], data: Dict[str, Any],
) -> Any: ) -> Any:
if not isinstance(event, Update):
raise RuntimeError("UserContextMiddleware got an unexpected event type!")
chat, user = self.resolve_event_context(event=event) chat, user = self.resolve_event_context(event=event)
with self.context(chat=chat, user=user): with self.context(chat=chat, user=user):
if user is not None: if user is not None:

View file

@ -1,9 +1,35 @@
from typing import Optional
from aiogram.methods import TelegramMethod from aiogram.methods import TelegramMethod
from aiogram.methods.base import TelegramType from aiogram.methods.base import TelegramType
from aiogram.utils.exceptions.base import TelegramAPIError
class RetryAfter(TelegramAPIError): class TelegramAPIError(Exception):
url: Optional[str] = None
def __init__(
self,
method: TelegramMethod[TelegramType],
message: str,
) -> None:
self.method = method
self.message = message
def render_description(self) -> str:
return self.message
def __str__(self) -> str:
message = [self.render_description()]
if self.url:
message.append(f"(background on this error at: {self.url})")
return "\n".join(message)
class TelegramNetworkError(TelegramAPIError):
pass
class TelegramRetryAfter(TelegramAPIError):
url = "https://core.telegram.org/bots/faq#my-bot-is-hitting-limits-how-do-i-avoid-this" url = "https://core.telegram.org/bots/faq#my-bot-is-hitting-limits-how-do-i-avoid-this"
def __init__( def __init__(
@ -23,7 +49,7 @@ class RetryAfter(TelegramAPIError):
return description return description
class MigrateToChat(TelegramAPIError): class TelegramMigrateToChat(TelegramAPIError):
url = "https://core.telegram.org/bots/api#responseparameters" url = "https://core.telegram.org/bots/api#responseparameters"
def __init__( def __init__(
@ -42,3 +68,35 @@ class MigrateToChat(TelegramAPIError):
if chat_id := getattr(self.method, "chat_id", None): if chat_id := getattr(self.method, "chat_id", None):
description += f" from {chat_id}" description += f" from {chat_id}"
return description return description
class TelegramBadRequest(TelegramAPIError):
pass
class TelegramNotFound(TelegramAPIError):
pass
class TelegramConflictError(TelegramAPIError):
pass
class TelegramUnauthorizedError(TelegramAPIError):
pass
class TelegramForbiddenError(TelegramAPIError):
pass
class TelegramServerError(TelegramAPIError):
pass
class RestartingTelegram(TelegramServerError):
pass
class TelegramEntityTooLarge(TelegramNetworkError):
url = "https://core.telegram.org/bots/api#sending-files"

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import InputFile, MaskPosition from ..types import InputFile, MaskPosition
from .base import Request, TelegramMethod, prepare_file from .base import Request, TelegramMethod, prepare_file
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional
from ..types import InlineQueryResult from ..types import InlineQueryResult
from .base import Request, TelegramMethod, prepare_parse_mode from .base import Request, TelegramMethod, prepare_parse_mode
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional
from ..types import ShippingOption from ..types import ShippingOption
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -9,7 +9,7 @@ from pydantic.generics import GenericModel
from ..types import UNSET, InputFile, ResponseParameters from ..types import UNSET, InputFile, ResponseParameters
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot
TelegramType = TypeVar("TelegramType", bound=Any) TelegramType = TypeVar("TelegramType", bound=Any)

View file

@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -13,7 +13,7 @@ from ..types import (
) )
from .base import Request, TelegramMethod, prepare_parse_mode from .base import Request, TelegramMethod, prepare_parse_mode
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import ChatInviteLink from ..types import ChatInviteLink
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import InputFile, MaskPosition from ..types import InputFile, MaskPosition
from .base import Request, TelegramMethod, prepare_file from .base import Request, TelegramMethod, prepare_file
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional
from ..types import BotCommandScope from ..types import BotCommandScope
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import ChatInviteLink from ..types import ChatInviteLink
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
from ..types import UNSET, InlineKeyboardMarkup, Message, MessageEntity from ..types import UNSET, InlineKeyboardMarkup, Message, MessageEntity
from .base import Request, TelegramMethod, prepare_parse_mode from .base import Request, TelegramMethod, prepare_parse_mode
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import InlineKeyboardMarkup, Message from ..types import InlineKeyboardMarkup, Message
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import InlineKeyboardMarkup, InputFile, InputMedia, Message from ..types import InlineKeyboardMarkup, InputFile, InputMedia, Message
from .base import Request, TelegramMethod, prepare_media_file, prepare_parse_mode from .base import Request, TelegramMethod, prepare_media_file, prepare_parse_mode
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import InlineKeyboardMarkup, Message from ..types import InlineKeyboardMarkup, Message
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
from ..types import UNSET, InlineKeyboardMarkup, Message, MessageEntity from ..types import UNSET, InlineKeyboardMarkup, Message, MessageEntity
from .base import Request, TelegramMethod, prepare_parse_mode from .base import Request, TelegramMethod, prepare_parse_mode
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import Message from ..types import Message
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union
from ..types import Chat from ..types import Chat
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -12,7 +12,7 @@ from ..types import (
) )
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -12,7 +12,7 @@ from ..types import (
) )
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict
from ..types import File from ..types import File
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional
from ..types import GameHighScore from ..types import GameHighScore
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict
from ..types import User from ..types import User
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional
from ..types import BotCommand, BotCommandScope from ..types import BotCommand, BotCommandScope
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict
from ..types import StickerSet from ..types import StickerSet
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional
from ..types import Update from ..types import Update
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional
from ..types import UserProfilePhotos from ..types import UserProfilePhotos
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict
from ..types import WebhookInfo from ..types import WebhookInfo
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -6,7 +6,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import ChatPermissions from ..types import ChatPermissions
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union
from ..types import ChatInviteLink from ..types import ChatInviteLink
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -14,7 +14,7 @@ from ..types import (
) )
from .base import Request, TelegramMethod, prepare_file, prepare_parse_mode from .base import Request, TelegramMethod, prepare_file, prepare_parse_mode
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -14,7 +14,7 @@ from ..types import (
) )
from .base import Request, TelegramMethod, prepare_file, prepare_parse_mode from .base import Request, TelegramMethod, prepare_file, prepare_parse_mode
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -11,7 +11,7 @@ from ..types import (
) )
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -11,7 +11,7 @@ from ..types import (
) )
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -14,7 +14,7 @@ from ..types import (
) )
from .base import Request, TelegramMethod, prepare_file, prepare_parse_mode from .base import Request, TelegramMethod, prepare_file, prepare_parse_mode
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional
from ..types import InlineKeyboardMarkup, Message from ..types import InlineKeyboardMarkup, Message
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
from ..types import InlineKeyboardMarkup, LabeledPrice, Message from ..types import InlineKeyboardMarkup, LabeledPrice, Message
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -11,7 +11,7 @@ from ..types import (
) )
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -12,7 +12,7 @@ from ..types import (
) )
from .base import Request, TelegramMethod, prepare_input_media, prepare_parse_mode from .base import Request, TelegramMethod, prepare_input_media, prepare_parse_mode
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -13,7 +13,7 @@ from ..types import (
) )
from .base import Request, TelegramMethod, prepare_parse_mode from .base import Request, TelegramMethod, prepare_parse_mode
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -14,7 +14,7 @@ from ..types import (
) )
from .base import Request, TelegramMethod, prepare_file, prepare_parse_mode from .base import Request, TelegramMethod, prepare_file, prepare_parse_mode
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -14,7 +14,7 @@ from ..types import (
) )
from .base import Request, TelegramMethod, prepare_parse_mode from .base import Request, TelegramMethod, prepare_parse_mode
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -12,7 +12,7 @@ from ..types import (
) )
from .base import Request, TelegramMethod, prepare_file from .base import Request, TelegramMethod, prepare_file
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -11,7 +11,7 @@ from ..types import (
) )
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -14,7 +14,7 @@ from ..types import (
) )
from .base import Request, TelegramMethod, prepare_file, prepare_parse_mode from .base import Request, TelegramMethod, prepare_file, prepare_parse_mode
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -12,7 +12,7 @@ from ..types import (
) )
from .base import Request, TelegramMethod, prepare_file from .base import Request, TelegramMethod, prepare_file
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -14,7 +14,7 @@ from ..types import (
) )
from .base import Request, TelegramMethod, prepare_file, prepare_parse_mode from .base import Request, TelegramMethod, prepare_file, prepare_parse_mode
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union
from ..types import ChatPermissions from ..types import ChatPermissions
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union
from ..types import InputFile from ..types import InputFile
from .base import Request, TelegramMethod, prepare_file from .base import Request, TelegramMethod, prepare_file
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union
from ..types import Message from ..types import Message
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional
from ..types import BotCommand, BotCommandScope from ..types import BotCommand, BotCommandScope
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

View file

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any, Dict, List
from ..types import PassportElementError from ..types import PassportElementError
from .base import Request, TelegramMethod from .base import Request, TelegramMethod
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING:
from ..client.bot import Bot from ..client.bot import Bot

Some files were not shown because too many files have changed in this diff Show more