Coverage for fastapi/openapi/models.py: 100%
276 statements
« prev ^ index » next coverage.py v7.6.1, created at 2025-05-05 00:03 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2025-05-05 00:03 +0000
1from enum import Enum 1abcdef
2from typing import Any, Callable, Dict, Iterable, List, Optional, Set, Type, Union 1abcdef
4from fastapi._compat import ( 1abcdef
5 PYDANTIC_V2,
6 CoreSchema,
7 GetJsonSchemaHandler,
8 JsonSchemaValue,
9 _model_rebuild,
10 with_info_plain_validator_function,
11)
12from fastapi.logger import logger 1abcdef
13from pydantic import AnyUrl, BaseModel, Field 1abcdef
14from typing_extensions import Annotated, Literal, TypedDict 1abcdef
15from typing_extensions import deprecated as typing_deprecated 1abcdef
17try: 1abcdef
18 import email_validator 1abcdef
20 assert email_validator # make autoflake ignore the unused import 1abcdef
21 from pydantic import EmailStr 1abcdef
22except ImportError: # pragma: no cover
24 class EmailStr(str): # type: ignore
25 @classmethod
26 def __get_validators__(cls) -> Iterable[Callable[..., Any]]:
27 yield cls.validate
29 @classmethod
30 def validate(cls, v: Any) -> str:
31 logger.warning(
32 "email-validator not installed, email fields will be treated as str.\n"
33 "To install, run: pip install email-validator"
34 )
35 return str(v)
37 @classmethod
38 def _validate(cls, __input_value: Any, _: Any) -> str:
39 logger.warning(
40 "email-validator not installed, email fields will be treated as str.\n"
41 "To install, run: pip install email-validator"
42 )
43 return str(__input_value)
45 @classmethod
46 def __get_pydantic_json_schema__(
47 cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler
48 ) -> JsonSchemaValue:
49 return {"type": "string", "format": "email"}
51 @classmethod
52 def __get_pydantic_core_schema__(
53 cls, source: Type[Any], handler: Callable[[Any], CoreSchema]
54 ) -> CoreSchema:
55 return with_info_plain_validator_function(cls._validate)
58class BaseModelWithConfig(BaseModel): 1abcdef
59 if PYDANTIC_V2: 1abcdef
60 model_config = {"extra": "allow"} 1abcdef
62 else:
64 class Config: 1abcdef
65 extra = "allow" 1abcdef
68class Contact(BaseModelWithConfig): 1abcdef
69 name: Optional[str] = None 1abcdef
70 url: Optional[AnyUrl] = None 1abcdef
71 email: Optional[EmailStr] = None 1abcdef
74class License(BaseModelWithConfig): 1abcdef
75 name: str 1abcdef
76 identifier: Optional[str] = None 1abcdef
77 url: Optional[AnyUrl] = None 1abcdef
80class Info(BaseModelWithConfig): 1abcdef
81 title: str 1abcdef
82 summary: Optional[str] = None 1abcdef
83 description: Optional[str] = None 1abcdef
84 termsOfService: Optional[str] = None 1abcdef
85 contact: Optional[Contact] = None 1abcdef
86 license: Optional[License] = None 1abcdef
87 version: str 1abcdef
90class ServerVariable(BaseModelWithConfig): 1abcdef
91 enum: Annotated[Optional[List[str]], Field(min_length=1)] = None 1abcdef
92 default: str 1abcdef
93 description: Optional[str] = None 1abcdef
96class Server(BaseModelWithConfig): 1abcdef
97 url: Union[AnyUrl, str] 1abcdef
98 description: Optional[str] = None 1abcdef
99 variables: Optional[Dict[str, ServerVariable]] = None 1abcdef
102class Reference(BaseModel): 1abcdef
103 ref: str = Field(alias="$ref") 1abcdef
106class Discriminator(BaseModel): 1abcdef
107 propertyName: str 1abcdef
108 mapping: Optional[Dict[str, str]] = None 1abcdef
111class XML(BaseModelWithConfig): 1abcdef
112 name: Optional[str] = None 1abcdef
113 namespace: Optional[str] = None 1abcdef
114 prefix: Optional[str] = None 1abcdef
115 attribute: Optional[bool] = None 1abcdef
116 wrapped: Optional[bool] = None 1abcdef
119class ExternalDocumentation(BaseModelWithConfig): 1abcdef
120 description: Optional[str] = None 1abcdef
121 url: AnyUrl 1abcdef
124class Schema(BaseModelWithConfig): 1abcdef
125 # Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-the-json-schema-core-vocabu
126 # Core Vocabulary
127 schema_: Optional[str] = Field(default=None, alias="$schema") 1abcdef
128 vocabulary: Optional[str] = Field(default=None, alias="$vocabulary") 1abcdef
129 id: Optional[str] = Field(default=None, alias="$id") 1abcdef
130 anchor: Optional[str] = Field(default=None, alias="$anchor") 1abcdef
131 dynamicAnchor: Optional[str] = Field(default=None, alias="$dynamicAnchor") 1abcdef
132 ref: Optional[str] = Field(default=None, alias="$ref") 1abcdef
133 dynamicRef: Optional[str] = Field(default=None, alias="$dynamicRef") 1abcdef
134 defs: Optional[Dict[str, "SchemaOrBool"]] = Field(default=None, alias="$defs") 1abcdef
135 comment: Optional[str] = Field(default=None, alias="$comment") 1abcdef
136 # Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-a-vocabulary-for-applying-s
137 # A Vocabulary for Applying Subschemas
138 allOf: Optional[List["SchemaOrBool"]] = None 1abcdef
139 anyOf: Optional[List["SchemaOrBool"]] = None 1abcdef
140 oneOf: Optional[List["SchemaOrBool"]] = None 1abcdef
141 not_: Optional["SchemaOrBool"] = Field(default=None, alias="not") 1abcdef
142 if_: Optional["SchemaOrBool"] = Field(default=None, alias="if") 1abcdef
143 then: Optional["SchemaOrBool"] = None 1abcdef
144 else_: Optional["SchemaOrBool"] = Field(default=None, alias="else") 1abcdef
145 dependentSchemas: Optional[Dict[str, "SchemaOrBool"]] = None 1abcdef
146 prefixItems: Optional[List["SchemaOrBool"]] = None 1abcdef
147 # TODO: uncomment and remove below when deprecating Pydantic v1
148 # It generales a list of schemas for tuples, before prefixItems was available
149 # items: Optional["SchemaOrBool"] = None
150 items: Optional[Union["SchemaOrBool", List["SchemaOrBool"]]] = None 1abcdef
151 contains: Optional["SchemaOrBool"] = None 1abcdef
152 properties: Optional[Dict[str, "SchemaOrBool"]] = None 1abcdef
153 patternProperties: Optional[Dict[str, "SchemaOrBool"]] = None 1abcdef
154 additionalProperties: Optional["SchemaOrBool"] = None 1abcdef
155 propertyNames: Optional["SchemaOrBool"] = None 1abcdef
156 unevaluatedItems: Optional["SchemaOrBool"] = None 1abcdef
157 unevaluatedProperties: Optional["SchemaOrBool"] = None 1abcdef
158 # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-structural
159 # A Vocabulary for Structural Validation
160 type: Optional[str] = None 1abcdef
161 enum: Optional[List[Any]] = None 1abcdef
162 const: Optional[Any] = None 1abcdef
163 multipleOf: Optional[float] = Field(default=None, gt=0) 1abcdef
164 maximum: Optional[float] = None 1abcdef
165 exclusiveMaximum: Optional[float] = None 1abcdef
166 minimum: Optional[float] = None 1abcdef
167 exclusiveMinimum: Optional[float] = None 1abcdef
168 maxLength: Optional[int] = Field(default=None, ge=0) 1abcdef
169 minLength: Optional[int] = Field(default=None, ge=0) 1abcdef
170 pattern: Optional[str] = None 1abcdef
171 maxItems: Optional[int] = Field(default=None, ge=0) 1abcdef
172 minItems: Optional[int] = Field(default=None, ge=0) 1abcdef
173 uniqueItems: Optional[bool] = None 1abcdef
174 maxContains: Optional[int] = Field(default=None, ge=0) 1abcdef
175 minContains: Optional[int] = Field(default=None, ge=0) 1abcdef
176 maxProperties: Optional[int] = Field(default=None, ge=0) 1abcdef
177 minProperties: Optional[int] = Field(default=None, ge=0) 1abcdef
178 required: Optional[List[str]] = None 1abcdef
179 dependentRequired: Optional[Dict[str, Set[str]]] = None 1abcdef
180 # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-vocabularies-for-semantic-c
181 # Vocabularies for Semantic Content With "format"
182 format: Optional[str] = None 1abcdef
183 # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-the-conten
184 # A Vocabulary for the Contents of String-Encoded Data
185 contentEncoding: Optional[str] = None 1abcdef
186 contentMediaType: Optional[str] = None 1abcdef
187 contentSchema: Optional["SchemaOrBool"] = None 1abcdef
188 # Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-basic-meta
189 # A Vocabulary for Basic Meta-Data Annotations
190 title: Optional[str] = None 1abcdef
191 description: Optional[str] = None 1abcdef
192 default: Optional[Any] = None 1abcdef
193 deprecated: Optional[bool] = None 1abcdef
194 readOnly: Optional[bool] = None 1abcdef
195 writeOnly: Optional[bool] = None 1abcdef
196 examples: Optional[List[Any]] = None 1abcdef
197 # Ref: OpenAPI 3.1.0: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#schema-object
198 # Schema Object
199 discriminator: Optional[Discriminator] = None 1abcdef
200 xml: Optional[XML] = None 1abcdef
201 externalDocs: Optional[ExternalDocumentation] = None 1abcdef
202 example: Annotated[ 1abcdef
203 Optional[Any],
204 typing_deprecated(
205 "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, "
206 "although still supported. Use examples instead."
207 ),
208 ] = None
211# Ref: https://json-schema.org/draft/2020-12/json-schema-core.html#name-json-schema-documents
212# A JSON Schema MUST be an object or a boolean.
213SchemaOrBool = Union[Schema, bool] 1abcdef
216class Example(TypedDict, total=False): 1abcdef
217 summary: Optional[str] 1abcdef
218 description: Optional[str] 1abcdef
219 value: Optional[Any] 1abcdef
220 externalValue: Optional[AnyUrl] 1abcdef
222 if PYDANTIC_V2: # type: ignore [misc] 1abcdef
223 __pydantic_config__ = {"extra": "allow"} 1abcdef
225 else:
227 class Config: 1abcdef
228 extra = "allow" 1abcdef
231class ParameterInType(Enum): 1abcdef
232 query = "query" 1abcdef
233 header = "header" 1abcdef
234 path = "path" 1abcdef
235 cookie = "cookie" 1abcdef
238class Encoding(BaseModelWithConfig): 1abcdef
239 contentType: Optional[str] = None 1abcdef
240 headers: Optional[Dict[str, Union["Header", Reference]]] = None 1abcdef
241 style: Optional[str] = None 1abcdef
242 explode: Optional[bool] = None 1abcdef
243 allowReserved: Optional[bool] = None 1abcdef
246class MediaType(BaseModelWithConfig): 1abcdef
247 schema_: Optional[Union[Schema, Reference]] = Field(default=None, alias="schema") 1abcdef
248 example: Optional[Any] = None 1abcdef
249 examples: Optional[Dict[str, Union[Example, Reference]]] = None 1abcdef
250 encoding: Optional[Dict[str, Encoding]] = None 1abcdef
253class ParameterBase(BaseModelWithConfig): 1abcdef
254 description: Optional[str] = None 1abcdef
255 required: Optional[bool] = None 1abcdef
256 deprecated: Optional[bool] = None 1abcdef
257 # Serialization rules for simple scenarios
258 style: Optional[str] = None 1abcdef
259 explode: Optional[bool] = None 1abcdef
260 allowReserved: Optional[bool] = None 1abcdef
261 schema_: Optional[Union[Schema, Reference]] = Field(default=None, alias="schema") 1abcdef
262 example: Optional[Any] = None 1abcdef
263 examples: Optional[Dict[str, Union[Example, Reference]]] = None 1abcdef
264 # Serialization rules for more complex scenarios
265 content: Optional[Dict[str, MediaType]] = None 1abcdef
268class Parameter(ParameterBase): 1abcdef
269 name: str 1abcdef
270 in_: ParameterInType = Field(alias="in") 1abcdef
273class Header(ParameterBase): 1abcdef
274 pass 1abcdef
277class RequestBody(BaseModelWithConfig): 1abcdef
278 description: Optional[str] = None 1abcdef
279 content: Dict[str, MediaType] 1abcdef
280 required: Optional[bool] = None 1abcdef
283class Link(BaseModelWithConfig): 1abcdef
284 operationRef: Optional[str] = None 1abcdef
285 operationId: Optional[str] = None 1abcdef
286 parameters: Optional[Dict[str, Union[Any, str]]] = None 1abcdef
287 requestBody: Optional[Union[Any, str]] = None 1abcdef
288 description: Optional[str] = None 1abcdef
289 server: Optional[Server] = None 1abcdef
292class Response(BaseModelWithConfig): 1abcdef
293 description: str 1abcdef
294 headers: Optional[Dict[str, Union[Header, Reference]]] = None 1abcdef
295 content: Optional[Dict[str, MediaType]] = None 1abcdef
296 links: Optional[Dict[str, Union[Link, Reference]]] = None 1abcdef
299class Operation(BaseModelWithConfig): 1abcdef
300 tags: Optional[List[str]] = None 1abcdef
301 summary: Optional[str] = None 1abcdef
302 description: Optional[str] = None 1abcdef
303 externalDocs: Optional[ExternalDocumentation] = None 1abcdef
304 operationId: Optional[str] = None 1abcdef
305 parameters: Optional[List[Union[Parameter, Reference]]] = None 1abcdef
306 requestBody: Optional[Union[RequestBody, Reference]] = None 1abcdef
307 # Using Any for Specification Extensions
308 responses: Optional[Dict[str, Union[Response, Any]]] = None 1abcdef
309 callbacks: Optional[Dict[str, Union[Dict[str, "PathItem"], Reference]]] = None 1abcdef
310 deprecated: Optional[bool] = None 1abcdef
311 security: Optional[List[Dict[str, List[str]]]] = None 1abcdef
312 servers: Optional[List[Server]] = None 1abcdef
315class PathItem(BaseModelWithConfig): 1abcdef
316 ref: Optional[str] = Field(default=None, alias="$ref") 1abcdef
317 summary: Optional[str] = None 1abcdef
318 description: Optional[str] = None 1abcdef
319 get: Optional[Operation] = None 1abcdef
320 put: Optional[Operation] = None 1abcdef
321 post: Optional[Operation] = None 1abcdef
322 delete: Optional[Operation] = None 1abcdef
323 options: Optional[Operation] = None 1abcdef
324 head: Optional[Operation] = None 1abcdef
325 patch: Optional[Operation] = None 1abcdef
326 trace: Optional[Operation] = None 1abcdef
327 servers: Optional[List[Server]] = None 1abcdef
328 parameters: Optional[List[Union[Parameter, Reference]]] = None 1abcdef
331class SecuritySchemeType(Enum): 1abcdef
332 apiKey = "apiKey" 1abcdef
333 http = "http" 1abcdef
334 oauth2 = "oauth2" 1abcdef
335 openIdConnect = "openIdConnect" 1abcdef
338class SecurityBase(BaseModelWithConfig): 1abcdef
339 type_: SecuritySchemeType = Field(alias="type") 1abcdef
340 description: Optional[str] = None 1abcdef
343class APIKeyIn(Enum): 1abcdef
344 query = "query" 1abcdef
345 header = "header" 1abcdef
346 cookie = "cookie" 1abcdef
349class APIKey(SecurityBase): 1abcdef
350 type_: SecuritySchemeType = Field(default=SecuritySchemeType.apiKey, alias="type") 1abcdef
351 in_: APIKeyIn = Field(alias="in") 1abcdef
352 name: str 1abcdef
355class HTTPBase(SecurityBase): 1abcdef
356 type_: SecuritySchemeType = Field(default=SecuritySchemeType.http, alias="type") 1abcdef
357 scheme: str 1abcdef
360class HTTPBearer(HTTPBase): 1abcdef
361 scheme: Literal["bearer"] = "bearer" 1abcdef
362 bearerFormat: Optional[str] = None 1abcdef
365class OAuthFlow(BaseModelWithConfig): 1abcdef
366 refreshUrl: Optional[str] = None 1abcdef
367 scopes: Dict[str, str] = {} 1abcdef
370class OAuthFlowImplicit(OAuthFlow): 1abcdef
371 authorizationUrl: str 1abcdef
374class OAuthFlowPassword(OAuthFlow): 1abcdef
375 tokenUrl: str 1abcdef
378class OAuthFlowClientCredentials(OAuthFlow): 1abcdef
379 tokenUrl: str 1abcdef
382class OAuthFlowAuthorizationCode(OAuthFlow): 1abcdef
383 authorizationUrl: str 1abcdef
384 tokenUrl: str 1abcdef
387class OAuthFlows(BaseModelWithConfig): 1abcdef
388 implicit: Optional[OAuthFlowImplicit] = None 1abcdef
389 password: Optional[OAuthFlowPassword] = None 1abcdef
390 clientCredentials: Optional[OAuthFlowClientCredentials] = None 1abcdef
391 authorizationCode: Optional[OAuthFlowAuthorizationCode] = None 1abcdef
394class OAuth2(SecurityBase): 1abcdef
395 type_: SecuritySchemeType = Field(default=SecuritySchemeType.oauth2, alias="type") 1abcdef
396 flows: OAuthFlows 1abcdef
399class OpenIdConnect(SecurityBase): 1abcdef
400 type_: SecuritySchemeType = Field( 1abcdef
401 default=SecuritySchemeType.openIdConnect, alias="type"
402 )
403 openIdConnectUrl: str 1abcdef
406SecurityScheme = Union[APIKey, HTTPBase, OAuth2, OpenIdConnect, HTTPBearer] 1abcdef
409class Components(BaseModelWithConfig): 1abcdef
410 schemas: Optional[Dict[str, Union[Schema, Reference]]] = None 1abcdef
411 responses: Optional[Dict[str, Union[Response, Reference]]] = None 1abcdef
412 parameters: Optional[Dict[str, Union[Parameter, Reference]]] = None 1abcdef
413 examples: Optional[Dict[str, Union[Example, Reference]]] = None 1abcdef
414 requestBodies: Optional[Dict[str, Union[RequestBody, Reference]]] = None 1abcdef
415 headers: Optional[Dict[str, Union[Header, Reference]]] = None 1abcdef
416 securitySchemes: Optional[Dict[str, Union[SecurityScheme, Reference]]] = None 1abcdef
417 links: Optional[Dict[str, Union[Link, Reference]]] = None 1abcdef
418 # Using Any for Specification Extensions
419 callbacks: Optional[Dict[str, Union[Dict[str, PathItem], Reference, Any]]] = None 1abcdef
420 pathItems: Optional[Dict[str, Union[PathItem, Reference]]] = None 1abcdef
423class Tag(BaseModelWithConfig): 1abcdef
424 name: str 1abcdef
425 description: Optional[str] = None 1abcdef
426 externalDocs: Optional[ExternalDocumentation] = None 1abcdef
429class OpenAPI(BaseModelWithConfig): 1abcdef
430 openapi: str 1abcdef
431 info: Info 1abcdef
432 jsonSchemaDialect: Optional[str] = None 1abcdef
433 servers: Optional[List[Server]] = None 1abcdef
434 # Using Any for Specification Extensions
435 paths: Optional[Dict[str, Union[PathItem, Any]]] = None 1abcdef
436 webhooks: Optional[Dict[str, Union[PathItem, Reference]]] = None 1abcdef
437 components: Optional[Components] = None 1abcdef
438 security: Optional[List[Dict[str, List[str]]]] = None 1abcdef
439 tags: Optional[List[Tag]] = None 1abcdef
440 externalDocs: Optional[ExternalDocumentation] = None 1abcdef
443_model_rebuild(Schema) 1abcdef
444_model_rebuild(Operation) 1abcdef
445_model_rebuild(Encoding) 1abcdef