Skip to content

Commit 65b3393

Browse files
committed
Enforce extra=forbid in pydantic models
1 parent 4fdf98d commit 65b3393

4 files changed

Lines changed: 25 additions & 8 deletions

File tree

discord_guild_config.schema.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"$defs": {
33
"Category": {
4+
"additionalProperties": false,
45
"properties": {
56
"name": {
67
"title": "Name",
@@ -47,6 +48,7 @@
4748
"type": "object"
4849
},
4950
"ForumChannel": {
51+
"additionalProperties": false,
5052
"properties": {
5153
"type": {
5254
"const": "forum",
@@ -90,6 +92,7 @@
9092
"type": "object"
9193
},
9294
"PermissionOverwrite": {
95+
"additionalProperties": false,
9396
"properties": {
9497
"roles": {
9598
"items": {
@@ -236,6 +239,7 @@
236239
"type": "object"
237240
},
238241
"Role": {
242+
"additionalProperties": false,
239243
"properties": {
240244
"name": {
241245
"title": "Name",
@@ -330,6 +334,7 @@
330334
"type": "object"
331335
},
332336
"TextChannel": {
337+
"additionalProperties": false,
333338
"properties": {
334339
"type": {
335340
"const": "text",
@@ -368,6 +373,7 @@
368373
"type": "object"
369374
},
370375
"VoiceChannel": {
376+
"additionalProperties": false,
371377
"properties": {
372378
"type": {
373379
"const": "voice",
@@ -394,6 +400,7 @@
394400
"type": "object"
395401
}
396402
},
403+
"additionalProperties": false,
397404
"properties": {
398405
"roles": {
399406
"items": {

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,6 @@ fixable = [
7777

7878
[tool.ruff.lint.pydocstyle]
7979
convention = "pep257"
80+
81+
[tool.ruff.lint.flake8-tidy-imports.banned-api]
82+
"pydantic.BaseModel" = { msg = "Use the custom StrictBaseModel instead" }
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from pydantic import BaseModel, ConfigDict # noqa: TID251 (plain BaseModel)
2+
3+
4+
class StrictBaseModel(BaseModel):
5+
model_config = ConfigDict(extra="forbid")

src/discord_guild_configurator/models.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import textwrap
55
from typing import Annotated, Literal, Self
66

7-
from pydantic import AfterValidator, BaseModel, Field, model_validator
7+
from pydantic import AfterValidator, Field, model_validator
8+
9+
from discord_guild_configurator._utils import StrictBaseModel
810

911
MultilineString = Annotated[
1012
str,
@@ -71,13 +73,13 @@
7173
]
7274

7375

74-
class PermissionOverwrite(BaseModel):
76+
class PermissionOverwrite(StrictBaseModel):
7577
roles: list[str]
7678
allow: list[Permission] = Field(default_factory=list)
7779
deny: list[Permission] = Field(default_factory=list)
7880

7981

80-
class ForumChannel(BaseModel):
82+
class ForumChannel(StrictBaseModel):
8183
type: Literal["forum"] = "forum"
8284

8385
name: str
@@ -88,7 +90,7 @@ class ForumChannel(BaseModel):
8890
require_tag: bool = False
8991

9092

91-
class TextChannel(BaseModel):
93+
class TextChannel(StrictBaseModel):
9294
type: Literal["text"] = "text"
9395

9496
name: str
@@ -98,30 +100,30 @@ class TextChannel(BaseModel):
98100
channel_messages: list[MultilineString] = Field(default_factory=list)
99101

100102

101-
class VoiceChannel(BaseModel):
103+
class VoiceChannel(StrictBaseModel):
102104
type: Literal["voice"] = "voice"
103105

104106
name: str
105107
permission_overwrites: list[PermissionOverwrite] = Field(default_factory=list)
106108

107109

108-
class Category(BaseModel):
110+
class Category(StrictBaseModel):
109111
name: str
110112
channels: list[
111113
Annotated[TextChannel | ForumChannel | VoiceChannel, Field(discriminator="type")]
112114
]
113115
permission_overwrites: list[PermissionOverwrite] = Field(default_factory=list)
114116

115117

116-
class Role(BaseModel):
118+
class Role(StrictBaseModel):
117119
name: str
118120
color: str = Field(pattern=re.compile("^#[0-9A-F]{6}$"))
119121
hoist: bool = False
120122
mentionable: bool = False
121123
permissions: list[Permission] = Field(default_factory=list)
122124

123125

124-
class GuildConfig(BaseModel):
126+
class GuildConfig(StrictBaseModel):
125127
roles: list[Role]
126128
rules_channel_name: str
127129
system_channel_name: str

0 commit comments

Comments
 (0)