Skip to content

Commit

Permalink
🎨 Add guidelines and reorganize
Browse files Browse the repository at this point in the history
  • Loading branch information
Paillat-dev committed Dec 20, 2024
1 parent 2069a4b commit 1b46c75
Show file tree
Hide file tree
Showing 11 changed files with 123 additions and 19 deletions.
6 changes: 3 additions & 3 deletions discord/guild.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
overload,
)

from . import abc, utils
from . import abc, models, utils
from .asset import Asset
from .automod import AutoModAction, AutoModRule, AutoModTriggerMetadata
from .channel import *
Expand Down Expand Up @@ -2114,9 +2114,9 @@ async def fetch_ban(self, user: Snowflake) -> BanEntry:
HTTPException
An error occurred while fetching the information.
"""
data: BanPayload = await self._state.http.get_ban(user.id, self.id)
data: models.Ban = await self._state.http.get_ban(user.id, self.id)
return BanEntry(
user=User(state=self._state, data=data["user"]), reason=data["reason"]
user=User(state=self._state, data=data.user), reason=data.reason
)

async def fetch_channel(self, channel_id: int, /) -> GuildChannel | Thread:
Expand Down
5 changes: 3 additions & 2 deletions discord/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -1648,14 +1648,15 @@ def get_bans(
Route("GET", "/guilds/{guild_id}/bans", guild_id=guild_id), params=params
)

def get_ban(self, user_id: Snowflake, guild_id: Snowflake) -> Response[guild.Ban]:
def get_ban(self, user_id: Snowflake, guild_id: Snowflake) -> Response[models.Ban]:
return self.request(
Route(
"GET",
"/guilds/{guild_id}/bans/{user_id}",
guild_id=guild_id,
user_id=user_id,
)
),
model=models.Ban,
)

def get_vanity_code(self, guild_id: Snowflake) -> Response[invite.VanityInvite]:
Expand Down
72 changes: 72 additions & 0 deletions discord/models/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Py-cord Models

This directory contains the pydantic models and types used by py-cord.

## Structure

The models are structured in a way that they mirror the structure of the Discord API.
They are subdivided into the following submodules:

> [!IMPORTANT] Each of the submodules is defined below in order. Submodules may only
> reference in their code classes from the same or lower level submodules. For example,
> `api` may reference classes from `api`, `base` and `types`, but `base` may not
> reference classes from `api`. This is to prevent circular imports and to keep the
> codebase clean and maintainable.
### `types`

Contains python types and dataclasses that are used in the following submodules. These
are used to represent the data in a more pythonic way, and are used to define the
pydantic models.

### `base`

Contains the base models defined in the Discord docs. These are the models you will
often find with a heading like "... Template", and hyperlinks linking to it referring to
it as an "object".

For example, the
[User Template](https://discord.com/developers/docs/resources/user#user-object) is
defined in `base/user.py`.

### `api`

Contains the models that are used to represent the data received and set trough discord
API requests. They represent payloads that are sent and received from the Discord API.

When representing a route, it is preferred to create a single python file for each base
route. If the file may become too large, it is preferred to split it into multiple
files, one for each sub-route. In that case, a submodule with the name of the base route
should be created to hold the sub-routes.

For example, the
[Modify Guild Template](https://discord.com/developers/docs/resources/guild-template#modify-guild-template)
is defined in `api/guild_template.py`.

### `gateway`

Contains the models that are used to represent the data received and sent trough the
Discord Gateway. They represent payloads that are sent and received from the Discord
Gateway.

For example, the [Ready Event](https://discord.com/developers/docs/topics/gateway#hello)
is defined in `gateway/ready.py`.

## Naming

The naming of the models is based on the Discord API documentation. The models are named
after the object they represent in the Discord API documentation. It is generally
preferred to create a new model for each object in the Discord API documentation, even
if the file may only contain a single class, so that the structure keeps a 1:1 mapping
with the Discord API documentation.

## Exporting strategies

The models are exported in the following way:

- The models are exported in the `__init__.py` of their respective submodules.
- Models from the `base` submodule are re-exported in the `__init__.py` of the `modules`
module.
- The other submodules are re-exported in the `__init__.py` of the `models` module as a
single import.
- The `models` module is re-exported in the `discord` module.
21 changes: 14 additions & 7 deletions discord/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
from discord.models.base.role import Role

from . import gateway, types
from .emoji import Emoji
from .guild import Guild, UnavailableGuild
from .role import Role
from .sticker import Sticker
from .base import (
AvatarDecorationData,
Ban,
Emoji,
Guild,
Sticker,
UnavailableGuild,
User,
)
from .types.utils import MISSING
from .user import AvatarDecorationData, User

__all__ = [
__all__ = (
"Emoji",
"Guild",
"UnavailableGuild",
Expand All @@ -17,4 +23,5 @@
"MISSING",
"AvatarDecorationData",
"gateway",
]
"Ban",
)
17 changes: 17 additions & 0 deletions discord/models/base/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from .ban import Ban
from .emoji import Emoji
from .guild import Guild, UnavailableGuild
from .role import Role
from .sticker import Sticker
from .user import AvatarDecorationData, User

__all__ = (
"Emoji",
"Guild",
"UnavailableGuild",
"Role",
"Sticker",
"User",
"Ban",
"AvatarDecorationData",
)
8 changes: 8 additions & 0 deletions discord/models/base/ban.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from pydantic import BaseModel

from .user import User


class Ban(BaseModel):
reason: str
user: User
2 changes: 1 addition & 1 deletion discord/models/emoji.py → discord/models/base/emoji.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from pydantic import BaseModel

from .types import MISSING, EmojiID, MissingSentinel, RoleID
from ..types import MISSING, EmojiID, MissingSentinel, RoleID
from .user import User


Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from pydantic import BaseModel

from .types import MISSING, GuildID, MissingSentinel, Snowflake, StickerID
from ..types import MISSING, GuildID, MissingSentinel, Snowflake, StickerID
from .user import User


Expand Down
4 changes: 2 additions & 2 deletions discord/models/user.py → discord/models/base/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

from pydantic import BaseModel

from .types import MISSING, Color, Locale, MissingSentinel, Snowflake, UserID
from .types.flags import UserFlags
from ..types import MISSING, Color, Locale, MissingSentinel, Snowflake, UserID
from ..types.flags import UserFlags


class PremiumType(IntEnum):
Expand Down
5 changes: 2 additions & 3 deletions discord/models/gateway/ready.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
from __future__ import annotations

from pydantic import BaseModel, field_validator
from pydantic import BaseModel

from ..guild import Guild, UnavailableGuild
from ..base import Guild, UnavailableGuild, User
from ..types.utils import MISSING, MissingSentinel
from ..user import User
from .base import GatewayEvent


Expand Down

0 comments on commit 1b46c75

Please sign in to comment.