From 04bd0c9e7c5421c060183b90d515050f41377bc1 Mon Sep 17 00:00:00 2001 From: Alex Root Junior Date: Tue, 29 Aug 2023 02:01:54 +0300 Subject: [PATCH] Fixed error overlapping when validation error is caused by remove_unset root validator in base types and methods. (#1290) * Ensure base type validation can handle non-dictionary values The update introduces a condition to verify whether the values being validated are a dictionary before attempting to handle UNSET_TYPE in the aiogram base type. This adjustment helps to prevent potential errors or incorrect validation when non-dictionary values are faced. * Added a test case for non-dictionary input in remove_unset method * Added changelog * Fixed tests --- CHANGES/1290.bugfix.rst | 1 + aiogram/methods/base.py | 2 ++ aiogram/types/base.py | 2 ++ tests/test_api/test_methods/test_base.py | 11 ++++++++--- 4 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 CHANGES/1290.bugfix.rst diff --git a/CHANGES/1290.bugfix.rst b/CHANGES/1290.bugfix.rst new file mode 100644 index 00000000..04ba92dc --- /dev/null +++ b/CHANGES/1290.bugfix.rst @@ -0,0 +1 @@ +Fixed error overlapping when validation error is caused by remove_unset root validator in base types and methods. diff --git a/aiogram/methods/base.py b/aiogram/methods/base.py index 221ad9c0..b2d35bec 100644 --- a/aiogram/methods/base.py +++ b/aiogram/methods/base.py @@ -61,6 +61,8 @@ class TelegramMethod(BotContextController, BaseModel, Generic[TelegramType], ABC but UNSET might be passing to a model initialization from `Bot.method_name`, so we must take care of it and remove it before fields validation. """ + if not isinstance(values, dict): + return values return {k: v for k, v in values.items() if not isinstance(v, UNSET_TYPE)} if TYPE_CHECKING: diff --git a/aiogram/types/base.py b/aiogram/types/base.py index 9c24c703..dae52156 100644 --- a/aiogram/types/base.py +++ b/aiogram/types/base.py @@ -28,6 +28,8 @@ class TelegramObject(BotContextController, BaseModel): but UNSET might be passed to a model initialization from `Bot.method_name`, so we must take care of it and remove it before fields validation. """ + if not isinstance(values, dict): + return values return {k: v for k, v in values.items() if not isinstance(v, UNSET_TYPE)} diff --git a/tests/test_api/test_methods/test_base.py b/tests/test_api/test_methods/test_base.py index 9626c9b7..498428ce 100644 --- a/tests/test_api/test_methods/test_base.py +++ b/tests/test_api/test_methods/test_base.py @@ -3,7 +3,7 @@ from unittest.mock import sentinel import pytest from aiogram.methods import GetMe, TelegramMethod -from aiogram.types import User +from aiogram.types import User, TelegramObject from tests.mocked_bot import MockedBot @@ -16,10 +16,15 @@ class TestTelegramMethodRemoveUnset: [{"foo": "bar", "baz": sentinel.DEFAULT}, {"foo"}], ], ) - def test_remove_unset(self, values, names): - validated = TelegramMethod.remove_unset(values) + @pytest.mark.parametrize("obj", [TelegramMethod, TelegramObject]) + def test_remove_unset(self, values, names, obj): + validated = obj.remove_unset(values) assert set(validated.keys()) == names + @pytest.mark.parametrize("obj", [TelegramMethod, TelegramObject]) + def test_remove_unset_non_dict(self, obj): + assert obj.remove_unset("") == "" + class TestTelegramMethodCall: async def test_async_emit_unsuccessful(self, bot: MockedBot):