Remove utils file

This gets rid of awkward lazy imports as well.
This commit is contained in:
Lonami Exo 2023-10-29 20:54:31 +01:00
parent 8fe89496d6
commit d80c6b3bb4
15 changed files with 167 additions and 151 deletions

View File

@ -3,8 +3,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from ...tl import abcs, functions, types
from ..types import AsyncList, ChatLike, File, Participant, RecentAction
from ..utils import build_chat_map
from ..types import AsyncList, ChatLike, File, Participant, RecentAction, build_chat_map
from .messages import SearchList
if TYPE_CHECKING:

View File

@ -4,8 +4,7 @@ import time
from typing import TYPE_CHECKING, Optional
from ...tl import functions, types
from ..types import AsyncList, ChatLike, Dialog, Draft
from ..utils import build_chat_map, build_msg_map
from ..types import AsyncList, ChatLike, Dialog, Draft, build_chat_map, build_msg_map
from .messages import parse_message
if TYPE_CHECKING:

View File

@ -16,9 +16,9 @@ from ..types import (
Message,
OutFileLike,
OutWrapper,
expand_stripped_size,
generate_random_id,
)
from ..types.file import expand_stripped_size
from ..utils import generate_random_id
from .messages import parse_message
if TYPE_CHECKING:

View File

@ -7,8 +7,16 @@ from typing import TYPE_CHECKING, Dict, List, Literal, Optional, Tuple, Union
from ...session import PackedChat
from ...tl import abcs, functions, types
from ..parsers import parse_html_message, parse_markdown_message
from ..types import AsyncList, Chat, ChatLike, Message, buttons
from ..utils import build_chat_map, generate_random_id, peer_id
from ..types import (
AsyncList,
Chat,
ChatLike,
Message,
build_chat_map,
buttons,
generate_random_id,
peer_id,
)
if TYPE_CHECKING:
from .client import Client

View File

@ -16,7 +16,7 @@ from ...session import Gap
from ...tl import abcs
from ..events import Event as EventBase
from ..events.filters import Filter
from ..utils import build_chat_map
from ..types import build_chat_map
if TYPE_CHECKING:
from .client import Client

View File

@ -5,8 +5,16 @@ from typing import TYPE_CHECKING, Optional
from ...mtproto import RpcError
from ...session import PackedChat, PackedType
from ...tl import abcs, functions, types
from ..types import AsyncList, Channel, Chat, ChatLike, Group, User
from ..utils import build_chat_map, peer_id
from ..types import (
AsyncList,
Channel,
Chat,
ChatLike,
Group,
User,
build_chat_map,
peer_id,
)
if TYPE_CHECKING:
from .client import Client

View File

@ -6,7 +6,7 @@ from typing import TYPE_CHECKING, Literal, Optional, Tuple, Union
from ..event import Event
if TYPE_CHECKING:
from ...client import Client
from ...client.client import Client
class Text:

View File

