Skip to content

Commit b8fe5c4

Browse files
authored
feat: update and correctly typehint user.pyi (#1278)
* feat: update and correctly typehint user.pyi * chore: run black on user.pyi --------- Co-authored-by: Astrea49 <[email protected]>
1 parent 43a09e1 commit b8fe5c4

File tree

1 file changed

+53
-13
lines changed

1 file changed

+53
-13
lines changed

interactions/models/discord/user.pyi

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,48 @@
1+
from .base import DiscordObject
2+
from aiohttp import FormData
13
from datetime import datetime
2-
from typing import Iterable, List, Optional, Union, Set
4+
from typing import type_check_only
5+
import attrs
36

7+
from interactions.client import Client
48
from interactions.client.const import Absent
59
from interactions.client.mixins.send import SendMixin
610
from interactions.models.discord.activity import Activity
711
from interactions.models.discord.asset import Asset
812
from interactions.models.discord.channel import DM, TYPE_GUILD_CHANNEL
913
from interactions.models.discord.color import Color
10-
from interactions.models.discord.enums import Permissions, PremiumType, Status, UserFlags
14+
from interactions.models.discord.enums import MemberFlags, Permissions, PremiumType, Status, UserFlags
1115
from interactions.models.discord.file import UPLOADABLE_TYPE
1216
from interactions.models.discord.guild import Guild
1317
from interactions.models.discord.role import Role
1418
from interactions.models.discord.snowflake import Snowflake_Type
1519
from interactions.models.discord.timestamp import Timestamp
1620
from interactions.models.discord.voice_state import VoiceState
17-
from .base import DiscordObject
21+
from typing import Any, Dict, Iterable, List, Optional, Set, Union
1822

1923
class _SendDMMixin(SendMixin):
2024
id: Snowflake_Type
25+
async def _send_http_request(
26+
self, message_payload: Union[dict, "FormData"], files: Union[list["UPLOADABLE_TYPE"], None] = ...
27+
) -> dict: ...
28+
29+
# note: what we're trying to achieve here is making isinstance checks as accurate as possible when typehinting
30+
# Member, while "having" the attributes of User (because of __getattr__), is not actually a subclass of either
31+
# BaseUser or User - it's its own seperate class
32+
# we still want to typehint Member with all of the User attributes though, so what we do is create fake
33+
# mixins that actually don't exist, and make BaseUser and User inherit from that
34+
# then, we can make Member inheir the fake user mixin, and now we have a Member class with User attributes
35+
# and that understands isinstance(member, User) is false
2136

22-
class BaseUser(DiscordObject, _SendDMMixin):
37+
@type_check_only
38+
@attrs.define(eq=False, order=False, hash=False, kw_only=True) # properly typehints added attributes by attrs
39+
class FakeBaseUserMixin(DiscordObject, _SendDMMixin):
2340
username: str
2441
discriminator: int
2542
avatar: Asset
43+
def __str__(self) -> str: ...
44+
@classmethod
45+
def _process_dict(cls, data: Dict[str, Any], client: Client) -> Dict[str, Any]: ...
2646
@property
2747
def tag(self) -> str: ...
2848
@property
@@ -36,7 +56,12 @@ class BaseUser(DiscordObject, _SendDMMixin):
3656
@property
3757
def mutual_guilds(self) -> List["Guild"]: ...
3858

39-
class User(BaseUser):
59+
@attrs.define(eq=False, order=False, hash=False, kw_only=True)
60+
class BaseUser(FakeBaseUserMixin): ...
61+
62+
@type_check_only
63+
@attrs.define(eq=False, order=False, hash=False, kw_only=True)
64+
class FakeUserMixin(FakeBaseUserMixin):
4065
bot: bool
4166
system: bool
4267
public_flags: UserFlags
@@ -45,36 +70,49 @@ class User(BaseUser):
4570
accent_color: Optional["Color"]
4671
activities: list[Activity]
4772
status: Absent[Status]
73+
@classmethod
74+
def _process_dict(cls, data: Dict[str, Any], client: Client) -> Dict[str, Any]: ...
4875
@property
4976
def member_instances(self) -> List["Member"]: ...
5077

78+
@attrs.define(eq=False, order=False, hash=False, kw_only=True)
79+
class User(FakeUserMixin, BaseUser): ...
80+
81+
@attrs.define(eq=False, order=False, hash=False, kw_only=True)
5182
class NaffUser(User):
5283
verified: bool
5384
mfa_enabled: bool
5485
email: Optional[str]
5586
locale: Optional[str]
5687
bio: Optional[str]
5788
flags: UserFlags
58-
_guild_ids: Set[Snowflake_Type]
89+
_guild_ids: Set["Snowflake_Type"]
90+
def _add_guilds(self, guild_ids: Set["Snowflake_Type"]) -> None: ...
5991
@property
6092
def guilds(self) -> List["Guild"]: ...
61-
async def edit(self, username: Absent[str] = ..., avatar: Absent[UPLOADABLE_TYPE] = ...) -> None: ...
93+
async def edit(self, *, username: Absent[str] = ..., avatar: Absent[UPLOADABLE_TYPE] = ...) -> None: ...
6294

63-
class Member(User): # for typehinting purposes, we can lie
95+
@attrs.define(eq=False, order=False, hash=False, kw_only=True)
96+
class Member(FakeUserMixin):
6497
bot: bool
6598
nick: Optional[str]
6699
deaf: bool
67100
mute: bool
101+
flags: MemberFlags
68102
joined_at: Timestamp
69103
premium_since: Optional["Timestamp"]
70104
pending: Optional[bool]
71105
guild_avatar: Asset
72-
communication_disabled_until: Optional[Timestamp]
106+
communication_disabled_until: Optional["Timestamp"]
73107
_guild_id: Snowflake_Type
74-
_role_ids: List[Snowflake_Type]
108+
_role_ids: List["Snowflake_Type"]
109+
_user_ref: frozenset
110+
@classmethod
111+
def _process_dict(cls, data: Dict[str, Any], client: Client) -> Dict[str, Any]: ...
75112
def update_from_dict(self, data) -> None: ...
76113
@property
77114
def user(self) -> User: ...
115+
def __str__(self) -> str: ...
78116
@property
79117
def nickname(self) -> str: ...
80118
@nickname.setter
@@ -113,12 +151,14 @@ class Member(User): # for typehinting purposes, we can lie
113151
self,
114152
*,
115153
nickname: Absent[str] = ...,
116-
roles: Absent[Iterable[Snowflake_Type]] = ...,
154+
roles: Absent[Iterable["Snowflake_Type"]] = ...,
117155
mute: Absent[bool] = ...,
118156
deaf: Absent[bool] = ...,
119157
channel_id: Absent["Snowflake_Type"] = ...,
120158
communication_disabled_until: Absent[Union["Timestamp", None]] = ...,
121-
reason: Absent[str] = ...,
159+
reason: Absent[str] = ...
122160
) -> None: ...
123161
async def kick(self, reason: Absent[str] = ...) -> None: ...
124-
async def ban(self, delete_message_days: int = ..., reason: Absent[str] = ...) -> None: ...
162+
async def ban(
163+
self, delete_message_days: Absent[int] = ..., delete_message_seconds: int = ..., reason: Absent[str] = ...
164+
) -> None: ...

0 commit comments

Comments
 (0)