You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

407 line
11 KiB

  1. from enum import Enum
  2. from typing import Any, Callable, Dict, Iterable, List, Optional, Union
  3. from fastapi.logger import logger
  4. from pydantic import AnyUrl, BaseModel, Field
  5. try:
  6. import email_validator # type: ignore
  7. assert email_validator # make autoflake ignore the unused import
  8. from pydantic import EmailStr
  9. except ImportError: # pragma: no cover
  10. class EmailStr(str): # type: ignore
  11. @classmethod
  12. def __get_validators__(cls) -> Iterable[Callable[..., Any]]:
  13. yield cls.validate
  14. @classmethod
  15. def validate(cls, v: Any) -> str:
  16. logger.warning(
  17. "email-validator not installed, email fields will be treated as str.\n"
  18. "To install, run: pip install email-validator"
  19. )
  20. return str(v)
  21. class Contact(BaseModel):
  22. name: Optional[str] = None
  23. url: Optional[AnyUrl] = None
  24. email: Optional[EmailStr] = None
  25. class Config:
  26. extra = "allow"
  27. class License(BaseModel):
  28. name: str
  29. url: Optional[AnyUrl] = None
  30. class Config:
  31. extra = "allow"
  32. class Info(BaseModel):
  33. title: str
  34. description: Optional[str] = None
  35. termsOfService: Optional[str] = None
  36. contact: Optional[Contact] = None
  37. license: Optional[License] = None
  38. version: str
  39. class Config:
  40. extra = "allow"
  41. class ServerVariable(BaseModel):
  42. enum: Optional[List[str]] = None
  43. default: str
  44. description: Optional[str] = None
  45. class Config:
  46. extra = "allow"
  47. class Server(BaseModel):
  48. url: Union[AnyUrl, str]
  49. description: Optional[str] = None
  50. variables: Optional[Dict[str, ServerVariable]] = None
  51. class Config:
  52. extra = "allow"
  53. class Reference(BaseModel):
  54. ref: str = Field(..., alias="$ref")
  55. class Discriminator(BaseModel):
  56. propertyName: str
  57. mapping: Optional[Dict[str, str]] = None
  58. class XML(BaseModel):
  59. name: Optional[str] = None
  60. namespace: Optional[str] = None
  61. prefix: Optional[str] = None
  62. attribute: Optional[bool] = None
  63. wrapped: Optional[bool] = None
  64. class Config:
  65. extra = "allow"
  66. class ExternalDocumentation(BaseModel):
  67. description: Optional[str] = None
  68. url: AnyUrl
  69. class Config:
  70. extra = "allow"
  71. class Schema(BaseModel):
  72. ref: Optional[str] = Field(None, alias="$ref")
  73. title: Optional[str] = None
  74. multipleOf: Optional[float] = None
  75. maximum: Optional[float] = None
  76. exclusiveMaximum: Optional[float] = None
  77. minimum: Optional[float] = None
  78. exclusiveMinimum: Optional[float] = None
  79. maxLength: Optional[int] = Field(None, gte=0)
  80. minLength: Optional[int] = Field(None, gte=0)
  81. pattern: Optional[str] = None
  82. maxItems: Optional[int] = Field(None, gte=0)
  83. minItems: Optional[int] = Field(None, gte=0)
  84. uniqueItems: Optional[bool] = None
  85. maxProperties: Optional[int] = Field(None, gte=0)
  86. minProperties: Optional[int] = Field(None, gte=0)
  87. required: Optional[List[str]] = None
  88. enum: Optional[List[Any]] = None
  89. type: Optional[str] = None
  90. allOf: Optional[List["Schema"]] = None
  91. oneOf: Optional[List["Schema"]] = None
  92. anyOf: Optional[List["Schema"]] = None
  93. not_: Optional["Schema"] = Field(None, alias="not")
  94. items: Optional["Schema"] = None
  95. properties: Optional[Dict[str, "Schema"]] = None
  96. additionalProperties: Optional[Union["Schema", Reference, bool]] = None
  97. description: Optional[str] = None
  98. format: Optional[str] = None
  99. default: Optional[Any] = None
  100. nullable: Optional[bool] = None
  101. discriminator: Optional[Discriminator] = None
  102. readOnly: Optional[bool] = None
  103. writeOnly: Optional[bool] = None
  104. xml: Optional[XML] = None
  105. externalDocs: Optional[ExternalDocumentation] = None
  106. example: Optional[Any] = None
  107. deprecated: Optional[bool] = None
  108. class Config:
  109. extra: str = "allow"
  110. class Example(BaseModel):
  111. summary: Optional[str] = None
  112. description: Optional[str] = None
  113. value: Optional[Any] = None
  114. externalValue: Optional[AnyUrl] = None
  115. class Config:
  116. extra = "allow"
  117. class ParameterInType(Enum):
  118. query = "query"
  119. header = "header"
  120. path = "path"
  121. cookie = "cookie"
  122. class Encoding(BaseModel):
  123. contentType: Optional[str] = None
  124. headers: Optional[Dict[str, Union["Header", Reference]]] = None
  125. style: Optional[str] = None
  126. explode: Optional[bool] = None
  127. allowReserved: Optional[bool] = None
  128. class Config:
  129. extra = "allow"
  130. class MediaType(BaseModel):
  131. schema_: Optional[Union[Schema, Reference]] = Field(None, alias="schema")
  132. example: Optional[Any] = None
  133. examples: Optional[Dict[str, Union[Example, Reference]]] = None
  134. encoding: Optional[Dict[str, Encoding]] = None
  135. class Config:
  136. extra = "allow"
  137. class ParameterBase(BaseModel):
  138. description: Optional[str] = None
  139. required: Optional[bool] = None
  140. deprecated: Optional[bool] = None
  141. # Serialization rules for simple scenarios
  142. style: Optional[str] = None
  143. explode: Optional[bool] = None
  144. allowReserved: Optional[bool] = None
  145. schema_: Optional[Union[Schema, Reference]] = Field(None, alias="schema")
  146. example: Optional[Any] = None
  147. examples: Optional[Dict[str, Union[Example, Reference]]] = None
  148. # Serialization rules for more complex scenarios
  149. content: Optional[Dict[str, MediaType]] = None
  150. class Config:
  151. extra = "allow"
  152. class Parameter(ParameterBase):
  153. name: str
  154. in_: ParameterInType = Field(..., alias="in")
  155. class Header(ParameterBase):
  156. pass
  157. class RequestBody(BaseModel):
  158. description: Optional[str] = None
  159. content: Dict[str, MediaType]
  160. required: Optional[bool] = None
  161. class Config:
  162. extra = "allow"
  163. class Link(BaseModel):
  164. operationRef: Optional[str] = None
  165. operationId: Optional[str] = None
  166. parameters: Optional[Dict[str, Union[Any, str]]] = None
  167. requestBody: Optional[Union[Any, str]] = None
  168. description: Optional[str] = None
  169. server: Optional[Server] = None
  170. class Config:
  171. extra = "allow"
  172. class Response(BaseModel):
  173. description: str
  174. headers: Optional[Dict[str, Union[Header, Reference]]] = None
  175. content: Optional[Dict[str, MediaType]] = None
  176. links: Optional[Dict[str, Union[Link, Reference]]] = None
  177. class Config:
  178. extra = "allow"
  179. class Operation(BaseModel):
  180. tags: Optional[List[str]] = None
  181. summary: Optional[str] = None
  182. description: Optional[str] = None
  183. externalDocs: Optional[ExternalDocumentation] = None
  184. operationId: Optional[str] = None
  185. parameters: Optional[List[Union[Parameter, Reference]]] = None
  186. requestBody: Optional[Union[RequestBody, Reference]] = None
  187. # Using Any for Specification Extensions
  188. responses: Dict[str, Union[Response, Any]]
  189. callbacks: Optional[Dict[str, Union[Dict[str, "PathItem"], Reference]]] = None
  190. deprecated: Optional[bool] = None
  191. security: Optional[List[Dict[str, List[str]]]] = None
  192. servers: Optional[List[Server]] = None
  193. class Config:
  194. extra = "allow"
  195. class PathItem(BaseModel):
  196. ref: Optional[str] = Field(None, alias="$ref")
  197. summary: Optional[str] = None
  198. description: Optional[str] = None
  199. get: Optional[Operation] = None
  200. put: Optional[Operation] = None
  201. post: Optional[Operation] = None
  202. delete: Optional[Operation] = None
  203. options: Optional[Operation] = None
  204. head: Optional[Operation] = None
  205. patch: Optional[Operation] = None
  206. trace: Optional[Operation] = None
  207. servers: Optional[List[Server]] = None
  208. parameters: Optional[List[Union[Parameter, Reference]]] = None
  209. class Config:
  210. extra = "allow"
  211. class SecuritySchemeType(Enum):
  212. apiKey = "apiKey"
  213. http = "http"
  214. oauth2 = "oauth2"
  215. openIdConnect = "openIdConnect"
  216. class SecurityBase(BaseModel):
  217. type_: SecuritySchemeType = Field(..., alias="type")
  218. description: Optional[str] = None
  219. class Config:
  220. extra = "allow"
  221. class APIKeyIn(Enum):
  222. query = "query"
  223. header = "header"
  224. cookie = "cookie"
  225. class APIKey(SecurityBase):
  226. type_ = Field(SecuritySchemeType.apiKey, alias="type")
  227. in_: APIKeyIn = Field(..., alias="in")
  228. name: str
  229. class HTTPBase(SecurityBase):
  230. type_ = Field(SecuritySchemeType.http, alias="type")
  231. scheme: str
  232. class HTTPBearer(HTTPBase):
  233. scheme = "bearer"
  234. bearerFormat: Optional[str] = None
  235. class OAuthFlow(BaseModel):
  236. refreshUrl: Optional[str] = None
  237. scopes: Dict[str, str] = {}
  238. class Config:
  239. extra = "allow"
  240. class OAuthFlowImplicit(OAuthFlow):
  241. authorizationUrl: str
  242. class OAuthFlowPassword(OAuthFlow):
  243. tokenUrl: str
  244. class OAuthFlowClientCredentials(OAuthFlow):
  245. tokenUrl: str
  246. class OAuthFlowAuthorizationCode(OAuthFlow):
  247. authorizationUrl: str
  248. tokenUrl: str
  249. class OAuthFlows(BaseModel):
  250. implicit: Optional[OAuthFlowImplicit] = None
  251. password: Optional[OAuthFlowPassword] = None
  252. clientCredentials: Optional[OAuthFlowClientCredentials] = None
  253. authorizationCode: Optional[OAuthFlowAuthorizationCode] = None
  254. class Config:
  255. extra = "allow"
  256. class OAuth2(SecurityBase):
  257. type_ = Field(SecuritySchemeType.oauth2, alias="type")
  258. flows: OAuthFlows
  259. class OpenIdConnect(SecurityBase):
  260. type_ = Field(SecuritySchemeType.openIdConnect, alias="type")
  261. openIdConnectUrl: str
  262. SecurityScheme = Union[APIKey, HTTPBase, OAuth2, OpenIdConnect, HTTPBearer]
  263. class Components(BaseModel):
  264. schemas: Optional[Dict[str, Union[Schema, Reference]]] = None
  265. responses: Optional[Dict[str, Union[Response, Reference]]] = None
  266. parameters: Optional[Dict[str, Union[Parameter, Reference]]] = None
  267. examples: Optional[Dict[str, Union[Example, Reference]]] = None
  268. requestBodies: Optional[Dict[str, Union[RequestBody, Reference]]] = None
  269. headers: Optional[Dict[str, Union[Header, Reference]]] = None
  270. securitySchemes: Optional[Dict[str, Union[SecurityScheme, Reference]]] = None
  271. links: Optional[Dict[str, Union[Link, Reference]]] = None
  272. # Using Any for Specification Extensions
  273. callbacks: Optional[Dict[str, Union[Dict[str, PathItem], Reference, Any]]] = None
  274. class Config:
  275. extra = "allow"
  276. class Tag(BaseModel):
  277. name: str
  278. description: Optional[str] = None
  279. externalDocs: Optional[ExternalDocumentation] = None
  280. class Config:
  281. extra = "allow"
  282. class OpenAPI(BaseModel):
  283. openapi: str
  284. info: Info
  285. servers: Optional[List[Server]] = None
  286. # Using Any for Specification Extensions
  287. paths: Dict[str, Union[PathItem, Any]]
  288. components: Optional[Components] = None
  289. security: Optional[List[Dict[str, List[str]]]] = None
  290. tags: Optional[List[Tag]] = None
  291. externalDocs: Optional[ExternalDocumentation] = None
  292. class Config:
  293. extra = "allow"
  294. Schema.update_forward_refs()
  295. Operation.update_forward_refs()
  296. Encoding.update_forward_refs()