-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathllms-full.txt
More file actions
261 lines (203 loc) · 7.8 KB
/
Copy pathllms-full.txt
File metadata and controls
261 lines (203 loc) · 7.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# azure-functions-validation — Full LLM Reference
> Pydantic-based request/response validation for Azure Functions Python v2.
## Package Info
- PyPI: `pip install azure-functions-validation`
- Version: see package metadata
- Python: >=3.10, <3.15
- License: MIT
- Docs: https://yeongseon.github.io/azure-functions-validation-python/
- Repository: https://github.com/yeongseon/azure-functions-validation-python
- Azure Functions programming model: v2
## Installation
```bash
pip install azure-functions-validation
```
For local development:
```bash
git clone https://github.com/yeongseon/azure-functions-validation-python.git
cd azure-functions-validation-python
pip install -e .[dev]
```
## Public API
### Main Decorator
```python
from azure_functions_validation import validate_http
from pydantic import BaseModel
def validate_http(
*,
body: type[BaseModel] | None = None,
query: type[BaseModel] | None = None,
path: type[BaseModel] | None = None,
headers: type[BaseModel] | None = None,
request_model: type[BaseModel] | None = None,
response_model: Any = None,
adapter: ValidationAdapter | None = None,
error_formatter: ErrorFormatter | None = None,
) -> Callable[[Callable], Callable]:
"""Decorator for validating HTTP request inputs and response outputs.
Args:
body: Pydantic model for request body validation.
query: Pydantic model for query parameter validation.
path: Pydantic model for path parameter validation.
headers: Pydantic model for header validation.
request_model: Shorthand alias for body parameter.
response_model: Pydantic model or TypeAdapter-compatible type for response validation.
adapter: Custom validation adapter (defaults to PydanticAdapter).
error_formatter: Per-handler custom error formatter.
Returns:
A decorator that wraps the handler with validation logic.
"""
```
### Error Classes
```python
from azure_functions_validation import ResponseValidationError, SerializationError
class ResponseValidationError(Exception):
"""Raised when response validation fails.
Attributes:
message: Error message describing the validation failure.
"""
def __init__(self, message: str = "Response validation error"):
pass
class SerializationError(TypeError):
"""Raised when an unsupported type is encountered during serialization.
Attributes:
type_name: Name of the unsupported type.
"""
def __init__(self, type_name: str) -> None:
pass
```
### Error Formatting
```python
from azure_functions_validation import ErrorFormatter
from typing import Any
ErrorFormatter = Callable[[Exception, int], dict[str, Any]]
```
Type alias for custom error formatters. Called with:
- `exception`: The caught validation or serialization exception
- `status_code`: HTTP status code (400, 422, 500, etc.)
Must return a dict representing the error response body (will be JSON-serialized).
## Common Patterns
### Basic Request Body Validation
```python
import azure.functions as func
from pydantic import BaseModel
from azure_functions_validation import validate_http
class UserCreateRequest(BaseModel):
name: str
email: str
app = func.FunctionApp()
@app.route(route="users", methods=["POST"])
@validate_http(body=UserCreateRequest)
def create_user(req: func.HttpRequest, body: UserCreateRequest) -> func.HttpResponse:
# body is already validated UserCreateRequest instance
return func.HttpResponse(f"Created {body.name}", status_code=201)
```
### Query and Path Parameters
```python
from pydantic import BaseModel
class SearchParams(BaseModel):
q: str
limit: int = 10
offset: int = 0
class UserPathParams(BaseModel):
user_id: str
@app.route(route="users/<user_id>")
@validate_http(path=UserPathParams, query=SearchParams)
def get_user(req: func.HttpRequest, path: UserPathParams, query: SearchParams) -> func.HttpResponse:
# path and query are validated instances
return func.HttpResponse(f"User: {path.user_id}, limit: {query.limit}")
```
### Request + Response Validation
```python
class CreateUserResponse(BaseModel):
id: str
name: str
created_at: str
@app.route(route="users", methods=["POST"])
@validate_http(body=UserCreateRequest, response_model=CreateUserResponse)
def create_user(req: func.HttpRequest, body: UserCreateRequest) -> CreateUserResponse:
# Response must match CreateUserResponse schema, or ResponseValidationError is raised
return CreateUserResponse(
id="123",
name=body.name,
created_at="2024-01-01T00:00:00Z"
)
```
### Custom Error Formatting
```python
from azure_functions_validation import ErrorFormatter
def my_error_formatter(exception: Exception, status_code: int) -> dict:
return {
"code": "VALIDATION_ERROR",
"message": str(exception),
"status": status_code,
}
@app.route(route="users", methods=["POST"])
@validate_http(
body=UserCreateRequest,
error_formatter=my_error_formatter
)
def create_user_custom_errors(
req: func.HttpRequest,
body: UserCreateRequest
) -> func.HttpResponse:
return func.HttpResponse(f"Created {body.name}")
```
### Header Validation
```python
from pydantic import BaseModel, ConfigDict, Field
class HeaderParams(BaseModel):
model_config = ConfigDict(populate_by_name=True)
authorization: str = Field(alias="authorization")
x_user_id: str | None = Field(default=None, alias="x-user-id")
@app.route(route="protected")
@validate_http(headers=HeaderParams)
def protected_endpoint(
req: func.HttpRequest,
headers: HeaderParams
) -> func.HttpResponse:
# headers.authorization is validated
return func.HttpResponse("OK")
```
## Design Principles
1. **Decorator-first**: Configuration happens at decoration time, validation at runtime.
2. **Explicit over implicit**: All parameters are explicit in decorator arguments.
3. **Pydantic v2 native**: Leverages Pydantic's validation power and error messages.
4. **Error consistency**: All validation errors return `400` or `422` with `{"detail": [...]}` format.
5. **Response enforcement**: Response models catch contract drift before deployment.
6. **Minimal overhead**: No request processing happens until handler is called.
7. **Azure Functions v2 aligned**: Follows Azure Functions Python v2 programming model conventions.
## Limitations
1. **Request type**: Only works with `azure.functions.HttpRequest`.
2. **Response types**: Supports anything JSON-serializable (BaseModel, dict, list, str, int, bool, None).
3. **Async support**: Both sync and async handlers are supported.
4. **No inheritance validation**: Inherited Pydantic fields work, but validation model itself cannot be inherited in decorator.
5. **File uploads**: Not designed for multipart/form-data or file uploads. Use raw request handling for that.
## Error Response Format
All validation errors return `{"detail": [{"loc": [...], "msg": "...", "type": "..."}]}` format
matching Pydantic ValidationError style. This is consistent across all handlers unless overridden
with a custom `ErrorFormatter`.
Example validation error:
```json
{
"detail": [
{
"loc": ["email"],
"msg": "value is not a valid email address",
"type": "value_error.email"
}
]
}
```
## Type Hints
All public functions and classes are fully type-hinted for IDE support and static analysis.
```python
from typing import Any, Callable
from pydantic import BaseModel
ErrorFormatter: type = Callable[[Exception, int], dict[str, Any]]
```
Supported parameter types in decorator:
- `body`, `query`, `path`, `headers`: Any Pydantic `BaseModel` subclass
- `response_model`: Pydantic `BaseModel` subclass, or any TypeAdapter-compatible type (e.g. `list[Model]`)
- `error_formatter`: Callable matching `ErrorFormatter` signature
- `adapter`: Custom validation adapter implementing `ValidationAdapter` protocol