mirror of
https://github.com/correl/openapi-core.git
synced 2024-11-22 03:00:10 +00:00
Merge pull request #211 from p1c2u/feature/extendable-schema
Extensible schema models
This commit is contained in:
commit
8c1e331377
24 changed files with 179 additions and 24 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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]
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in a new issue