From 42faee0178779c22593afd75070f83814b764119 Mon Sep 17 00:00:00 2001 From: Alex Root Junior Date: Mon, 13 Jan 2020 21:17:53 +0200 Subject: [PATCH] Update filters typing and cover ContentTypesFilter --- aiogram/dispatcher/filters/base.py | 2 +- aiogram/dispatcher/filters/content_types.py | 4 +-- .../test_filters/test_content_types.py | 32 +++++++++++++++++-- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/aiogram/dispatcher/filters/base.py b/aiogram/dispatcher/filters/base.py index fabaaf21..c0a6c377 100644 --- a/aiogram/dispatcher/filters/base.py +++ b/aiogram/dispatcher/filters/base.py @@ -10,7 +10,7 @@ class BaseFilter(ABC, BaseModel): # error: Signature of "__call__" incompatible with supertype "BaseFilter" [override] # https://mypy.readthedocs.io/en/latest/error_code_list.html#check-validity-of-overrides-override - __call__: Any + pass else: # pragma: no cover @abstractmethod diff --git a/aiogram/dispatcher/filters/content_types.py b/aiogram/dispatcher/filters/content_types.py index 0f8134e2..f755f8e9 100644 --- a/aiogram/dispatcher/filters/content_types.py +++ b/aiogram/dispatcher/filters/content_types.py @@ -10,7 +10,7 @@ from .base import BaseFilter class ContentTypesFilter(BaseFilter): content_types: Optional[List[str]] = None - @validator("content_types", always=True) + @validator("content_types") def _validate_content_types(cls, value: Optional[List[str]]) -> Optional[List[str]]: if not value: value = [ContentType.TEXT] @@ -23,5 +23,5 @@ class ContentTypesFilter(BaseFilter): async def __call__(self, message: Message) -> Union[bool, Dict[str, Any]]: if not self.content_types: # pragma: no cover # Is impossible but needed for valid typechecking - return False + self.content_types = [ContentType.TEXT] return ContentType.ANY in self.content_types or message.content_type in self.content_types diff --git a/tests/test_dispatcher/test_filters/test_content_types.py b/tests/test_dispatcher/test_filters/test_content_types.py index 8efa5084..9c83cc09 100644 --- a/tests/test_dispatcher/test_filters/test_content_types.py +++ b/tests/test_dispatcher/test_filters/test_content_types.py @@ -1,13 +1,25 @@ +from dataclasses import dataclass +from typing import cast + import pytest from pydantic import ValidationError +from aiogram.api.types import ContentType, Message from aiogram.dispatcher.filters import ContentTypesFilter +@dataclass +class MinimalMessage: + content_type: str + + class TestContentTypesFilter: - def test_validator_empty(self): + @pytest.mark.asyncio + async def test_validator_empty(self): filter_ = ContentTypesFilter() - assert filter_.content_types == ["text"] + assert not filter_.content_types + await filter_(cast(Message, MinimalMessage(ContentType.TEXT))) + assert filter_.content_types == [ContentType.TEXT] def test_validator_empty_list(self): filter_ = ContentTypesFilter(content_types=[]) @@ -22,3 +34,19 @@ class TestContentTypesFilter: def test_validator_with_bad_values(self, values): with pytest.raises(ValidationError): ContentTypesFilter(content_types=values) + + @pytest.mark.parametrize( + "values,content_type,result", + [ + [[], ContentType.TEXT, True], + [[ContentType.TEXT], ContentType.TEXT, True], + [[ContentType.PHOTO], ContentType.TEXT, False], + [[ContentType.ANY], ContentType.TEXT, True], + [[ContentType.TEXT, ContentType.PHOTO, ContentType.DOCUMENT], ContentType.TEXT, True], + [[ContentType.ANY, ContentType.PHOTO, ContentType.DOCUMENT], ContentType.TEXT, True], + ], + ) + @pytest.mark.asyncio + async def test_call(self, values, content_type, result): + filter_ = ContentTypesFilter(content_types=values) + assert await filter_(cast(Message, MinimalMessage(content_type=content_type))) == result