From 322a98bc1ba05e58c37140e111cd002fc83ea9da Mon Sep 17 00:00:00 2001 From: Alex Root Junior Date: Sun, 7 Feb 2021 18:43:43 +0200 Subject: [PATCH] More docs --- Makefile | 5 +++++ aiogram/client/session/aiohttp.py | 2 +- aiogram/dispatcher/filters/base.py | 16 ++++++++++++++++ aiogram/dispatcher/filters/command.py | 17 ++++++++++++----- aiogram/dispatcher/filters/content_types.py | 6 ++++++ aiogram/dispatcher/filters/exception.py | 10 ++++++++++ aiogram/dispatcher/filters/text.py | 19 +++++++++++++++++-- docs2/conf.py | 4 ++++ docs2/dispatcher/dispatcher.rst | 18 ------------------ docs2/dispatcher/index.rst | 3 +++ .../test_session/test_aiohttp_session.py | 2 +- .../test_types/test_reply_keyboard_remove.py | 3 ++- 12 files changed, 77 insertions(+), 28 deletions(-) diff --git a/Makefile b/Makefile index ca31515a..c3b1bc48 100644 --- a/Makefile +++ b/Makefile @@ -131,6 +131,11 @@ docs: docs-serve: $(py) mkdocs serve +.PHONY: docs2-serve +docs2-serve: + rm -rf docs2/_build + $(py) sphinx-autobuild --watch aiogram/ docs2/ docs2/_build/ + .PHONY: docs-copy-reports docs-copy-reports: mv $(reports_dir)/* site/reports diff --git a/aiogram/client/session/aiohttp.py b/aiogram/client/session/aiohttp.py index 1dd7bb42..3373d800 100644 --- a/aiogram/client/session/aiohttp.py +++ b/aiogram/client/session/aiohttp.py @@ -19,7 +19,7 @@ from aiohttp import BasicAuth, ClientSession, FormData, TCPConnector from aiogram.methods import Request, TelegramMethod -from .base import BaseSession, UNSET +from .base import UNSET, BaseSession if TYPE_CHECKING: # pragma: no cover from ..bot import Bot diff --git a/aiogram/dispatcher/filters/base.py b/aiogram/dispatcher/filters/base.py index 04631dfc..c9c3fc15 100644 --- a/aiogram/dispatcher/filters/base.py +++ b/aiogram/dispatcher/filters/base.py @@ -5,6 +5,15 @@ from pydantic import BaseModel class BaseFilter(ABC, BaseModel): + """ + If you want to register own filters like builtin filters you will need to write subclass + of this class with overriding the :code:`__call__` + method and adding filter attributes. + + BaseFilter is subclass of :class:`pydantic.BaseModel` that's mean all subclasses of BaseFilter has + the validators based on class attributes and custom validator. + """ + if TYPE_CHECKING: # pragma: no cover # This checking type-hint is needed because mypy checks validity of overrides and raises: # error: Signature of "__call__" incompatible with supertype "BaseFilter" [override] @@ -14,6 +23,13 @@ class BaseFilter(ABC, BaseModel): @abstractmethod async def __call__(self, *args: Any, **kwargs: Any) -> Union[bool, Dict[str, Any]]: + """ + This method should be overridden. + + Accepts incoming event and should return boolean or dict. + + :return: :class:`bool` or :class:`Dict[str, Any]` + """ pass def __await__(self): # type: ignore # pragma: no cover diff --git a/aiogram/dispatcher/filters/command.py b/aiogram/dispatcher/filters/command.py index 1d48c711..899b09be 100644 --- a/aiogram/dispatcher/filters/command.py +++ b/aiogram/dispatcher/filters/command.py @@ -14,10 +14,21 @@ CommandPatterType = Union[str, re.Pattern] class Command(BaseFilter): + """ + This filter can be helpful for handling commands from the text messages. + + Works only with :class:`aiogram.types.message.Message` events which have the :code:`text`. + """ + commands: Union[Sequence[CommandPatterType], CommandPatterType] + """List of commands (string or compiled regexp patterns)""" commands_prefix: str = "/" + """Prefix for command. Prefix is always is single char but here you can pass all of allowed prefixes, + for example: :code:`"/!"` will work with commands prefixed by :code:`"/"` or :code:`"!"`.""" commands_ignore_case: bool = False + """Ignore case (Does not work with regexp, use flags instead)""" commands_ignore_mention: bool = False + """Ignore bot mention. By default bot can not handle commands intended for other bots""" @validator("commands", always=True) def _validate_commands( @@ -100,7 +111,7 @@ class Command(BaseFilter): class CommandObject: """ Instance of this object is always has command and it prefix. - Can be passed as keyword argument ``command`` to the handler + Can be passed as keyword argument **command** to the handler """ prefix: str = "/" @@ -118,8 +129,6 @@ class CommandObject: def mentioned(self) -> bool: """ This command has mention? - - :return: """ return bool(self.mention) @@ -127,8 +136,6 @@ class CommandObject: def text(self) -> str: """ Generate original text from object - - :return: """ line = self.prefix + self.command if self.mention: diff --git a/aiogram/dispatcher/filters/content_types.py b/aiogram/dispatcher/filters/content_types.py index c8cc4392..640a8b64 100644 --- a/aiogram/dispatcher/filters/content_types.py +++ b/aiogram/dispatcher/filters/content_types.py @@ -9,7 +9,13 @@ from .base import BaseFilter class ContentTypesFilter(BaseFilter): + """ + Is useful for handling specific types of messages (For example separate text and stickers handlers). + This is always automatically adds to the filters list for message handlers. + """ + content_types: Optional[Union[Sequence[str], str]] = None + """Sequence of allowed content types""" @validator("content_types") def _validate_content_types( diff --git a/aiogram/dispatcher/filters/exception.py b/aiogram/dispatcher/filters/exception.py index 8291291a..f46cd739 100644 --- a/aiogram/dispatcher/filters/exception.py +++ b/aiogram/dispatcher/filters/exception.py @@ -7,7 +7,12 @@ from aiogram.dispatcher.filters import BaseFilter class ExceptionTypeFilter(BaseFilter): + """ + Allows to match exception by type + """ + exception: Union[Type[Exception], Tuple[Type[Exception]]] + """Exception type(s)""" class Config: arbitrary_types_allowed = True @@ -17,7 +22,12 @@ class ExceptionTypeFilter(BaseFilter): class ExceptionMessageFilter(BaseFilter): + """ + Allow to match exception by message + """ + match: Union[str, Pattern[str]] + """Regexp pattern""" class Config: arbitrary_types_allowed = True diff --git a/aiogram/dispatcher/filters/text.py b/aiogram/dispatcher/filters/text.py index 8141e07c..55e7fe5e 100644 --- a/aiogram/dispatcher/filters/text.py +++ b/aiogram/dispatcher/filters/text.py @@ -10,15 +10,30 @@ TextType = str class Text(BaseFilter): """ - Is useful for filtering text Message, any CallbackQuery with `data`, - InlineQuery or Poll question. + Is useful for filtering text :class:`aiogram.types.message.Message`, + any :class:`aiogram.types.callback_query.CallbackQuery` with `data`, + :class:`aiogram.types.inline_query.InlineQuery` or :class:`aiogram.types.poll.Poll` question. + + .. warning:: + + Only one of `text`, `text_contains`, `text_startswith` or `text_endswith` argument can be used at once. + Any of that arguments can be string, list, set or tuple of strings. + + .. deprecated:: 3.0 + + use :ref:`magic-filter `. For example do :pycode:`F.text == "text"` instead """ text: Optional[Union[Sequence[TextType], TextType]] = None + """Text equals value or one of values""" text_contains: Optional[Union[Sequence[TextType], TextType]] = None + """Text contains value or one of values""" text_startswith: Optional[Union[Sequence[TextType], TextType]] = None + """Text starts with value or one of values""" text_endswith: Optional[Union[Sequence[TextType], TextType]] = None + """Text ends with value or one of values""" text_ignore_case: bool = False + """Ignore case when checks""" @root_validator def _validate_constraints(cls, values: Dict[str, Any]) -> Dict[str, Any]: diff --git a/docs2/conf.py b/docs2/conf.py index 42ace9f6..9fd7778d 100644 --- a/docs2/conf.py +++ b/docs2/conf.py @@ -19,6 +19,7 @@ html_theme_options = {} html_css_files = [ "stylesheets/extra.css", ] +highlight_language = 'python3' extensions = [ "sphinx.ext.todo", @@ -33,6 +34,9 @@ extensions = [ rst_prolog = f""" .. |api_version| replace:: {aiogram.__api_version__} + +.. role:: pycode(code) + :language: python3 """ language = None diff --git a/docs2/dispatcher/dispatcher.rst b/docs2/dispatcher/dispatcher.rst index 798d74da..28d50538 100644 --- a/docs2/dispatcher/dispatcher.rst +++ b/docs2/dispatcher/dispatcher.rst @@ -52,21 +52,3 @@ All updates can be propagated to the dispatcher by :obj:`Dispatcher.feed_update( ... result = await dp.feed_update(bot=bot, update=incoming_update) - -Polling -======= - -.. warning:: - - not yet docummented - -... - -Webhook -======= - -.. warning:: - - not yet docummented - -... diff --git a/docs2/dispatcher/index.rst b/docs2/dispatcher/index.rst index 36b27ec8..8e1d1932 100644 --- a/docs2/dispatcher/index.rst +++ b/docs2/dispatcher/index.rst @@ -20,3 +20,6 @@ Dispatcher is subclass of router and should be always is root router. observer router dispatcher + class_based_handlers/index + filters/index + filters/magic_filters diff --git a/tests/test_api/test_client/test_session/test_aiohttp_session.py b/tests/test_api/test_client/test_session/test_aiohttp_session.py index 5649628b..42ee7e3e 100644 --- a/tests/test_api/test_client/test_session/test_aiohttp_session.py +++ b/tests/test_api/test_client/test_session/test_aiohttp_session.py @@ -8,7 +8,7 @@ from aiogram import Bot from aiogram.client.session import aiohttp from aiogram.client.session.aiohttp import AiohttpSession from aiogram.methods import Request, TelegramMethod -from aiogram.types import InputFile, UNSET +from aiogram.types import UNSET, InputFile from tests.mocked_bot import MockedBot try: diff --git a/tests/test_api/test_types/test_reply_keyboard_remove.py b/tests/test_api/test_types/test_reply_keyboard_remove.py index 677c36e6..984932a5 100644 --- a/tests/test_api/test_types/test_reply_keyboard_remove.py +++ b/tests/test_api/test_types/test_reply_keyboard_remove.py @@ -14,7 +14,8 @@ class TestReplyKeyboardRemove: ), "Remove keyboard has incorrect default value!" @pytest.mark.parametrize( - "kwargs,expected", [[{}, True], [{"remove_keyboard": True}, True]], + "kwargs,expected", + [[{}, True], [{"remove_keyboard": True}, True]], ) def test_remove_keyboard_values(self, kwargs, expected): assert ReplyKeyboardRemove(**kwargs).remove_keyboard is expected