From e1b4835b91f460285097907fef84cbeea02f1d76 Mon Sep 17 00:00:00 2001 From: Mikhail Opryshko Date: Thu, 18 Sep 2025 15:28:04 +0300 Subject: [PATCH 1/3] fix: fixed convert chat type --- pybotx/client/chats_api/create_chat.py | 14 ++++++-------- tests/client/chats_api/test_create_chat.py | 10 ++++------ 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/pybotx/client/chats_api/create_chat.py b/pybotx/client/chats_api/create_chat.py index 7bc1cc37..afe6d0e6 100644 --- a/pybotx/client/chats_api/create_chat.py +++ b/pybotx/client/chats_api/create_chat.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Literal, Optional, Set, Union +from typing import List, Literal, Optional, Set, Union from uuid import UUID from pydantic import ( @@ -6,7 +6,6 @@ ConfigDict, field_serializer, field_validator, - model_validator, ) from pybotx.client.authorized_botx_method import AuthorizedBotXMethod @@ -36,12 +35,11 @@ class BotXAPICreateChatRequestPayload(UnverifiedPayloadBaseModel): shared_history: Missing[bool] avatar: Optional[str] = None - @model_validator(mode="before") - def _convert_chat_type(cls, values: Dict[str, Any]) -> Dict[str, Any]: - ct = values.get("chat_type") - if isinstance(ct, ChatTypes): - values["chat_type"] = convert_chat_type_from_domain(ct) - return values + @field_validator("chat_type", mode="before") + def _convert_chat_type(cls, v: Union[APIChatTypes, ChatTypes]) -> APIChatTypes: + if isinstance(v, ChatTypes): + return convert_chat_type_from_domain(v) + return v @field_validator("avatar") def _validate_avatar(cls, v: Optional[str]) -> Optional[str]: diff --git a/tests/client/chats_api/test_create_chat.py b/tests/client/chats_api/test_create_chat.py index 4abca1d9..5393731b 100644 --- a/tests/client/chats_api/test_create_chat.py +++ b/tests/client/chats_api/test_create_chat.py @@ -205,14 +205,12 @@ def test__create_chat_payload__convert_chat_type_validator() -> None: from pybotx.models.enums import ChatTypes, APIChatTypes # Test with ChatTypes enum - values = {"chat_type": ChatTypes.GROUP_CHAT} - result = BotXAPICreateChatRequestPayload._convert_chat_type(values) # type: ignore[operator] - assert result["chat_type"] == APIChatTypes.GROUP_CHAT + result = BotXAPICreateChatRequestPayload._convert_chat_type(ChatTypes.GROUP_CHAT) # type: ignore[operator] + assert result == APIChatTypes.GROUP_CHAT # Test with non-ChatTypes value (should remain unchanged) - values = {"chat_type": APIChatTypes.CHAT} # type: ignore[dict-item] - result = BotXAPICreateChatRequestPayload._convert_chat_type(values) # type: ignore[operator] - assert result["chat_type"] == APIChatTypes.CHAT + result = BotXAPICreateChatRequestPayload._convert_chat_type(APIChatTypes.CHAT) # type: ignore[operator] + assert result == APIChatTypes.CHAT # Test with missing chat_type key values = {"name": "test"} # type: ignore[dict-item] From de0b0445af9162bad1ed083147bbcf2714bb5e64 Mon Sep 17 00:00:00 2001 From: Mikhail Opryshko Date: Fri, 24 Oct 2025 16:11:44 +0300 Subject: [PATCH 2/3] fix: fixed convert chat type --- pybotx/bot/bot.py | 2 +- pybotx/client/chats_api/create_chat.py | 29 ++++++++++---- tests/client/chats_api/test_create_chat.py | 46 ++++++++++++++++------ 3 files changed, 58 insertions(+), 19 deletions(-) diff --git a/pybotx/bot/bot.py b/pybotx/bot/bot.py index 206724fd..884ab328 100644 --- a/pybotx/bot/bot.py +++ b/pybotx/bot/bot.py @@ -1200,7 +1200,7 @@ async def create_chat( self._bot_accounts_storage, ) - payload = BotXAPICreateChatRequestPayload( + payload = BotXAPICreateChatRequestPayload.from_domain( name=name, chat_type=chat_type, members=huids, diff --git a/pybotx/client/chats_api/create_chat.py b/pybotx/client/chats_api/create_chat.py index afe6d0e6..b23f653b 100644 --- a/pybotx/client/chats_api/create_chat.py +++ b/pybotx/client/chats_api/create_chat.py @@ -1,12 +1,7 @@ from typing import List, Literal, Optional, Set, Union from uuid import UUID -from pydantic import ( - Field, - ConfigDict, - field_serializer, - field_validator, -) +from pydantic import Field, ConfigDict, field_serializer, field_validator from pybotx.client.authorized_botx_method import AuthorizedBotXMethod from pybotx.client.botx_method import response_exception_thrower @@ -35,7 +30,7 @@ class BotXAPICreateChatRequestPayload(UnverifiedPayloadBaseModel): shared_history: Missing[bool] avatar: Optional[str] = None - @field_validator("chat_type", mode="before") + @classmethod def _convert_chat_type(cls, v: Union[APIChatTypes, ChatTypes]) -> APIChatTypes: if isinstance(v, ChatTypes): return convert_chat_type_from_domain(v) @@ -57,6 +52,26 @@ def _validate_avatar(cls, v: Optional[str]) -> Optional[str]: def _serialize_chat_type(self, v: APIChatTypes) -> str: return v.value.lower() + @classmethod + def from_domain( + cls, + name: str, + chat_type: Union[APIChatTypes, ChatTypes], + members: List[UUID], + shared_history: Missing[bool], + description: Optional[str] = None, + avatar: Optional[str] = None, + ) -> "BotXAPICreateChatRequestPayload": + converted_chat_type = cls._convert_chat_type(chat_type) + return cls( + name=name, + chat_type=converted_chat_type, + members=members, + shared_history=shared_history, + description=description, + avatar=avatar, + ) + class BotXAPIChatIdResult(VerifiedPayloadBaseModel): model_config = ConfigDict(frozen=True) diff --git a/tests/client/chats_api/test_create_chat.py b/tests/client/chats_api/test_create_chat.py index 5393731b..5530017b 100644 --- a/tests/client/chats_api/test_create_chat.py +++ b/tests/client/chats_api/test_create_chat.py @@ -14,6 +14,7 @@ HandlerCollector, lifespan_wrapper, ) +from pybotx.missing import Undefined pytestmark = [ pytest.mark.asyncio, @@ -204,18 +205,41 @@ def test__create_chat_payload__convert_chat_type_validator() -> None: from pybotx.client.chats_api.create_chat import BotXAPICreateChatRequestPayload from pybotx.models.enums import ChatTypes, APIChatTypes - # Test with ChatTypes enum - result = BotXAPICreateChatRequestPayload._convert_chat_type(ChatTypes.GROUP_CHAT) # type: ignore[operator] - assert result == APIChatTypes.GROUP_CHAT - - # Test with non-ChatTypes value (should remain unchanged) - result = BotXAPICreateChatRequestPayload._convert_chat_type(APIChatTypes.CHAT) # type: ignore[operator] - assert result == APIChatTypes.CHAT + # Arrange + name = "Test Chat" + description = "Test Description" + chat_type = ChatTypes.PERSONAL_CHAT + members = [UUID("2fc83441-366a-49ba-81fc-6c39f065bb58")] + shared_history = Undefined + avatar = None + + # Act + payload = BotXAPICreateChatRequestPayload.from_domain( + name=name, + chat_type=chat_type, + members=members, + shared_history=shared_history, + description=description, + avatar=avatar, + ) - # Test with missing chat_type key - values = {"name": "test"} # type: ignore[dict-item] - result = BotXAPICreateChatRequestPayload._convert_chat_type(values) # type: ignore[operator] - assert result == {"name": "test"} + # Assert + assert payload.name == name + assert payload.description == description + assert payload.chat_type == APIChatTypes.CHAT + assert payload.members == members + + # Test with APIChatTypes + api_chat_type = APIChatTypes.CHANNEL + payload = BotXAPICreateChatRequestPayload.from_domain( + name=name, + chat_type=api_chat_type, + members=members, + shared_history=shared_history, + description=description, + avatar=avatar, + ) + assert payload.chat_type == api_chat_type async def test__create_chat__with_valid_avatar_succeed( From a52e404ecb1af5f3d84ac6561fd6b5d3f7441f77 Mon Sep 17 00:00:00 2001 From: Mikhail Opryshko Date: Wed, 24 Dec 2025 17:11:26 +0300 Subject: [PATCH 3/3] deleted Optional body from EventEdit --- pybotx/models/system_events/event_edit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pybotx/models/system_events/event_edit.py b/pybotx/models/system_events/event_edit.py index fd04ba24..e4fedd54 100644 --- a/pybotx/models/system_events/event_edit.py +++ b/pybotx/models/system_events/event_edit.py @@ -37,7 +37,7 @@ class EventEdit(BotCommandBase): entities: Entities from updated message. """ - body: Optional[str] + body: str sync_id: UUID chat_id: UUID huid: UUID