Skip to content

fix(typing): Improve typing and other related issues in state.py - #3435

Draft
ToothyDev wants to merge 13 commits into
masterfrom
fix/typing-statepy
Draft

ToothyDev wants to merge 13 commits into
masterfrom
fix/typing-statepy

Conversation

@ToothyDev

@ToothyDev ToothyDev commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Just a best-effort attempt at trying to improve typing in this file. Goal is to improve, not fix everything, that would need way too many changes across too many files.
Method of the madness: Installed basedpyright, then just went from the top to the bottom of the file

Information

  • This PR fixes an issue.
  • This PR adds something new (e.g. new method or parameters).
  • This PR is a breaking change (e.g. methods or parameters removed/renamed).
  • This PR is not a code change (e.g. documentation, README, typehinting,
    examples, ...).

Checklist

  • I have searched the open pull requests for duplicates.
  • If code changes were made then they have been tested.
    • I have updated the documentation to reflect the changes.
  • If type: ignore comments were used, a comment is also left explaining why.
  • I have updated the changelog to include these changes.
  • I have read the Contributing Guidelines.
  • AI Usage has been disclosed. -> None
    • If AI has been used, I understand fully what the code does

@ToothyDev ToothyDev added help wanted Extra attention is needed typing Is related to / changes python typing labels Nov 7, 2026
@github-project-automation github-project-automation Bot moved this to Todo in Pycord Nov 7, 2026
@pycord-app

pycord-app Bot commented Nov 7, 2026

Copy link
Copy Markdown

Thanks for opening this pull request!
Please make sure you have read the Contributing Guidelines and Code of Conduct.

This pull request can be checked-out with:

git fetch origin pull/3435/head:pr-3435
git checkout pr-3435

This pull request can be installed with:

pip install git+https://github.com/Pycord-Development/pycord@refs/pull/3435/head

Comment thread discord/state.py Resolved
Comment thread discord/state.py Resolved
Comment thread discord/state.py Resolved
First rough sweep up to line 1350 fixing what I could
@ToothyDev

Copy link
Copy Markdown
Contributor Author

For context, I'm trying to stay in state.py, but if minor type additions in other files fix an issue, I will of course do so. Just to explain why I touched other files too

Comment thread discord/state.py Resolved
@ToothyDev

Copy link
Copy Markdown
Contributor Author

I've done my best and killed over 200 type errors, with a sad 396 left. There are many things that are definitely too complex for me / requiring better lib knowledge, as well as a couple of things we seem to lack data dicts for. You'll see those for yourself if you run basedpyright over this horrible file.
Feel free to be critical as I basically just went through with the intention of "remove red squiggly line" as my primary goal

@plun1331 plun1331 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i know its not in the pr but:
state 786 has a typing error (and probably just doesn't work at all)
1246 is mad about something
overload for request_guild_channel_info needs to be fixed to include a default

probably a few other things

Comment thread discord/state.py Resolved
Comment thread discord/state.py Resolved
Comment thread discord/state.py Resolved
Comment thread discord/state.py Resolved
Comment thread discord/state.py Resolved
Comment thread discord/state.py Resolved
Comment thread discord/state.py
def parse_guild_member_remove(self, data) -> None:
def parse_guild_member_remove(self, data: MemberRemoveEventPayload) -> None:
user = self.store_user(data["user"])
raw = RawMemberRemoveEvent(data, user)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change the type for this to also include member

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I change it in RawMemberRemoveEvent i get all sorts of new errors in that file, not doing that in this PR

Comment thread discord/state.py
@@ -1680,6 +1786,8 @@ def parse_guild_audit_log_entry_create(self, data) -> None:
payload = RawAuditLogEntryEvent(data)
payload.guild = guild

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably make guild a possible attr on this event

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added it only to its slots, ig thats enough

Comment thread discord/state.py Outdated
else guild.get_member(data.get("creator_id"))
)
creator = None
if data.get("creator"):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typeddict is wrong here, creator is NotRequired

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(A TypedDict with 5 required fields is always truthy: Inferred type User is always truthytyredundant-condition)

Comment thread discord/state.py Resolved
@ToothyDev
ToothyDev requested a review from plun1331 November 12, 2026 09:55
@ToothyDev

Copy link
Copy Markdown
Contributor Author

