Skip to content

Commit ff0238e

Browse files
committed
Some more Pydantic warnings fixed
Signed-off-by: Madhav Kandukuri <[email protected]>
1 parent b89fbf4 commit ff0238e

File tree

1 file changed

+48
-33
lines changed

1 file changed

+48
-33
lines changed

mcpgateway/schemas.py

Lines changed: 48 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@
4040
BaseModel,
4141
Field,
4242
model_validator,
43-
root_validator,
44-
validator,
4543
ConfigDict,
46-
field_serializer
44+
field_serializer,
45+
field_validator,
46+
ValidationInfo
4747
)
4848

4949
logger = logging.getLogger(__name__)
@@ -284,7 +284,7 @@ class ToolCreate(BaseModelWithConfigDict):
284284
auth: Optional[AuthenticationValues] = Field(None, description="Authentication credentials (Basic or Bearer Token or custom headers) if required")
285285
gateway_id: Optional[str] = Field(None, description="id of gateway for the tool")
286286

287-
@root_validator(pre=True)
287+
@model_validator(mode="before")
288288
def assemble_auth(cls, values: Dict[str, Any]) -> Dict[str, Any]:
289289
"""
290290
Assemble authentication information from separate keys if provided.
@@ -343,7 +343,7 @@ class ToolUpdate(BaseModelWithConfigDict):
343343
auth: Optional[AuthenticationValues] = Field(None, description="Authentication credentials (Basic or Bearer Token or custom headers) if required")
344344
gateway_id: Optional[str] = Field(None, description="id of gateway for the tool")
345345

346-
@root_validator(pre=True)
346+
@model_validator(mode="before")
347347
def assemble_auth(cls, values: Dict[str, Any]) -> Dict[str, Any]:
348348
"""
349349
Assemble authentication information from separate keys if provided.
@@ -546,9 +546,21 @@ class PromptArgument(BaseModelWithConfigDict):
546546
description: Optional[str] = Field(None, description="Argument description")
547547
required: bool = Field(default=False, description="Whether argument is required")
548548

549+
549550
model_config: ConfigDict = ConfigDict(
550-
**BaseModelWithConfigDict.model_config, # carry over the base settings
551-
schema_extra = {"example": {"name": "language", "description": "Programming language", "required": True}}
551+
**{
552+
# start with every key from the base
553+
**BaseModelWithConfigDict.model_config,
554+
# override only json_schema_extra by merging the two dicts:
555+
"json_schema_extra": {
556+
**BaseModelWithConfigDict.model_config.get("json_schema_extra", {}),
557+
"example": {
558+
"name": "language",
559+
"description": "Programming language",
560+
"required": True,
561+
},
562+
},
563+
}
552564
)
553565

554566

@@ -641,9 +653,9 @@ class GatewayCreate(BaseModelWithConfigDict):
641653
auth_header_value: Optional[str] = Field(None, description="Value for custom headers authentication")
642654

643655
# Adding `auth_value` as an alias for better access post-validation
644-
auth_value: Optional[str] = None
656+
auth_value: Optional[str] = Field(None, validate_default=True)
645657

646-
@validator("url", pre=True)
658+
@field_validator("url", mode="before")
647659
def ensure_url_scheme(cls, v: str) -> str:
648660
"""
649661
Ensure URL has an http/https scheme.
@@ -659,31 +671,32 @@ def ensure_url_scheme(cls, v: str) -> str:
659671
return f"http://{v}"
660672
return v
661673

662-
@validator("auth_value", pre=True, always=True)
663-
def create_auth_value(cls, v, values):
674+
@field_validator("auth_value", mode="before")
675+
def create_auth_value(cls, v, info):
664676
"""
665-
This validator will run before the model is fully instantiated (pre=True)
677+
This validator will run before the model is fully instantiated (mode="before")
666678
It will process the auth fields based on auth_type and generate auth_value.
667679
668680
Args:
669681
v: Input url
670-
values: Dict containing auth_type
682+
info: ValidationInfo containing auth_type
671683
672684
Returns:
673685
str: Auth value
674686
"""
675-
auth_type = values.get("auth_type")
687+
data = info.data
688+
auth_type = data.get("auth_type")
676689

677690
if (auth_type is None) or (auth_type == ""):
678691
return v # If no auth_type is provided, no need to create auth_value
679692

680693
# Process the auth fields and generate auth_value based on auth_type
681-
auth_value = cls._process_auth_fields(values)
694+
auth_value = cls._process_auth_fields(info)
682695

683696
return auth_value
684697

685698
@staticmethod
686-
def _process_auth_fields(values: Dict[str, Any]) -> Optional[Dict[str, Any]]:
699+
def _process_auth_fields(info: ValidationInfo) -> Optional[Dict[str, Any]]:
687700
"""
688701
Processes the input authentication fields and returns the correct auth_value.
689702
This method is called based on the selected auth_type.
@@ -697,12 +710,13 @@ def _process_auth_fields(values: Dict[str, Any]) -> Optional[Dict[str, Any]]:
697710
Raises:
698711
ValueError: If auth_type is invalid
699712
"""
700-
auth_type = values.get("auth_type")
713+
data = info.data
714+
auth_type = data.get("auth_type")
701715

702716
if auth_type == "basic":
703717
# For basic authentication, both username and password must be present
704-
username = values.get("auth_username")
705-
password = values.get("auth_password")
718+
username = data.get("auth_username")
719+
password = data.get("auth_password")
706720

707721
if not username or not password:
708722
raise ValueError("For 'basic' auth, both 'auth_username' and 'auth_password' must be provided.")
@@ -712,7 +726,7 @@ def _process_auth_fields(values: Dict[str, Any]) -> Optional[Dict[str, Any]]:
712726

713727
if auth_type == "bearer":
714728
# For bearer authentication, only token is required
715-
token = values.get("auth_token")
729+
token = data.get("auth_token")
716730

717731
if not token:
718732
raise ValueError("For 'bearer' auth, 'auth_token' must be provided.")
@@ -721,8 +735,8 @@ def _process_auth_fields(values: Dict[str, Any]) -> Optional[Dict[str, Any]]:
721735

722736
if auth_type == "authheaders":
723737
# For headers authentication, both key and value must be present
724-
header_key = values.get("auth_header_key")
725-
header_value = values.get("auth_header_value")
738+
header_key = data.get("auth_header_key")
739+
header_value = data.get("auth_header_value")
726740

727741
if not header_key or not header_value:
728742
raise ValueError("For 'headers' auth, both 'auth_header_key' and 'auth_header_value' must be provided.")
@@ -753,9 +767,9 @@ class GatewayUpdate(BaseModelWithConfigDict):
753767
auth_header_value: Optional[str] = Field(None, description="vallue for custom headers authentication")
754768

755769
# Adding `auth_value` as an alias for better access post-validation
756-
auth_value: Optional[str] = None
770+
auth_value: Optional[str] = Field(None, validate_default=True)
757771

758-
@validator("url", pre=True)
772+
@field_validator("url", mode="before")
759773
def ensure_url_scheme(cls, v: Optional[str]) -> Optional[str]:
760774
"""
761775
Ensure URL has an http/https scheme.
@@ -770,10 +784,10 @@ def ensure_url_scheme(cls, v: Optional[str]) -> Optional[str]:
770784
return f"http://{v}"
771785
return v
772786

