Skip to content

Commit

Permalink
refactor: Update UNSUPPORTED chat type implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
lxmnk committed Dec 15, 2022
1 parent f9ca74b commit c82abff
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 69 deletions.
8 changes: 0 additions & 8 deletions pybotx/client/chats_api/create_chat.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
from typing import List, Literal, Optional
from uuid import UUID

from pydantic import ValidationError

from pybotx.client.authorized_botx_method import AuthorizedBotXMethod
from pybotx.client.botx_method import response_exception_thrower
from pybotx.client.exceptions.chats import (
Expand Down Expand Up @@ -30,12 +28,6 @@ def from_domain(
shared_history: Missing[bool],
description: Optional[str] = None,
) -> "BotXAPICreateChatRequestPayload":
if chat_type == ChatTypes.UNSUPPORTED:
raise ValidationError(
errors=["Can't create chat of unsupported type."],
model=cls,
)

return cls(
name=name,
chat_type=convert_chat_type_from_domain(chat_type),
Expand Down
5 changes: 1 addition & 4 deletions pybotx/client/chats_api/list_chats.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,7 @@ def to_domain(self) -> List[ChatListItem]:
shared_history=chat_item.shared_history,
)
for chat_item in self.result
if not (
isinstance(chat_item, Dict)
or chat_item.chat_type == APIChatTypes.UNSUPPORTED
)
if isinstance(chat_item, BotXAPIListChatResult)
]

if len(chats_list) != len(self.result):
Expand Down
8 changes: 0 additions & 8 deletions pybotx/models/api_base.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import json
from enum import Enum
from typing import Any, Dict, List, Optional, Set, Union, cast

from pydantic import BaseModel
Expand Down Expand Up @@ -61,9 +60,6 @@ def jsonable_dict(self) -> Dict[str, Any]:
class VerifiedPayloadBaseModel(PayloadBaseModel):
"""Pydantic base model for API models."""

class Config:
use_enum_values = True


