···
1
+
from typing import Any
2
+
from pydantic import field_validator
3
+
from ..base import DataModel
5
+
class ArrayModel(DataModel):
7
+
Model for AT Protocol array type.
9
+
Represents an array of elements with support for item schema definition,
10
+
minimum/maximum length constraints as specified in Lexicon.
14
+
"""Schema definition for array elements"""
16
+
minLength: int | None = None
17
+
"""Minimum number of elements"""
19
+
maxLength: int | None = None
20
+
"""Maximum number of elements"""
25
+
def __init__(self, **data: Any) -> None:
27
+
Initialize array model with validation.
30
+
**data: Input data containing array values
33
+
ValueError: If array violates constraints
35
+
super().__init__(**data)
37
+
@field_validator("value", mode="before")
38
+
def validate_array(cls, v: Any) -> list[Any]:
40
+
Validate array structure and elements.
43
+
v: Value to validate
49
+
ValueError: If array violates constraints
51
+
if not isinstance(v, list):
52
+
raise ValueError("Value must be an array")
54
+
# Validate length constraints
55
+
if cls.minLength is not None and len(v) < cls.minLength:
56
+
raise ValueError(f"Array must have at least {cls.minLength} items")
58
+
if cls.maxLength is not None and len(v) > cls.maxLength:
59
+
raise ValueError(f"Array must have at most {cls.maxLength} items")
63
+
class ObjectModel(DataModel):
65
+
Model for AT Protocol object type.
67
+
Represents a generic object schema with properties definitions,
68
+
required fields and nullable fields as specified in Lexicon.
71
+
properties: dict[str, Any]
72
+
"""Map of property names to their schema definitions"""
74
+
required: list[str] | None = None
75
+
"""List of required property names"""
77
+
nullable: list[str] | None = None
78
+
"""List of properties that can be null"""
80
+
value: dict[str, Any]
81
+
"""Object property values"""
83
+
def __init__(self, **data: Any) -> None:
85
+
Initialize object model with validation.
88
+
**data: Input data containing object properties
91
+
ValueError: If object violates constraints
93
+
super().__init__(**data)
95
+
@field_validator("value", mode="before")
96
+
def validate_object(cls, v: Any) -> dict[str, Any]:
98
+
Validate object structure and properties.
101
+
v: Value to validate
107
+
ValueError: If object violates constraints
109
+
if not isinstance(v, dict):
110
+
raise ValueError("Value must be an object")
112
+
# Validate required fields
114
+
for field in cls.required:
116
+
raise ValueError(f"Missing required field: {field}")
118
+
# Validate nullable fields
120
+
for field, value in v.items():
121
+
if field not in cls.nullable and value is None:
122
+
raise ValueError(f"Field {field} cannot be null")
126
+
class ParamsModel(DataModel):
128
+
Model for AT Protocol params type.
130
+
Specialized for HTTP query parameters with support for boolean,
131
+
integer, string and unknown types as specified in Lexicon.
134
+
required: list[str] | None = None
135
+
"""List of required parameter names"""
137
+
properties: dict[str, Any]
138
+
"""Map of parameter names to their schema definitions"""
140
+
value: dict[str, Any]
141
+
"""Parameter values
147
+
- array (of boolean/integer/string/unknown)
151
+
def __init__(self, **data: Any) -> None:
153
+
Initialize params model with validation.
156
+
**data: Input data containing parameter values
159
+
ValueError: If parameters violate constraints
161
+
super().__init__(**data)
163
+
@field_validator("value", mode="before")
164
+
def validate_params(cls, v: Any) -> dict[str, Any]:
166
+
Validate parameters structure and values.
169
+
v: Value to validate
172
+
Validated parameters
175
+
ValueError: If parameters violate constraints
177
+
if not isinstance(v, dict):
178
+
raise ValueError("Value must be a dictionary of parameters")
180
+
# Validate required parameters
182
+
for param in cls.required:
184
+
raise ValueError(f"Missing required parameter: {param}")
186
+
# Validate parameter types
187
+
for param, value in v.items():
188
+
if param in cls.properties:
189
+
prop_type = cls.properties[param].get("type")
190
+
if prop_type == "boolean" and not isinstance(value, bool):
191
+
raise ValueError(f"Parameter {param} must be boolean")
192
+
elif prop_type == "integer" and not isinstance(value, int):
193
+
raise ValueError(f"Parameter {param} must be integer")
194
+
elif prop_type == "string" and not isinstance(value, str):
195
+
raise ValueError(f"Parameter {param} must be string")
196
+
elif prop_type == "array":
197
+
if not isinstance(value, list):
198
+
raise ValueError(f"Parameter {param} must be array")
199
+
# Validate array items if schema is specified
200
+
if "items" in cls.properties[param]:
201
+
item_type = cls.properties[param]["items"].get("type")
203
+
if item_type == "boolean" and not isinstance(item, bool):
204
+
raise ValueError(f"Array item in {param} must be boolean")
205
+
elif item_type == "integer" and not isinstance(item, int):
206
+
raise ValueError(f"Array item in {param} must be integer")
207
+
elif item_type == "string" and not isinstance(item, str):
208
+
raise ValueError(f"Array item in {param} must be string")
209
+
elif item_type == "unknown" and not isinstance(item, dict):
210
+
raise ValueError(f"Array item in {param} must be object")
211
+
elif prop_type == "unknown" and not isinstance(value, dict):
212
+
raise ValueError(f"Parameter {param} must be object")