From 658f1fc082e2d2ae485537a5b752d53bc1554483 Mon Sep 17 00:00:00 2001 From: m-xim <170838360+m-xim@users.noreply.github.com> Date: Tue, 11 Mar 2025 01:14:13 +0300 Subject: [PATCH] Fix handling of default empty string ("") in CallbackData filter (#1493) * Update callback_data.py Allows using a default value in the class which is equal to an empty string (""). Example: class MyCallbackData(CallbackData, prefix="MyCallbackData"): input1: str input2: str = "" * Create 1493.bugfix.rst * Update callback_data.py Fixed an issue that prevented unpacking None values. * Added tests for CallbackData * Update tests/test_filters/test_callback_data.py Co-authored-by: Oleg A. * Update test_callback_data.py * Update callback_data.py * Update 1493.bugfix.rst --------- Co-authored-by: Oleg A. --- CHANGES/1493.bugfix.rst | 1 + aiogram/filters/callback_data.py | 5 +++-- tests/test_filters/test_callback_data.py | 7 +++++++ 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 CHANGES/1493.bugfix.rst diff --git a/CHANGES/1493.bugfix.rst b/CHANGES/1493.bugfix.rst new file mode 100644 index 00000000..386cdb71 --- /dev/null +++ b/CHANGES/1493.bugfix.rst @@ -0,0 +1 @@ +Fix handling of default empty string ("") in CallbackData filter diff --git a/aiogram/filters/callback_data.py b/aiogram/filters/callback_data.py index c60cd818..e504d50b 100644 --- a/aiogram/filters/callback_data.py +++ b/aiogram/filters/callback_data.py @@ -22,6 +22,7 @@ from uuid import UUID from magic_filter import MagicFilter from pydantic import BaseModel from pydantic.fields import FieldInfo +from pydantic_core import PydanticUndefined from aiogram.filters.base import Filter from aiogram.types import CallbackQuery @@ -130,8 +131,8 @@ class CallbackData(BaseModel): payload = {} for k, v in zip(names, parts): # type: str, Optional[str] if field := cls.model_fields.get(k): - if v == "" and _check_field_is_nullable(field): - v = None + if v == "" and _check_field_is_nullable(field) and field.default != "": + v = field.default if field.default is not PydanticUndefined else None payload[k] = v return cls(**payload) diff --git a/tests/test_filters/test_callback_data.py b/tests/test_filters/test_callback_data.py index 8cc2f51f..1bc50cae 100644 --- a/tests/test_filters/test_callback_data.py +++ b/tests/test_filters/test_callback_data.py @@ -160,6 +160,13 @@ class TestCallbackData: assert MyCallback3.unpack("test3:experiment:42") == MyCallback3(bar=42) assert MyCallback3.unpack("test3:spam:42") == MyCallback3(foo="spam", bar=42) + class MyCallback4(CallbackData, prefix="test4"): + foo: Optional[str] = "" + bar: Optional[str] = None + + assert MyCallback4.unpack("test4::") == MyCallback4(foo="", bar=None) + assert MyCallback4.unpack("test4::") == MyCallback4() + @pytest.mark.parametrize( "hint", [