class UnverifiedPayloadBaseModel(PayloadBaseModel):
def __init__(
Expand All @@ -76,7 +72,3 @@ def __init__(

class Config:
arbitrary_types_allowed = True


class StrEnum(str, Enum): # noqa: WPS600 (pydantic needs this inheritance)
"""Enum base for API models."""
4 changes: 2 additions & 2 deletions pybotx/models/base_command.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from dataclasses import dataclass
from typing import Any, Dict, Literal, Optional
from typing import Any, Dict, Literal, Optional, Union
from uuid import UUID

from pydantic import validator
Expand Down Expand Up @@ -47,7 +47,7 @@ class BotAPIUserContext(BaseBotAPIContext):

class BotAPIChatContext(BaseBotAPIContext):
group_chat_id: UUID
chat_type: APIChatTypes
chat_type: Union[APIChatTypes, str]


class BotAPIDeviceContext(BaseBotAPIContext):
Expand Down
4 changes: 2 additions & 2 deletions pybotx/models/chats.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
from typing import List, Optional
from uuid import UUID

from pybotx.models.enums import ChatTypes, UserKinds
from pybotx.models.enums import ChatTypes, IncomingChatTypes, UserKinds


@dataclass
class Chat:
id: UUID
type: ChatTypes
type: IncomingChatTypes


@dataclass
Expand Down
57 changes: 36 additions & 21 deletions pybotx/models/enums.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
from enum import Enum, auto

from pybotx.models.api_base import StrEnum
from typing import Literal, Optional, Union, overload


class AutoName(Enum):
def _generate_next_value_( # type: ignore # noqa: WPS120
def _generate_next_value_( # type: ignore
name, # noqa: N805 (copied from official python docs)
start,
count,
Expand Down Expand Up @@ -54,17 +53,11 @@ class ChatTypes(AutoName):
PERSONAL_CHAT: Personal chat with user.
GROUP_CHAT: Group chat.
CHANNEL: Public channel.
UNSUPPORTED: Unknown chat type.
"""

PERSONAL_CHAT = auto()
GROUP_CHAT = auto()
CHANNEL = auto()
UNSUPPORTED = auto()

@classmethod
def _missing_(cls, instance: object) -> "ChatTypes":
return cls.UNSUPPORTED # pragma: no cover


class SyncSourceTypes(AutoName):
Expand All @@ -74,15 +67,20 @@ class SyncSourceTypes(AutoName):
OPENID = auto()


class APIChatTypes(StrEnum):
IncomingChatTypes = Union[ChatTypes, Literal["UNSUPPORTED"]]


class StrEnum(str, Enum): # noqa: WPS600 (pydantic needs this inheritance)
"""Enum base for API models."""

# https://github.com/pydantic/pydantic/issues/3850
# TODO: Use plain enums after migrating to Pydantic 2.0


class APIChatTypes(Enum):
CHAT = "chat"
GROUP_CHAT = "group_chat"
CHANNEL = "channel"
UNSUPPORTED = "unsupported"

@classmethod
def _missing_(cls, instance: object) -> "APIChatTypes":
return cls.UNSUPPORTED


class BotAPICommandTypes(StrEnum):
Expand All @@ -101,7 +99,7 @@ class BotAPISystemEventTypes(StrEnum):
SMARTAPP_EVENT = "system:smartapp_event"


class BotAPIClientPlatforms(StrEnum):
class BotAPIClientPlatforms(Enum):
WEB = "web"
ANDROID = "android"
IOS = "ios"
Expand All @@ -122,7 +120,7 @@ class BotAPIMentionTypes(StrEnum):
ALL = "all"


class APIUserKinds(StrEnum):
class APIUserKinds(Enum):
USER = "user"
CTS_USER = "cts_user"
BOTX = "botx"
Expand All @@ -141,7 +139,7 @@ class APIAttachmentTypes(StrEnum):
STICKER = "sticker"


class APISyncSourceTypes(StrEnum):
class APISyncSourceTypes(Enum):
AD = "ad"
ADMIN = "admin"
EMAIL = "email"
Expand Down Expand Up @@ -249,21 +247,38 @@ def convert_chat_type_from_domain(chat_type: ChatTypes) -> APIChatTypes:

converted_type = chat_types_mapping.get(chat_type)
if converted_type is None:
return APIChatTypes.UNSUPPORTED # pragma: no cover
raise NotImplementedError(f"Unsupported chat type: {chat_type}")

return converted_type


@overload
def convert_chat_type_to_domain(chat_type: APIChatTypes) -> ChatTypes:
... # noqa: WPS428


@overload
def convert_chat_type_to_domain(chat_type: str) -> Literal["UNSUPPORTED"]:
... # noqa: WPS428


def convert_chat_type_to_domain(
chat_type: Union[APIChatTypes, str],
) -> IncomingChatTypes:
chat_types_mapping = {
APIChatTypes.CHAT: ChatTypes.PERSONAL_CHAT,
APIChatTypes.GROUP_CHAT: ChatTypes.GROUP_CHAT,
APIChatTypes.CHANNEL: ChatTypes.CHANNEL,
}

converted_type = chat_types_mapping.get(chat_type)
converted_type: Optional[IncomingChatTypes]
try:
converted_type = chat_types_mapping.get(APIChatTypes(chat_type))
except ValueError:
converted_type = "UNSUPPORTED"

if converted_type is None:
return ChatTypes.UNSUPPORTED
raise NotImplementedError(f"Unsupported chat type: {chat_type}") from None

return converted_type

Expand Down
10 changes: 7 additions & 3 deletions pybotx/models/status.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
from pydantic import validator

from pybotx.models.api_base import VerifiedPayloadBaseModel
from pybotx.models.enums import APIChatTypes, ChatTypes, convert_chat_type_to_domain
from pybotx.models.enums import (
APIChatTypes,
IncomingChatTypes,
convert_chat_type_to_domain,
)
from pybotx.models.message.incoming_message import IncomingMessage

BotMenu = NewType("BotMenu", Dict[str, str])
Expand All @@ -18,7 +22,7 @@ class StatusRecipient:
ad_login: Optional[str]
ad_domain: Optional[str]
is_admin: Optional[bool]
chat_type: ChatTypes
chat_type: IncomingChatTypes

@classmethod
def from_incoming_message(
Expand All @@ -41,7 +45,7 @@ class BotAPIStatusRecipient(VerifiedPayloadBaseModel):
ad_login: Optional[str]
ad_domain: Optional[str]
is_admin: Optional[bool]
chat_type: APIChatTypes
chat_type: Union[APIChatTypes, str]

@validator("ad_login", "ad_domain", "is_admin", pre=True)
@classmethod
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "pybotx"
version = "0.51.3"
version = "0.52.0"
description = "A python library for interacting with eXpress BotX API"
authors = [
"Sidnev Nikolay <[email protected]>",
Expand Down
18 changes: 0 additions & 18 deletions tests/client/chats_api/test_create_chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import httpx
import pytest
from pydantic import ValidationError
from respx.router import MockRouter

from pybotx import (
Expand Down Expand Up @@ -158,20 +157,3 @@ async def test__create_chat__maximum_filled_succeed(
# - Assert -
assert created_chat_id == UUID("054af49e-5e18-4dca-ad73-4f96b6de63fa")
assert endpoint.called


async def test__create_chat__validation_error_raised(
bot_id: UUID,
bot_account: BotAccountWithSecret,
) -> None:
built_bot = Bot(collectors=[HandlerCollector()], bot_accounts=[bot_account])

# - Act -
async with lifespan_wrapper(built_bot) as bot:
with pytest.raises(ValidationError) as _: # noqa: WPS122
await bot.create_chat(
bot_id=bot_id,
name="Test chat name",
chat_type=ChatTypes.UNSUPPORTED,
huids=[],
)
4 changes: 2 additions & 2 deletions tests/test_incoming_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ async def test__async_execute_raw_bot_command__unsupported_chat_type_accepted(
"ad_domain": None,
"ad_login": None,
"app_version": None,
"chat_type": "usupported_chat_type",
"chat_type": "unsupported_chat_type",
"device": None,
"device_meta": None,
"device_software": None,
Expand Down Expand Up @@ -574,5 +574,5 @@ async def default_handler(message: IncomingMessage, bot: Bot) -> None:
assert incoming_message
assert incoming_message.chat == Chat(
id=UUID("30dc1980-643a-00ad-37fc-7cc10d74e935"),
type=ChatTypes.UNSUPPORTED,
type="UNSUPPORTED",
)

0 comments on commit c82abff

Please sign in to comment.