773-
@validator("auth_value", pre=True, always=True)
774-
def create_auth_value(cls, v, values):
787+
@field_validator("auth_value", mode="before")
788+
def create_auth_value(cls, v, info):
775789
"""
776-
This validator will run before the model is fully instantiated (pre=True)
790+
This validator will run before the model is fully instantiated (mode="before")
777791
It will process the auth fields based on auth_type and generate auth_value.
778792
779793
Args:
@@ -783,13 +797,14 @@ def create_auth_value(cls, v, values):
783797
Returns:
784798
str: Auth value or URL
785799
"""
786-
auth_type = values.get("auth_type")
800+
data = info.data
801+
auth_type = data.get("auth_type")
787802

788803
if (auth_type is None) or (auth_type == ""):
789804
return v # If no auth_type is provided, no need to create auth_value
790805

791806
# Process the auth fields and generate auth_value based on auth_type
792-
auth_value = cls._process_auth_fields(values)
807+
auth_value = cls._process_auth_fields(info)
793808

794809
return auth_value
795810

@@ -1029,7 +1044,7 @@ class AdminToolCreate(BaseModelWithConfigDict):
10291044
headers: Optional[str] = None # JSON string
10301045
input_schema: Optional[str] = None # JSON string
10311046

1032-
@validator("headers", "input_schema")
1047+
@field_validator("headers", "input_schema")
10331048
def validate_json(cls, v: Optional[str]) -> Optional[Dict[str, Any]]:
10341049
"""
10351050
Validate and parse JSON string inputs.
@@ -1114,7 +1129,7 @@ class ServerCreate(BaseModelWithConfigDict):
11141129
associated_resources: Optional[List[str]] = Field(None, description="Comma-separated resource IDs")
11151130
associated_prompts: Optional[List[str]] = Field(None, description="Comma-separated prompt IDs")
11161131

1117-
@validator("associated_tools", "associated_resources", "associated_prompts", pre=True)
1132+
@field_validator("associated_tools", "associated_resources", "associated_prompts", mode="before")
11181133
def split_comma_separated(cls, v):
11191134
"""
11201135
Splits a comma-separated string into a list of strings if needed.
@@ -1143,7 +1158,7 @@ class ServerUpdate(BaseModelWithConfigDict):
11431158
associated_resources: Optional[List[str]] = Field(None, description="Comma-separated resource IDs")
11441159
associated_prompts: Optional[List[str]] = Field(None, description="Comma-separated prompt IDs")
11451160

1146-
@validator("associated_tools", "associated_resources", "associated_prompts", pre=True)
1161+
@field_validator("associated_tools", "associated_resources", "associated_prompts", mode="before")
11471162
def split_comma_separated(cls, v):
11481163
"""
11491164
Splits a comma-separated string into a list of strings if needed.
@@ -1182,7 +1197,7 @@ class ServerRead(BaseModelWithConfigDict):
11821197
associated_prompts: List[int] = []
11831198
metrics: ServerMetrics
11841199

1185-
@root_validator(pre=True)
1200+
@model_validator(mode="before")
11861201
def populate_associated_ids(cls, values):
11871202
"""
11881203
Pre-validation method that converts associated objects to their 'id'.

0 commit comments

Comments
 (0)