More docs

This commit is contained in:
Alex Root Junior 2021-02-07 18:43:43 +02:00
parent 4008a3114d
commit 322a98bc1b
12 changed files with 77 additions and 28 deletions

View file

@ -131,6 +131,11 @@ docs:
docs-serve: docs-serve:
$(py) mkdocs 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 .PHONY: docs-copy-reports
docs-copy-reports: docs-copy-reports:
mv $(reports_dir)/* site/reports mv $(reports_dir)/* site/reports

View file

@ -19,7 +19,7 @@ from aiohttp import BasicAuth, ClientSession, FormData, TCPConnector
from aiogram.methods import Request, TelegramMethod from aiogram.methods import Request, TelegramMethod
from .base import BaseSession, UNSET from .base import UNSET, BaseSession
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING: # pragma: no cover
from ..bot import Bot from ..bot import Bot

View file

@ -5,6 +5,15 @@ from pydantic import BaseModel
class BaseFilter(ABC, 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 if TYPE_CHECKING: # pragma: no cover
# 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]
@ -14,6 +23,13 @@ class BaseFilter(ABC, BaseModel):
@abstractmethod @abstractmethod
async def __call__(self, *args: Any, **kwargs: Any) -> Union[bool, Dict[str, Any]]: 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 pass
def __await__(self): # type: ignore # pragma: no cover def __await__(self): # type: ignore # pragma: no cover

View file

@ -14,10 +14,21 @@ CommandPatterType = Union[str, re.Pattern]
class Command(BaseFilter): 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] commands: Union[Sequence[CommandPatterType], CommandPatterType]
"""List of commands (string or compiled regexp patterns)"""
commands_prefix: str = "/" 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 commands_ignore_case: bool = False
"""Ignore case (Does not work with regexp, use flags instead)"""
commands_ignore_mention: bool = False commands_ignore_mention: bool = False
"""Ignore bot mention. By default bot can not handle commands intended for other bots"""
@validator("commands", always=True) @validator("commands", always=True)
def _validate_commands( def _validate_commands(
@ -100,7 +111,7 @@ class Command(BaseFilter):
class CommandObject: class CommandObject:
""" """
Instance of this object is always has command and it prefix. 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 = "/" prefix: str = "/"
@ -118,8 +129,6 @@ class CommandObject:
def mentioned(self) -> bool: def mentioned(self) -> bool:
""" """
This command has mention? This command has mention?
:return:
""" """
return bool(self.mention) return bool(self.mention)
@ -127,8 +136,6 @@ class CommandObject:
def text(self) -> str: def text(self) -> str:
""" """
Generate original text from object Generate original text from object
:return:
""" """
line = self.prefix + self.command line = self.prefix + self.command
if self.mention: if self.mention:

View file

@ -9,7 +9,13 @@ from .base import BaseFilter
class ContentTypesFilter(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 content_types: Optional[Union[Sequence[str], str]] = None
"""Sequence of allowed content types"""
@validator("content_types") @validator("content_types")
def _validate_content_types( def _validate_content_types(

View file

@ -7,7 +7,12 @@ from aiogram.dispatcher.filters import BaseFilter
class ExceptionTypeFilter(BaseFilter): class ExceptionTypeFilter(BaseFilter):
"""
Allows to match exception by type
"""
exception: Union[Type[Exception], Tuple[Type[Exception]]] exception: Union[Type[Exception], Tuple[Type[Exception]]]
"""Exception type(s)"""
class Config: class Config:
arbitrary_types_allowed = True arbitrary_types_allowed = True
@ -17,7 +22,12 @@ class ExceptionTypeFilter(BaseFilter):
class ExceptionMessageFilter(BaseFilter): class ExceptionMessageFilter(BaseFilter):
"""
Allow to match exception by message
"""
match: Union[str, Pattern[str]] match: Union[str, Pattern[str]]
"""Regexp pattern"""
class Config: class Config:
arbitrary_types_allowed = True arbitrary_types_allowed = True

View file

@ -10,15 +10,30 @@ TextType = str
class Text(BaseFilter): class Text(BaseFilter):
""" """
Is useful for filtering text Message, any CallbackQuery with `data`, Is useful for filtering text :class:`aiogram.types.message.Message`,
InlineQuery or Poll question. 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 <magic-filters>`. For example do :pycode:`F.text == "text"` instead
""" """
text: Optional[Union[Sequence[TextType], TextType]] = None text: Optional[Union[Sequence[TextType], TextType]] = None
"""Text equals value or one of values"""
text_contains: Optional[Union[Sequence[TextType], TextType]] = None text_contains: Optional[Union[Sequence[TextType], TextType]] = None
"""Text contains value or one of values"""
text_startswith: Optional[Union[Sequence[TextType], TextType]] = None 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_endswith: Optional[Union[Sequence[TextType], TextType]] = None
"""Text ends with value or one of values"""
text_ignore_case: bool = False text_ignore_case: bool = False
"""Ignore case when checks"""
@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]:

View file

@ -19,6 +19,7 @@ html_theme_options = {}
html_css_files = [ html_css_files = [
"stylesheets/extra.css", "stylesheets/extra.css",
] ]
highlight_language = 'python3'
extensions = [ extensions = [
"sphinx.ext.todo", "sphinx.ext.todo",
@ -33,6 +34,9 @@ extensions = [
rst_prolog = f""" rst_prolog = f"""
.. |api_version| replace:: {aiogram.__api_version__} .. |api_version| replace:: {aiogram.__api_version__}
.. role:: pycode(code)
:language: python3
""" """
language = None language = None

View file

@ -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) result = await dp.feed_update(bot=bot, update=incoming_update)
Polling
=======
.. warning::
not yet docummented
...
Webhook
=======
.. warning::
not yet docummented
...

View file

@ -20,3 +20,6 @@ Dispatcher is subclass of router and should be always is root router.
observer observer
router router
dispatcher dispatcher
class_based_handlers/index
filters/index
filters/magic_filters

View file

@ -8,7 +8,7 @@ from aiogram import Bot
from aiogram.client.session import aiohttp from aiogram.client.session import aiohttp
from aiogram.client.session.aiohttp import AiohttpSession from aiogram.client.session.aiohttp import AiohttpSession
from aiogram.methods import Request, TelegramMethod from aiogram.methods import Request, TelegramMethod
from aiogram.types import InputFile, UNSET from aiogram.types import UNSET, InputFile
from tests.mocked_bot import MockedBot from tests.mocked_bot import MockedBot
try: try:

View file

@ -14,7 +14,8 @@ class TestReplyKeyboardRemove:
), "Remove keyboard has incorrect default value!" ), "Remove keyboard has incorrect default value!"
@pytest.mark.parametrize( @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): def test_remove_keyboard_values(self, kwargs, expected):
assert ReplyKeyboardRemove(**kwargs).remove_keyboard is expected assert ReplyKeyboardRemove(**kwargs).remove_keyboard is expected