diff --git a/openapi_core/schema/components/factories.py b/openapi_core/schema/components/factories.py index 053f099..6afab0a 100644 --- a/openapi_core/schema/components/factories.py +++ b/openapi_core/schema/components/factories.py @@ -1,5 +1,6 @@ from openapi_core.compat import lru_cache from openapi_core.schema.components.models import Components +from openapi_core.schema.extensions.generators import ExtensionsGenerator from openapi_core.schema.schemas.generators import SchemasGenerator from openapi_core.schema.security_schemes.generators import ( SecuritySchemesGenerator, @@ -21,6 +22,8 @@ class ComponentsFactory(object): request_bodies_spec = components_deref.get('requestBodies', {}) security_schemes_spec = components_deref.get('securitySchemes', {}) + extensions = self.extensions_generator.generate(components_deref) + schemas = self.schemas_generator.generate(schemas_spec) responses = self._generate_response(responses_spec) parameters = self._generate_parameters(parameters_spec) @@ -30,6 +33,7 @@ class ComponentsFactory(object): return Components( schemas=list(schemas), responses=responses, parameters=parameters, request_bodies=request_bodies, security_schemes=security_schemes, + extensions=extensions, ) @property @@ -37,6 +41,11 @@ class ComponentsFactory(object): def schemas_generator(self): return SchemasGenerator(self.dereferencer, self.schemas_registry) + @property + @lru_cache() + def extensions_generator(self): + return ExtensionsGenerator(self.dereferencer) + def _generate_response(self, responses_spec): return responses_spec diff --git a/openapi_core/schema/components/models.py b/openapi_core/schema/components/models.py index ee9312f..11a605b 100644 --- a/openapi_core/schema/components/models.py +++ b/openapi_core/schema/components/models.py @@ -3,7 +3,7 @@ class Components(object): def __init__( self, schemas=None, responses=None, parameters=None, - request_bodies=None, security_schemes=None): + request_bodies=None, security_schemes=None, extensions=None): self.schemas = schemas and dict(schemas) or {} self.responses = responses and dict(responses) or {} self.parameters = parameters and dict(parameters) or {} @@ -11,3 +11,5 @@ class Components(object): self.security_schemes = ( security_schemes and dict(security_schemes) or {} ) + + self.extensions = extensions and dict(extensions) or {} diff --git a/openapi_core/schema/contacts/factories.py b/openapi_core/schema/contacts/factories.py index cec1b3d..d1724d9 100644 --- a/openapi_core/schema/contacts/factories.py +++ b/openapi_core/schema/contacts/factories.py @@ -1,5 +1,7 @@ """OpenAPI core contacts factories module""" +from openapi_core.compat import lru_cache from openapi_core.schema.contacts.models import Contact +from openapi_core.schema.extensions.generators import ExtensionsGenerator class ContactFactory(object): @@ -12,4 +14,12 @@ class ContactFactory(object): name = contact_deref.get('name') url = contact_deref.get('url') email = contact_deref.get('email') - return Contact(name=name, url=url, email=email) + + extensions = self.extensions_generator.generate(contact_deref) + + return Contact(name=name, url=url, email=email, extensions=extensions) + + @property + @lru_cache() + def extensions_generator(self): + return ExtensionsGenerator(self.dereferencer) diff --git a/openapi_core/schema/contacts/models.py b/openapi_core/schema/contacts/models.py index 4c2328e..9e5bb2a 100644 --- a/openapi_core/schema/contacts/models.py +++ b/openapi_core/schema/contacts/models.py @@ -3,7 +3,9 @@ class Contact(object): - def __init__(self, name=None, url=None, email=None): + def __init__(self, name=None, url=None, email=None, extensions=None): self.name = name self.url = url self.email = email + + self.extensions = extensions and dict(extensions) or {} diff --git a/openapi_core/schema/external_docs/factories.py b/openapi_core/schema/external_docs/factories.py index a2a3900..a1ef10b 100644 --- a/openapi_core/schema/external_docs/factories.py +++ b/openapi_core/schema/external_docs/factories.py @@ -1,4 +1,6 @@ """OpenAPI core external docs factories module""" +from openapi_core.compat import lru_cache +from openapi_core.schema.extensions.generators import ExtensionsGenerator from openapi_core.schema.external_docs.models import ExternalDocumentation @@ -11,4 +13,14 @@ class ExternalDocumentationFactory(object): url = external_doc_spec['url'] description = external_doc_spec.get('description') - return ExternalDocumentation(url, description=description) + extensions = self.extensions_generator.generate(external_doc_spec) + + return ExternalDocumentation( + url, + description=description, extensions=extensions, + ) + + @property + @lru_cache() + def extensions_generator(self): + return ExtensionsGenerator(self.dereferencer) diff --git a/openapi_core/schema/external_docs/models.py b/openapi_core/schema/external_docs/models.py index e44cd8b..b0d0a0e 100644 --- a/openapi_core/schema/external_docs/models.py +++ b/openapi_core/schema/external_docs/models.py @@ -4,6 +4,8 @@ class ExternalDocumentation(object): """Represents an OpenAPI External Documentation.""" - def __init__(self, url, description=None): + def __init__(self, url, description=None, extensions=None): self.url = url self.description = description + + self.extensions = extensions and dict(extensions) or {} diff --git a/openapi_core/schema/infos/factories.py b/openapi_core/schema/infos/factories.py index 74b0189..20b8b60 100644 --- a/openapi_core/schema/infos/factories.py +++ b/openapi_core/schema/infos/factories.py @@ -1,6 +1,7 @@ """OpenAPI core infos factories module""" from openapi_core.compat import lru_cache from openapi_core.schema.contacts.factories import ContactFactory +from openapi_core.schema.extensions.generators import ExtensionsGenerator from openapi_core.schema.infos.models import Info from openapi_core.schema.licenses.factories import LicenseFactory @@ -17,6 +18,8 @@ class InfoFactory(object): description = info_deref.get('description') terms_of_service = info_deref.get('termsOfService') + extensions = self.extensions_generator.generate(info_deref) + contact = None if 'contact' in info_deref: contact_spec = info_deref.get('contact') @@ -30,7 +33,7 @@ class InfoFactory(object): return Info( title, version, description=description, terms_of_service=terms_of_service, - contact=contact, license=license, + contact=contact, license=license, extensions=extensions, ) @property @@ -42,3 +45,8 @@ class InfoFactory(object): @lru_cache() def license_factory(self): return LicenseFactory(self.dereferencer) + + @property + @lru_cache() + def extensions_generator(self): + return ExtensionsGenerator(self.dereferencer) diff --git a/openapi_core/schema/infos/models.py b/openapi_core/schema/infos/models.py index 18aebbd..9ccd66a 100644 --- a/openapi_core/schema/infos/models.py +++ b/openapi_core/schema/infos/models.py @@ -5,7 +5,7 @@ class Info(object): def __init__( self, title, version, description=None, terms_of_service=None, - contact=None, license=None, + contact=None, license=None, extensions=None, ): self.title = title self.version = version @@ -13,3 +13,5 @@ class Info(object): self.terms_of_service = terms_of_service self.contact = contact self.license = license + + self.extensions = extensions and dict(extensions) or {} diff --git a/openapi_core/schema/licenses/factories.py b/openapi_core/schema/licenses/factories.py index 886386f..294babe 100644 --- a/openapi_core/schema/licenses/factories.py +++ b/openapi_core/schema/licenses/factories.py @@ -1,4 +1,6 @@ """OpenAPI core licenses factories module""" +from openapi_core.compat import lru_cache +from openapi_core.schema.extensions.generators import ExtensionsGenerator from openapi_core.schema.licenses.models import License @@ -11,4 +13,12 @@ class LicenseFactory(object): license_deref = self.dereferencer.dereference(license_spec) name = license_deref['name'] url = license_deref.get('url') - return License(name, url=url) + + extensions = self.extensions_generator.generate(license_deref) + + return License(name, url=url, extensions=extensions) + + @property + @lru_cache() + def extensions_generator(self): + return ExtensionsGenerator(self.dereferencer) diff --git a/openapi_core/schema/licenses/models.py b/openapi_core/schema/licenses/models.py index 939eb17..c6dd506 100644 --- a/openapi_core/schema/licenses/models.py +++ b/openapi_core/schema/licenses/models.py @@ -3,6 +3,8 @@ class License(object): - def __init__(self, name, url=None): + def __init__(self, name, url=None, extensions=None): self.name = name self.url = url + + self.extensions = extensions and dict(extensions) or {} diff --git a/openapi_core/schema/media_types/generators.py b/openapi_core/schema/media_types/generators.py index 3eceffb..dcaff53 100644 --- a/openapi_core/schema/media_types/generators.py +++ b/openapi_core/schema/media_types/generators.py @@ -1,6 +1,8 @@ """OpenAPI core media types generators module""" from six import iteritems +from openapi_core.compat import lru_cache +from openapi_core.schema.extensions.generators import ExtensionsGenerator from openapi_core.schema.media_types.models import MediaType @@ -21,8 +23,18 @@ class MediaTypeGenerator(object): else: example = example_spec + extensions = self.extensions_generator.generate(media_type) + schema = None if schema_spec: schema, _ = self.schemas_registry.get_or_create(schema_spec) - yield mimetype, MediaType(mimetype, schema=schema, example=example) + yield mimetype, MediaType( + mimetype, + schema=schema, example=example, extensions=extensions, + ) + + @property + @lru_cache() + def extensions_generator(self): + return ExtensionsGenerator(self.dereferencer) diff --git a/openapi_core/schema/media_types/models.py b/openapi_core/schema/media_types/models.py index fc29853..76079f7 100644 --- a/openapi_core/schema/media_types/models.py +++ b/openapi_core/schema/media_types/models.py @@ -4,7 +4,9 @@ class MediaType(object): """Represents an OpenAPI MediaType.""" - def __init__(self, mimetype, schema=None, example=None): + def __init__(self, mimetype, schema=None, example=None, extensions=None): self.mimetype = mimetype self.schema = schema self.example = example + + self.extensions = extensions and dict(extensions) or {} diff --git a/openapi_core/schema/operations/generators.py b/openapi_core/schema/operations/generators.py index 07b7ba4..c149856 100644 --- a/openapi_core/schema/operations/generators.py +++ b/openapi_core/schema/operations/generators.py @@ -4,6 +4,7 @@ from six import iteritems from openapi_spec_validator.validators import PathItemValidator from openapi_core.compat import lru_cache +from openapi_core.schema.extensions.generators import ExtensionsGenerator from openapi_core.schema.external_docs.factories import ( ExternalDocumentationFactory, ) @@ -47,6 +48,7 @@ class OperationsGenerator(object): servers = self.servers_generator.generate(servers_spec) security = self.security_requirements_generator.generate( security_spec) + extensions = self.extensions_generator.generate(operation_deref) external_docs = None if 'externalDocs' in operation_deref: @@ -68,7 +70,7 @@ class OperationsGenerator(object): external_docs=external_docs, security=list(security), request_body=request_body, deprecated=deprecated, operation_id=operation_id, tags=list(tags_list), - servers=list(servers), + servers=list(servers), extensions=extensions, ), ) @@ -101,3 +103,8 @@ class OperationsGenerator(object): @lru_cache() def servers_generator(self): return ServersGenerator(self.dereferencer) + + @property + @lru_cache() + def extensions_generator(self): + return ExtensionsGenerator(self.dereferencer) diff --git a/openapi_core/schema/operations/models.py b/openapi_core/schema/operations/models.py index 7da4ef3..f7bc773 100644 --- a/openapi_core/schema/operations/models.py +++ b/openapi_core/schema/operations/models.py @@ -10,7 +10,7 @@ class Operation(object): self, http_method, path_name, responses, parameters, summary=None, description=None, external_docs=None, security=None, request_body=None, deprecated=False, operation_id=None, tags=None, - servers=None): + servers=None, extensions=None): self.http_method = http_method self.path_name = path_name self.responses = dict(responses) @@ -25,6 +25,8 @@ class Operation(object): self.tags = tags self.servers = servers + self.extensions = extensions and dict(extensions) or {} + def __getitem__(self, name): return self.parameters[name] diff --git a/openapi_core/schema/paths/generators.py b/openapi_core/schema/paths/generators.py index cc85164..82809f2 100644 --- a/openapi_core/schema/paths/generators.py +++ b/openapi_core/schema/paths/generators.py @@ -2,6 +2,7 @@ from six import iteritems from openapi_core.compat import lru_cache +from openapi_core.schema.extensions.generators import ExtensionsGenerator from openapi_core.schema.operations.generators import OperationsGenerator from openapi_core.schema.parameters.generators import ParametersGenerator from openapi_core.schema.paths.models import Path @@ -29,12 +30,14 @@ class PathsGenerator(object): servers = self.servers_generator.generate(servers_spec) parameters = self.parameters_generator.generate_from_list( parameters_list) + extensions = self.extensions_generator.generate(path_deref) + yield ( path_name, Path( path_name, list(operations), parameters=list(parameters), summary=summary, description=description, - servers=list(servers), + servers=list(servers), extensions=extensions, ), ) @@ -52,3 +55,8 @@ class PathsGenerator(object): @lru_cache() def parameters_generator(self): return ParametersGenerator(self.dereferencer, self.schemas_registry) + + @property + @lru_cache() + def extensions_generator(self): + return ExtensionsGenerator(self.dereferencer) diff --git a/openapi_core/schema/paths/models.py b/openapi_core/schema/paths/models.py index 9b6f5b0..74a57a9 100644 --- a/openapi_core/schema/paths/models.py +++ b/openapi_core/schema/paths/models.py @@ -7,6 +7,7 @@ class Path(object): def __init__( self, name, operations, summary=None, description=None, parameters=None, servers=None, + extensions=None, ): self.name = name self.operations = dict(operations) @@ -15,5 +16,7 @@ class Path(object): self.servers = servers self.parameters = dict(parameters) if parameters else {} + self.extensions = extensions and dict(extensions) or {} + def __getitem__(self, http_method): return self.operations[http_method] diff --git a/openapi_core/schema/request_bodies/factories.py b/openapi_core/schema/request_bodies/factories.py index ba659a3..a8a756e 100644 --- a/openapi_core/schema/request_bodies/factories.py +++ b/openapi_core/schema/request_bodies/factories.py @@ -1,5 +1,6 @@ """OpenAPI core request bodies factories module""" from openapi_core.compat import lru_cache +from openapi_core.schema.extensions.generators import ExtensionsGenerator from openapi_core.schema.media_types.generators import MediaTypeGenerator from openapi_core.schema.request_bodies.models import RequestBody @@ -16,9 +17,20 @@ class RequestBodyFactory(object): content = request_body_deref['content'] media_types = self.media_types_generator.generate(content) required = request_body_deref.get('required', False) - return RequestBody(media_types, required=required) + + extensions = self.extensions_generator.generate(request_body_deref) + + return RequestBody( + media_types, + required=required, extensions=extensions, + ) @property @lru_cache() def media_types_generator(self): return MediaTypeGenerator(self.dereferencer, self.schemas_registry) + + @property + @lru_cache() + def extensions_generator(self): + return ExtensionsGenerator(self.dereferencer) diff --git a/openapi_core/schema/request_bodies/models.py b/openapi_core/schema/request_bodies/models.py index a15c748..925112d 100644 --- a/openapi_core/schema/request_bodies/models.py +++ b/openapi_core/schema/request_bodies/models.py @@ -7,10 +7,12 @@ from openapi_core.schema.media_types.exceptions import InvalidContentType class RequestBody(object): """Represents an OpenAPI RequestBody.""" - def __init__(self, content, required=False): + def __init__(self, content, required=False, extensions=None): self.content = Content(content) self.required = required + self.extensions = extensions and dict(extensions) or {} + def __getitem__(self, mimetype): try: return self.content[mimetype] diff --git a/openapi_core/schema/responses/generators.py b/openapi_core/schema/responses/generators.py index c207095..f74e152 100644 --- a/openapi_core/schema/responses/generators.py +++ b/openapi_core/schema/responses/generators.py @@ -2,6 +2,7 @@ from six import iteritems from openapi_core.compat import lru_cache +from openapi_core.schema.extensions.generators import ExtensionsGenerator from openapi_core.schema.links.generators import LinksGenerator from openapi_core.schema.media_types.generators import MediaTypeGenerator from openapi_core.schema.parameters.generators import ParametersGenerator @@ -23,6 +24,8 @@ class ResponsesGenerator(object): links_dict = response_deref.get('links', {}) links = self.links_generator.generate(links_dict) + extensions = self.extensions_generator.generate(response_deref) + media_types = None if content: media_types = self.media_types_generator.generate(content) @@ -33,7 +36,9 @@ class ResponsesGenerator(object): yield http_status, Response( http_status, description, - content=media_types, headers=parameters, links=links) + content=media_types, headers=parameters, links=links, + extensions=extensions, + ) @property @lru_cache() @@ -49,3 +54,8 @@ class ResponsesGenerator(object): @lru_cache() def links_generator(self): return LinksGenerator(self.dereferencer, self.schemas_registry) + + @property + @lru_cache() + def extensions_generator(self): + return ExtensionsGenerator(self.dereferencer) diff --git a/openapi_core/schema/responses/models.py b/openapi_core/schema/responses/models.py index 080f60f..21dffc5 100644 --- a/openapi_core/schema/responses/models.py +++ b/openapi_core/schema/responses/models.py @@ -8,13 +8,15 @@ class Response(object): def __init__( self, http_status, description, headers=None, content=None, - links=None): + links=None, extensions=None): self.http_status = http_status self.description = description self.headers = headers and dict(headers) or {} self.content = content and Content(content) or Content() self.links = links and dict(links) or {} + self.extensions = extensions and dict(extensions) or {} + def __getitem__(self, mimetype): return self.get_content_type(mimetype) diff --git a/openapi_core/schema/servers/generators.py b/openapi_core/schema/servers/generators.py index c9c41b6..ca8dbc7 100644 --- a/openapi_core/schema/servers/generators.py +++ b/openapi_core/schema/servers/generators.py @@ -2,6 +2,7 @@ from six import iteritems from openapi_core.compat import lru_cache +from openapi_core.schema.extensions.generators import ExtensionsGenerator from openapi_core.schema.servers.models import Server, ServerVariable @@ -17,17 +18,28 @@ class ServersGenerator(object): variables_spec = server_spec.get('variables', {}) description = server_spec.get('description') + extensions = self.extensions_generator.generate(server_spec) + variables = None if variables_spec: variables = self.variables_generator.generate(variables_spec) - yield Server(url, variables=variables, description=description) + yield Server( + url, + variables=variables, description=description, + extensions=extensions, + ) @property @lru_cache() def variables_generator(self): return ServerVariablesGenerator(self.dereferencer) + @property + @lru_cache() + def extensions_generator(self): + return ExtensionsGenerator(self.dereferencer) + class ServerVariablesGenerator(object): @@ -41,5 +53,15 @@ class ServerVariablesGenerator(object): default = variable_spec['default'] enum = variable_spec.get('enum') - variable = ServerVariable(variable_name, default, enum=enum) + extensions = self.extensions_generator.generate(variable_spec) + + variable = ServerVariable( + variable_name, default, + enum=enum, extensions=extensions, + ) yield variable_name, variable + + @property + @lru_cache() + def extensions_generator(self): + return ExtensionsGenerator(self.dereferencer) diff --git a/openapi_core/schema/servers/models.py b/openapi_core/schema/servers/models.py index 3620b28..7c4ac9f 100644 --- a/openapi_core/schema/servers/models.py +++ b/openapi_core/schema/servers/models.py @@ -5,11 +5,13 @@ from six.moves.urllib.parse import urljoin class Server(object): - def __init__(self, url, variables=None, description=None): + def __init__(self, url, variables=None, description=None, extensions=None): self.url = url self.variables = variables and dict(variables) or {} self.description = description + self.extensions = extensions and dict(extensions) or {} + @property def default_url(self): return self.get_url() @@ -38,7 +40,9 @@ class Server(object): class ServerVariable(object): - def __init__(self, name, default, enum=None): + def __init__(self, name, default, enum=None, extensions=None): self.name = name self.default = default self.enum = enum and list(enum) or [] + + self.extensions = extensions and dict(extensions) or {} diff --git a/openapi_core/schema/specs/factories.py b/openapi_core/schema/specs/factories.py index 592cf04..384ef8e 100644 --- a/openapi_core/schema/specs/factories.py +++ b/openapi_core/schema/specs/factories.py @@ -6,6 +6,7 @@ from openapi_spec_validator.validators import Dereferencer from openapi_core.compat import lru_cache from openapi_core.schema.components.factories import ComponentsFactory +from openapi_core.schema.extensions.generators import ExtensionsGenerator from openapi_core.schema.infos.factories import InfoFactory from openapi_core.schema.paths.generators import PathsGenerator from openapi_core.schema.schemas.registries import SchemaRegistry @@ -39,6 +40,8 @@ class SpecFactory(object): {'url': '/'}, ] + extensions = self.extensions_generator.generate(spec_dict_deref) + info = self.info_factory.create(info_spec) servers = self.servers_generator.generate(servers_spec) paths = self.paths_generator.generate(paths) @@ -49,7 +52,7 @@ class SpecFactory(object): spec = Spec( info, list(paths), servers=list(servers), components=components, - security=list(security), + security=list(security), extensions=extensions, _resolver=self.spec_resolver, ) return spec @@ -88,3 +91,8 @@ class SpecFactory(object): @lru_cache() def security_requirements_generator(self): return SecurityRequirementsGenerator(self.dereferencer) + + @property + @lru_cache() + def extensions_generator(self): + return ExtensionsGenerator(self.dereferencer) diff --git a/openapi_core/schema/specs/models.py b/openapi_core/schema/specs/models.py index 7f41b70..6c24ab9 100644 --- a/openapi_core/schema/specs/models.py +++ b/openapi_core/schema/specs/models.py @@ -16,13 +16,15 @@ class Spec(object): def __init__( self, info, paths, servers=None, components=None, - security=None, _resolver=None): + security=None, extensions=None, _resolver=None): self.info = info self.paths = paths and dict(paths) self.servers = servers or [] self.components = components self.security = security + self.extensions = extensions and dict(extensions) or {} + self._resolver = _resolver def __getitem__(self, path_pattern):