From aad2de43248bd4157bb019f5248211b93cae4a5b Mon Sep 17 00:00:00 2001 From: Alex Root Junior Date: Fri, 21 Apr 2023 00:17:28 +0300 Subject: [PATCH] Improve callback data serialization (#1163) * Improve callback data serialization * Added tests and changelog --- CHANGES/1163.feature.rst | 4 ++ aiogram/filters/callback_data.py | 6 ++- tests/test_filters/test_callback_data.py | 52 +++++++++++++----------- 3 files changed, 37 insertions(+), 25 deletions(-) create mode 100644 CHANGES/1163.feature.rst diff --git a/CHANGES/1163.feature.rst b/CHANGES/1163.feature.rst new file mode 100644 index 00000000..06e97c3d --- /dev/null +++ b/CHANGES/1163.feature.rst @@ -0,0 +1,4 @@ +Improved CallbackData serialization. + +- Minimized UUID (hex without dashes) +- Replaced bool values with int (true=1, false=0) diff --git a/aiogram/filters/callback_data.py b/aiogram/filters/callback_data.py index 84ec1e88..05d7783d 100644 --- a/aiogram/filters/callback_data.py +++ b/aiogram/filters/callback_data.py @@ -67,7 +67,11 @@ class CallbackData(BaseModel): return "" if isinstance(value, Enum): return str(value.value) - if isinstance(value, (int, str, float, Decimal, Fraction, UUID)): + if isinstance(value, UUID): + return value.hex + if isinstance(value, bool): + return str(int(value)) + if isinstance(value, (int, str, float, Decimal, Fraction)): return str(value) raise ValueError( f"Attribute {key}={value!r} of type {type(value).__name__!r}" diff --git a/tests/test_filters/test_callback_data.py b/tests/test_filters/test_callback_data.py index 70388689..e8721a41 100644 --- a/tests/test_filters/test_callback_data.py +++ b/tests/test_filters/test_callback_data.py @@ -49,34 +49,38 @@ class TestCallbackData: pass @pytest.mark.parametrize( - "value,success,expected", + "value,expected", [ - [None, True, ""], - [42, True, "42"], - ["test", True, "test"], - [9.99, True, "9.99"], - [Decimal("9.99"), True, "9.99"], - [Fraction("3/2"), True, "3/2"], - [ - UUID("123e4567-e89b-12d3-a456-426655440000"), - True, - "123e4567-e89b-12d3-a456-426655440000", - ], - [MyIntEnum.FOO, True, "1"], - [MyStringEnum.FOO, True, "FOO"], - [..., False, "..."], - [object, False, "..."], - [object(), False, "..."], - [User(id=42, is_bot=False, first_name="test"), False, "..."], + [None, ""], + [True, "1"], + [False, "0"], + [42, "42"], + ["test", "test"], + [9.99, "9.99"], + [Decimal("9.99"), "9.99"], + [Fraction("3/2"), "3/2"], + [UUID("123e4567-e89b-12d3-a456-426655440000"), "123e4567e89b12d3a456426655440000"], + [MyIntEnum.FOO, "1"], + [MyStringEnum.FOO, "FOO"], ], ) - def test_encode_value(self, value, success, expected): + def test_encode_value_positive(self, value, expected): callback = MyCallback(foo="test", bar=42) - if success: - assert callback._encode_value("test", value) == expected - else: - with pytest.raises(ValueError): - assert callback._encode_value("test", value) == expected + assert callback._encode_value("test", value) == expected + + @pytest.mark.parametrize( + "value", + [ + ..., + object, + object(), + User(id=42, is_bot=False, first_name="test"), + ], + ) + def test_encode_value_negative(self, value): + callback = MyCallback(foo="test", bar=42) + with pytest.raises(ValueError): + callback._encode_value("test", value) def test_pack(self): with pytest.raises(ValueError, match="Separator symbol .+"):