Coverage for fastapi / openapi / models.py: 100%
272 statements
« prev ^ index » next coverage.py v7.13.3, created at 2026-04-06 01:24 +0000
« prev ^ index » next coverage.py v7.13.3, created at 2026-04-06 01:24 +0000
1from collections.abc import Callable, Iterable, Mapping 1adbc
2from enum import Enum 1adbc
3from typing import Annotated, Any, Literal, Optional, Union 1adbc
5from fastapi._compat import with_info_plain_validator_function 1adbc
6from fastapi.logger import logger 1adbc
7from pydantic import ( 1adbc
8 AnyUrl,
9 BaseModel,
10 Field,
11 GetJsonSchemaHandler,
12)
13from typing_extensions import TypedDict 1adbc
14from typing_extensions import deprecated as typing_deprecated 1adbc
16try: 1adbc
17 import email_validator 1adbc
19 assert email_validator # make autoflake ignore the unused import 1adbc
20 from pydantic import EmailStr 1adbc
21except ImportError: # pragma: no cover
23 class EmailStr(str): # type: ignore
24 @classmethod
25 def __get_validators__(cls) -> Iterable[Callable[..., Any]]:
26 yield cls.validate
28 @classmethod
29 def validate(cls, v: Any) -> str:
30 logger.warning(
31 "email-validator not installed, email fields will be treated as str.\n"
32 "To install, run: pip install email-validator"
33 )
34 return str(v)
36 @classmethod
37 def _validate(cls, __input_value: Any, _: Any) -> str:
38 logger.warning(
39 "email-validator not installed, email fields will be treated as str.\n"
40 "To install, run: pip install email-validator"
41 )
42 return str(__input_value)
44 @classmethod
45 def __get_pydantic_json_schema__(
46 cls, core_schema: Mapping[str, Any], handler: GetJsonSchemaHandler
47 ) -> dict[str, Any]:
48 return {"type": "string", "format": "email"}
50 @classmethod
51 def __get_pydantic_core_schema__(
52 cls, source: type[Any], handler: Callable[[Any], Mapping[str, Any]]
53 ) -> Mapping[str, Any]:
54 return with_info_plain_validator_function(cls._validate)
57class BaseModelWithConfig(BaseModel): 1adbc
58 model_config = {"extra": "allow"} 1adbc
61class Contact(BaseModelWithConfig): 1adbc
62 name: str | None = None 1adbc
63 url: AnyUrl | None = None 1adbc
64 email: EmailStr | None = None 1adbc
67class License(BaseModelWithConfig): 1adbc
68 name: str 1abc
69 identifier: str | None = None 1adbc
70 url: AnyUrl | None = None 1adbc
73class Info(BaseModelWithConfig): 1adbc
74 title: str 1abc
75 summary: str | None = None 1adbc
76 description: str | None = None 1adbc
77 termsOfService: str | None = None 1adbc
78 contact: Contact | None = None 1adbc
79 license: License | None = None 1adbc
80 version: str 1abc
83class ServerVariable(BaseModelWithConfig): 1adbc
84 enum: Annotated[list[str] | None, Field(min_length=1)] = None 1adbc
85 default: str 1abc
86 description: str | None = None 1adbc
89class Server(BaseModelWithConfig): 1adbc
90 url: AnyUrl | str 1abc
91 description: str | None = None 1adbc
92 variables: dict[str, ServerVariable] | None = None 1adbc
95class Reference(BaseModel): 1adbc
96 ref: str = Field(alias="$ref") 1adbc
99class Discriminator(BaseModel): 1adbc
100 propertyName: str 1abc
101 mapping: dict[str, str] | None = None 1adbc
104class XML(BaseModelWithConfig): 1adbc
105 name: str | None = None 1adbc
106 namespace: str | None = None 1adbc
107 prefix: str | None = None 1adbc
108 attribute: bool | None = None 1adbc
109 wrapped: bool | None = None 1adbc
112class ExternalDocumentation(BaseModelWithConfig): 1adbc
113 description: str | None = None 1adbc
114 url: AnyUrl 1abc
117# Ref JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation#name-type
118SchemaType = Literal[ 1adbc
119 "array", "boolean", "integer", "null", "number", "object", "string"
120]
123class Schema(BaseModelWithConfig): 1adbc
124 # Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-the-json-schema-core-vocabu
125 # Core Vocabulary
126 schema_: str | None = Field(default=None, alias="$schema") 1adbc
127 vocabulary: str | None = Field(default=None, alias="$vocabulary") 1adbc
128 id: str | None = Field(default=None, alias="$id") 1adbc
129 anchor: str | None = Field(default=None, alias="$anchor") 1adbc
130 dynamicAnchor: str | None = Field(default=None, alias="$dynamicAnchor") 1adbc
131 ref: str | None = Field(default=None, alias="$ref") 1adbc
132 dynamicRef: str | None = Field(default=None, alias="$dynamicRef") 1adbc
133 defs: dict[str, "SchemaOrBool"] | None = Field(default=None, alias="$defs") 1adbc
134 comment: str | None = Field(default=None, alias="$comment") 1adbc
135 # Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-a-vocabulary-for-applying-s
136 # A Vocabulary for Applying Subschemas
137 allOf: list["SchemaOrBool"] | None = None 1adbc
138 anyOf: list["SchemaOrBool"] | None = None 1adbc
139 oneOf: list["SchemaOrBool"] | None = None 1adbc
140 not_: Optional["SchemaOrBool"] = Field(default=None, alias="not") 1adbc
141 if_: Optional["SchemaOrBool"] = Field(default=None, alias="if") 1adbc
142 then: Optional["SchemaOrBool"] = None 1adbc
143 else_: Optional["SchemaOrBool"] = Field(default=None, alias="else") 1adbc
144 dependentSchemas: dict[str, "SchemaOrBool"] | None = None 1adbc
145 prefixItems: list["SchemaOrBool"] | None = None 1adbc
146 items: Optional["SchemaOrBool"] = None 1adbc
147 contains: Optional["SchemaOrBool"] = None 1adbc
148 properties: dict[str, "SchemaOrBool"] | None = None 1adbc
149 patternProperties: dict[str, "SchemaOrBool"] | None = None 1adbc
150 additionalProperties: Optional["SchemaOrBool"] = None 1adbc
151 propertyNames: Optional["SchemaOrBool"] = None 1adbc
152 unevaluatedItems: Optional["SchemaOrBool"] = None 1adbc
153 unevaluatedProperties: Optional["SchemaOrBool"] = None 1adbc
154 # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-structural
155 # A Vocabulary for Structural Validation
156 type: SchemaType | list[SchemaType] | None = None 1adbc
157 enum: list[Any] | None = None 1adbc
158 const: Any | None = None 1adbc
159 multipleOf: float | None = Field(default=None, gt=0) 1adbc
160 maximum: float | None = None 1adbc
161 exclusiveMaximum: float | None = None 1adbc
162 minimum: float | None = None 1adbc
163 exclusiveMinimum: float | None = None 1adbc
164 maxLength: int | None = Field(default=None, ge=0) 1adbc
165 minLength: int | None = Field(default=None, ge=0) 1adbc
166 pattern: str | None = None 1adbc
167 maxItems: int | None = Field(default=None, ge=0) 1adbc
168 minItems: int | None = Field(default=None, ge=0) 1adbc
169 uniqueItems: bool | None = None 1adbc
170 maxContains: int | None = Field(default=None, ge=0) 1adbc
171 minContains: int | None = Field(default=None, ge=0) 1adbc
172 maxProperties: int | None = Field(default=None, ge=0) 1adbc
173 minProperties: int | None = Field(default=None, ge=0) 1adbc
174 required: list[str] | None = None 1adbc
175 dependentRequired: dict[str, set[str]] | None = None 1adbc
176 # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-vocabularies-for-semantic-c
177 # Vocabularies for Semantic Content With "format"
178 format: str | None = None 1adbc
179 # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-the-conten
180 # A Vocabulary for the Contents of String-Encoded Data
181 contentEncoding: str | None = None 1adbc
182 contentMediaType: str | None = None 1adbc
183 contentSchema: Optional["SchemaOrBool"] = None 1adbc
184 # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-basic-meta
185 # A Vocabulary for Basic Meta-Data Annotations
186 title: str | None = None 1adbc
187 description: str | None = None 1adbc
188 default: Any | None = None 1adbc
189 deprecated: bool | None = None 1adbc
190 readOnly: bool | None = None 1adbc
191 writeOnly: bool | None = None 1adbc
192 examples: list[Any] | None = None 1adbc
193 # Ref: OpenAPI 3.1.0: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#schema-object
194 # Schema Object
195 discriminator: Discriminator | None = None 1adbc
196 xml: XML | None = None 1adbc
197 externalDocs: ExternalDocumentation | None = None 1adbc
198 example: Annotated[ 1adbc
199 Any | None,
200 typing_deprecated(
201 "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, "
202 "although still supported. Use examples instead."
203 ),
204 ] = None
207# Ref: https://json-schema.org/draft/2020-12/json-schema-core.html#name-json-schema-documents
208# A JSON Schema MUST be an object or a boolean.
209SchemaOrBool = Schema | bool 1adbc
212class Example(TypedDict, total=False): 1adbc
213 summary: str | None 1abc
214 description: str | None 1abc
215 value: Any | None 1abc
216 externalValue: AnyUrl | None 1abc
218 __pydantic_config__ = {"extra": "allow"} # type: ignore[misc] 1adbc
221class ParameterInType(Enum): 1adbc
222 query = "query" 1adbc
223 header = "header" 1adbc
224 path = "path" 1adbc
225 cookie = "cookie" 1adbc
228class Encoding(BaseModelWithConfig): 1adbc
229 contentType: str | None = None 1adbc
230 headers: dict[str, Union["Header", Reference]] | None = None 1adbc
231 style: str | None = None 1adbc
232 explode: bool | None = None 1adbc
233 allowReserved: bool | None = None 1adbc
236class MediaType(BaseModelWithConfig): 1adbc
237 schema_: Schema | Reference | None = Field(default=None, alias="schema") 1adbc
238 example: Any | None = None 1adbc
239 examples: dict[str, Example | Reference] | None = None 1adbc
240 encoding: dict[str, Encoding] | None = None 1adbc
243class ParameterBase(BaseModelWithConfig): 1adbc
244 description: str | None = None 1adbc
245 required: bool | None = None 1adbc
246 deprecated: bool | None = None 1adbc
247 # Serialization rules for simple scenarios
248 style: str | None = None 1adbc
249 explode: bool | None = None 1adbc
250 allowReserved: bool | None = None 1adbc
251 schema_: Schema | Reference | None = Field(default=None, alias="schema") 1adbc
252 example: Any | None = None 1adbc
253 examples: dict[str, Example | Reference] | None = None 1adbc
254 # Serialization rules for more complex scenarios
255 content: dict[str, MediaType] | None = None 1adbc
258class Parameter(ParameterBase): 1adbc
259 name: str 1abc
260 in_: ParameterInType = Field(alias="in") 1adbc
263class Header(ParameterBase): 1adbc
264 pass 1adbc
267class RequestBody(BaseModelWithConfig): 1adbc
268 description: str | None = None 1adbc
269 content: dict[str, MediaType] 1abc
270 required: bool | None = None 1adbc
273class Link(BaseModelWithConfig): 1adbc
274 operationRef: str | None = None 1adbc
275 operationId: str | None = None 1adbc
276 parameters: dict[str, Any | str] | None = None 1adbc
277 requestBody: Any | str | None = None 1adbc
278 description: str | None = None 1adbc
279 server: Server | None = None 1adbc
282class Response(BaseModelWithConfig): 1adbc
283 description: str 1abc
284 headers: dict[str, Header | Reference] | None = None 1adbc
285 content: dict[str, MediaType] | None = None 1adbc
286 links: dict[str, Link | Reference] | None = None 1adbc
289class Operation(BaseModelWithConfig): 1adbc
290 tags: list[str] | None = None 1adbc
291 summary: str | None = None 1adbc
292 description: str | None = None 1adbc
293 externalDocs: ExternalDocumentation | None = None 1adbc
294 operationId: str | None = None 1adbc
295 parameters: list[Parameter | Reference] | None = None 1adbc
296 requestBody: RequestBody | Reference | None = None 1adbc
297 # Using Any for Specification Extensions
298 responses: dict[str, Response | Any] | None = None 1adbc
299 callbacks: dict[str, dict[str, "PathItem"] | Reference] | None = None 1adbc
300 deprecated: bool | None = None 1adbc
301 security: list[dict[str, list[str]]] | None = None 1adbc
302 servers: list[Server] | None = None 1adbc
305class PathItem(BaseModelWithConfig): 1adbc
306 ref: str | None = Field(default=None, alias="$ref") 1adbc
307 summary: str | None = None 1adbc
308 description: str | None = None 1adbc
309 get: Operation | None = None 1adbc
310 put: Operation | None = None 1adbc
311 post: Operation | None = None 1adbc
312 delete: Operation | None = None 1adbc
313 options: Operation | None = None 1adbc
314 head: Operation | None = None 1adbc
315 patch: Operation | None = None 1adbc
316 trace: Operation | None = None 1adbc
317 servers: list[Server] | None = None 1adbc
318 parameters: list[Parameter | Reference] | None = None 1adbc
321class SecuritySchemeType(Enum): 1adbc
322 apiKey = "apiKey" 1adbc
323 http = "http" 1adbc
324 oauth2 = "oauth2" 1adbc
325 openIdConnect = "openIdConnect" 1adbc
328class SecurityBase(BaseModelWithConfig): 1adbc
329 type_: SecuritySchemeType = Field(alias="type") 1adbc
330 description: str | None = None 1adbc
333class APIKeyIn(Enum): 1adbc
334 query = "query" 1adbc
335 header = "header" 1adbc
336 cookie = "cookie" 1adbc
339class APIKey(SecurityBase): 1adbc
340 type_: SecuritySchemeType = Field(default=SecuritySchemeType.apiKey, alias="type") 1adbc
341 in_: APIKeyIn = Field(alias="in") 1adbc
342 name: str 1abc
345class HTTPBase(SecurityBase): 1adbc
346 type_: SecuritySchemeType = Field(default=SecuritySchemeType.http, alias="type") 1adbc
347 scheme: str 1abc
350class HTTPBearer(HTTPBase): 1adbc
351 scheme: Literal["bearer"] = "bearer" 1adbc
352 bearerFormat: str | None = None 1adbc
355class OAuthFlow(BaseModelWithConfig): 1adbc
356 refreshUrl: str | None = None 1adbc
357 scopes: dict[str, str] = {} 1adbc
360class OAuthFlowImplicit(OAuthFlow): 1adbc
361 authorizationUrl: str 1abc
364class OAuthFlowPassword(OAuthFlow): 1adbc
365 tokenUrl: str 1abc
368class OAuthFlowClientCredentials(OAuthFlow): 1adbc
369 tokenUrl: str 1abc
372class OAuthFlowAuthorizationCode(OAuthFlow): 1adbc
373 authorizationUrl: str 1abc
374 tokenUrl: str 1abc
377class OAuthFlows(BaseModelWithConfig): 1adbc
378 implicit: OAuthFlowImplicit | None = None 1adbc
379 password: OAuthFlowPassword | None = None 1adbc
380 clientCredentials: OAuthFlowClientCredentials | None = None 1adbc
381 authorizationCode: OAuthFlowAuthorizationCode | None = None 1adbc
384class OAuth2(SecurityBase): 1adbc
385 type_: SecuritySchemeType = Field(default=SecuritySchemeType.oauth2, alias="type") 1adbc
386 flows: OAuthFlows 1abc
389class OpenIdConnect(SecurityBase): 1adbc
390 type_: SecuritySchemeType = Field( 1adbc
391 default=SecuritySchemeType.openIdConnect, alias="type"
392 )
393 openIdConnectUrl: str 1abc
396SecurityScheme = APIKey | HTTPBase | OAuth2 | OpenIdConnect | HTTPBearer 1adbc
399class Components(BaseModelWithConfig): 1adbc
400 schemas: dict[str, Schema | Reference] | None = None 1adbc
401 responses: dict[str, Response | Reference] | None = None 1adbc
402 parameters: dict[str, Parameter | Reference] | None = None 1adbc
403 examples: dict[str, Example | Reference] | None = None 1adbc
404 requestBodies: dict[str, RequestBody | Reference] | None = None 1adbc
405 headers: dict[str, Header | Reference] | None = None 1adbc
406 securitySchemes: dict[str, SecurityScheme | Reference] | None = None 1adbc
407 links: dict[str, Link | Reference] | None = None 1adbc
408 # Using Any for Specification Extensions
409 callbacks: dict[str, dict[str, PathItem] | Reference | Any] | None = None 1adbc
410 pathItems: dict[str, PathItem | Reference] | None = None 1adbc
413class Tag(BaseModelWithConfig): 1adbc
414 name: str 1abc
415 description: str | None = None 1adbc
416 externalDocs: ExternalDocumentation | None = None 1adbc
419class OpenAPI(BaseModelWithConfig): 1adbc
420 openapi: str 1abc
421 info: Info 1abc
422 jsonSchemaDialect: str | None = None 1adbc
423 servers: list[Server] | None = None 1adbc
424 # Using Any for Specification Extensions
425 paths: dict[str, PathItem | Any] | None = None 1adbc
426 webhooks: dict[str, PathItem | Reference] | None = None 1adbc
427 components: Components | None = None 1adbc
428 security: list[dict[str, list[str]]] | None = None 1adbc
429 tags: list[Tag] | None = None 1adbc
430 externalDocs: ExternalDocumentation | None = None 1adbc
433Schema.model_rebuild() 1adbc
434Operation.model_rebuild() 1adbc
435Encoding.model_rebuild() 1adbc