Addressed all comments, only resolved the ones I felt confident in, please check yourself what you consider resolved

Comment thread discord/channel.py

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

278:65 error [reportArgumentType]
    Argument of type "ChannelFlags | Any | int" cannot be assigned to parameter "value" of type "int" in function "_from_value"
      Type "ChannelFlags | Any | int" is not assignable to type "int"
        "ChannelFlags" is not assignable to "int"

New issue in this file

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Paillat-dev Flags are a GIGANTIC mess imho, the built-in class seems to confuse the typechecker hella and the lib can't agree on whether to type them as ints or xFlag classes

Comment thread discord/state.py
)
)
member, before, after = guild._update_voice_state(data, channel_id) # type: ignore
if not isinstance(channel_id, int):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When someone leaves voice, channel_id IS None so this should most likely not return early

Comment thread discord/state.py
self._stickers.pop(emoji.id, None)
# guild won't be None here
guild.stickers = tuple(
map(lambda d: self.store_sticker(guild, d), data["stickers"])

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1614:57 error [reportGeneralTypeIssues]
    Could not access item in TypedDict
      "stickers" is not a defined key in "GuildSticker"

P sure your typing above is not right, for data.

Comment thread discord/message.py
Comment on lines +1255 to +1260
def _add_reaction(
self,
data: ReactionPayload,
emoji: PartialEmoji | GuildEmoji | AppEmoji | str | None,
user_id: int,
) -> Reaction:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This causes a new issue in state.py:

1027:46 error [reportArgumentType]
    Argument of type "ReactionActionEvent" cannot be assigned to parameter "data" of type "Reaction" in function "_add_reaction"
      "count" is missing from "ReactionActionEvent"
      "me" is missing from "ReactionActionEvent"
      "me_burst" is missing from "ReactionActionEvent"
      "count_details" is missing from "ReactionActionEvent"

Comment thread discord/state.py
Comment on lines +518 to 525
def store_emoji(self, guild: Guild, data: EmojiPayload) -> GuildEmoji | None:
# the id will be present here
emoji_id = int(data["id"]) # type: ignore
if data["id"] is None:
_log.warning("Received emoji without id")
return None
emoji_id = int(data["id"])
self._emojis[emoji_id] = emoji = GuildEmoji(guild=guild, state=self, data=data)
return emoji

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Causing new issues in multiple files:
guild.py:

615:47 error [reportAttributeAccessIssue]
    Cannot assign to attribute "emojis" for class "Guild*"
      "tuple[GuildEmoji | None, ...]" is not assignable to "tuple[GuildEmoji, ...]"
        Tuple entry 1 is incorrect type
          Type "GuildEmoji | None" is not assignable to type "GuildEmoji"
            "None" is not assignable to "GuildEmoji"

3295:16 error [reportReturnType]
    Type "GuildEmoji | None" is not assignable to return type "GuildEmoji"
      Type "GuildEmoji | None" is not assignable to type "GuildEmoji"
        "None" is not assignable to "GuildEmoji"

state.py

1594:24 error [reportAttributeAccessIssue]
    Cannot assign to attribute "emojis" for class "Guild"
      "tuple[GuildEmoji | None, ...]" is not assignable to "tuple[GuildEmoji, ...]"
        Tuple entry 1 is incorrect type
          Type "GuildEmoji | None" is not assignable to type "GuildEmoji"
            "None" is not assignable to "GuildEmoji"

Comment thread discord/state.py
Comment on lines +2304 to 2307
def get_reaction_emoji(
self, data: PartialEmojiPayload
) -> GuildEmoji | AppEmoji | PartialEmoji | str | None:
emoji_id = utils._get_as_snowflake(data, "id")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This causes a new issue in reaction.py

106:66 error [reportAttributeAccessIssue]
    Cannot assign to attribute "emoji" for class "Reaction*"
      Type "PartialEmoji | GuildEmoji | AppEmoji | str | None" is not assignable to type "PartialEmoji | GuildEmoji | AppEmoji | str"
        Type "None" is not assignable to type "PartialEmoji | GuildEmoji | AppEmoji | str"
          "None" is not assignable to "PartialEmoji"
          "None" is not assignable to "GuildEmoji"
          "None" is not assignable to "AppEmoji"
          "None" is not assignable to "str"

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

help wanted Extra attention is needed typing Is related to / changes python typing

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

3 participants