@ -1,12 +1,21 @@
from .async_list import AsyncList
from .callback_answer import CallbackAnswer
from .chat import Channel, Chat, ChatLike, Group, User
from .chat import (
Channel,
Chat,
ChatLike,
Group,
User,
build_chat_map,
expand_peer,
peer_id,
)
from .dialog import Dialog
from .draft import Draft
from .file import File, InFileLike, OutFileLike, OutWrapper
from .file import File, InFileLike, OutFileLike, OutWrapper, expand_stripped_size
from .inline_result import InlineResult
from .login_token import LoginToken
from .message import Message
from .message import Message, adapt_date, build_msg_map, generate_random_id
from .meta import NoPublicConstructor
from .participant import Participant
from .password_token import PasswordToken
@ -20,15 +29,22 @@ __all__ = [
"ChatLike",
"Group",
"User",
"build_chat_map",
"expand_peer",
"peer_id",
"Dialog",
"Draft",
"File",
"InFileLike",
"OutFileLike",
"OutWrapper",
"expand_stripped_size",
"InlineResult",
"LoginToken",
"Message",
"adapt_date",
"build_msg_map",
"generate_random_id",
"NoPublicConstructor",
"Participant",
"PasswordToken",

View File

@ -1,6 +1,10 @@
from typing import Union
import itertools
import sys
from collections import defaultdict
from typing import DefaultDict, Dict, List, Optional, Union
from ....session import PackedChat
from ....tl import abcs, types
from .channel import Channel
from .chat import Chat
from .group import Group
@ -8,4 +12,81 @@ from .user import User
ChatLike = Union[Chat, PackedChat, int, str]
__all__ = ["Chat", "ChatLike", "Channel", "Group", "User"]
def build_chat_map(users: List[abcs.User], chats: List[abcs.Chat]) -> Dict[int, Chat]:
users_iter = (User._from_raw(u) for u in users)
chats_iter = (
Channel._from_raw(c)
if isinstance(c, (types.Channel, types.ChannelForbidden)) and c.broadcast
else Group._from_raw(c)
for c in chats
)
result: Dict[int, Chat] = {c.id: c for c in itertools.chain(users_iter, chats_iter)}
if len(result) != len(users) + len(chats):
# The fabled ID collision between different chat types.
counter: DefaultDict[int, List[Union[abcs.User, abcs.Chat]]] = defaultdict(list)
for user in users:
if (id := getattr(user, "id", None)) is not None:
counter[id].append(user)
for chat in chats:
if (id := getattr(chat, "id", None)) is not None:
counter[id].append(chat)
for k, v in counter.items():
if len(v) > 1:
for x in v:
print(x, file=sys.stderr)
raise RuntimeError(
f"chat identifier collision: {k}; please report this"
)
return result
def peer_id(peer: abcs.Peer) -> int:
if isinstance(peer, types.PeerUser):
return peer.user_id
elif isinstance(peer, types.PeerChat):
return peer.chat_id
elif isinstance(peer, types.PeerChannel):
return peer.channel_id
else:
raise RuntimeError("unexpected case")
def expand_peer(peer: abcs.Peer, *, broadcast: Optional[bool]) -> Chat:
if isinstance(peer, types.PeerUser):
return User._from_raw(types.UserEmpty(id=peer.user_id))
elif isinstance(peer, types.PeerChat):
return Group._from_raw(types.ChatEmpty(id=peer.chat_id))
elif isinstance(peer, types.PeerChannel):
if broadcast is None:
broadcast = True # assume broadcast by default (Channel type is more accurate than Group)
channel = types.ChannelForbidden(
broadcast=broadcast,
megagroup=not broadcast,
id=peer.channel_id,
access_hash=0,
title="",
until_date=None,
)
return Channel._from_raw(channel) if broadcast else Group._from_raw(channel)
else:
raise RuntimeError("unexpected case")
__all__ = [
"Chat",
"ChatLike",
"Channel",
"Group",
"User",
"build_chat_map",
"peer_id",
"expand_peer",
]

View File

@ -3,13 +3,13 @@ from __future__ import annotations
from typing import TYPE_CHECKING, Dict, Optional, Self, Union
from ...tl import abcs, types
from .chat import Chat
from .chat import Chat, peer_id
from .draft import Draft
from .message import Message
from .meta import NoPublicConstructor
if TYPE_CHECKING:
from ..client import Client
from ..client.client import Client
class Dialog(metaclass=NoPublicConstructor):
@ -51,8 +51,6 @@ class Dialog(metaclass=NoPublicConstructor):
"""
The chat where messages are sent in this dialog.
"""
from ..utils import peer_id
return self._chat_map[peer_id(self._raw.peer)]
@property

View File

@ -6,12 +6,12 @@ from typing import TYPE_CHECKING, Dict, Optional, Self
from ...session import PackedChat
from ...tl import abcs, functions, types
from ..parsers import generate_html_message, generate_markdown_message
from .chat import Chat
from .message import Message
from .chat import Chat, expand_peer, peer_id
from .message import Message, generate_random_id
from .meta import NoPublicConstructor
if TYPE_CHECKING:
from ..client import Client
from ..client.client import Client
class Draft(metaclass=NoPublicConstructor):
@ -60,8 +60,6 @@ class Draft(metaclass=NoPublicConstructor):
This is also the chat where the message will be sent to by :meth:`send`.
"""
from ..utils import expand_peer, peer_id
return self._chat_map.get(peer_id(self._peer)) or expand_peer(
self._peer, broadcast=None
)
@ -161,8 +159,6 @@ class Draft(metaclass=NoPublicConstructor):
)
async def _packed_chat(self) -> PackedChat:
from ..utils import peer_id
packed = None
if chat := self._chat_map.get(peer_id(self._peer)):
packed = chat.pack()
@ -184,8 +180,6 @@ class Draft(metaclass=NoPublicConstructor):
await draft.send(clear=False)
"""
from ..utils import generate_random_id
packed = await self._packed_chat()
peer = packed._to_input_peer()

View File

@ -10,7 +10,7 @@ from ...tl import abcs, types
from .meta import NoPublicConstructor
if TYPE_CHECKING:
from ..client import Client
from ..client.client import Client
math_round = round

View File

@ -4,11 +4,11 @@ from typing import TYPE_CHECKING, Optional, Union
from ...tl import abcs, functions, types
from .chat import ChatLike
from .message import Message
from .message import Message, generate_random_id
from .meta import NoPublicConstructor
if TYPE_CHECKING:
from ..client import Client
from ..client.client import Client
class InlineResult(metaclass=NoPublicConstructor):
@ -62,8 +62,6 @@ class InlineResult(metaclass=NoPublicConstructor):
:return: The sent message.
"""
from ..utils import generate_random_id
if chat is None and isinstance(self._default_peer, types.InputPeerEmpty):
raise ValueError("no target chat was specified")

View File

@ -1,17 +1,37 @@
from __future__ import annotations
import datetime
import time
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Self, Union
from ...tl import abcs, types
from ..parsers import generate_html_message, generate_markdown_message
from .buttons import Button, as_concrete_row, create_button
from .chat import Chat, ChatLike
from .chat import Chat, ChatLike, expand_peer, peer_id
from .file import File
from .meta import NoPublicConstructor
if TYPE_CHECKING:
from ..client import Client
from ..client.client import Client
_last_id = 0
def generate_random_id() -> int:
global _last_id
if _last_id == 0:
_last_id = int(time.time() * 1e9)
_last_id += 1
return _last_id
def adapt_date(date: Optional[int]) -> Optional[datetime.datetime]:
return (
datetime.datetime.fromtimestamp(date, tz=datetime.timezone.utc)
if date is not None
else None
)
class Message(metaclass=NoPublicConstructor):
@ -148,8 +168,6 @@ class Message(metaclass=NoPublicConstructor):
"""
The date when the message was sent.
"""
from ..utils import adapt_date
return adapt_date(getattr(self._raw, "date", None))
@property
@ -157,8 +175,6 @@ class Message(metaclass=NoPublicConstructor):
"""
The :term:`chat` when the message was sent.
"""
from ..utils import expand_peer, peer_id
peer = self._raw.peer_id or types.PeerUser(user_id=0)
pid = peer_id(peer)
if pid not in self._chat_map:
@ -176,8 +192,6 @@ class Message(metaclass=NoPublicConstructor):
If there is no sender, it means the message was sent by an anonymous user.
"""
from ..utils import expand_peer, peer_id
if (from_ := getattr(self._raw, "from_id", None)) is not None:
return self._chat_map.get(peer_id(from_)) or expand_peer(
from_, broadcast=getattr(self._raw, "post", None)
@ -444,3 +458,12 @@ class Message(metaclass=NoPublicConstructor):
return not self._raw.noforwards
else:
return False
def build_msg_map(
client: Client, messages: List[abcs.Message], chat_map: Dict[int, Chat]
) -> Dict[int, Message]:
return {
msg.id: msg
for msg in (Message._from_raw(client, m, chat_map) for m in messages)
}

View File

@ -1,108 +0,0 @@
from __future__ import annotations
import datetime
import itertools
import sys
import time
from collections import defaultdict
from typing import TYPE_CHECKING, DefaultDict, Dict, List, Optional, Union
from ..tl import abcs, types
from .types import Channel, Chat, Group, Message, User
if TYPE_CHECKING:
from .client import Client
_last_id = 0
def generate_random_id() -> int:
global _last_id
if _last_id == 0:
_last_id = int(time.time() * 1e9)
_last_id += 1
return _last_id
def build_chat_map(users: List[abcs.User], chats: List[abcs.Chat]) -> Dict[int, Chat]:
users_iter = (User._from_raw(u) for u in users)
chats_iter = (
Channel._from_raw(c)
if isinstance(c, (types.Channel, types.ChannelForbidden)) and c.broadcast
else Group._from_raw(c)
for c in chats
)
result: Dict[int, Chat] = {c.id: c for c in itertools.chain(users_iter, chats_iter)}
if len(result) != len(users) + len(chats):
# The fabled ID collision between different chat types.
counter: DefaultDict[int, List[Union[abcs.User, abcs.Chat]]] = defaultdict(list)
for user in users:
if (id := getattr(user, "id", None)) is not None:
counter[id].append(user)
for chat in chats:
if (id := getattr(chat, "id", None)) is not None:
counter[id].append(chat)
for k, v in counter.items():
if len(v) > 1:
for x in v:
print(x, file=sys.stderr)
raise RuntimeError(
f"chat identifier collision: {k}; please report this"
)
return result
def build_msg_map(
client: Client, messages: List[abcs.Message], chat_map: Dict[int, Chat]
) -> Dict[int, Message]:
return {
msg.id: msg
for msg in (Message._from_raw(client, m, chat_map) for m in messages)
}
def peer_id(peer: abcs.Peer) -> int:
if isinstance(peer, types.PeerUser):
return peer.user_id
elif isinstance(peer, types.PeerChat):
return peer.chat_id
elif isinstance(peer, types.PeerChannel):
return peer.channel_id
else:
raise RuntimeError("unexpected case")
def expand_peer(peer: abcs.Peer, *, broadcast: Optional[bool]) -> Chat:
if isinstance(peer, types.PeerUser):
return User._from_raw(types.UserEmpty(id=peer.user_id))
elif isinstance(peer, types.PeerChat):
return Group._from_raw(types.ChatEmpty(id=peer.chat_id))
elif isinstance(peer, types.PeerChannel):
if broadcast is None:
broadcast = True # assume broadcast by default (Channel type is more accurate than Group)
channel = types.ChannelForbidden(
broadcast=broadcast,
megagroup=not broadcast,
id=peer.channel_id,
access_hash=0,
title="",
until_date=None,
)
return Channel._from_raw(channel) if broadcast else Group._from_raw(channel)
else:
raise RuntimeError("unexpected case")
def adapt_date(date: Optional[int]) -> Optional[datetime.datetime]:
return (
datetime.datetime.fromtimestamp(date, tz=datetime.timezone.utc)
if date is not None
else None
)