From ec1a8bc5df84bceed314433acb201ff6d8a64f3d Mon Sep 17 00:00:00 2001 From: Nementon Date: Thu, 13 May 2021 01:11:31 +0200 Subject: [PATCH 01/13] updated vendored openapi_schema_pydantic / correct oai false negative validation --- .../schema/openapi_schema_pydantic/README.md | 3 + .../openapi_schema_pydantic/__init__.py | 44 +++---- .../openapi_schema_pydantic/callback.py | 20 ++++ .../openapi_schema_pydantic/components.py | 7 +- .../schema/openapi_schema_pydantic/contact.py | 3 +- .../openapi_schema_pydantic/discriminator.py | 5 +- .../openapi_schema_pydantic/encoding.py | 17 +-- .../schema/openapi_schema_pydantic/example.py | 5 +- .../external_documentation.py | 5 +- .../schema/openapi_schema_pydantic/header.py | 3 +- .../schema/openapi_schema_pydantic/info.py | 7 +- .../schema/openapi_schema_pydantic/license.py | 5 +- .../schema/openapi_schema_pydantic/link.py | 7 +- .../openapi_schema_pydantic/media_type.py | 15 +-- .../openapi_schema_pydantic/oauth_flow.py | 9 +- .../openapi_schema_pydantic/oauth_flows.py | 9 +- .../openapi_schema_pydantic/open_api.py | 19 +-- .../openapi_schema_pydantic/operation.py | 24 ++-- .../openapi_schema_pydantic/parameter.py | 19 +-- .../openapi_schema_pydantic/path_item.py | 5 +- .../schema/openapi_schema_pydantic/paths.py | 3 +- .../openapi_schema_pydantic/reference.py | 3 +- .../openapi_schema_pydantic/request_body.py | 11 +- .../openapi_schema_pydantic/response.py | 9 +- .../openapi_schema_pydantic/responses.py | 3 +- .../schema/openapi_schema_pydantic/schema.py | 110 +++++++++--------- .../security_requirement.py | 1 + .../security_scheme.py | 9 +- .../schema/openapi_schema_pydantic/server.py | 9 +- .../server_variable.py | 9 +- .../schema/openapi_schema_pydantic/tag.py | 5 +- .../schema/openapi_schema_pydantic/xml.py | 3 +- 32 files changed, 239 insertions(+), 167 deletions(-) create mode 100644 openapi_python_client/schema/openapi_schema_pydantic/callback.py diff --git a/openapi_python_client/schema/openapi_schema_pydantic/README.md b/openapi_python_client/schema/openapi_schema_pydantic/README.md index 0e4d40146..f58b36909 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/README.md +++ b/openapi_python_client/schema/openapi_schema_pydantic/README.md @@ -1,5 +1,8 @@ Everything in this directory (including the rest of this file after this paragraph) is a vendored copy of [openapi-schem-pydantic](https://github.com/kuimono/openapi-schema-pydantic) and is licensed under the LICENSE file in this directory. +Included vendored version is the [following](https://github.com/kuimono/openapi-schema-pydantic/commit/0836b429086917feeb973de3367a7ac4c2b3a665) +Small patches has been applied to it. + ## Alias Due to the reserved words in python and pydantic, diff --git a/openapi_python_client/schema/openapi_schema_pydantic/__init__.py b/openapi_python_client/schema/openapi_schema_pydantic/__init__.py index 9edb7d3d9..27fba924f 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/__init__.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/__init__.py @@ -38,32 +38,34 @@ "XML", ] -from .components import Components -from .contact import Contact -from .discriminator import Discriminator -from .encoding import Encoding -from .example import Example -from .external_documentation import ExternalDocumentation -from .header import Header + +from .open_api import OpenAPI from .info import Info +from .contact import Contact from .license import License -from .link import Link -from .media_type import MediaType -from .oauth_flow import OAuthFlow -from .oauth_flows import OAuthFlows -from .open_api import OpenAPI +from .server import Server +from .server_variable import ServerVariable +from .components import Components +from .paths import Paths +from .path_item import PathItem from .operation import Operation +from .external_documentation import ExternalDocumentation from .parameter import Parameter -from .path_item import PathItem -from .paths import Paths -from .reference import Reference from .request_body import RequestBody -from .response import Response +from .media_type import MediaType +from .encoding import Encoding from .responses import Responses -from .schema import Schema -from .security_requirement import SecurityRequirement -from .security_scheme import SecurityScheme -from .server import Server -from .server_variable import ServerVariable +from .response import Response +from .callback import Callback +from .example import Example +from .link import Link +from .header import Header from .tag import Tag +from .reference import Reference +from .schema import Schema +from .discriminator import Discriminator from .xml import XML +from .security_scheme import SecurityScheme +from .oauth_flows import OAuthFlows +from .oauth_flow import OAuthFlow +from .security_requirement import SecurityRequirement diff --git a/openapi_python_client/schema/openapi_schema_pydantic/callback.py b/openapi_python_client/schema/openapi_schema_pydantic/callback.py new file mode 100644 index 000000000..35bea75d7 --- /dev/null +++ b/openapi_python_client/schema/openapi_schema_pydantic/callback.py @@ -0,0 +1,20 @@ +from typing import Dict + + +Callback = Dict[str, "PathItem"] +""" +A map of possible out-of band callbacks related to the parent operation. +Each value in the map is a [Path Item Object](#pathItemObject) +that describes a set of requests that may be initiated by the API provider and the expected responses. +The key value used to identify the path item object is an expression, evaluated at runtime, +that identifies a URL to use for the callback operation. +""" + +"""Patterned Fields""" + +# {expression}: 'PathItem' = ... +""" +A Path Item Object used to define a callback request and expected responses. + +A [complete example](../examples/v3.0/callback-example.yaml) is available. +""" diff --git a/openapi_python_client/schema/openapi_schema_pydantic/components.py b/openapi_python_client/schema/openapi_schema_pydantic/components.py index 8ad888906..95b3a6e97 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/components.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/components.py @@ -1,7 +1,8 @@ from typing import Dict, Optional, Union -from pydantic import BaseModel +from pydantic import BaseModel, Extra +from .callback import Callback from .example import Example from .header import Header from .link import Link @@ -44,7 +45,11 @@ class Components(BaseModel): links: Optional[Dict[str, Union[Link, Reference]]] = None """An object to hold reusable [Link Objects](#linkObject).""" + callbacks: Optional[Dict[str, Union[Callback, Reference]]] = None + """An object to hold reusable [Callback Objects](#callbackObject).""" + class Config: + extra = Extra.forbid schema_extra = { "examples": [ { diff --git a/openapi_python_client/schema/openapi_schema_pydantic/contact.py b/openapi_python_client/schema/openapi_schema_pydantic/contact.py index c41aa8406..8cf450fbb 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/contact.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/contact.py @@ -1,6 +1,6 @@ from typing import Optional -from pydantic import AnyUrl, BaseModel +from pydantic import AnyUrl, BaseModel, Extra class Contact(BaseModel): @@ -26,6 +26,7 @@ class Contact(BaseModel): """ class Config: + extra = Extra.forbid schema_extra = { "examples": [ {"name": "API Support", "url": "http://www.example.com/support", "email": "support@example.com"} diff --git a/openapi_python_client/schema/openapi_schema_pydantic/discriminator.py b/openapi_python_client/schema/openapi_schema_pydantic/discriminator.py index 1dfd06a5b..74338386d 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/discriminator.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/discriminator.py @@ -1,6 +1,6 @@ from typing import Dict, Optional -from pydantic import BaseModel +from pydantic import BaseModel, Extra class Discriminator(BaseModel): @@ -14,7 +14,7 @@ class Discriminator(BaseModel): When using the discriminator, _inline_ schemas will not be considered. """ - propertyName: str + propertyName: str = ... """ **REQUIRED**. The name of the property in the payload that will hold the discriminator value. """ @@ -25,6 +25,7 @@ class Discriminator(BaseModel): """ class Config: + extra = Extra.forbid schema_extra = { "examples": [ { diff --git a/openapi_python_client/schema/openapi_schema_pydantic/encoding.py b/openapi_python_client/schema/openapi_schema_pydantic/encoding.py index 9bf2ea177..d18447639 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/encoding.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/encoding.py @@ -1,6 +1,6 @@ -from typing import Dict, Optional +from typing import Dict, Optional, Union -from pydantic import BaseModel +from pydantic import BaseModel, Extra from .reference import Reference @@ -12,20 +12,20 @@ class Encoding(BaseModel): """ The Content-Type for encoding a specific property. Default value depends on the property type: - + - for `string` with `format` being `binary` – `application/octet-stream`; - for other primitive types – `text/plain`; - for `object` - `application/json`; - for `array` – the default is defined based on the inner type. - + The value can be a specific media type (e.g. `application/json`), a wildcard media type (e.g. `image/*`), or a comma-separated list of the two types. """ - headers: Optional[Dict[str, Reference]] = None + headers: Optional[Dict[str, Union["Header", Reference]]] = None """ A map allowing additional information to be provided as headers, for example `Content-Disposition`. - + `Content-Type` is described separately and SHALL be ignored in this section. This property SHALL be ignored if the request body media type is not a `multipart`. """ @@ -33,7 +33,7 @@ class Encoding(BaseModel): style: Optional[str] = None """ Describes how a specific property value will be serialized depending on its type. - + See [Parameter Object](#parameterObject) for details on the [`style`](#parameterStyle) property. The behavior follows the same values as `query` parameters, including default values. This property SHALL be ignored if the request body media type is not `application/x-www-form-urlencoded`. @@ -43,7 +43,7 @@ class Encoding(BaseModel): """ When this is true, property values of type `array` or `object` generate separate parameters for each value of the array, or key-value-pair of the map. - + For other types of properties this property has no effect. When [`style`](#encodingStyle) is `form`, the default value is `true`. For all other styles, the default value is `false`. @@ -60,6 +60,7 @@ class Encoding(BaseModel): """ class Config: + extra = Extra.forbid schema_extra = { "examples": [ { diff --git a/openapi_python_client/schema/openapi_schema_pydantic/example.py b/openapi_python_client/schema/openapi_schema_pydantic/example.py index 6da3710b1..1eda5a11b 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/example.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/example.py @@ -1,6 +1,6 @@ from typing import Any, Optional -from pydantic import BaseModel +from pydantic import BaseModel, Extra class Example(BaseModel): @@ -28,11 +28,12 @@ class Example(BaseModel): """ A URL that points to the literal example. This provides the capability to reference examples that cannot easily be included in JSON or YAML documents. - + The `value` field and `externalValue` field are mutually exclusive. """ class Config: + extra = Extra.forbid schema_extra = { "examples": [ {"summary": "A foo example", "value": {"foo": "bar"}}, diff --git a/openapi_python_client/schema/openapi_schema_pydantic/external_documentation.py b/openapi_python_client/schema/openapi_schema_pydantic/external_documentation.py index 92676a2ae..d2859b1aa 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/external_documentation.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/external_documentation.py @@ -1,6 +1,6 @@ from typing import Optional -from pydantic import AnyUrl, BaseModel +from pydantic import AnyUrl, BaseModel, Extra class ExternalDocumentation(BaseModel): @@ -12,11 +12,12 @@ class ExternalDocumentation(BaseModel): [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. """ - url: AnyUrl + url: AnyUrl = ... """ **REQUIRED**. The URL for the target documentation. Value MUST be in the format of a URL. """ class Config: + extra = Extra.forbid schema_extra = {"examples": [{"description": "Find more info here", "url": "https://example.com"}]} diff --git a/openapi_python_client/schema/openapi_schema_pydantic/header.py b/openapi_python_client/schema/openapi_schema_pydantic/header.py index 5e59e8a66..f5ad792c9 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/header.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/header.py @@ -1,4 +1,4 @@ -from pydantic import Field +from pydantic import Extra, Field from ..parameter_location import ParameterLocation from .parameter import Parameter @@ -18,6 +18,7 @@ class Header(Parameter): param_in = Field(default=ParameterLocation.HEADER, const=True, alias="in") class Config: + extra = Extra.forbid allow_population_by_field_name = True schema_extra = { "examples": [ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/info.py b/openapi_python_client/schema/openapi_schema_pydantic/info.py index 36caba733..13376475c 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/info.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/info.py @@ -1,6 +1,6 @@ from typing import Optional -from pydantic import AnyUrl, BaseModel +from pydantic import AnyUrl, BaseModel, Extra from .contact import Contact from .license import License @@ -13,7 +13,7 @@ class Info(BaseModel): and MAY be presented in editing or documentation generation tools for convenience. """ - title: str + title: str = ... """ **REQUIRED**. The title of the API. """ @@ -40,13 +40,14 @@ class Info(BaseModel): The license information for the exposed API. """ - version: str + version: str = ... """ **REQUIRED**. The version of the OpenAPI document (which is distinct from the [OpenAPI Specification version](#oasVersion) or the API implementation version). """ class Config: + extra = Extra.forbid schema_extra = { "examples": [ { diff --git a/openapi_python_client/schema/openapi_schema_pydantic/license.py b/openapi_python_client/schema/openapi_schema_pydantic/license.py index 567a5d117..d44267696 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/license.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/license.py @@ -1,6 +1,6 @@ from typing import Optional -from pydantic import AnyUrl, BaseModel +from pydantic import AnyUrl, BaseModel, Extra class License(BaseModel): @@ -8,7 +8,7 @@ class License(BaseModel): License information for the exposed API. """ - name: str + name: str = ... """ **REQUIRED**. The license name used for the API. """ @@ -20,4 +20,5 @@ class License(BaseModel): """ class Config: + extra = Extra.forbid schema_extra = {"examples": [{"name": "Apache 2.0", "url": "https://www.apache.org/licenses/LICENSE-2.0.html"}]} diff --git a/openapi_python_client/schema/openapi_schema_pydantic/link.py b/openapi_python_client/schema/openapi_schema_pydantic/link.py index 97bbc8aeb..174dca9b5 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/link.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/link.py @@ -1,6 +1,6 @@ from typing import Any, Dict, Optional -from pydantic import BaseModel +from pydantic import BaseModel, Extra from .server import Server @@ -31,7 +31,7 @@ class Link(BaseModel): operationId: Optional[str] = None """ The name of an _existing_, resolvable OAS operation, as defined with a unique `operationId`. - + This field is mutually exclusive of the `operationRef` field. """ @@ -41,7 +41,7 @@ class Link(BaseModel): as specified with `operationId` or identified via `operationRef`. The key is the parameter name to be used, whereas the value can be a constant or an expression to be evaluated and passed to the linked operation. - + The parameter name can be qualified using the [parameter location](#parameterIn) `[{in}.]{name}` for operations that use the same parameter name in different locations (e.g. path.id). """ @@ -63,6 +63,7 @@ class Link(BaseModel): """ class Config: + extra = Extra.forbid schema_extra = { "examples": [ {"operationId": "getUserAddressByUUID", "parameters": {"userUuid": "$response.body#/uuid"}}, diff --git a/openapi_python_client/schema/openapi_schema_pydantic/media_type.py b/openapi_python_client/schema/openapi_schema_pydantic/media_type.py index 7c00d3bc1..38319c5e9 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/media_type.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/media_type.py @@ -1,6 +1,6 @@ from typing import Any, Dict, Optional, Union -from pydantic import BaseModel, Field +from pydantic import BaseModel, Extra, Field from .encoding import Encoding from .example import Example @@ -19,11 +19,11 @@ class MediaType(BaseModel): example: Optional[Any] = None """ Example of the media type. - + The example object SHOULD be in the correct format as specified by the media type. - + The `example` field is mutually exclusive of the `examples` field. - + Furthermore, if referencing a `schema` which contains an example, the `example` value SHALL _override_ the example provided by the schema. """ @@ -31,11 +31,11 @@ class MediaType(BaseModel): examples: Optional[Dict[str, Union[Example, Reference]]] = None """ Examples of the media type. - + Each example object SHOULD match the media type and specified schema if present. - + The `examples` field is mutually exclusive of the `example` field. - + Furthermore, if referencing a `schema` which contains an example, the `examples` value SHALL _override_ the example provided by the schema. """ @@ -49,6 +49,7 @@ class MediaType(BaseModel): """ class Config: + extra = Extra.forbid allow_population_by_field_name = True schema_extra = { "examples": [ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py b/openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py index cdf474bee..524be0f2b 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py @@ -1,6 +1,6 @@ -from typing import Dict, Optional +from typing import Dict, Optional, Union -from pydantic import AnyUrl, BaseModel +from pydantic import AnyUrl, BaseModel, Extra class OAuthFlow(BaseModel): @@ -15,7 +15,7 @@ class OAuthFlow(BaseModel): This MUST be in the form of a URL. """ - tokenUrl: Optional[str] = None + tokenUrl: Optional[AnyUrl] = None """ **REQUIRED** for `oauth2 ("password", "clientCredentials", "authorizationCode")`. The token URL to be used for this flow. @@ -27,7 +27,7 @@ class OAuthFlow(BaseModel): The URL to be used for obtaining refresh tokens. This MUST be in the form of a URL. """ - scopes: Dict[str, str] + scopes: Dict[str, str] = ... """ **REQUIRED**. The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. @@ -35,6 +35,7 @@ class OAuthFlow(BaseModel): """ class Config: + extra = Extra.forbid schema_extra = { "examples": [ { diff --git a/openapi_python_client/schema/openapi_schema_pydantic/oauth_flows.py b/openapi_python_client/schema/openapi_schema_pydantic/oauth_flows.py index fcb9ba348..c71370cd1 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/oauth_flows.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/oauth_flows.py @@ -1,6 +1,6 @@ from typing import Optional -from pydantic import BaseModel +from pydantic import BaseModel, Extra from .oauth_flow import OAuthFlow @@ -23,13 +23,16 @@ class OAuthFlows(BaseModel): clientCredentials: Optional[OAuthFlow] = None """ Configuration for the OAuth Client Credentials flow. - + Previously called `application` in OpenAPI 2.0. """ authorizationCode: Optional[OAuthFlow] = None """ Configuration for the OAuth Authorization Code flow. - + Previously called `accessCode` in OpenAPI 2.0. """ + + class Config: + extra = Extra.forbid diff --git a/openapi_python_client/schema/openapi_schema_pydantic/open_api.py b/openapi_python_client/schema/openapi_schema_pydantic/open_api.py index dd480a8f5..a03080470 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/open_api.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/open_api.py @@ -1,6 +1,6 @@ from typing import List, Optional -from pydantic import BaseModel +from pydantic import BaseModel, Extra from .components import Components from .external_documentation import ExternalDocumentation @@ -14,19 +14,19 @@ class OpenAPI(BaseModel): """This is the root document object of the OpenAPI document.""" - info: Info + info: Info = ... """ **REQUIRED**. Provides metadata about the API. The metadata MAY be used by tooling as required. """ servers: List[Server] = [Server(url="/")] """ - An array of Server Objects, which provide connectivity information to a target server. + An array of Server Objects, which provide connectivity information to a target server. If the `servers` property is not provided, or is an empty array, the default value would be a [Server Object](#serverObject) with a [url](#serverUrl) value of `/`. """ - paths: Paths + paths: Paths = ... """ **REQUIRED**. The available paths and operations for the API. """ @@ -38,10 +38,10 @@ class OpenAPI(BaseModel): security: Optional[List[SecurityRequirement]] = None """ - A declaration of which security mechanisms can be used across the API. - The list of values includes alternative security requirement objects that can be used. - Only one of the security requirement objects need to be satisfied to authorize a request. - Individual operations can override this definition. + A declaration of which security mechanisms can be used across the API. + The list of values includes alternative security requirement objects that can be used. + Only one of the security requirement objects need to be satisfied to authorize a request. + Individual operations can override this definition. To make security optional, an empty security requirement (`{}`) can be included in the array. """ @@ -58,3 +58,6 @@ class OpenAPI(BaseModel): """ Additional external documentation. """ + + class Config: + extra = Extra.forbid diff --git a/openapi_python_client/schema/openapi_schema_pydantic/operation.py b/openapi_python_client/schema/openapi_schema_pydantic/operation.py index 860c3c24a..49150e6f7 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/operation.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/operation.py @@ -1,7 +1,8 @@ -from typing import List, Optional, Union +from typing import Dict, List, Optional, Union -from pydantic import BaseModel +from pydantic import BaseModel, Extra +from .callback import Callback from .external_documentation import ExternalDocumentation from .parameter import Parameter from .reference import Reference @@ -58,18 +59,26 @@ class Operation(BaseModel): requestBody: Optional[Union[RequestBody, Reference]] = None """ - The request body applicable for this operation. - + The request body applicable for this operation. + The `requestBody` is only supported in HTTP methods where the HTTP 1.1 specification - [RFC7231](https://tools.ietf.org/html/rfc7231#section-4.3.1) has explicitly defined semantics for request bodies. + [RFC7231](https://tools.ietf.org/html/rfc7231#section-4.3.1) has explicitly defined semantics for request bodies. In other cases where the HTTP spec is vague, `requestBody` SHALL be ignored by consumers. """ - responses: Responses + responses: Responses = ... """ **REQUIRED**. The list of possible responses as they are returned from executing this operation. """ + callbacks: Optional[Dict[str, Callback]] = None + """ + A map of possible out-of band callbacks related to the parent operation. + The key is a unique identifier for the Callback Object. + Each value in the map is a [Callback Object](#callbackObject) + that describes a request that may be initiated by the API provider and the expected responses. + """ + deprecated: bool = False """ Declares this operation to be deprecated. @@ -90,11 +99,12 @@ class Operation(BaseModel): servers: Optional[List[Server]] = None """ An alternative `server` array to service this operation. - If an alternative `server` object is specified at the Path Item Object or Root level, + If an alternative `server` object is specified at the Path Item Object or Root level, it will be overridden by this value. """ class Config: + extra = Extra.forbid schema_extra = { "examples": [ { diff --git a/openapi_python_client/schema/openapi_schema_pydantic/parameter.py b/openapi_python_client/schema/openapi_schema_pydantic/parameter.py index 52f1b6885..c4ffd5ef2 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/parameter.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/parameter.py @@ -1,6 +1,6 @@ from typing import Any, Dict, Optional, Union -from pydantic import BaseModel, Field +from pydantic import BaseModel, Field, Extra from ..parameter_location import ParameterLocation from .example import Example @@ -18,15 +18,15 @@ class Parameter(BaseModel): """Fixed Fields""" - name: str + name: str = ... """ **REQUIRED**. The name of the parameter. - Parameter names are *case sensitive*. - - - If [`in`](#parameterIn) is `"path"`, the `name` field MUST correspond to a template expression occurring + Parameter names are *case sensitive*. + + - If [`in`](#parameterIn) is `"path"`, the `name` field MUST correspond to a template expression occurring within the [path](#pathsPath) field in the [Paths Object](#pathsObject). See [Path Templating](#pathTemplating) for further information. - - If [`in`](#parameterIn) is `"header"` and the `name` field is `"Accept"`, `"Content-Type"` or `"Authorization"`. + - If [`in`](#parameterIn) is `"header"` and the `name` field is `"Accept"`, `"Content-Type"` or `"Authorization"`, the parameter definition SHALL be ignored. - For all other cases, the `name` corresponds to the parameter name used by the [`in`](#parameterIn) property. """ @@ -76,7 +76,7 @@ class Parameter(BaseModel): """ Describes how the parameter value will be serialized depending on the type of the parameter value. Default values (based on value of `in`): - + - for `query` - `form`; - for `path` - `simple`; - for `header` - `simple`; @@ -111,7 +111,7 @@ class Parameter(BaseModel): Example of the parameter's potential value. The example SHOULD match the specified schema and encoding properties if present. The `example` field is mutually exclusive of the `examples` field. - Furthermore, if referencing a `schema` that contains an example, + Furthermore, if referencing a `schema` that contains an example, the `example` value SHALL _override_ the example provided by the schema. To represent examples of media types that cannot naturally be represented in JSON or YAML, a string value can contain the example with escaping where necessary. @@ -127,7 +127,7 @@ class Parameter(BaseModel): """ """ - For more complex scenarios, the [`content`](#parameterContent) property + For more complex scenarios, the [`content`](#parameterContent) property can define the media type and schema of the parameter. A parameter MUST contain either a `schema` property, or a `content` property, but not both. When `example` or `examples` are provided in conjunction with the `schema` object, @@ -142,6 +142,7 @@ class Parameter(BaseModel): """ class Config: + extra = Extra.forbid allow_population_by_field_name = True schema_extra = { "examples": [ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/path_item.py b/openapi_python_client/schema/openapi_schema_pydantic/path_item.py index 911c1e805..da96ede56 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/path_item.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/path_item.py @@ -1,6 +1,6 @@ from typing import List, Optional, Union -from pydantic import BaseModel, Field +from pydantic import BaseModel, Extra, Field from .operation import Operation from .parameter import Parameter @@ -20,7 +20,7 @@ class PathItem(BaseModel): """ Allows for an external definition of this path item. The referenced structure MUST be in the format of a [Path Item Object](#pathItemObject). - + In case a Path Item Object field appears both in the defined object and the referenced object, the behavior is undefined. """ @@ -92,6 +92,7 @@ class PathItem(BaseModel): """ class Config: + extra = Extra.forbid allow_population_by_field_name = True schema_extra = { "examples": [ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/paths.py b/openapi_python_client/schema/openapi_schema_pydantic/paths.py index 5f31b6e29..9e2b13c24 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/paths.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/paths.py @@ -2,6 +2,7 @@ from .path_item import PathItem + Paths = Dict[str, PathItem] """ Holds the relative paths to the individual endpoints and their operations. @@ -16,7 +17,7 @@ """ A relative path to an individual endpoint. The field name MUST begin with a forward slash (`/`). -The path is **appended** (no relative URL resolution) to the expanded URL +The path is **appended** (no relative URL resolution) to the expanded URL from the [`Server Object`](#serverObject)'s `url` field in order to construct the full URL. [Path templating](#pathTemplating) is allowed. When matching URLs, concrete (non-templated) paths would be matched before their templated counterparts. diff --git a/openapi_python_client/schema/openapi_schema_pydantic/reference.py b/openapi_python_client/schema/openapi_schema_pydantic/reference.py index 7803b3a54..54a73a290 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/reference.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/reference.py @@ -1,4 +1,4 @@ -from pydantic import BaseModel, Field +from pydantic import BaseModel, Extra, Field class Reference(BaseModel): @@ -16,6 +16,7 @@ class Reference(BaseModel): """**REQUIRED**. The reference string.""" class Config: + extra = Extra.forbid allow_population_by_field_name = True schema_extra = { "examples": [{"$ref": "#/components/schemas/Pet"}, {"$ref": "Pet.json"}, {"$ref": "definitions.json#/Pet"}] diff --git a/openapi_python_client/schema/openapi_schema_pydantic/request_body.py b/openapi_python_client/schema/openapi_schema_pydantic/request_body.py index 626b795d7..308fc1ea3 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/request_body.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/request_body.py @@ -1,6 +1,6 @@ from typing import Dict, Optional -from pydantic import BaseModel +from pydantic import BaseModel, Extra from .media_type import MediaType @@ -11,17 +11,17 @@ class RequestBody(BaseModel): description: Optional[str] = None """ A brief description of the request body. - This could contain examples of use. - + This could contain examples of use. + [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. """ - content: Dict[str, MediaType] + content: Dict[str, MediaType] = ... """ **REQUIRED**. The content of the request body. The key is a media type or [media type range](https://tools.ietf.org/html/rfc7231#appendix-D) and the value describes it. - + For requests that match multiple keys, only the most specific key is applicable. e.g. text/plain overrides text/* """ @@ -31,6 +31,7 @@ class RequestBody(BaseModel): """ class Config: + extra = Extra.forbid schema_extra = { "examples": [ { diff --git a/openapi_python_client/schema/openapi_schema_pydantic/response.py b/openapi_python_client/schema/openapi_schema_pydantic/response.py index 8c8e539ec..f432faeb6 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/response.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/response.py @@ -1,6 +1,6 @@ from typing import Dict, Optional, Union -from pydantic import BaseModel +from pydantic import BaseModel, Extra from .header import Header from .link import Link @@ -14,7 +14,7 @@ class Response(BaseModel): static `links` to operations based on the response. """ - description: str + description: str = ... """ **REQUIRED**. A short description of the response. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. @@ -31,8 +31,8 @@ class Response(BaseModel): """ A map containing descriptions of potential response payloads. The key is a media type or [media type range](https://tools.ietf.org/html/rfc7231#appendix-D) - and the value describes it. - + and the value describes it. + For responses that match multiple keys, only the most specific key is applicable. e.g. text/plain overrides text/* """ @@ -44,6 +44,7 @@ class Response(BaseModel): """ class Config: + extra = Extra.forbid schema_extra = { "examples": [ { diff --git a/openapi_python_client/schema/openapi_schema_pydantic/responses.py b/openapi_python_client/schema/openapi_schema_pydantic/responses.py index 6f3d9f8ce..980dcb9f7 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/responses.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/responses.py @@ -1,7 +1,8 @@ from typing import Dict, Union -from .reference import Reference from .response import Response +from .reference import Reference + Responses = Dict[str, Union[Response, Reference]] """ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/schema.py b/openapi_python_client/schema/openapi_schema_pydantic/schema.py index 5941d79f5..c7898eb15 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/schema.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/schema.py @@ -1,7 +1,6 @@ from typing import Any, Dict, List, Optional, Union -from pydantic import BaseModel, Field - +from pydantic import BaseModel, Extra, Field from .discriminator import Discriminator from .external_documentation import ExternalDocumentation from .reference import Reference @@ -36,7 +35,7 @@ class Schema(BaseModel): multipleOf: Optional[float] = Field(default=None, gt=0.0) """ The value of "multipleOf" MUST be a number, strictly greater than 0. - + A numeric instance is only valid if division by this keyword's value results in an integer. """ @@ -45,7 +44,7 @@ class Schema(BaseModel): """ The value of "maximum" MUST be a number, representing an upper limit for a numeric instance. - + If the instance is a number, then this keyword validates if "exclusiveMaximum" is true and instance is less than the provided value, or else if the instance is less than or exactly equal to the @@ -57,7 +56,7 @@ class Schema(BaseModel): The value of "exclusiveMaximum" MUST be a boolean, representing whether the limit in "maximum" is exclusive or not. An undefined value is the same as false. - + If "exclusiveMaximum" is true, then a numeric instance SHOULD NOT be equal to the value specified in "maximum". If "exclusiveMaximum" is false (or not specified), then a numeric instance MAY be equal to the @@ -68,7 +67,7 @@ class Schema(BaseModel): """ The value of "minimum" MUST be a number, representing a lower limit for a numeric instance. - + If the instance is a number, then this keyword validates if "exclusiveMinimum" is true and instance is greater than the provided value, or else if the instance is greater than or exactly equal to @@ -80,7 +79,7 @@ class Schema(BaseModel): The value of "exclusiveMinimum" MUST be a boolean, representing whether the limit in "minimum" is exclusive or not. An undefined value is the same as false. - + If "exclusiveMinimum" is true, then a numeric instance SHOULD NOT be equal to the value specified in "minimum". If "exclusiveMinimum" is false (or not specified), then a numeric instance MAY be equal to the @@ -93,10 +92,10 @@ class Schema(BaseModel): The value of this keyword MUST be an integer. This integer MUST be greater than, or equal to, 0. - + A string instance is valid against this keyword if its length is less than, or equal to, the value of this keyword. - + The length of a string instance is defined as the number of its characters as defined by RFC 7159 [RFC7159]. """ @@ -105,13 +104,13 @@ class Schema(BaseModel): """ A string instance is valid against this keyword if its length is greater than, or equal to, the value of this keyword. - + The length of a string instance is defined as the number of its characters as defined by RFC 7159 [RFC7159]. - + The value of this keyword MUST be an integer. This integer MUST be greater than, or equal to, 0. - + "minLength", if absent, may be considered as being present with integer value 0. """ @@ -121,7 +120,7 @@ class Schema(BaseModel): The value of this keyword MUST be a string. This string SHOULD be a valid regular expression, according to the ECMA 262 regular expression dialect. - + A string instance is considered valid if the regular expression matches the instance successfully. Recall: regular expressions are not implicitly anchored. @@ -131,7 +130,7 @@ class Schema(BaseModel): """ The value of this keyword MUST be an integer. This integer MUST be greater than, or equal to, 0. - + An array instance is valid against "maxItems" if its size is less than, or equal to, the value of this keyword. """ @@ -140,10 +139,10 @@ class Schema(BaseModel): """ The value of this keyword MUST be an integer. This integer MUST be greater than, or equal to, 0. - + An array instance is valid against "minItems" if its size is greater than, or equal to, the value of this keyword. - + If this keyword is not present, it may be considered present with a value of 0. """ @@ -155,7 +154,7 @@ class Schema(BaseModel): If this keyword has boolean value false, the instance validates successfully. If it has boolean value true, the instance validates successfully if all of its elements are unique. - + If not present, this keyword may be considered present with boolean value false. """ @@ -164,7 +163,7 @@ class Schema(BaseModel): """ The value of this keyword MUST be an integer. This integer MUST be greater than, or equal to, 0. - + An object instance is valid against "maxProperties" if its number of properties is less than, or equal to, the value of this keyword. """ @@ -173,10 +172,10 @@ class Schema(BaseModel): """ The value of this keyword MUST be an integer. This integer MUST be greater than, or equal to, 0. - + An object instance is valid against "minProperties" if its number of properties is greater than, or equal to, the value of this keyword. - + If this keyword is not present, it may be considered present with a value of 0. """ @@ -186,7 +185,7 @@ class Schema(BaseModel): The value of this keyword MUST be an array. This array MUST have at least one element. Elements of this array MUST be strings, and MUST be unique. - + An object instance is valid against this keyword if its property set contains all elements in this keyword's array value. """ @@ -195,9 +194,9 @@ class Schema(BaseModel): """ The value of this keyword MUST be an array. This array SHOULD have at least one element. Elements in the array SHOULD be unique. - + Elements in the array MAY be of any type, including null. - + An instance validates successfully against this keyword if its value is equal to one of the elements in this keyword's array value. """ @@ -211,15 +210,15 @@ class Schema(BaseModel): """ **From OpenAPI spec: Value MUST be a string. Multiple types via an array are not supported.** - + From JSON Schema: The value of this keyword MUST be either a string or an array. If it is an array, elements of the array MUST be strings and MUST be unique. - + String values MUST be one of the seven primitive types defined by the core specification. - + An instance matches successfully if its primitive type is one of the types defined by keyword. Recall: "number" includes "integer". """ @@ -228,48 +227,48 @@ class Schema(BaseModel): """ **From OpenAPI spec: Inline or referenced schema MUST be of a [Schema Object](#schemaObject) and not a standard JSON Schema.** - + From JSON Schema: This keyword's value MUST be an array. This array MUST have at least one element. - + Elements of the array MUST be objects. Each object MUST be a valid JSON Schema. - + An instance validates successfully against this keyword if it validates successfully against all schemas defined by this keyword's value. """ - oneOf: List[Union[Reference, "Schema"]] = [] + oneOf: Optional[List[Union[Reference, "Schema"]]] = None """ **From OpenAPI spec: Inline or referenced schema MUST be of a [Schema Object](#schemaObject) and not a standard JSON Schema.** - + From JSON Schema: This keyword's value MUST be an array. This array MUST have at least one element. - + Elements of the array MUST be objects. Each object MUST be a valid JSON Schema. - + An instance validates successfully against this keyword if it validates successfully against exactly one schema defined by this keyword's value. """ - anyOf: List[Union[Reference, "Schema"]] = [] + anyOf: Optional[List[Union[Reference, "Schema"]]] = None """ **From OpenAPI spec: Inline or referenced schema MUST be of a [Schema Object](#schemaObject) and not a standard JSON Schema.** - + From JSON Schema: This keyword's value MUST be an array. This array MUST have at least one element. - + Elements of the array MUST be objects. Each object MUST be a valid JSON Schema. - + An instance validates successfully against this keyword if it validates successfully against at least one schema defined by this keyword's value. @@ -279,11 +278,11 @@ class Schema(BaseModel): """ **From OpenAPI spec: Inline or referenced schema MUST be of a [Schema Object](#schemaObject) and not a standard JSON Schema.** - + From JSON Schema: This keyword's value MUST be an object. This object MUST be a valid JSON Schema. - + An instance is valid against this keyword if it fails to validate successfully against the schema defined by this keyword. """ @@ -294,13 +293,13 @@ class Schema(BaseModel): Value MUST be an object and not an array. Inline or referenced schema MUST be of a [Schema Object](#schemaObject) and not a standard JSON Schema. `items` MUST be present if the `type` is `array`.** - + From JSON Schema: The value of "items" MUST be either a schema or array of schemas. Successful validation of an array instance with regards to these two keywords is determined as follows: - + - if "items" is not present, or its value is an object, validation of the instance always succeeds, regardless of the value of "additionalItems"; @@ -316,12 +315,12 @@ class Schema(BaseModel): **From OpenAPI spec: Property definitions MUST be a [Schema Object](#schemaObject) and not a standard JSON Schema (inline or referenced).** - + From JSON Schema: The value of "properties" MUST be an object. Each value of this object MUST be an object, and each object MUST be a valid JSON Schema. - + If absent, it can be considered the same as an empty object. """ @@ -331,19 +330,19 @@ class Schema(BaseModel): Value can be boolean or object. Inline or referenced schema MUST be of a [Schema Object](#schemaObject) and not a standard JSON Schema. Consistent with JSON Schema, `additionalProperties` defaults to `true`.** - + From JSON Schema: The value of "additionalProperties" MUST be a boolean or a schema. If "additionalProperties" is absent, it may be considered present with an empty schema as a value. - + If "additionalProperties" is true, validation always succeeds. - + If "additionalProperties" is false, validation succeeds only if the instance is an object and all properties on the instance were covered by "properties" and/or "patternProperties". - + If "additionalProperties" is an object, validate the value as a schema to all of the properties that weren't validated by "properties" nor "patternProperties". @@ -353,7 +352,7 @@ class Schema(BaseModel): """ **From OpenAPI spec: [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation.** - + From JSON Schema: The value "description" MUST be a string. @@ -368,7 +367,7 @@ class Schema(BaseModel): **From OpenAPI spec: [Data Type Formats](#dataTypeFormat) for further details. While relying on JSON Schema's defined formats, the OAS offers a few additional predefined formats.** - + From JSON Schema: Structural validation alone may be insufficient to validate that an instance meets all the requirements of an application. The "format" @@ -376,7 +375,7 @@ class Schema(BaseModel): fixed subset of values which are accurately described by authoritative resources, be they RFCs or other external specifications. - + The value of this keyword is called a format attribute. It MUST be a string. A format attribute can generally only validate a given set of instance types. If the type of the instance to validate is not in @@ -391,14 +390,14 @@ class Schema(BaseModel): as the value of the schema if one is not provided. Unlike JSON Schema, the value MUST conform to the defined type for the Schema Object defined at the same level. For example, if `type` is `string`, then `default` can be `"foo"` but cannot be `1`.** - + From JSON Schema: There are no restrictions placed on the value of this keyword. - + This keyword can be used to supply a default JSON value associated with a particular schema. It is RECOMMENDED that a default value be valid against the associated schema. - + This keyword MAY be used in root schemas, and in any subschemas. """ @@ -406,7 +405,7 @@ class Schema(BaseModel): Other than the JSON Schema subset fields, the following fields MAY be used for further schema documentation: """ - nullable: bool = False + nullable: Optional[bool] = None """ A `true` value adds `"null"` to the allowed type specified by the `type` keyword, only if `type` is explicitly defined within the same Schema Object. @@ -466,12 +465,13 @@ class Schema(BaseModel): """ deprecated: Optional[bool] = None - """ + """ Specifies that a schema is deprecated and SHOULD be transitioned out of usage. Default value is `false`. """ class Config: + extra = Extra.forbid allow_population_by_field_name = True schema_extra = { "examples": [ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/security_requirement.py b/openapi_python_client/schema/openapi_schema_pydantic/security_requirement.py index b5165f4f9..4eeb19e57 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/security_requirement.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/security_requirement.py @@ -1,5 +1,6 @@ from typing import Dict, List + SecurityRequirement = Dict[str, List[str]] """ Lists the required security schemes to execute this operation. diff --git a/openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py b/openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py index aee65bc2b..79ab33337 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py @@ -1,6 +1,6 @@ from typing import Optional -from pydantic import AnyUrl, BaseModel, Field +from pydantic import AnyUrl, BaseModel, Extra, Field from .oauth_flows import OAuthFlows @@ -15,7 +15,7 @@ class SecurityScheme(BaseModel): and [OpenID Connect Discovery](https://tools.ietf.org/html/draft-ietf-oauth-discovery-06). """ - type: str + type: str = ... """ **REQUIRED**. The type of the security scheme. Valid values are `"apiKey"`, `"http"`, `"oauth2"`, `"openIdConnect"`. @@ -41,7 +41,7 @@ class SecurityScheme(BaseModel): """ **REQUIRED** for `http`. The name of the HTTP Authorization scheme to be used in the [Authorization header as defined in RFC7235](https://tools.ietf.org/html/rfc7235#section-5.1). - + The values used SHOULD be registered in the [IANA Authentication Scheme registry](https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml). """ @@ -49,7 +49,7 @@ class SecurityScheme(BaseModel): bearerFormat: Optional[str] = None """ A hint to the client to identify how the bearer token is formatted. - + Bearer tokens are usually generated by an authorization server, so this information is primarily for documentation purposes. """ @@ -66,6 +66,7 @@ class SecurityScheme(BaseModel): """ class Config: + extra = Extra.forbid allow_population_by_field_name = True schema_extra = { "examples": [ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/server.py b/openapi_python_client/schema/openapi_schema_pydantic/server.py index 43c511f34..983d5a383 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/server.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/server.py @@ -1,6 +1,6 @@ from typing import Dict, Optional -from pydantic import BaseModel +from pydantic import BaseModel, Extra from .server_variable import ServerVariable @@ -8,10 +8,10 @@ class Server(BaseModel): """An object representing a Server.""" - url: str + url: str = ... """ **REQUIRED**. A URL to the target host. - + This URL supports Server Variables and MAY be relative, to indicate that the host location is relative to the location where the OpenAPI document is being served. Variable substitutions will be made when a variable is named in `{`brackets`}`. @@ -26,11 +26,12 @@ class Server(BaseModel): variables: Optional[Dict[str, ServerVariable]] = None """ A map between a variable name and its value. - + The value is used for substitution in the server's URL template. """ class Config: + extra = Extra.forbid schema_extra = { "examples": [ {"url": "https://development.gigantic-server.com/v1", "description": "Development server"}, diff --git a/openapi_python_client/schema/openapi_schema_pydantic/server_variable.py b/openapi_python_client/schema/openapi_schema_pydantic/server_variable.py index 224c79411..fabb643c8 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/server_variable.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/server_variable.py @@ -1,6 +1,6 @@ from typing import List, Optional -from pydantic import BaseModel +from pydantic import BaseModel, Extra class ServerVariable(BaseModel): @@ -12,11 +12,11 @@ class ServerVariable(BaseModel): The array SHOULD NOT be empty. """ - default: str + default: str = ... """ **REQUIRED**. The default value to use for substitution, which SHALL be sent if an alternate value is _not_ supplied. - Note this behavior is different than the [Schema Object's](#schemaObject) treatment of default values, + Note this behavior is different than the [Schema Object's](#schemaObject) treatment of default values, because in those cases parameter values are optional. If the [`enum`](#serverVariableEnum) is defined, the value SHOULD exist in the enum's values. """ @@ -26,3 +26,6 @@ class ServerVariable(BaseModel): An optional description for the server variable. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. """ + + class Config: + extra = Extra.forbid diff --git a/openapi_python_client/schema/openapi_schema_pydantic/tag.py b/openapi_python_client/schema/openapi_schema_pydantic/tag.py index 531de02b4..8b6f21a0c 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/tag.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/tag.py @@ -1,6 +1,6 @@ from typing import Optional -from pydantic import BaseModel +from pydantic import BaseModel, Extra from .external_documentation import ExternalDocumentation @@ -11,7 +11,7 @@ class Tag(BaseModel): It is not mandatory to have a Tag Object per tag defined in the Operation Object instances. """ - name: str + name: str = ... """ **REQUIRED**. The name of the tag. """ @@ -28,4 +28,5 @@ class Tag(BaseModel): """ class Config: + extra = Extra.forbid schema_extra = {"examples": [{"name": "pet", "description": "Pets operations"}]} diff --git a/openapi_python_client/schema/openapi_schema_pydantic/xml.py b/openapi_python_client/schema/openapi_schema_pydantic/xml.py index 9ddaf13e3..5feb02417 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/xml.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/xml.py @@ -1,6 +1,6 @@ from typing import Optional -from pydantic import BaseModel +from pydantic import BaseModel, Extra class XML(BaseModel): @@ -48,6 +48,7 @@ class XML(BaseModel): """ class Config: + extra = Extra.forbid schema_extra = { "examples": [ {"namespace": "http://example.com/schema/sample", "prefix": "sample"}, From a36b49cb564429009a3e08cdd72f5acf6f6f6e48 Mon Sep 17 00:00:00 2001 From: Nementon Date: Thu, 13 May 2021 13:08:23 +0200 Subject: [PATCH 02/13] vendored openapi_schema_pydantic / correct flake8 warnings - correct: W293, W291, F821 --- .../openapi_schema_pydantic/__init__.py | 45 ++++---- .../openapi_schema_pydantic/callback.py | 3 +- .../openapi_schema_pydantic/encoding.py | 12 +-- .../schema/openapi_schema_pydantic/example.py | 2 +- .../schema/openapi_schema_pydantic/link.py | 4 +- .../openapi_schema_pydantic/media_type.py | 12 +-- .../openapi_schema_pydantic/oauth_flow.py | 2 +- .../openapi_schema_pydantic/oauth_flows.py | 4 +- .../openapi_schema_pydantic/open_api.py | 10 +- .../openapi_schema_pydantic/operation.py | 10 +- .../openapi_schema_pydantic/parameter.py | 16 +-- .../openapi_schema_pydantic/path_item.py | 2 +- .../schema/openapi_schema_pydantic/paths.py | 3 +- .../openapi_schema_pydantic/request_body.py | 6 +- .../openapi_schema_pydantic/response.py | 4 +- .../openapi_schema_pydantic/responses.py | 3 +- .../schema/openapi_schema_pydantic/schema.py | 101 +++++++++--------- .../security_requirement.py | 1 - .../security_scheme.py | 4 +- .../schema/openapi_schema_pydantic/server.py | 4 +- .../server_variable.py | 2 +- 21 files changed, 124 insertions(+), 126 deletions(-) diff --git a/openapi_python_client/schema/openapi_schema_pydantic/__init__.py b/openapi_python_client/schema/openapi_schema_pydantic/__init__.py index 27fba924f..6b02446a8 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/__init__.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/__init__.py @@ -36,36 +36,37 @@ "ServerVariable", "Tag", "XML", + "Callback", ] -from .open_api import OpenAPI -from .info import Info +from .callback import Callback +from .components import Components from .contact import Contact +from .discriminator import Discriminator +from .encoding import Encoding +from .example import Example +from .external_documentation import ExternalDocumentation +from .header import Header +from .info import Info from .license import License -from .server import Server -from .server_variable import ServerVariable -from .components import Components -from .paths import Paths -from .path_item import PathItem +from .link import Link +from .media_type import MediaType +from .oauth_flow import OAuthFlow +from .oauth_flows import OAuthFlows +from .open_api import OpenAPI from .operation import Operation -from .external_documentation import ExternalDocumentation from .parameter import Parameter +from .path_item import PathItem +from .paths import Paths +from .reference import Reference from .request_body import RequestBody -from .media_type import MediaType -from .encoding import Encoding -from .responses import Responses from .response import Response -from .callback import Callback -from .example import Example -from .link import Link -from .header import Header -from .tag import Tag -from .reference import Reference +from .responses import Responses from .schema import Schema -from .discriminator import Discriminator -from .xml import XML -from .security_scheme import SecurityScheme -from .oauth_flows import OAuthFlows -from .oauth_flow import OAuthFlow from .security_requirement import SecurityRequirement +from .security_scheme import SecurityScheme +from .server import Server +from .server_variable import ServerVariable +from .tag import Tag +from .xml import XML diff --git a/openapi_python_client/schema/openapi_schema_pydantic/callback.py b/openapi_python_client/schema/openapi_schema_pydantic/callback.py index 35bea75d7..7607e95f3 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/callback.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/callback.py @@ -1,7 +1,6 @@ from typing import Dict - -Callback = Dict[str, "PathItem"] +Callback = Dict[str, "PathItem"] # noqa """ A map of possible out-of band callbacks related to the parent operation. Each value in the map is a [Path Item Object](#pathItemObject) diff --git a/openapi_python_client/schema/openapi_schema_pydantic/encoding.py b/openapi_python_client/schema/openapi_schema_pydantic/encoding.py index d18447639..b42c3c9a6 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/encoding.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/encoding.py @@ -12,20 +12,20 @@ class Encoding(BaseModel): """ The Content-Type for encoding a specific property. Default value depends on the property type: - + - for `string` with `format` being `binary` – `application/octet-stream`; - for other primitive types – `text/plain`; - for `object` - `application/json`; - for `array` – the default is defined based on the inner type. - + The value can be a specific media type (e.g. `application/json`), a wildcard media type (e.g. `image/*`), or a comma-separated list of the two types. """ - headers: Optional[Dict[str, Union["Header", Reference]]] = None + headers: Optional[Dict[str, Union["Header", Reference]]] = None # noqa """ A map allowing additional information to be provided as headers, for example `Content-Disposition`. - + `Content-Type` is described separately and SHALL be ignored in this section. This property SHALL be ignored if the request body media type is not a `multipart`. """ @@ -33,7 +33,7 @@ class Encoding(BaseModel): style: Optional[str] = None """ Describes how a specific property value will be serialized depending on its type. - + See [Parameter Object](#parameterObject) for details on the [`style`](#parameterStyle) property. The behavior follows the same values as `query` parameters, including default values. This property SHALL be ignored if the request body media type is not `application/x-www-form-urlencoded`. @@ -43,7 +43,7 @@ class Encoding(BaseModel): """ When this is true, property values of type `array` or `object` generate separate parameters for each value of the array, or key-value-pair of the map. - + For other types of properties this property has no effect. When [`style`](#encodingStyle) is `form`, the default value is `true`. For all other styles, the default value is `false`. diff --git a/openapi_python_client/schema/openapi_schema_pydantic/example.py b/openapi_python_client/schema/openapi_schema_pydantic/example.py index 1eda5a11b..206145f0a 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/example.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/example.py @@ -28,7 +28,7 @@ class Example(BaseModel): """ A URL that points to the literal example. This provides the capability to reference examples that cannot easily be included in JSON or YAML documents. - + The `value` field and `externalValue` field are mutually exclusive. """ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/link.py b/openapi_python_client/schema/openapi_schema_pydantic/link.py index 174dca9b5..bb0ff90b6 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/link.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/link.py @@ -31,7 +31,7 @@ class Link(BaseModel): operationId: Optional[str] = None """ The name of an _existing_, resolvable OAS operation, as defined with a unique `operationId`. - + This field is mutually exclusive of the `operationRef` field. """ @@ -41,7 +41,7 @@ class Link(BaseModel): as specified with `operationId` or identified via `operationRef`. The key is the parameter name to be used, whereas the value can be a constant or an expression to be evaluated and passed to the linked operation. - + The parameter name can be qualified using the [parameter location](#parameterIn) `[{in}.]{name}` for operations that use the same parameter name in different locations (e.g. path.id). """ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/media_type.py b/openapi_python_client/schema/openapi_schema_pydantic/media_type.py index 38319c5e9..690948ed8 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/media_type.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/media_type.py @@ -19,11 +19,11 @@ class MediaType(BaseModel): example: Optional[Any] = None """ Example of the media type. - + The example object SHOULD be in the correct format as specified by the media type. - + The `example` field is mutually exclusive of the `examples` field. - + Furthermore, if referencing a `schema` which contains an example, the `example` value SHALL _override_ the example provided by the schema. """ @@ -31,11 +31,11 @@ class MediaType(BaseModel): examples: Optional[Dict[str, Union[Example, Reference]]] = None """ Examples of the media type. - + Each example object SHOULD match the media type and specified schema if present. - + The `examples` field is mutually exclusive of the `example` field. - + Furthermore, if referencing a `schema` which contains an example, the `examples` value SHALL _override_ the example provided by the schema. """ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py b/openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py index 524be0f2b..65286da57 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py @@ -1,4 +1,4 @@ -from typing import Dict, Optional, Union +from typing import Dict, Optional from pydantic import AnyUrl, BaseModel, Extra diff --git a/openapi_python_client/schema/openapi_schema_pydantic/oauth_flows.py b/openapi_python_client/schema/openapi_schema_pydantic/oauth_flows.py index c71370cd1..642a8c850 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/oauth_flows.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/oauth_flows.py @@ -23,14 +23,14 @@ class OAuthFlows(BaseModel): clientCredentials: Optional[OAuthFlow] = None """ Configuration for the OAuth Client Credentials flow. - + Previously called `application` in OpenAPI 2.0. """ authorizationCode: Optional[OAuthFlow] = None """ Configuration for the OAuth Authorization Code flow. - + Previously called `accessCode` in OpenAPI 2.0. """ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/open_api.py b/openapi_python_client/schema/openapi_schema_pydantic/open_api.py index a03080470..e6ca4d929 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/open_api.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/open_api.py @@ -21,7 +21,7 @@ class OpenAPI(BaseModel): servers: List[Server] = [Server(url="/")] """ - An array of Server Objects, which provide connectivity information to a target server. + An array of Server Objects, which provide connectivity information to a target server. If the `servers` property is not provided, or is an empty array, the default value would be a [Server Object](#serverObject) with a [url](#serverUrl) value of `/`. """ @@ -38,10 +38,10 @@ class OpenAPI(BaseModel): security: Optional[List[SecurityRequirement]] = None """ - A declaration of which security mechanisms can be used across the API. - The list of values includes alternative security requirement objects that can be used. - Only one of the security requirement objects need to be satisfied to authorize a request. - Individual operations can override this definition. + A declaration of which security mechanisms can be used across the API. + The list of values includes alternative security requirement objects that can be used. + Only one of the security requirement objects need to be satisfied to authorize a request. + Individual operations can override this definition. To make security optional, an empty security requirement (`{}`) can be included in the array. """ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/operation.py b/openapi_python_client/schema/openapi_schema_pydantic/operation.py index 49150e6f7..9f04ebd5d 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/operation.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/operation.py @@ -59,10 +59,10 @@ class Operation(BaseModel): requestBody: Optional[Union[RequestBody, Reference]] = None """ - The request body applicable for this operation. - + The request body applicable for this operation. + The `requestBody` is only supported in HTTP methods where the HTTP 1.1 specification - [RFC7231](https://tools.ietf.org/html/rfc7231#section-4.3.1) has explicitly defined semantics for request bodies. + [RFC7231](https://tools.ietf.org/html/rfc7231#section-4.3.1) has explicitly defined semantics for request bodies. In other cases where the HTTP spec is vague, `requestBody` SHALL be ignored by consumers. """ @@ -75,7 +75,7 @@ class Operation(BaseModel): """ A map of possible out-of band callbacks related to the parent operation. The key is a unique identifier for the Callback Object. - Each value in the map is a [Callback Object](#callbackObject) + Each value in the map is a [Callback Object](#callbackObject) that describes a request that may be initiated by the API provider and the expected responses. """ @@ -99,7 +99,7 @@ class Operation(BaseModel): servers: Optional[List[Server]] = None """ An alternative `server` array to service this operation. - If an alternative `server` object is specified at the Path Item Object or Root level, + If an alternative `server` object is specified at the Path Item Object or Root level, it will be overridden by this value. """ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/parameter.py b/openapi_python_client/schema/openapi_schema_pydantic/parameter.py index c4ffd5ef2..cd52493e4 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/parameter.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/parameter.py @@ -1,6 +1,6 @@ from typing import Any, Dict, Optional, Union -from pydantic import BaseModel, Field, Extra +from pydantic import BaseModel, Extra, Field from ..parameter_location import ParameterLocation from .example import Example @@ -21,12 +21,12 @@ class Parameter(BaseModel): name: str = ... """ **REQUIRED**. The name of the parameter. - Parameter names are *case sensitive*. - - - If [`in`](#parameterIn) is `"path"`, the `name` field MUST correspond to a template expression occurring + Parameter names are *case sensitive*. + + - If [`in`](#parameterIn) is `"path"`, the `name` field MUST correspond to a template expression occurring within the [path](#pathsPath) field in the [Paths Object](#pathsObject). See [Path Templating](#pathTemplating) for further information. - - If [`in`](#parameterIn) is `"header"` and the `name` field is `"Accept"`, `"Content-Type"` or `"Authorization"`, + - If [`in`](#parameterIn) is `"header"` and the `name` field is `"Accept"`, `"Content-Type"` or `"Authorization"`, the parameter definition SHALL be ignored. - For all other cases, the `name` corresponds to the parameter name used by the [`in`](#parameterIn) property. """ @@ -76,7 +76,7 @@ class Parameter(BaseModel): """ Describes how the parameter value will be serialized depending on the type of the parameter value. Default values (based on value of `in`): - + - for `query` - `form`; - for `path` - `simple`; - for `header` - `simple`; @@ -111,7 +111,7 @@ class Parameter(BaseModel): Example of the parameter's potential value. The example SHOULD match the specified schema and encoding properties if present. The `example` field is mutually exclusive of the `examples` field. - Furthermore, if referencing a `schema` that contains an example, + Furthermore, if referencing a `schema` that contains an example, the `example` value SHALL _override_ the example provided by the schema. To represent examples of media types that cannot naturally be represented in JSON or YAML, a string value can contain the example with escaping where necessary. @@ -127,7 +127,7 @@ class Parameter(BaseModel): """ """ - For more complex scenarios, the [`content`](#parameterContent) property + For more complex scenarios, the [`content`](#parameterContent) property can define the media type and schema of the parameter. A parameter MUST contain either a `schema` property, or a `content` property, but not both. When `example` or `examples` are provided in conjunction with the `schema` object, diff --git a/openapi_python_client/schema/openapi_schema_pydantic/path_item.py b/openapi_python_client/schema/openapi_schema_pydantic/path_item.py index da96ede56..8c6bc12f8 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/path_item.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/path_item.py @@ -20,7 +20,7 @@ class PathItem(BaseModel): """ Allows for an external definition of this path item. The referenced structure MUST be in the format of a [Path Item Object](#pathItemObject). - + In case a Path Item Object field appears both in the defined object and the referenced object, the behavior is undefined. """ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/paths.py b/openapi_python_client/schema/openapi_schema_pydantic/paths.py index 9e2b13c24..5f31b6e29 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/paths.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/paths.py @@ -2,7 +2,6 @@ from .path_item import PathItem - Paths = Dict[str, PathItem] """ Holds the relative paths to the individual endpoints and their operations. @@ -17,7 +16,7 @@ """ A relative path to an individual endpoint. The field name MUST begin with a forward slash (`/`). -The path is **appended** (no relative URL resolution) to the expanded URL +The path is **appended** (no relative URL resolution) to the expanded URL from the [`Server Object`](#serverObject)'s `url` field in order to construct the full URL. [Path templating](#pathTemplating) is allowed. When matching URLs, concrete (non-templated) paths would be matched before their templated counterparts. diff --git a/openapi_python_client/schema/openapi_schema_pydantic/request_body.py b/openapi_python_client/schema/openapi_schema_pydantic/request_body.py index 308fc1ea3..f4b598b29 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/request_body.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/request_body.py @@ -11,8 +11,8 @@ class RequestBody(BaseModel): description: Optional[str] = None """ A brief description of the request body. - This could contain examples of use. - + This could contain examples of use. + [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. """ @@ -21,7 +21,7 @@ class RequestBody(BaseModel): **REQUIRED**. The content of the request body. The key is a media type or [media type range](https://tools.ietf.org/html/rfc7231#appendix-D) and the value describes it. - + For requests that match multiple keys, only the most specific key is applicable. e.g. text/plain overrides text/* """ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/response.py b/openapi_python_client/schema/openapi_schema_pydantic/response.py index f432faeb6..335ae40ae 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/response.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/response.py @@ -31,8 +31,8 @@ class Response(BaseModel): """ A map containing descriptions of potential response payloads. The key is a media type or [media type range](https://tools.ietf.org/html/rfc7231#appendix-D) - and the value describes it. - + and the value describes it. + For responses that match multiple keys, only the most specific key is applicable. e.g. text/plain overrides text/* """ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/responses.py b/openapi_python_client/schema/openapi_schema_pydantic/responses.py index 980dcb9f7..6f3d9f8ce 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/responses.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/responses.py @@ -1,8 +1,7 @@ from typing import Dict, Union -from .response import Response from .reference import Reference - +from .response import Response Responses = Dict[str, Union[Response, Reference]] """ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/schema.py b/openapi_python_client/schema/openapi_schema_pydantic/schema.py index c7898eb15..158ee15d7 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/schema.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/schema.py @@ -1,6 +1,7 @@ from typing import Any, Dict, List, Optional, Union from pydantic import BaseModel, Extra, Field + from .discriminator import Discriminator from .external_documentation import ExternalDocumentation from .reference import Reference @@ -35,7 +36,7 @@ class Schema(BaseModel): multipleOf: Optional[float] = Field(default=None, gt=0.0) """ The value of "multipleOf" MUST be a number, strictly greater than 0. - + A numeric instance is only valid if division by this keyword's value results in an integer. """ @@ -44,7 +45,7 @@ class Schema(BaseModel): """ The value of "maximum" MUST be a number, representing an upper limit for a numeric instance. - + If the instance is a number, then this keyword validates if "exclusiveMaximum" is true and instance is less than the provided value, or else if the instance is less than or exactly equal to the @@ -56,7 +57,7 @@ class Schema(BaseModel): The value of "exclusiveMaximum" MUST be a boolean, representing whether the limit in "maximum" is exclusive or not. An undefined value is the same as false. - + If "exclusiveMaximum" is true, then a numeric instance SHOULD NOT be equal to the value specified in "maximum". If "exclusiveMaximum" is false (or not specified), then a numeric instance MAY be equal to the @@ -67,7 +68,7 @@ class Schema(BaseModel): """ The value of "minimum" MUST be a number, representing a lower limit for a numeric instance. - + If the instance is a number, then this keyword validates if "exclusiveMinimum" is true and instance is greater than the provided value, or else if the instance is greater than or exactly equal to @@ -79,7 +80,7 @@ class Schema(BaseModel): The value of "exclusiveMinimum" MUST be a boolean, representing whether the limit in "minimum" is exclusive or not. An undefined value is the same as false. - + If "exclusiveMinimum" is true, then a numeric instance SHOULD NOT be equal to the value specified in "minimum". If "exclusiveMinimum" is false (or not specified), then a numeric instance MAY be equal to the @@ -92,10 +93,10 @@ class Schema(BaseModel): The value of this keyword MUST be an integer. This integer MUST be greater than, or equal to, 0. - + A string instance is valid against this keyword if its length is less than, or equal to, the value of this keyword. - + The length of a string instance is defined as the number of its characters as defined by RFC 7159 [RFC7159]. """ @@ -104,13 +105,13 @@ class Schema(BaseModel): """ A string instance is valid against this keyword if its length is greater than, or equal to, the value of this keyword. - + The length of a string instance is defined as the number of its characters as defined by RFC 7159 [RFC7159]. - + The value of this keyword MUST be an integer. This integer MUST be greater than, or equal to, 0. - + "minLength", if absent, may be considered as being present with integer value 0. """ @@ -120,7 +121,7 @@ class Schema(BaseModel): The value of this keyword MUST be a string. This string SHOULD be a valid regular expression, according to the ECMA 262 regular expression dialect. - + A string instance is considered valid if the regular expression matches the instance successfully. Recall: regular expressions are not implicitly anchored. @@ -130,7 +131,7 @@ class Schema(BaseModel): """ The value of this keyword MUST be an integer. This integer MUST be greater than, or equal to, 0. - + An array instance is valid against "maxItems" if its size is less than, or equal to, the value of this keyword. """ @@ -139,10 +140,10 @@ class Schema(BaseModel): """ The value of this keyword MUST be an integer. This integer MUST be greater than, or equal to, 0. - + An array instance is valid against "minItems" if its size is greater than, or equal to, the value of this keyword. - + If this keyword is not present, it may be considered present with a value of 0. """ @@ -154,7 +155,7 @@ class Schema(BaseModel): If this keyword has boolean value false, the instance validates successfully. If it has boolean value true, the instance validates successfully if all of its elements are unique. - + If not present, this keyword may be considered present with boolean value false. """ @@ -163,7 +164,7 @@ class Schema(BaseModel): """ The value of this keyword MUST be an integer. This integer MUST be greater than, or equal to, 0. - + An object instance is valid against "maxProperties" if its number of properties is less than, or equal to, the value of this keyword. """ @@ -172,10 +173,10 @@ class Schema(BaseModel): """ The value of this keyword MUST be an integer. This integer MUST be greater than, or equal to, 0. - + An object instance is valid against "minProperties" if its number of properties is greater than, or equal to, the value of this keyword. - + If this keyword is not present, it may be considered present with a value of 0. """ @@ -185,7 +186,7 @@ class Schema(BaseModel): The value of this keyword MUST be an array. This array MUST have at least one element. Elements of this array MUST be strings, and MUST be unique. - + An object instance is valid against this keyword if its property set contains all elements in this keyword's array value. """ @@ -194,9 +195,9 @@ class Schema(BaseModel): """ The value of this keyword MUST be an array. This array SHOULD have at least one element. Elements in the array SHOULD be unique. - + Elements in the array MAY be of any type, including null. - + An instance validates successfully against this keyword if its value is equal to one of the elements in this keyword's array value. """ @@ -210,15 +211,15 @@ class Schema(BaseModel): """ **From OpenAPI spec: Value MUST be a string. Multiple types via an array are not supported.** - + From JSON Schema: The value of this keyword MUST be either a string or an array. If it is an array, elements of the array MUST be strings and MUST be unique. - + String values MUST be one of the seven primitive types defined by the core specification. - + An instance matches successfully if its primitive type is one of the types defined by keyword. Recall: "number" includes "integer". """ @@ -227,14 +228,14 @@ class Schema(BaseModel): """ **From OpenAPI spec: Inline or referenced schema MUST be of a [Schema Object](#schemaObject) and not a standard JSON Schema.** - + From JSON Schema: This keyword's value MUST be an array. This array MUST have at least one element. - + Elements of the array MUST be objects. Each object MUST be a valid JSON Schema. - + An instance validates successfully against this keyword if it validates successfully against all schemas defined by this keyword's value. @@ -244,14 +245,14 @@ class Schema(BaseModel): """ **From OpenAPI spec: Inline or referenced schema MUST be of a [Schema Object](#schemaObject) and not a standard JSON Schema.** - + From JSON Schema: This keyword's value MUST be an array. This array MUST have at least one element. - + Elements of the array MUST be objects. Each object MUST be a valid JSON Schema. - + An instance validates successfully against this keyword if it validates successfully against exactly one schema defined by this keyword's value. @@ -261,14 +262,14 @@ class Schema(BaseModel): """ **From OpenAPI spec: Inline or referenced schema MUST be of a [Schema Object](#schemaObject) and not a standard JSON Schema.** - + From JSON Schema: This keyword's value MUST be an array. This array MUST have at least one element. - + Elements of the array MUST be objects. Each object MUST be a valid JSON Schema. - + An instance validates successfully against this keyword if it validates successfully against at least one schema defined by this keyword's value. @@ -278,11 +279,11 @@ class Schema(BaseModel): """ **From OpenAPI spec: Inline or referenced schema MUST be of a [Schema Object](#schemaObject) and not a standard JSON Schema.** - + From JSON Schema: This keyword's value MUST be an object. This object MUST be a valid JSON Schema. - + An instance is valid against this keyword if it fails to validate successfully against the schema defined by this keyword. """ @@ -293,13 +294,13 @@ class Schema(BaseModel): Value MUST be an object and not an array. Inline or referenced schema MUST be of a [Schema Object](#schemaObject) and not a standard JSON Schema. `items` MUST be present if the `type` is `array`.** - + From JSON Schema: The value of "items" MUST be either a schema or array of schemas. Successful validation of an array instance with regards to these two keywords is determined as follows: - + - if "items" is not present, or its value is an object, validation of the instance always succeeds, regardless of the value of "additionalItems"; @@ -315,12 +316,12 @@ class Schema(BaseModel): **From OpenAPI spec: Property definitions MUST be a [Schema Object](#schemaObject) and not a standard JSON Schema (inline or referenced).** - + From JSON Schema: The value of "properties" MUST be an object. Each value of this object MUST be an object, and each object MUST be a valid JSON Schema. - + If absent, it can be considered the same as an empty object. """ @@ -330,19 +331,19 @@ class Schema(BaseModel): Value can be boolean or object. Inline or referenced schema MUST be of a [Schema Object](#schemaObject) and not a standard JSON Schema. Consistent with JSON Schema, `additionalProperties` defaults to `true`.** - + From JSON Schema: The value of "additionalProperties" MUST be a boolean or a schema. If "additionalProperties" is absent, it may be considered present with an empty schema as a value. - + If "additionalProperties" is true, validation always succeeds. - + If "additionalProperties" is false, validation succeeds only if the instance is an object and all properties on the instance were covered by "properties" and/or "patternProperties". - + If "additionalProperties" is an object, validate the value as a schema to all of the properties that weren't validated by "properties" nor "patternProperties". @@ -352,7 +353,7 @@ class Schema(BaseModel): """ **From OpenAPI spec: [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation.** - + From JSON Schema: The value "description" MUST be a string. @@ -367,7 +368,7 @@ class Schema(BaseModel): **From OpenAPI spec: [Data Type Formats](#dataTypeFormat) for further details. While relying on JSON Schema's defined formats, the OAS offers a few additional predefined formats.** - + From JSON Schema: Structural validation alone may be insufficient to validate that an instance meets all the requirements of an application. The "format" @@ -375,7 +376,7 @@ class Schema(BaseModel): fixed subset of values which are accurately described by authoritative resources, be they RFCs or other external specifications. - + The value of this keyword is called a format attribute. It MUST be a string. A format attribute can generally only validate a given set of instance types. If the type of the instance to validate is not in @@ -390,14 +391,14 @@ class Schema(BaseModel): as the value of the schema if one is not provided. Unlike JSON Schema, the value MUST conform to the defined type for the Schema Object defined at the same level. For example, if `type` is `string`, then `default` can be `"foo"` but cannot be `1`.** - + From JSON Schema: There are no restrictions placed on the value of this keyword. - + This keyword can be used to supply a default JSON value associated with a particular schema. It is RECOMMENDED that a default value be valid against the associated schema. - + This keyword MAY be used in root schemas, and in any subschemas. """ @@ -465,7 +466,7 @@ class Schema(BaseModel): """ deprecated: Optional[bool] = None - """ + """ Specifies that a schema is deprecated and SHOULD be transitioned out of usage. Default value is `false`. """ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/security_requirement.py b/openapi_python_client/schema/openapi_schema_pydantic/security_requirement.py index 4eeb19e57..b5165f4f9 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/security_requirement.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/security_requirement.py @@ -1,6 +1,5 @@ from typing import Dict, List - SecurityRequirement = Dict[str, List[str]] """ Lists the required security schemes to execute this operation. diff --git a/openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py b/openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py index 79ab33337..7c278afd9 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py @@ -41,7 +41,7 @@ class SecurityScheme(BaseModel): """ **REQUIRED** for `http`. The name of the HTTP Authorization scheme to be used in the [Authorization header as defined in RFC7235](https://tools.ietf.org/html/rfc7235#section-5.1). - + The values used SHOULD be registered in the [IANA Authentication Scheme registry](https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml). """ @@ -49,7 +49,7 @@ class SecurityScheme(BaseModel): bearerFormat: Optional[str] = None """ A hint to the client to identify how the bearer token is formatted. - + Bearer tokens are usually generated by an authorization server, so this information is primarily for documentation purposes. """ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/server.py b/openapi_python_client/schema/openapi_schema_pydantic/server.py index 983d5a383..17802478f 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/server.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/server.py @@ -11,7 +11,7 @@ class Server(BaseModel): url: str = ... """ **REQUIRED**. A URL to the target host. - + This URL supports Server Variables and MAY be relative, to indicate that the host location is relative to the location where the OpenAPI document is being served. Variable substitutions will be made when a variable is named in `{`brackets`}`. @@ -26,7 +26,7 @@ class Server(BaseModel): variables: Optional[Dict[str, ServerVariable]] = None """ A map between a variable name and its value. - + The value is used for substitution in the server's URL template. """ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/server_variable.py b/openapi_python_client/schema/openapi_schema_pydantic/server_variable.py index fabb643c8..4b30c3415 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/server_variable.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/server_variable.py @@ -16,7 +16,7 @@ class ServerVariable(BaseModel): """ **REQUIRED**. The default value to use for substitution, which SHALL be sent if an alternate value is _not_ supplied. - Note this behavior is different than the [Schema Object's](#schemaObject) treatment of default values, + Note this behavior is different than the [Schema Object's](#schemaObject) treatment of default values, because in those cases parameter values are optional. If the [`enum`](#serverVariableEnum) is defined, the value SHOULD exist in the enum's values. """ From 655f7c0a4675479b280e68b3d994bab281771f63 Mon Sep 17 00:00:00 2001 From: Nementon Date: Thu, 13 May 2021 01:51:33 +0200 Subject: [PATCH 03/13] correct openapi_schema_pydantic schemas breaking changes - anyOf, allOf, oneOf now default to `None` instead of `[]` --- .../parser/properties/__init__.py | 15 ++++++++++++--- .../parser/properties/property.py | 2 +- openapi_python_client/utils.py | 12 +++++++++++- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/openapi_python_client/parser/properties/__init__.py b/openapi_python_client/parser/properties/__init__.py index 908745a6a..6a5fa357f 100644 --- a/openapi_python_client/parser/properties/__init__.py +++ b/openapi_python_client/parser/properties/__init__.py @@ -9,7 +9,6 @@ "property_from_data", ] -from itertools import chain from typing import Any, ClassVar, Dict, Generic, Iterable, Iterator, List, Optional, Set, Tuple, TypeVar, Union import attr @@ -352,7 +351,13 @@ def build_union_property( *, data: oai.Schema, name: str, required: bool, schemas: Schemas, parent_name: str, config: Config ) -> Tuple[Union[UnionProperty, PropertyError], Schemas]: sub_properties: List[Property] = [] - for i, sub_prop_data in enumerate(chain(data.anyOf, data.oneOf)): + + sub_data: List[Union[oai.Schema, oai.Reference]] = [] + for _data in [data.anyOf, data.oneOf]: + if isinstance(_data, Iterable): + sub_data.extend(_data) + + for i, sub_prop_data in enumerate(sub_data): sub_prop, schemas = property_from_data( name=f"{name}_type{i}", required=required, @@ -439,8 +444,12 @@ def _property_from_data( if isinstance(data, oai.Reference): return _property_from_ref(name=name, required=required, parent=None, data=data, schemas=schemas) + sub_data: List[Union[oai.Schema, oai.Reference]] = [] + for _data in [data.allOf, data.anyOf, data.oneOf]: + if isinstance(_data, Iterable): + sub_data.extend(_data) + # A union of a single reference should just be passed through to that reference (don't create copy class) - sub_data = (data.allOf or []) + data.anyOf + data.oneOf if len(sub_data) == 1 and isinstance(sub_data[0], oai.Reference): return _property_from_ref(name=name, required=required, parent=data, data=sub_data[0], schemas=schemas) diff --git a/openapi_python_client/parser/properties/property.py b/openapi_python_client/parser/properties/property.py index d4ce54980..d82921377 100644 --- a/openapi_python_client/parser/properties/property.py +++ b/openapi_python_client/parser/properties/property.py @@ -22,7 +22,7 @@ class Property: name: str required: bool - nullable: bool + nullable: bool = attr.ib(converter=utils.optin_bool_to_bool_converter) _type_string: ClassVar[str] = "" _json_type_string: ClassVar[str] = "" # Type of the property after JSON serialization default: Optional[str] = attr.ib() diff --git a/openapi_python_client/utils.py b/openapi_python_client/utils.py index 7a7c84185..e8338948f 100644 --- a/openapi_python_client/utils.py +++ b/openapi_python_client/utils.py @@ -1,7 +1,7 @@ import builtins import re from keyword import iskeyword -from typing import List +from typing import List, Optional delimiters = " _-" @@ -73,3 +73,13 @@ def to_valid_python_identifier(value: str) -> str: return new_value return f"{FIELD_PREFIX}{new_value}" + + +def optin_bool_to_bool_converter(value: Optional[bool]) -> bool: + """ + Given an Option[bool] return a bool + None are converted to False + """ + if value is None: + return False + return value From 1903a751ae957655c488f3dca55a2f3b12616bd1 Mon Sep 17 00:00:00 2001 From: p1-ra Date: Thu, 13 May 2021 17:32:30 +0200 Subject: [PATCH 04/13] update unit tests --- tests/test_parser/test_openapi.py | 6 ++++-- tests/test_parser/test_properties/test_init.py | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/test_parser/test_openapi.py b/tests/test_parser/test_openapi.py index a220d243c..b135543c4 100644 --- a/tests/test_parser/test_openapi.py +++ b/tests/test_parser/test_openapi.py @@ -92,13 +92,15 @@ def test_swagger_document_invalid_schema(self, mocker): header="Failed to parse OpenAPI document", detail=( "You may be trying to use a Swagger document; this is not supported by this project.\n\n" - "3 validation errors for OpenAPI\n" + "4 validation errors for OpenAPI\n" "info\n" " field required (type=value_error.missing)\n" "paths\n" " field required (type=value_error.missing)\n" "openapi\n" - " field required (type=value_error.missing)" + " field required (type=value_error.missing)\n" + "swagger\n" + " extra fields not permitted (type=value_error.extra)" ), ) Schemas.build.assert_not_called() diff --git a/tests/test_parser/test_properties/test_init.py b/tests/test_parser/test_properties/test_init.py index 1f5646d74..5666726a1 100644 --- a/tests/test_parser/test_properties/test_init.py +++ b/tests/test_parser/test_properties/test_init.py @@ -974,14 +974,14 @@ def test_property_from_data_union(self, mocker): name=name, required=required, data=data, schemas=Schemas(), parent_name="parent", config=MagicMock() ) - FloatProperty.assert_called_once_with(name=name, required=required, default=0.0, nullable=False) - IntProperty.assert_called_once_with(name=name, required=required, default=0, nullable=False) + FloatProperty.assert_called_once_with(name=name, required=required, default=0.0, nullable=None) + IntProperty.assert_called_once_with(name=name, required=required, default=0, nullable=None) UnionProperty.assert_called_once_with( name=name, required=required, default=None, inner_properties=[FloatProperty.return_value, IntProperty.return_value], - nullable=False, + nullable=None, ) assert p == UnionProperty.return_value assert s == Schemas() From 65a6c94e361a17eb7999f5896293461cc65cd699 Mon Sep 17 00:00:00 2001 From: p1-ra Date: Thu, 13 May 2021 18:41:14 +0200 Subject: [PATCH 05/13] parser / properties / avoid call to isinstance for perf imprv --- openapi_python_client/parser/properties/__init__.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/openapi_python_client/parser/properties/__init__.py b/openapi_python_client/parser/properties/__init__.py index 6a5fa357f..1df7bea17 100644 --- a/openapi_python_client/parser/properties/__init__.py +++ b/openapi_python_client/parser/properties/__init__.py @@ -9,6 +9,7 @@ "property_from_data", ] +from itertools import chain from typing import Any, ClassVar, Dict, Generic, Iterable, Iterator, List, Optional, Set, Tuple, TypeVar, Union import attr @@ -352,12 +353,7 @@ def build_union_property( ) -> Tuple[Union[UnionProperty, PropertyError], Schemas]: sub_properties: List[Property] = [] - sub_data: List[Union[oai.Schema, oai.Reference]] = [] - for _data in [data.anyOf, data.oneOf]: - if isinstance(_data, Iterable): - sub_data.extend(_data) - - for i, sub_prop_data in enumerate(sub_data): + for i, sub_prop_data in enumerate(chain(data.anyOf or [], data.oneOf or [])): sub_prop, schemas = property_from_data( name=f"{name}_type{i}", required=required, @@ -445,8 +441,8 @@ def _property_from_data( return _property_from_ref(name=name, required=required, parent=None, data=data, schemas=schemas) sub_data: List[Union[oai.Schema, oai.Reference]] = [] - for _data in [data.allOf, data.anyOf, data.oneOf]: - if isinstance(_data, Iterable): + for _data in (data.allOf, data.anyOf, data.oneOf): + if _data: sub_data.extend(_data) # A union of a single reference should just be passed through to that reference (don't create copy class) From 75fff054afa9b0424c9c3f68d5f126d025eb003f Mon Sep 17 00:00:00 2001 From: p1-ra Date: Thu, 13 May 2021 18:43:54 +0200 Subject: [PATCH 06/13] openapi_schema_pydantic / schema / set `nullable` type to `bool` --- openapi_python_client/parser/properties/property.py | 2 +- .../schema/openapi_schema_pydantic/schema.py | 2 +- openapi_python_client/utils.py | 12 +----------- tests/test_parser/test_properties/test_init.py | 6 +++--- 4 files changed, 6 insertions(+), 16 deletions(-) diff --git a/openapi_python_client/parser/properties/property.py b/openapi_python_client/parser/properties/property.py index d82921377..d4ce54980 100644 --- a/openapi_python_client/parser/properties/property.py +++ b/openapi_python_client/parser/properties/property.py @@ -22,7 +22,7 @@ class Property: name: str required: bool - nullable: bool = attr.ib(converter=utils.optin_bool_to_bool_converter) + nullable: bool _type_string: ClassVar[str] = "" _json_type_string: ClassVar[str] = "" # Type of the property after JSON serialization default: Optional[str] = attr.ib() diff --git a/openapi_python_client/schema/openapi_schema_pydantic/schema.py b/openapi_python_client/schema/openapi_schema_pydantic/schema.py index 158ee15d7..5a0cb1f91 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/schema.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/schema.py @@ -406,7 +406,7 @@ class Schema(BaseModel): Other than the JSON Schema subset fields, the following fields MAY be used for further schema documentation: """ - nullable: Optional[bool] = None + nullable: bool = False """ A `true` value adds `"null"` to the allowed type specified by the `type` keyword, only if `type` is explicitly defined within the same Schema Object. diff --git a/openapi_python_client/utils.py b/openapi_python_client/utils.py index e8338948f..7a7c84185 100644 --- a/openapi_python_client/utils.py +++ b/openapi_python_client/utils.py @@ -1,7 +1,7 @@ import builtins import re from keyword import iskeyword -from typing import List, Optional +from typing import List delimiters = " _-" @@ -73,13 +73,3 @@ def to_valid_python_identifier(value: str) -> str: return new_value return f"{FIELD_PREFIX}{new_value}" - - -def optin_bool_to_bool_converter(value: Optional[bool]) -> bool: - """ - Given an Option[bool] return a bool - None are converted to False - """ - if value is None: - return False - return value diff --git a/tests/test_parser/test_properties/test_init.py b/tests/test_parser/test_properties/test_init.py index 5666726a1..1f5646d74 100644 --- a/tests/test_parser/test_properties/test_init.py +++ b/tests/test_parser/test_properties/test_init.py @@ -974,14 +974,14 @@ def test_property_from_data_union(self, mocker): name=name, required=required, data=data, schemas=Schemas(), parent_name="parent", config=MagicMock() ) - FloatProperty.assert_called_once_with(name=name, required=required, default=0.0, nullable=None) - IntProperty.assert_called_once_with(name=name, required=required, default=0, nullable=None) + FloatProperty.assert_called_once_with(name=name, required=required, default=0.0, nullable=False) + IntProperty.assert_called_once_with(name=name, required=required, default=0, nullable=False) UnionProperty.assert_called_once_with( name=name, required=required, default=None, inner_properties=[FloatProperty.return_value, IntProperty.return_value], - nullable=None, + nullable=False, ) assert p == UnionProperty.return_value assert s == Schemas() From 450b0d412e360b230f86a2452fe522e4b30e359f Mon Sep 17 00:00:00 2001 From: p1-ra Date: Thu, 13 May 2021 18:51:04 +0200 Subject: [PATCH 07/13] openapi_schema_pydantic / remove ellipsis notation - Mypy do not well support it to declare `undefined` value --- .../schema/openapi_schema_pydantic/discriminator.py | 2 +- .../schema/openapi_schema_pydantic/external_documentation.py | 2 +- openapi_python_client/schema/openapi_schema_pydantic/info.py | 4 ++-- .../schema/openapi_schema_pydantic/license.py | 2 +- .../schema/openapi_schema_pydantic/oauth_flow.py | 2 +- .../schema/openapi_schema_pydantic/open_api.py | 4 ++-- .../schema/openapi_schema_pydantic/operation.py | 2 +- .../schema/openapi_schema_pydantic/parameter.py | 2 +- .../schema/openapi_schema_pydantic/request_body.py | 2 +- .../schema/openapi_schema_pydantic/response.py | 2 +- .../schema/openapi_schema_pydantic/security_scheme.py | 2 +- .../schema/openapi_schema_pydantic/server.py | 2 +- .../schema/openapi_schema_pydantic/server_variable.py | 2 +- openapi_python_client/schema/openapi_schema_pydantic/tag.py | 2 +- 14 files changed, 16 insertions(+), 16 deletions(-) diff --git a/openapi_python_client/schema/openapi_schema_pydantic/discriminator.py b/openapi_python_client/schema/openapi_schema_pydantic/discriminator.py index 74338386d..7174e1264 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/discriminator.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/discriminator.py @@ -14,7 +14,7 @@ class Discriminator(BaseModel): When using the discriminator, _inline_ schemas will not be considered. """ - propertyName: str = ... + propertyName: str """ **REQUIRED**. The name of the property in the payload that will hold the discriminator value. """ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/external_documentation.py b/openapi_python_client/schema/openapi_schema_pydantic/external_documentation.py index d2859b1aa..e99651690 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/external_documentation.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/external_documentation.py @@ -12,7 +12,7 @@ class ExternalDocumentation(BaseModel): [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. """ - url: AnyUrl = ... + url: AnyUrl """ **REQUIRED**. The URL for the target documentation. Value MUST be in the format of a URL. diff --git a/openapi_python_client/schema/openapi_schema_pydantic/info.py b/openapi_python_client/schema/openapi_schema_pydantic/info.py index 13376475c..95ffb5c89 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/info.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/info.py @@ -13,7 +13,7 @@ class Info(BaseModel): and MAY be presented in editing or documentation generation tools for convenience. """ - title: str = ... + title: str """ **REQUIRED**. The title of the API. """ @@ -40,7 +40,7 @@ class Info(BaseModel): The license information for the exposed API. """ - version: str = ... + version: str """ **REQUIRED**. The version of the OpenAPI document (which is distinct from the [OpenAPI Specification version](#oasVersion) or the API implementation version). diff --git a/openapi_python_client/schema/openapi_schema_pydantic/license.py b/openapi_python_client/schema/openapi_schema_pydantic/license.py index d44267696..363a06c47 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/license.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/license.py @@ -8,7 +8,7 @@ class License(BaseModel): License information for the exposed API. """ - name: str = ... + name: str """ **REQUIRED**. The license name used for the API. """ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py b/openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py index 65286da57..50fd627b5 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py @@ -27,7 +27,7 @@ class OAuthFlow(BaseModel): The URL to be used for obtaining refresh tokens. This MUST be in the form of a URL. """ - scopes: Dict[str, str] = ... + scopes: Dict[str, str] """ **REQUIRED**. The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. diff --git a/openapi_python_client/schema/openapi_schema_pydantic/open_api.py b/openapi_python_client/schema/openapi_schema_pydantic/open_api.py index e6ca4d929..3927cdd96 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/open_api.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/open_api.py @@ -14,7 +14,7 @@ class OpenAPI(BaseModel): """This is the root document object of the OpenAPI document.""" - info: Info = ... + info: Info """ **REQUIRED**. Provides metadata about the API. The metadata MAY be used by tooling as required. """ @@ -26,7 +26,7 @@ class OpenAPI(BaseModel): the default value would be a [Server Object](#serverObject) with a [url](#serverUrl) value of `/`. """ - paths: Paths = ... + paths: Paths """ **REQUIRED**. The available paths and operations for the API. """ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/operation.py b/openapi_python_client/schema/openapi_schema_pydantic/operation.py index 9f04ebd5d..620436214 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/operation.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/operation.py @@ -66,7 +66,7 @@ class Operation(BaseModel): In other cases where the HTTP spec is vague, `requestBody` SHALL be ignored by consumers. """ - responses: Responses = ... + responses: Responses """ **REQUIRED**. The list of possible responses as they are returned from executing this operation. """ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/parameter.py b/openapi_python_client/schema/openapi_schema_pydantic/parameter.py index cd52493e4..9e9d0674a 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/parameter.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/parameter.py @@ -18,7 +18,7 @@ class Parameter(BaseModel): """Fixed Fields""" - name: str = ... + name: str """ **REQUIRED**. The name of the parameter. Parameter names are *case sensitive*. diff --git a/openapi_python_client/schema/openapi_schema_pydantic/request_body.py b/openapi_python_client/schema/openapi_schema_pydantic/request_body.py index f4b598b29..f15d41f31 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/request_body.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/request_body.py @@ -16,7 +16,7 @@ class RequestBody(BaseModel): [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. """ - content: Dict[str, MediaType] = ... + content: Dict[str, MediaType] """ **REQUIRED**. The content of the request body. The key is a media type or [media type range](https://tools.ietf.org/html/rfc7231#appendix-D) diff --git a/openapi_python_client/schema/openapi_schema_pydantic/response.py b/openapi_python_client/schema/openapi_schema_pydantic/response.py index 335ae40ae..152661e7a 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/response.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/response.py @@ -14,7 +14,7 @@ class Response(BaseModel): static `links` to operations based on the response. """ - description: str = ... + description: str """ **REQUIRED**. A short description of the response. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. diff --git a/openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py b/openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py index 7c278afd9..868bb2c71 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py @@ -15,7 +15,7 @@ class SecurityScheme(BaseModel): and [OpenID Connect Discovery](https://tools.ietf.org/html/draft-ietf-oauth-discovery-06). """ - type: str = ... + type: str """ **REQUIRED**. The type of the security scheme. Valid values are `"apiKey"`, `"http"`, `"oauth2"`, `"openIdConnect"`. diff --git a/openapi_python_client/schema/openapi_schema_pydantic/server.py b/openapi_python_client/schema/openapi_schema_pydantic/server.py index 17802478f..b94fe6bbd 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/server.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/server.py @@ -8,7 +8,7 @@ class Server(BaseModel): """An object representing a Server.""" - url: str = ... + url: str """ **REQUIRED**. A URL to the target host. diff --git a/openapi_python_client/schema/openapi_schema_pydantic/server_variable.py b/openapi_python_client/schema/openapi_schema_pydantic/server_variable.py index 4b30c3415..57254c2e1 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/server_variable.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/server_variable.py @@ -12,7 +12,7 @@ class ServerVariable(BaseModel): The array SHOULD NOT be empty. """ - default: str = ... + default: str """ **REQUIRED**. The default value to use for substitution, which SHALL be sent if an alternate value is _not_ supplied. diff --git a/openapi_python_client/schema/openapi_schema_pydantic/tag.py b/openapi_python_client/schema/openapi_schema_pydantic/tag.py index 8b6f21a0c..e80e57b93 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/tag.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/tag.py @@ -11,7 +11,7 @@ class Tag(BaseModel): It is not mandatory to have a Tag Object per tag defined in the Operation Object instances. """ - name: str = ... + name: str """ **REQUIRED**. The name of the tag. """ From b90f5f7d15f686600a326a470394079486e68180 Mon Sep 17 00:00:00 2001 From: p1-ra Date: Thu, 13 May 2021 19:27:18 +0200 Subject: [PATCH 08/13] openapi_schema_pydantic / allow extra values - For support of OAI vendor extension --- .../schema/openapi_schema_pydantic/components.py | 2 +- .../schema/openapi_schema_pydantic/contact.py | 2 +- .../schema/openapi_schema_pydantic/discriminator.py | 2 +- .../schema/openapi_schema_pydantic/encoding.py | 2 +- .../schema/openapi_schema_pydantic/example.py | 2 +- .../openapi_schema_pydantic/external_documentation.py | 2 +- .../schema/openapi_schema_pydantic/header.py | 2 +- .../schema/openapi_schema_pydantic/info.py | 2 +- .../schema/openapi_schema_pydantic/license.py | 2 +- .../schema/openapi_schema_pydantic/link.py | 2 +- .../schema/openapi_schema_pydantic/media_type.py | 2 +- .../schema/openapi_schema_pydantic/oauth_flow.py | 2 +- .../schema/openapi_schema_pydantic/oauth_flows.py | 2 +- .../schema/openapi_schema_pydantic/open_api.py | 2 +- .../schema/openapi_schema_pydantic/operation.py | 2 +- .../schema/openapi_schema_pydantic/parameter.py | 2 +- .../schema/openapi_schema_pydantic/path_item.py | 2 +- .../schema/openapi_schema_pydantic/reference.py | 2 +- .../schema/openapi_schema_pydantic/request_body.py | 2 +- .../schema/openapi_schema_pydantic/response.py | 2 +- .../schema/openapi_schema_pydantic/schema.py | 2 +- .../schema/openapi_schema_pydantic/security_scheme.py | 2 +- .../schema/openapi_schema_pydantic/server.py | 2 +- .../schema/openapi_schema_pydantic/server_variable.py | 2 +- openapi_python_client/schema/openapi_schema_pydantic/tag.py | 2 +- openapi_python_client/schema/openapi_schema_pydantic/xml.py | 2 +- tests/test_parser/test_openapi.py | 6 ++---- 27 files changed, 28 insertions(+), 30 deletions(-) diff --git a/openapi_python_client/schema/openapi_schema_pydantic/components.py b/openapi_python_client/schema/openapi_schema_pydantic/components.py index 95b3a6e97..a9a2f0339 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/components.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/components.py @@ -49,7 +49,7 @@ class Components(BaseModel): """An object to hold reusable [Callback Objects](#callbackObject).""" class Config: - extra = Extra.forbid + extra = Extra.allow schema_extra = { "examples": [ { diff --git a/openapi_python_client/schema/openapi_schema_pydantic/contact.py b/openapi_python_client/schema/openapi_schema_pydantic/contact.py index 8cf450fbb..cbe2fb8eb 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/contact.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/contact.py @@ -26,7 +26,7 @@ class Contact(BaseModel): """ class Config: - extra = Extra.forbid + extra = Extra.allow schema_extra = { "examples": [ {"name": "API Support", "url": "http://www.example.com/support", "email": "support@example.com"} diff --git a/openapi_python_client/schema/openapi_schema_pydantic/discriminator.py b/openapi_python_client/schema/openapi_schema_pydantic/discriminator.py index 7174e1264..c2deb5a17 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/discriminator.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/discriminator.py @@ -25,7 +25,7 @@ class Discriminator(BaseModel): """ class Config: - extra = Extra.forbid + extra = Extra.allow schema_extra = { "examples": [ { diff --git a/openapi_python_client/schema/openapi_schema_pydantic/encoding.py b/openapi_python_client/schema/openapi_schema_pydantic/encoding.py index b42c3c9a6..ee0373469 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/encoding.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/encoding.py @@ -60,7 +60,7 @@ class Encoding(BaseModel): """ class Config: - extra = Extra.forbid + extra = Extra.allow schema_extra = { "examples": [ { diff --git a/openapi_python_client/schema/openapi_schema_pydantic/example.py b/openapi_python_client/schema/openapi_schema_pydantic/example.py index 206145f0a..4ac234b37 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/example.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/example.py @@ -33,7 +33,7 @@ class Example(BaseModel): """ class Config: - extra = Extra.forbid + extra = Extra.allow schema_extra = { "examples": [ {"summary": "A foo example", "value": {"foo": "bar"}}, diff --git a/openapi_python_client/schema/openapi_schema_pydantic/external_documentation.py b/openapi_python_client/schema/openapi_schema_pydantic/external_documentation.py index e99651690..467c98150 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/external_documentation.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/external_documentation.py @@ -19,5 +19,5 @@ class ExternalDocumentation(BaseModel): """ class Config: - extra = Extra.forbid + extra = Extra.allow schema_extra = {"examples": [{"description": "Find more info here", "url": "https://example.com"}]} diff --git a/openapi_python_client/schema/openapi_schema_pydantic/header.py b/openapi_python_client/schema/openapi_schema_pydantic/header.py index f5ad792c9..8d6ee2ff1 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/header.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/header.py @@ -18,7 +18,7 @@ class Header(Parameter): param_in = Field(default=ParameterLocation.HEADER, const=True, alias="in") class Config: - extra = Extra.forbid + extra = Extra.allow allow_population_by_field_name = True schema_extra = { "examples": [ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/info.py b/openapi_python_client/schema/openapi_schema_pydantic/info.py index 95ffb5c89..fcff5b742 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/info.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/info.py @@ -47,7 +47,7 @@ class Info(BaseModel): """ class Config: - extra = Extra.forbid + extra = Extra.allow schema_extra = { "examples": [ { diff --git a/openapi_python_client/schema/openapi_schema_pydantic/license.py b/openapi_python_client/schema/openapi_schema_pydantic/license.py index 363a06c47..7e8b7f3d9 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/license.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/license.py @@ -20,5 +20,5 @@ class License(BaseModel): """ class Config: - extra = Extra.forbid + extra = Extra.allow schema_extra = {"examples": [{"name": "Apache 2.0", "url": "https://www.apache.org/licenses/LICENSE-2.0.html"}]} diff --git a/openapi_python_client/schema/openapi_schema_pydantic/link.py b/openapi_python_client/schema/openapi_schema_pydantic/link.py index bb0ff90b6..de1403a8c 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/link.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/link.py @@ -63,7 +63,7 @@ class Link(BaseModel): """ class Config: - extra = Extra.forbid + extra = Extra.allow schema_extra = { "examples": [ {"operationId": "getUserAddressByUUID", "parameters": {"userUuid": "$response.body#/uuid"}}, diff --git a/openapi_python_client/schema/openapi_schema_pydantic/media_type.py b/openapi_python_client/schema/openapi_schema_pydantic/media_type.py index 690948ed8..387f33b92 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/media_type.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/media_type.py @@ -49,7 +49,7 @@ class MediaType(BaseModel): """ class Config: - extra = Extra.forbid + extra = Extra.allow allow_population_by_field_name = True schema_extra = { "examples": [ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py b/openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py index 50fd627b5..7b3c93bfe 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py @@ -35,7 +35,7 @@ class OAuthFlow(BaseModel): """ class Config: - extra = Extra.forbid + extra = Extra.allow schema_extra = { "examples": [ { diff --git a/openapi_python_client/schema/openapi_schema_pydantic/oauth_flows.py b/openapi_python_client/schema/openapi_schema_pydantic/oauth_flows.py index 642a8c850..e23b3d5dd 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/oauth_flows.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/oauth_flows.py @@ -35,4 +35,4 @@ class OAuthFlows(BaseModel): """ class Config: - extra = Extra.forbid + extra = Extra.allow diff --git a/openapi_python_client/schema/openapi_schema_pydantic/open_api.py b/openapi_python_client/schema/openapi_schema_pydantic/open_api.py index 3927cdd96..cbfaa2038 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/open_api.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/open_api.py @@ -60,4 +60,4 @@ class OpenAPI(BaseModel): """ class Config: - extra = Extra.forbid + extra = Extra.allow diff --git a/openapi_python_client/schema/openapi_schema_pydantic/operation.py b/openapi_python_client/schema/openapi_schema_pydantic/operation.py index 620436214..98b2bd2ad 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/operation.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/operation.py @@ -104,7 +104,7 @@ class Operation(BaseModel): """ class Config: - extra = Extra.forbid + extra = Extra.allow schema_extra = { "examples": [ { diff --git a/openapi_python_client/schema/openapi_schema_pydantic/parameter.py b/openapi_python_client/schema/openapi_schema_pydantic/parameter.py index 9e9d0674a..56070a720 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/parameter.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/parameter.py @@ -142,7 +142,7 @@ class Parameter(BaseModel): """ class Config: - extra = Extra.forbid + extra = Extra.allow allow_population_by_field_name = True schema_extra = { "examples": [ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/path_item.py b/openapi_python_client/schema/openapi_schema_pydantic/path_item.py index 8c6bc12f8..cdbd6b564 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/path_item.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/path_item.py @@ -92,7 +92,7 @@ class PathItem(BaseModel): """ class Config: - extra = Extra.forbid + extra = Extra.allow allow_population_by_field_name = True schema_extra = { "examples": [ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/reference.py b/openapi_python_client/schema/openapi_schema_pydantic/reference.py index 54a73a290..851b28301 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/reference.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/reference.py @@ -16,7 +16,7 @@ class Reference(BaseModel): """**REQUIRED**. The reference string.""" class Config: - extra = Extra.forbid + extra = Extra.allow allow_population_by_field_name = True schema_extra = { "examples": [{"$ref": "#/components/schemas/Pet"}, {"$ref": "Pet.json"}, {"$ref": "definitions.json#/Pet"}] diff --git a/openapi_python_client/schema/openapi_schema_pydantic/request_body.py b/openapi_python_client/schema/openapi_schema_pydantic/request_body.py index f15d41f31..3f7a602d9 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/request_body.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/request_body.py @@ -31,7 +31,7 @@ class RequestBody(BaseModel): """ class Config: - extra = Extra.forbid + extra = Extra.allow schema_extra = { "examples": [ { diff --git a/openapi_python_client/schema/openapi_schema_pydantic/response.py b/openapi_python_client/schema/openapi_schema_pydantic/response.py index 152661e7a..24899815e 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/response.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/response.py @@ -44,7 +44,7 @@ class Response(BaseModel): """ class Config: - extra = Extra.forbid + extra = Extra.allow schema_extra = { "examples": [ { diff --git a/openapi_python_client/schema/openapi_schema_pydantic/schema.py b/openapi_python_client/schema/openapi_schema_pydantic/schema.py index 5a0cb1f91..029ef72c0 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/schema.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/schema.py @@ -472,7 +472,7 @@ class Schema(BaseModel): """ class Config: - extra = Extra.forbid + extra = Extra.allow allow_population_by_field_name = True schema_extra = { "examples": [ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py b/openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py index 868bb2c71..7bd3b4e8e 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py @@ -66,7 +66,7 @@ class SecurityScheme(BaseModel): """ class Config: - extra = Extra.forbid + extra = Extra.allow allow_population_by_field_name = True schema_extra = { "examples": [ diff --git a/openapi_python_client/schema/openapi_schema_pydantic/server.py b/openapi_python_client/schema/openapi_schema_pydantic/server.py index b94fe6bbd..949fec8c8 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/server.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/server.py @@ -31,7 +31,7 @@ class Server(BaseModel): """ class Config: - extra = Extra.forbid + extra = Extra.allow schema_extra = { "examples": [ {"url": "https://development.gigantic-server.com/v1", "description": "Development server"}, diff --git a/openapi_python_client/schema/openapi_schema_pydantic/server_variable.py b/openapi_python_client/schema/openapi_schema_pydantic/server_variable.py index 57254c2e1..8aa4fac46 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/server_variable.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/server_variable.py @@ -28,4 +28,4 @@ class ServerVariable(BaseModel): """ class Config: - extra = Extra.forbid + extra = Extra.allow diff --git a/openapi_python_client/schema/openapi_schema_pydantic/tag.py b/openapi_python_client/schema/openapi_schema_pydantic/tag.py index e80e57b93..1db40d325 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/tag.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/tag.py @@ -28,5 +28,5 @@ class Tag(BaseModel): """ class Config: - extra = Extra.forbid + extra = Extra.allow schema_extra = {"examples": [{"name": "pet", "description": "Pets operations"}]} diff --git a/openapi_python_client/schema/openapi_schema_pydantic/xml.py b/openapi_python_client/schema/openapi_schema_pydantic/xml.py index 5feb02417..cfc9c64cb 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/xml.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/xml.py @@ -48,7 +48,7 @@ class XML(BaseModel): """ class Config: - extra = Extra.forbid + extra = Extra.allow schema_extra = { "examples": [ {"namespace": "http://example.com/schema/sample", "prefix": "sample"}, diff --git a/tests/test_parser/test_openapi.py b/tests/test_parser/test_openapi.py index b135543c4..a220d243c 100644 --- a/tests/test_parser/test_openapi.py +++ b/tests/test_parser/test_openapi.py @@ -92,15 +92,13 @@ def test_swagger_document_invalid_schema(self, mocker): header="Failed to parse OpenAPI document", detail=( "You may be trying to use a Swagger document; this is not supported by this project.\n\n" - "4 validation errors for OpenAPI\n" + "3 validation errors for OpenAPI\n" "info\n" " field required (type=value_error.missing)\n" "paths\n" " field required (type=value_error.missing)\n" "openapi\n" - " field required (type=value_error.missing)\n" - "swagger\n" - " extra fields not permitted (type=value_error.extra)" + " field required (type=value_error.missing)" ), ) Schemas.build.assert_not_called() From a7fe7e2f8b7b43acb25b7d40dd887b465bb94c39 Mon Sep 17 00:00:00 2001 From: p1-ra Date: Thu, 13 May 2021 22:23:06 +0200 Subject: [PATCH 09/13] openapi_schema_pydantic / correct typing --- .../schema/openapi_schema_pydantic/callback.py | 7 +++++-- .../schema/openapi_schema_pydantic/encoding.py | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/openapi_python_client/schema/openapi_schema_pydantic/callback.py b/openapi_python_client/schema/openapi_schema_pydantic/callback.py index 7607e95f3..9d95ffe89 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/callback.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/callback.py @@ -1,6 +1,9 @@ -from typing import Dict +from typing import TYPE_CHECKING, Dict -Callback = Dict[str, "PathItem"] # noqa +if TYPE_CHECKING: + from .path_item import PathItem + +Callback = Dict[str, "PathItem"] """ A map of possible out-of band callbacks related to the parent operation. Each value in the map is a [Path Item Object](#pathItemObject) diff --git a/openapi_python_client/schema/openapi_schema_pydantic/encoding.py b/openapi_python_client/schema/openapi_schema_pydantic/encoding.py index ee0373469..a9c08a67e 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/encoding.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/encoding.py @@ -1,9 +1,12 @@ -from typing import Dict, Optional, Union +from typing import TYPE_CHECKING, Dict, Optional, Union from pydantic import BaseModel, Extra from .reference import Reference +if TYPE_CHECKING: + from .header import Header + class Encoding(BaseModel): """A single encoding definition applied to a single schema property.""" @@ -22,7 +25,7 @@ class Encoding(BaseModel): or a comma-separated list of the two types. """ - headers: Optional[Dict[str, Union["Header", Reference]]] = None # noqa + headers: Optional[Dict[str, Union["Header", Reference]]] = None """ A map allowing additional information to be provided as headers, for example `Content-Disposition`. From e58f7902d7a4ec8462485bfc94b19a7c5d4a27de Mon Sep 17 00:00:00 2001 From: p1-ra Date: Fri, 14 May 2021 00:52:09 +0200 Subject: [PATCH 10/13] openapi_schema_pydantic / schema / {any,all,one}Of default to `List.Empty` --- openapi_python_client/parser/properties/__init__.py | 8 ++------ openapi_python_client/parser/properties/model_property.py | 2 +- .../schema/openapi_schema_pydantic/schema.py | 6 +++--- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/openapi_python_client/parser/properties/__init__.py b/openapi_python_client/parser/properties/__init__.py index 1df7bea17..65dfe42f5 100644 --- a/openapi_python_client/parser/properties/__init__.py +++ b/openapi_python_client/parser/properties/__init__.py @@ -353,7 +353,7 @@ def build_union_property( ) -> Tuple[Union[UnionProperty, PropertyError], Schemas]: sub_properties: List[Property] = [] - for i, sub_prop_data in enumerate(chain(data.anyOf or [], data.oneOf or [])): + for i, sub_prop_data in enumerate(chain(data.anyOf, data.oneOf)): sub_prop, schemas = property_from_data( name=f"{name}_type{i}", required=required, @@ -440,11 +440,7 @@ def _property_from_data( if isinstance(data, oai.Reference): return _property_from_ref(name=name, required=required, parent=None, data=data, schemas=schemas) - sub_data: List[Union[oai.Schema, oai.Reference]] = [] - for _data in (data.allOf, data.anyOf, data.oneOf): - if _data: - sub_data.extend(_data) - + sub_data: List[Union[oai.Schema, oai.Reference]] = data.allOf + data.anyOf + data.oneOf # A union of a single reference should just be passed through to that reference (don't create copy class) if len(sub_data) == 1 and isinstance(sub_data[0], oai.Reference): return _property_from_ref(name=name, required=required, parent=data, data=sub_data[0], schemas=schemas) diff --git a/openapi_python_client/parser/properties/model_property.py b/openapi_python_client/parser/properties/model_property.py index a40460886..7ed00553d 100644 --- a/openapi_python_client/parser/properties/model_property.py +++ b/openapi_python_client/parser/properties/model_property.py @@ -88,7 +88,7 @@ def _check_existing(prop: Property) -> Union[Property, PropertyError]: return prop_or_error unprocessed_props = data.properties or {} - for sub_prop in data.allOf or []: + for sub_prop in data.allOf: if isinstance(sub_prop, oai.Reference): ref_path = parse_reference_path(sub_prop.ref) if isinstance(ref_path, ParseError): diff --git a/openapi_python_client/schema/openapi_schema_pydantic/schema.py b/openapi_python_client/schema/openapi_schema_pydantic/schema.py index 029ef72c0..87492eadc 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/schema.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/schema.py @@ -224,7 +224,7 @@ class Schema(BaseModel): types defined by keyword. Recall: "number" includes "integer". """ - allOf: Optional[List[Union[Reference, "Schema"]]] = None + allOf: List[Union[Reference, "Schema"]] = Field(default_factory=list) """ **From OpenAPI spec: Inline or referenced schema MUST be of a [Schema Object](#schemaObject) and not a standard JSON Schema.** @@ -241,7 +241,7 @@ class Schema(BaseModel): value. """ - oneOf: Optional[List[Union[Reference, "Schema"]]] = None + oneOf: List[Union[Reference, "Schema"]] = Field(default_factory=list) """ **From OpenAPI spec: Inline or referenced schema MUST be of a [Schema Object](#schemaObject) and not a standard JSON Schema.** @@ -258,7 +258,7 @@ class Schema(BaseModel): keyword's value. """ - anyOf: Optional[List[Union[Reference, "Schema"]]] = None + anyOf: List[Union[Reference, "Schema"]] = Field(default_factory=list) """ **From OpenAPI spec: Inline or referenced schema MUST be of a [Schema Object](#schemaObject) and not a standard JSON Schema.** From 767d8069b4bf08900ed027e9f39a3e724ad8e1fe Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Tue, 18 Jan 2022 12:12:12 -0700 Subject: [PATCH 11/13] style: Obey pylint --- .../schema/openapi_schema_pydantic/callback.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/openapi_python_client/schema/openapi_schema_pydantic/callback.py b/openapi_python_client/schema/openapi_schema_pydantic/callback.py index 9d95ffe89..e8d71758c 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/callback.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/callback.py @@ -2,8 +2,10 @@ if TYPE_CHECKING: from .path_item import PathItem +else: + PathItem = "PathItem" # pylint: disable=invalid-name -Callback = Dict[str, "PathItem"] +Callback = Dict[str, PathItem] """ A map of possible out-of band callbacks related to the parent operation. Each value in the map is a [Path Item Object](#pathItemObject) @@ -11,12 +13,3 @@ The key value used to identify the path item object is an expression, evaluated at runtime, that identifies a URL to use for the callback operation. """ - -"""Patterned Fields""" - -# {expression}: 'PathItem' = ... -""" -A Path Item Object used to define a callback request and expected responses. - -A [complete example](../examples/v3.0/callback-example.yaml) is available. -""" From 2ce92bf3f9980b40ed12a4838c634004c03efe5c Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Tue, 18 Jan 2022 12:18:29 -0700 Subject: [PATCH 12/13] style: A couple tweaks after code review --- .../schema/openapi_schema_pydantic/components.py | 2 -- .../schema/openapi_schema_pydantic/encoding.py | 4 +++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openapi_python_client/schema/openapi_schema_pydantic/components.py b/openapi_python_client/schema/openapi_schema_pydantic/components.py index 276a210b7..442b376c1 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/components.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/components.py @@ -33,9 +33,7 @@ class Components(BaseModel): headers: Optional[Dict[str, Union[Header, Reference]]] = None securitySchemes: Optional[Dict[str, Union[SecurityScheme, Reference]]] = None links: Optional[Dict[str, Union[Link, Reference]]] = None - callbacks: Optional[Dict[str, Union[Callback, Reference]]] = None - """An object to hold reusable [Callback Objects](#callbackObject).""" class Config: # pylint: disable=missing-class-docstring extra = Extra.allow diff --git a/openapi_python_client/schema/openapi_schema_pydantic/encoding.py b/openapi_python_client/schema/openapi_schema_pydantic/encoding.py index 63cff417c..47d79b73e 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/encoding.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/encoding.py @@ -6,6 +6,8 @@ if TYPE_CHECKING: from .header import Header +else: + Header = "Header" # pylint: disable=invalid-name class Encoding(BaseModel): @@ -17,7 +19,7 @@ class Encoding(BaseModel): """ contentType: Optional[str] = None - headers: Optional[Dict[str, Union["Header", Reference]]] = None + headers: Optional[Dict[str, Union[Header, Reference]]] = None style: Optional[str] = None explode: bool = False allowReserved: bool = False From 1bbbc98bcadfbcbf4d7323cc5e1a8a749a8cfc6a Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Tue, 18 Jan 2022 12:22:50 -0700 Subject: [PATCH 13/13] ci: Don't cover type-checking-only code --- .../schema/openapi_schema_pydantic/callback.py | 2 +- .../schema/openapi_schema_pydantic/encoding.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openapi_python_client/schema/openapi_schema_pydantic/callback.py b/openapi_python_client/schema/openapi_schema_pydantic/callback.py index e8d71758c..7535cdab8 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/callback.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/callback.py @@ -1,6 +1,6 @@ from typing import TYPE_CHECKING, Dict -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from .path_item import PathItem else: PathItem = "PathItem" # pylint: disable=invalid-name diff --git a/openapi_python_client/schema/openapi_schema_pydantic/encoding.py b/openapi_python_client/schema/openapi_schema_pydantic/encoding.py index 47d79b73e..7497b1650 100644 --- a/openapi_python_client/schema/openapi_schema_pydantic/encoding.py +++ b/openapi_python_client/schema/openapi_schema_pydantic/encoding.py @@ -4,7 +4,7 @@ from .reference import Reference -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from .header import Header else: Header = "Header" # pylint: disable=invalid-name