Conversation
935ce0f to
1a6141a
Compare
4f778db to
a5a4a93
Compare
- Add test_models_facade_and_layers.py for export consistency and layer checks - Create request/response/gateway.event package skeletons - Move 15 entity domains from http/ to common/ (application, audit_log, etc.) - Keep http/ modules as shims for backward compatibility
- Change all gateway imports from ..http.* to ..common.* - Update layer guard test to forbid gateway->http imports - Files modified: - gateway_event_fields.py, channel_events.py, gateway_payloads.py - integration_events.py, auto_moderation_events.py, invite_events.py - monetization_events.py, guild_events.py, gateway_events.py
- Add gateway/event/ directory with 8 domain files: auto_moderation, channels, guilds, integrations, invites, monetization, interactions, messages - Convert old *_events.py files to shims - Convert gateway_events.py to shim importing from event/
- Add request/messages.py, request/webhooks.py, request/user.py - Add request/permissions.py, response/oauth2.py - Remove request/response models from common/* - Update facade imports in models/__init__.py
- Add request/channels.py with all *Params classes - Add response/channels.py with *Response classes - Keep http/channels.py as shim re-exporting from common/request/response
- Add request/guilds.py, request/guild_members.py - Add request/guild_scheduled_events.py, request/guild_templates.py - Add request/guild_welcome.py - Add common/guild_templates.py for shared objects - Convert http/guild*.py to shims
Tasks 9-11: - Application/Gateway/AutoModeration: request/application, request/auto_moderation, response/gateway - Emoji/Voice/Stickers/Soundboard/Polls: request/* and response/* for each domain - Webhooks/Lobby/Invites: common/* for objects, request/* for params All http/* modules converted to shims re-exporting from new locations
- Add common/interactions.py with all reusable interaction models - Add request/interactions.py with request-specific interaction models - Convert interactions/*.py to shims - Update common/messages.py TYPE_CHECKING imports - Update layer guard test to forbid common/gateway -> interactions/http
- Update AGENTS.md with new directory structure - Document layer dependency constraints - Add new model addition workflow - Fix remaining lint issues in gateway/http modules
There was a problem hiding this comment.
Pull request overview
This PR refactors the Discord adapter’s API models by splitting the previous monolithic api/model.py into a layered api/models/ package and introducing a facade module for re-exports, then updates imports/tests/tooling to use the new structure.
Changes:
- Introduces
nonebot.adapters.discord.api.modelsas a facade that aggregates models fromcommon/,request/,response/,http/, andgateway/, and rebuilds forward references. - Updates adapter/event/api code, stub generation, and tests to import from
api.models(and related submodules) instead of the removedapi.model/payloadlocations. - Adds tests to validate
models.__all__integrity and enforce model-layer dependency rules.
Reviewed changes
Copilot reviewed 116 out of 117 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_models_facade_and_layers.py | New tests for facade __all__ consistency and AST-based layer dependency checks |
| tests/test_message_snapshot_missing_mention_roles.py | Update imports to new api.models facade |
| tests/test_invite_target_users_upload.py | Update imports to new api.models facade |
| tests/test_guild_create_compat_event.py | Switch gateway frame imports to api.models (from old payload module) |
| tests/test_attachment_segment_url.py | Update imports to new api.models facade |
| tests/test_api_nullability.py | Update imports to new api.models facade |
| scripts/generate_client_pyi.py | Teach stub generator to treat models as the model import source and emit from .models import ... |
| nonebot/adapters/discord/event.py | Update model imports to new facade/submodules for gateway payload mixins |
| nonebot/adapters/discord/commands/params.py | Update model import path for interaction option type |
| nonebot/adapters/discord/api/utils.py | Update model imports to new api.models facade |
| nonebot/adapters/discord/api/models/response/stickers.py | New response models split-out (stickers) |
| nonebot/adapters/discord/api/models/response/soundboard.py | New response models split-out (soundboard) |
| nonebot/adapters/discord/api/models/response/oauth2.py | New response models split-out (oauth2) |
| nonebot/adapters/discord/api/models/response/gateway.py | New response models split-out (gateway URL responses) |
| nonebot/adapters/discord/api/models/response/emoji.py | New response models split-out (emoji) |
| nonebot/adapters/discord/api/models/response/channels.py | New response models split-out (channels) |
| nonebot/adapters/discord/api/models/response/init.py | Response package exports |
| nonebot/adapters/discord/api/models/request/webhooks.py | New request models split-out (webhooks) |
| nonebot/adapters/discord/api/models/request/voice.py | New request models split-out (voice) |
| nonebot/adapters/discord/api/models/request/user.py | New request models split-out (user) |
| nonebot/adapters/discord/api/models/request/stickers.py | New request models split-out (stickers) |
| nonebot/adapters/discord/api/models/request/soundboard.py | New request models split-out (soundboard) |
| nonebot/adapters/discord/api/models/request/polls.py | New request models split-out (polls) |
| nonebot/adapters/discord/api/models/request/permissions.py | New request models split-out (role permissions) |
| nonebot/adapters/discord/api/models/request/messages.py | New request models split-out (message send/edit + multipart file types) |
| nonebot/adapters/discord/api/models/request/lobby.py | New request models split-out (lobby) |
| nonebot/adapters/discord/api/models/request/interactions.py | New request models split-out (interactions) |
| nonebot/adapters/discord/api/models/request/guilds.py | New request models split-out (guilds) |
| nonebot/adapters/discord/api/models/request/guild_welcome.py | New request models split-out (welcome screen) |
| nonebot/adapters/discord/api/models/request/guild_templates.py | New request models split-out (guild templates) |
| nonebot/adapters/discord/api/models/request/guild_scheduled_events.py | New request models split-out (scheduled events) |
| nonebot/adapters/discord/api/models/request/guild_members.py | New request models split-out (guild members) |
| nonebot/adapters/discord/api/models/request/emoji.py | New request models split-out (emoji) |
| nonebot/adapters/discord/api/models/request/channels.py | New request models split-out (channels) |
| nonebot/adapters/discord/api/models/request/auto_moderation.py | New request models split-out (auto moderation) |
| nonebot/adapters/discord/api/models/request/application.py | New request models split-out (application) |
| nonebot/adapters/discord/api/models/request/init.py | Request package exports |
| nonebot/adapters/discord/api/models/interactions/message_components.py | New interactions re-export module (components) |
| nonebot/adapters/discord/api/models/interactions/interactions.py | New interactions aggregation module (common + request) |
| nonebot/adapters/discord/api/models/interactions/application_commands.py | New interactions aggregation module (application commands) |
| nonebot/adapters/discord/api/models/interactions/init.py | Interactions package exports |
| nonebot/adapters/discord/api/models/http/webhooks.py | New http “endpoint surface” exports (webhooks) |
| nonebot/adapters/discord/api/models/http/voice.py | New http exports (voice) |
| nonebot/adapters/discord/api/models/http/stickers.py | New http exports (stickers) |
| nonebot/adapters/discord/api/models/http/stage_instance.py | New http exports (stage instance) |
| nonebot/adapters/discord/api/models/http/soundboard.py | New http exports (soundboard) |
| nonebot/adapters/discord/api/models/http/polls.py | New http exports (polls) |
| nonebot/adapters/discord/api/models/http/monetization.py | New http exports (monetization) |
| nonebot/adapters/discord/api/models/http/lobby.py | New http exports (lobby) |
| nonebot/adapters/discord/api/models/http/invites.py | New http exports (invites) |
| nonebot/adapters/discord/api/models/http/integrations.py | New http exports (integrations) |
| nonebot/adapters/discord/api/models/http/guilds.py | New http exports (guilds) |
| nonebot/adapters/discord/api/models/http/guild_welcome.py | New http exports (welcome screen) |
| nonebot/adapters/discord/api/models/http/guild_templates.py | New http exports (guild templates) |
| nonebot/adapters/discord/api/models/http/guild_scheduled_events.py | New http exports (scheduled events) |
| nonebot/adapters/discord/api/models/http/guild_members.py | New http exports (guild members) |
| nonebot/adapters/discord/api/models/http/gateway.py | New http exports (gateway response models) |
| nonebot/adapters/discord/api/models/http/emoji.py | New http exports (emoji) |
| nonebot/adapters/discord/api/models/http/channels.py | New http exports (channels) |
| nonebot/adapters/discord/api/models/http/auto_moderation.py | New http exports (auto moderation) |
| nonebot/adapters/discord/api/models/http/audit_log.py | New http exports (audit log) |
| nonebot/adapters/discord/api/models/http/application.py | New http exports (application) |
| nonebot/adapters/discord/api/models/http/init.py | HTTP package exports (aggregated) |
| nonebot/adapters/discord/api/models/gateway/monetization_events.py | New gateway event re-export module (monetization) |
| nonebot/adapters/discord/api/models/gateway/invite_events.py | New gateway event re-export module (invites) |
| nonebot/adapters/discord/api/models/gateway/integration_events.py | New gateway event re-export module (integrations) |
| nonebot/adapters/discord/api/models/gateway/guild_events.py | New gateway event re-export module (guilds) |
| nonebot/adapters/discord/api/models/gateway/gateway_payloads.py | New gateway payload data models (identify/resume/etc.) |
| nonebot/adapters/discord/api/models/gateway/gateway_events.py | Aggregate gateway event payload exports (__all__) |
| nonebot/adapters/discord/api/models/gateway/gateway_event_fields.py | Shared gateway event field models (presence/activity/etc.) |
| nonebot/adapters/discord/api/models/gateway/frame.py | Gateway frame models (opcodes/payload union) updated to new imports |
| nonebot/adapters/discord/api/models/gateway/event/monetization.py | New gateway event models (monetization) |
| nonebot/adapters/discord/api/models/gateway/event/messages.py | Gateway message event payload models split-out |
| nonebot/adapters/discord/api/models/gateway/event/invites.py | New gateway event models (invites) |
| nonebot/adapters/discord/api/models/gateway/event/interactions.py | Gateway interaction event payload models split-out |
| nonebot/adapters/discord/api/models/gateway/event/integrations.py | New gateway event models (integrations) |
| nonebot/adapters/discord/api/models/gateway/event/guilds.py | New gateway event models (guilds) |
| nonebot/adapters/discord/api/models/gateway/event/channels.py | New gateway event models (channels) |
| nonebot/adapters/discord/api/models/gateway/event/auto_moderation.py | New gateway event models (auto moderation) |
| nonebot/adapters/discord/api/models/gateway/event/init.py | Gateway event package marker |
| nonebot/adapters/discord/api/models/gateway/channel_events.py | New gateway event re-export module (channels) |
| nonebot/adapters/discord/api/models/gateway/auto_moderation_events.py | New gateway event re-export module (auto moderation) |
| nonebot/adapters/discord/api/models/gateway/init.py | Gateway package exports (aggregated) |
| nonebot/adapters/discord/api/models/common/webhooks.py | New common models split-out (webhooks) |
| nonebot/adapters/discord/api/models/common/voice.py | New common models split-out (voice) |
| nonebot/adapters/discord/api/models/common/user.py | New common models split-out (user) |
| nonebot/adapters/discord/api/models/common/teams.py | New common models split-out (teams) |
| nonebot/adapters/discord/api/models/common/stickers.py | New common models split-out (stickers) |
| nonebot/adapters/discord/api/models/common/stage_instance.py | New common models split-out (stage instance) |
| nonebot/adapters/discord/api/models/common/soundboard.py | New common models split-out (soundboard) |
| nonebot/adapters/discord/api/models/common/snowflake.py | New common type split-out (Snowflake) |
| nonebot/adapters/discord/api/models/common/polls.py | New common models split-out (polls) |
| nonebot/adapters/discord/api/models/common/permissions.py | New common models split-out (permissions/roles) |
| nonebot/adapters/discord/api/models/common/monetization.py | New common models split-out (monetization) |
| nonebot/adapters/discord/api/models/common/messages.py | New common models split-out (messages) |
| nonebot/adapters/discord/api/models/common/lobby.py | New common models split-out (lobby) |
| nonebot/adapters/discord/api/models/common/invites.py | New common models split-out (invites) |
| nonebot/adapters/discord/api/models/common/interactions.py | New common models split-out (interactions + components) |
| nonebot/adapters/discord/api/models/common/integrations.py | New common models split-out (integrations) |
| nonebot/adapters/discord/api/models/common/guilds.py | New common models split-out (guilds) |
| nonebot/adapters/discord/api/models/common/guild_welcome.py | New common models split-out (welcome screen) |
| nonebot/adapters/discord/api/models/common/guild_templates.py | New common models split-out (guild templates) |
| nonebot/adapters/discord/api/models/common/guild_scheduled_events.py | New common models split-out (scheduled events) |
| nonebot/adapters/discord/api/models/common/guild_members.py | New common models split-out (guild members) |
| nonebot/adapters/discord/api/models/common/emoji.py | New common models split-out (emoji) |
| nonebot/adapters/discord/api/models/common/embeds.py | New common models split-out (embeds) |
| nonebot/adapters/discord/api/models/common/channels.py | New common models split-out (channels/threads) |
| nonebot/adapters/discord/api/models/common/auto_moderation.py | New common models split-out (auto moderation) |
| nonebot/adapters/discord/api/models/common/audit_log.py | New common models split-out (audit log) |
| nonebot/adapters/discord/api/models/common/application.py | New common models split-out (application) |
| nonebot/adapters/discord/api/models/common/init.py | Common package exports (aggregated) |
| nonebot/adapters/discord/api/models/init.py | Facade re-exports + forward-ref rebuild + __all__ |
| nonebot/adapters/discord/api/handle.py | Update handle to import model types from .models |
| nonebot/adapters/discord/api/client.pyi | Regenerated stubs to import from .models |
| nonebot/adapters/discord/api/init.py | Update public API re-exports to source from .models |
| nonebot/adapters/discord/adapter.py | Update gateway frame/model imports to new api.models facade |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| msg = ( | ||
| f"Illegal import in {py_file}: from {node.module} import ... " | ||
| "(common layer should not depend on request/response/gateway/interactions/http)", | ||
| ) | ||
| raise AssertionError(msg) |
There was a problem hiding this comment.
msg is being created as a single-element tuple due to the trailing comma in the assignment. This makes the AssertionError message render as a tuple repr instead of a readable string; remove the trailing comma so msg is a plain str.
| if TYPE_CHECKING: | ||
| from ..common.embeds import Embed | ||
| from ..common.interactions import Component, DirectComponent | ||
| from ..common.messages import MessageReference | ||
| from ..http.polls import PollRequest | ||
|
|
There was a problem hiding this comment.
PollRequest is imported under TYPE_CHECKING from ..http.polls, which introduces an unnecessary cross-layer dependency (and can create type-checker import cycles since http modules themselves depend on request). Import PollRequest from the local request layer (.polls) instead.
| def __init__(self, **data) -> None: # noqa: ANN003 | ||
| super().__init__(**data) | ||
| warnings.warn( | ||
| "InviteStageInstance is deprecated by Discord", | ||
| DeprecationWarning, | ||
| stacklevel=2, | ||
| ) |
There was a problem hiding this comment.
InviteDelete.__init__ currently emits a DeprecationWarning saying "InviteStageInstance is deprecated by Discord" for every InviteDelete payload. This warning appears unrelated to this model (it has no stage_instance field) and will create noisy warnings; remove it or move the deprecation warning to the model/field that is actually deprecated.
| from .client import ApiClient as ApiClient | ||
| from .model import ( | ||
| from .models import ( | ||
| SKU, |
There was a problem hiding this comment.
This refactor switches imports from nonebot.adapters.discord.api.model to nonebot.adapters.discord.api.models, but there is no longer an api/model.py module in the package. If api.model was part of the public import surface (and existing user code relies on it), this is a breaking change; consider adding a small api/model.py compatibility shim (optionally emitting a DeprecationWarning) that re-exports from .models.
| msg = ( | ||
| f"Illegal import in {py_file}: from {node.module} import ... " | ||
| "(gateway layer should not depend on request/response/interactions/http)", | ||
| ) | ||
| raise AssertionError(msg) |
There was a problem hiding this comment.
Same as above: the trailing comma makes msg a single-element tuple instead of a string, so the AssertionError message becomes a tuple repr. Drop the trailing comma so msg is str.
No description provided.