Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

446 строки
15 KiB

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