Schema objects restructure

This commit is contained in:
Artur Maciag 2018-04-17 13:18:40 +01:00
parent 548a7d6565
commit 734a4673f8
55 changed files with 572 additions and 512 deletions

View file

@ -0,0 +1 @@
"""OpenAPI extensions package"""

View file

@ -0,0 +1 @@
"""OpenAPI X-Model extension package"""

View file

@ -0,0 +1,12 @@
"""OpenAPI X-Model extension factories module"""
from openapi_core.extensions.models.models import BaseModel
class ModelFactory(object):
def create(self, properties, name=None):
model = BaseModel
if name is not None:
model = type(name, (BaseModel, ), {})
return model(**properties)

View file

@ -1,8 +1,8 @@
"""OpenAPI core models module"""
"""OpenAPI X-Model extension models module"""
class BaseModel(dict):
"""Base class for OpenAPI models."""
"""Base class for OpenAPI X-Model."""
def __getattr__(self, attr_name):
"""Only search through properties if attribute not found normally.
@ -15,13 +15,3 @@ class BaseModel(dict):
'type object {0!r} has no attribute {1!r}'
.format(type(self).__name__, attr_name)
)
class ModelFactory(object):
def create(self, properties, name=None):
model = BaseModel
if name is not None:
model = type(name, (BaseModel, ), {})
return model(**properties)

View file

View file

@ -1,18 +1,7 @@
from functools import lru_cache
from openapi_core.schemas import SchemasGenerator
class Components(object):
"""Represents an OpenAPI Components in a service."""
def __init__(
self, schemas=None, responses=None, parameters=None,
request_bodies=None):
self.schemas = schemas and dict(schemas) or {}
self.responses = responses and dict(responses) or {}
self.parameters = parameters and dict(parameters) or {}
self.request_bodies = request_bodies and dict(request_bodies) or {}
from openapi_core.schema.components.models import Components
from openapi_core.schema.schemas.generators import SchemasGenerator
class ComponentsFactory(object):

View file

@ -0,0 +1,10 @@
class Components(object):
"""Represents an OpenAPI Components in a service."""
def __init__(
self, schemas=None, responses=None, parameters=None,
request_bodies=None):
self.schemas = schemas and dict(schemas) or {}
self.responses = responses and dict(responses) or {}
self.parameters = parameters and dict(parameters) or {}
self.request_bodies = request_bodies and dict(request_bodies) or {}

View file

View file

@ -1,8 +1,5 @@
class Info(object):
def __init__(self, title, version):
self.title = title
self.version = version
"""OpenAPI core infos factories module"""
from openapi_core.schema.infos.models import Info
class InfoFactory(object):

View file

@ -0,0 +1,8 @@
"""OpenAPI core infos models module"""
class Info(object):
def __init__(self, title, version):
self.title = title
self.version = version

View file

@ -0,0 +1,21 @@
"""OpenAPI core media types generators module"""
from six import iteritems
from openapi_core.schema.media_types.models import MediaType
class MediaTypeGenerator(object):
def __init__(self, dereferencer, schemas_registry):
self.dereferencer = dereferencer
self.schemas_registry = schemas_registry
def generate(self, content):
for mimetype, media_type in iteritems(content):
schema_spec = media_type.get('schema')
schema = None
if schema_spec:
schema, _ = self.schemas_registry.get_or_create(schema_spec)
yield mimetype, MediaType(mimetype, schema)

View file

@ -1,4 +1,4 @@
"""OpenAPI core mediaTypes module"""
"""OpenAPI core media types models module"""
from collections import defaultdict
from json import loads
@ -44,20 +44,3 @@ class MediaType(object):
return self.schema.unmarshal(deserialized)
except InvalidValueType as exc:
raise InvalidMediaTypeValue(str(exc))
class MediaTypeGenerator(object):
def __init__(self, dereferencer, schemas_registry):
self.dereferencer = dereferencer
self.schemas_registry = schemas_registry
def generate(self, content):
for mimetype, media_type in iteritems(content):
schema_spec = media_type.get('schema')
schema = None
if schema_spec:
schema, _ = self.schemas_registry.get_or_create(schema_spec)
yield mimetype, MediaType(mimetype, schema)

View file

@ -1,50 +1,14 @@
# -*- coding: utf-8 -*-
"""OpenAPI core operations module"""
import logging
"""OpenAPI core operations models module"""
from functools import lru_cache
from six import iteritems
from openapi_spec_validator.validators import PathItemValidator
from openapi_core.exceptions import InvalidResponse
from openapi_core.parameters import ParametersGenerator
from openapi_core.request_bodies import RequestBodyFactory
from openapi_core.responses import ResponsesGenerator
log = logging.getLogger(__name__)
class Operation(object):
"""Represents an OpenAPI Operation."""
def __init__(
self, http_method, path_name, responses, parameters,
request_body=None, deprecated=False, operation_id=None):
self.http_method = http_method
self.path_name = path_name
self.responses = dict(responses)
self.parameters = dict(parameters)
self.request_body = request_body
self.deprecated = deprecated
self.operation_id = operation_id
def __getitem__(self, name):
return self.parameters[name]
def get_response(self, http_status='default'):
try:
return self.responses[http_status]
except KeyError:
# try range
http_status_range = '{0}XX'.format(http_status[0])
if http_status_range in self.responses:
return self.responses[http_status_range]
if 'default' not in self.responses:
raise InvalidResponse(
"Unknown response http status {0}".format(http_status))
return self.responses['default']
from openapi_core.schema.operations.models import Operation
from openapi_core.schema.parameters.generators import ParametersGenerator
from openapi_core.schema.request_bodies.factories import RequestBodyFactory
from openapi_core.schema.responses.generators import ResponsesGenerator
class OperationsGenerator(object):

View file

@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
"""OpenAPI core operations models module"""
from openapi_core.exceptions import InvalidResponse
class Operation(object):
"""Represents an OpenAPI Operation."""
def __init__(
self, http_method, path_name, responses, parameters,
request_body=None, deprecated=False, operation_id=None):
self.http_method = http_method
self.path_name = path_name
self.responses = dict(responses)
self.parameters = dict(parameters)
self.request_body = request_body
self.deprecated = deprecated
self.operation_id = operation_id
def __getitem__(self, name):
return self.parameters[name]
def get_response(self, http_status='default'):
try:
return self.responses[http_status]
except KeyError:
# try range
http_status_range = '{0}XX'.format(http_status[0])
if http_status_range in self.responses:
return self.responses[http_status_range]
if 'default' not in self.responses:
raise InvalidResponse(
"Unknown response http status {0}".format(http_status))
return self.responses['default']

View file

@ -1,3 +1,4 @@
"""OpenAPI core parameters enums module"""
from enum import Enum
@ -22,27 +23,3 @@ class ParameterStyle(Enum):
SPACE_DELIMITED = 'spaceDelimited'
PIPE_DELIMITED = 'pipeDelimited'
DEEP_OBJECT = 'deepObject'
class SchemaType(Enum):
INTEGER = 'integer'
NUMBER = 'number'
STRING = 'string'
BOOLEAN = 'boolean'
ARRAY = 'array'
OBJECT = 'object'
class SchemaFormat(Enum):
NONE = None
INT32 = 'int32'
INT64 = 'int64'
FLOAT = 'float'
DOUBLE = 'double'
BYTE = 'byte'
BINARY = 'binary'
DATE = 'date'
DATETIME = 'date-time'
PASSWORD = 'password'

View file

@ -0,0 +1,33 @@
"""OpenAPI core parameters factories module"""
from openapi_core.schema.parameters.models import Parameter
class ParameterFactory(object):
def __init__(self, dereferencer, schemas_registry):
self.dereferencer = dereferencer
self.schemas_registry = schemas_registry
def create(self, parameter_spec, parameter_name=None):
parameter_deref = self.dereferencer.dereference(parameter_spec)
parameter_name = parameter_name or parameter_deref['name']
parameter_in = parameter_deref.get('in', 'header')
allow_empty_value = parameter_deref.get('allowEmptyValue')
required = parameter_deref.get('required', False)
style = parameter_deref.get('style')
explode = parameter_deref.get('explode')
schema_spec = parameter_deref.get('schema', None)
schema = None
if schema_spec:
schema, _ = self.schemas_registry.get_or_create(schema_spec)
return Parameter(
parameter_name, parameter_in,
schema=schema, required=required,
allow_empty_value=allow_empty_value,
style=style, explode=explode,
)

View file

@ -0,0 +1,31 @@
"""OpenAPI core parameters generators module"""
from functools import lru_cache
from six import iteritems
from openapi_core.schema.parameters.factories import ParameterFactory
class ParametersGenerator(object):
def __init__(self, dereferencer, schemas_registry):
self.dereferencer = dereferencer
self.schemas_registry = schemas_registry
def generate(self, parameters):
for parameter_name, parameter_spec in iteritems(parameters):
parameter = self.parameter_factory.create(
parameter_spec, parameter_name=parameter_name)
yield (parameter_name, parameter)
def generate_from_list(self, parameters_list):
for parameter_spec in parameters_list:
parameter = self.parameter_factory.create(parameter_spec)
yield (parameter.name, parameter)
@property
@lru_cache()
def parameter_factory(self):
return ParameterFactory(self.dereferencer, self.schemas_registry)

View file

@ -1,28 +1,26 @@
"""OpenAPI core parameters module"""
"""OpenAPI core parameters models module"""
import logging
import warnings
from functools import lru_cache
from six import iteritems
from openapi_core.enums import ParameterLocation, ParameterStyle, SchemaType
from openapi_core.exceptions import (
EmptyValue, InvalidValueType, InvalidParameterValue,
)
from openapi_core.schema.parameters.enums import ParameterLocation, ParameterStyle
from openapi_core.schema.schemas.enums import SchemaType
log = logging.getLogger(__name__)
PARAMETER_STYLE_DESERIALIZERS = {
ParameterStyle.FORM: lambda x: x.split(','),
ParameterStyle.SIMPLE: lambda x: x.split(','),
ParameterStyle.SPACE_DELIMITED: lambda x: x.split(' '),
ParameterStyle.PIPE_DELIMITED: lambda x: x.split('|'),
}
class Parameter(object):
"""Represents an OpenAPI operation Parameter."""
PARAMETER_STYLE_DESERIALIZERS = {
ParameterStyle.FORM: lambda x: x.split(','),
ParameterStyle.SIMPLE: lambda x: x.split(','),
ParameterStyle.SPACE_DELIMITED: lambda x: x.split(' '),
ParameterStyle.PIPE_DELIMITED: lambda x: x.split('|'),
}
def __init__(
self, name, location, schema=None, required=False,
deprecated=False, allow_empty_value=False,
@ -61,7 +59,7 @@ class Parameter(object):
return self.style == ParameterStyle.FORM
def get_dererializer(self):
return PARAMETER_STYLE_DESERIALIZERS[self.style]
return self.PARAMETER_STYLE_DESERIALIZERS[self.style]
def deserialize(self, value):
if not self.aslist or self.explode:
@ -91,59 +89,3 @@ class Parameter(object):
return self.schema.unmarshal(deserialized)
except InvalidValueType as exc:
raise InvalidParameterValue(str(exc))
class ParameterFactory(object):
def __init__(self, dereferencer, schemas_registry):
self.dereferencer = dereferencer
self.schemas_registry = schemas_registry
def create(self, parameter_spec, parameter_name=None):
parameter_deref = self.dereferencer.dereference(parameter_spec)
parameter_name = parameter_name or parameter_deref['name']
parameter_in = parameter_deref.get('in', 'header')
allow_empty_value = parameter_deref.get('allowEmptyValue')
required = parameter_deref.get('required', False)
style = parameter_deref.get('style')
explode = parameter_deref.get('explode')
schema_spec = parameter_deref.get('schema', None)
schema = None
if schema_spec:
schema, _ = self.schemas_registry.get_or_create(schema_spec)
return Parameter(
parameter_name, parameter_in,
schema=schema, required=required,
allow_empty_value=allow_empty_value,
style=style, explode=explode,
)
class ParametersGenerator(object):
def __init__(self, dereferencer, schemas_registry):
self.dereferencer = dereferencer
self.schemas_registry = schemas_registry
def generate(self, parameters):
for parameter_name, parameter_spec in iteritems(parameters):
parameter = self.parameter_factory.create(
parameter_spec, parameter_name=parameter_name)
yield (parameter_name, parameter)
def generate_from_list(self, parameters_list):
for parameter_spec in parameters_list:
parameter = self.parameter_factory.create(parameter_spec)
yield (parameter.name, parameter)
@property
@lru_cache()
def parameter_factory(self):
return ParameterFactory(self.dereferencer, self.schemas_registry)

View file

View file

@ -1,20 +1,10 @@
"""OpenAPI core paths module"""
"""OpenAPI core paths generators module"""
from functools import lru_cache
from six import iteritems
from openapi_core.operations import OperationsGenerator
class Path(object):
"""Represents an OpenAPI Path."""
def __init__(self, name, operations):
self.name = name
self.operations = dict(operations)
def __getitem__(self, http_method):
return self.operations[http_method]
from openapi_core.schema.operations.generators import OperationsGenerator
from openapi_core.schema.paths.models import Path
class PathsGenerator(object):

View file

@ -0,0 +1,12 @@
"""OpenAPI core paths models module"""
class Path(object):
"""Represents an OpenAPI Path."""
def __init__(self, name, operations):
self.name = name
self.operations = dict(operations)
def __getitem__(self, http_method):
return self.operations[http_method]

View file

@ -0,0 +1,17 @@
"""OpenAPI core properties generators module"""
from six import iteritems
class PropertiesGenerator(object):
def __init__(self, dereferencer):
self.dereferencer = dereferencer
def generate(self, properties):
for property_name, schema_spec in iteritems(properties):
schema = self._create_schema(schema_spec)
yield property_name, schema
def _create_schema(self, schema_spec):
from openapi_core.schema.schemas.factories import SchemaFactory
return SchemaFactory(self.dereferencer).create(schema_spec)

View file

@ -1,23 +1,8 @@
"""OpenAPI core requestBodies module"""
"""OpenAPI core request bodies factories module"""
from functools import lru_cache
from openapi_core.exceptions import InvalidContentType
from openapi_core.media_types import MediaTypeGenerator
class RequestBody(object):
"""Represents an OpenAPI RequestBody."""
def __init__(self, content, required=False):
self.content = dict(content)
self.required = required
def __getitem__(self, mimetype):
try:
return self.content[mimetype]
except KeyError:
raise InvalidContentType(
"Invalid mime type `{0}`".format(mimetype))
from openapi_core.schema.media_types.generators import MediaTypeGenerator
from openapi_core.schema.request_bodies.models import RequestBody
class RequestBodyFactory(object):

View file

@ -0,0 +1,17 @@
"""OpenAPI core request bodies models module"""
from openapi_core.exceptions import InvalidContentType
class RequestBody(object):
"""Represents an OpenAPI RequestBody."""
def __init__(self, content, required=False):
self.content = dict(content)
self.required = required
def __getitem__(self, mimetype):
try:
return self.content[mimetype]
except KeyError:
raise InvalidContentType(
"Invalid mime type `{0}`".format(mimetype))

View file

@ -1,30 +1,11 @@
"""OpenAPI core responses module"""
"""OpenAPI core responses generators module"""
from functools import lru_cache
from six import iteritems
from openapi_core.exceptions import InvalidContentType
from openapi_core.media_types import MediaTypeGenerator
from openapi_core.parameters import ParametersGenerator
class Response(object):
def __init__(
self, http_status, description, headers=None, content=None,
links=None):
self.http_status = http_status
self.description = description
self.headers = headers and dict(headers) or {}
self.content = content and dict(content) or {}
self.links = links and dict(links) or {}
def __getitem__(self, mimetype):
try:
return self.content[mimetype]
except KeyError:
raise InvalidContentType(
"Invalid mime type `{0}`".format(mimetype))
from openapi_core.schema.media_types.generators import MediaTypeGenerator
from openapi_core.schema.parameters.generators import ParametersGenerator
from openapi_core.schema.responses.models import Response
class ResponsesGenerator(object):

View file

@ -0,0 +1,21 @@
"""OpenAPI core responses models module"""
from openapi_core.exceptions import InvalidContentType
class Response(object):
def __init__(
self, http_status, description, headers=None, content=None,
links=None):
self.http_status = http_status
self.description = description
self.headers = headers and dict(headers) or {}
self.content = content and dict(content) or {}
self.links = links and dict(links) or {}
def __getitem__(self, mimetype):
try:
return self.content[mimetype]
except KeyError:
raise InvalidContentType(
"Invalid mime type `{0}`".format(mimetype))

View file

View file

@ -0,0 +1,26 @@
"""OpenAPI core schemas enums module"""
from enum import Enum
class SchemaType(Enum):
INTEGER = 'integer'
NUMBER = 'number'
STRING = 'string'
BOOLEAN = 'boolean'
ARRAY = 'array'
OBJECT = 'object'
class SchemaFormat(Enum):
NONE = None
INT32 = 'int32'
INT64 = 'int64'
FLOAT = 'float'
DOUBLE = 'double'
BYTE = 'byte'
BINARY = 'binary'
DATE = 'date'
DATETIME = 'date-time'
PASSWORD = 'password'

View file

@ -0,0 +1,56 @@
"""OpenAPI core schemas factories module"""
import logging
from functools import lru_cache
from openapi_core.schema.properties.generators import PropertiesGenerator
from openapi_core.schema.schemas.models import Schema
log = logging.getLogger(__name__)
class SchemaFactory(object):
def __init__(self, dereferencer):
self.dereferencer = dereferencer
def create(self, schema_spec):
schema_deref = self.dereferencer.dereference(schema_spec)
schema_type = schema_deref.get('type', 'object')
schema_format = schema_deref.get('format')
model = schema_deref.get('x-model', None)
required = schema_deref.get('required', False)
default = schema_deref.get('default', None)
properties_spec = schema_deref.get('properties', None)
items_spec = schema_deref.get('items', None)
nullable = schema_deref.get('nullable', False)
enum = schema_deref.get('enum', None)
deprecated = schema_deref.get('deprecated', False)
all_of_spec = schema_deref.get('allOf', None)
properties = None
if properties_spec:
properties = self.properties_generator.generate(properties_spec)
all_of = []
if all_of_spec:
all_of = map(self.create, all_of_spec)
items = None
if items_spec:
items = self._create_items(items_spec)
return Schema(
schema_type=schema_type, model=model, properties=properties,
items=items, schema_format=schema_format, required=required,
default=default, nullable=nullable, enum=enum,
deprecated=deprecated, all_of=all_of,
)
@property
@lru_cache()
def properties_generator(self):
return PropertiesGenerator(self.dereferencer)
def _create_items(self, items_spec):
return self.create(items_spec)

View file

@ -0,0 +1,20 @@
"""OpenAPI core schemas generators module"""
import logging
from six import iteritems
log = logging.getLogger(__name__)
class SchemasGenerator(object):
def __init__(self, dereferencer, schemas_registry):
self.dereferencer = dereferencer
self.schemas_registry = schemas_registry
def generate(self, schemas_spec):
schemas_deref = self.dereferencer.dereference(schemas_spec)
for schema_name, schema_spec in iteritems(schemas_deref):
schema, _ = self.schemas_registry.get_or_create(schema_spec)
yield schema_name, schema

View file

@ -1,39 +1,29 @@
"""OpenAPI core schemas module"""
"""OpenAPI core schemas models module"""
import logging
from collections import defaultdict
import warnings
from distutils.util import strtobool
from functools import lru_cache
from six import iteritems
from openapi_core.enums import SchemaType, SchemaFormat
from openapi_core.exceptions import (
InvalidValueType, UndefinedSchemaProperty, MissingProperty, InvalidValue,
)
from openapi_core.models import ModelFactory
from openapi_core.extensions.models.factories import ModelFactory
from openapi_core.schema.schemas.enums import SchemaType, SchemaFormat
from openapi_core.schema.schemas.util import forcebool
log = logging.getLogger(__name__)
def forcebool(val):
if isinstance(val, str):
val = strtobool(val)
return bool(val)
DEFAULT_CAST_CALLABLE_GETTER = {
SchemaType.INTEGER: int,
SchemaType.NUMBER: float,
SchemaType.BOOLEAN: forcebool,
}
class Schema(object):
"""Represents an OpenAPI Schema."""
DEFAULT_CAST_CALLABLE_GETTER = {
SchemaType.INTEGER: int,
SchemaType.NUMBER: float,
SchemaType.BOOLEAN: forcebool,
}
def __init__(
self, schema_type=None, model=None, properties=None, items=None,
schema_format=None, required=None, default=None, nullable=False,
@ -72,7 +62,7 @@ class Schema(object):
return required
def get_cast_mapping(self):
mapping = DEFAULT_CAST_CALLABLE_GETTER.copy()
mapping = self.DEFAULT_CAST_CALLABLE_GETTER.copy()
mapping.update({
SchemaType.ARRAY: self._unmarshal_collection,
SchemaType.OBJECT: self._unmarshal_object,
@ -152,95 +142,3 @@ class Schema(object):
prop_value = prop.default
properties[prop_name] = prop.unmarshal(prop_value)
return ModelFactory().create(properties, name=self.model)
class PropertiesGenerator(object):
def __init__(self, dereferencer):
self.dereferencer = dereferencer
def generate(self, properties):
for property_name, schema_spec in iteritems(properties):
schema = self._create_schema(schema_spec)
yield property_name, schema
def _create_schema(self, schema_spec):
return SchemaFactory(self.dereferencer).create(schema_spec)
class SchemaFactory(object):
def __init__(self, dereferencer):
self.dereferencer = dereferencer
def create(self, schema_spec):
schema_deref = self.dereferencer.dereference(schema_spec)
schema_type = schema_deref.get('type', 'object')
schema_format = schema_deref.get('format')
model = schema_deref.get('x-model', None)
required = schema_deref.get('required', False)
default = schema_deref.get('default', None)
properties_spec = schema_deref.get('properties', None)
items_spec = schema_deref.get('items', None)
nullable = schema_deref.get('nullable', False)
enum = schema_deref.get('enum', None)
deprecated = schema_deref.get('deprecated', False)
all_of_spec = schema_deref.get('allOf', None)
properties = None
if properties_spec:
properties = self.properties_generator.generate(properties_spec)
all_of = []
if all_of_spec:
all_of = map(self.create, all_of_spec)
items = None
if items_spec:
items = self._create_items(items_spec)
return Schema(
schema_type=schema_type, model=model, properties=properties,
items=items, schema_format=schema_format, required=required,
default=default, nullable=nullable, enum=enum,
deprecated=deprecated, all_of=all_of,
)
@property
@lru_cache()
def properties_generator(self):
return PropertiesGenerator(self.dereferencer)
def _create_items(self, items_spec):
return self.create(items_spec)
class SchemaRegistry(SchemaFactory):
def __init__(self, dereferencer):
super(SchemaRegistry, self).__init__(dereferencer)
self._schemas = {}
def get_or_create(self, schema_spec):
schema_deref = self.dereferencer.dereference(schema_spec)
model = schema_deref.get('x-model', None)
if model and model in self._schemas:
return self._schemas[model], False
return self.create(schema_deref), True
class SchemasGenerator(object):
def __init__(self, dereferencer, schemas_registry):
self.dereferencer = dereferencer
self.schemas_registry = schemas_registry
def generate(self, schemas_spec):
schemas_deref = self.dereferencer.dereference(schemas_spec)
for schema_name, schema_spec in iteritems(schemas_deref):
schema, _ = self.schemas_registry.get_or_create(schema_spec)
yield schema_name, schema

View file

@ -0,0 +1,22 @@
"""OpenAPI core schemas registries module"""
import logging
from openapi_core.schema.schemas.factories import SchemaFactory
log = logging.getLogger(__name__)
class SchemaRegistry(SchemaFactory):
def __init__(self, dereferencer):
super(SchemaRegistry, self).__init__(dereferencer)
self._schemas = {}
def get_or_create(self, schema_spec):
schema_deref = self.dereferencer.dereference(schema_spec)
model = schema_deref.get('x-model', None)
if model and model in self._schemas:
return self._schemas[model], False
return self.create(schema_deref), True

View file

@ -0,0 +1,9 @@
"""OpenAPI core schemas util module"""
from distutils.util import strtobool
def forcebool(val):
if isinstance(val, str):
val = strtobool(val)
return bool(val)

View file

View file

@ -1,37 +1,9 @@
"""OpenAPI core servers generators module"""
from functools import lru_cache
from six import iteritems
class Server(object):
def __init__(self, url, variables=None):
self.url = url
self.variables = variables and dict(variables) or {}
@property
def default_url(self):
return self.get_url()
@property
def default_variables(self):
defaults = {}
for name, variable in iteritems(self.variables):
defaults[name] = variable.default
return defaults
def get_url(self, **variables):
if not variables:
variables = self.default_variables
return self.url.format(**variables)
class ServerVariable(object):
def __init__(self, name, default, enum=None):
self.name = name
self.default = default
self.enum = enum and list(enum) or []
from openapi_core.schema.servers.models import Server, ServerVariable
class ServersGenerator(object):

View file

@ -0,0 +1,33 @@
"""OpenAPI core servers models module"""
from six import iteritems
class Server(object):
def __init__(self, url, variables=None):
self.url = url
self.variables = variables and dict(variables) or {}
@property
def default_url(self):
return self.get_url()
@property
def default_variables(self):
defaults = {}
for name, variable in iteritems(self.variables):
defaults[name] = variable.default
return defaults
def get_url(self, **variables):
if not variables:
variables = self.default_variables
return self.url.format(**variables)
class ServerVariable(object):
def __init__(self, name, default, enum=None):
self.name = name
self.default = default
self.enum = enum and list(enum) or []

View file

View file

@ -0,0 +1,64 @@
# -*- coding: utf-8 -*-
"""OpenAPI core specs factories module"""
from functools import lru_cache
from openapi_spec_validator import openapi_v3_spec_validator
from openapi_core.exceptions import InvalidOperation, InvalidServer
from openapi_core.schema.components.factories import ComponentsFactory
from openapi_core.schema.infos.factories import InfoFactory
from openapi_core.schema.paths.generators import PathsGenerator
from openapi_core.schema.schemas.registries import SchemaRegistry
from openapi_core.schema.servers.generators import ServersGenerator
from openapi_core.schema.specs.models import Spec
class SpecFactory(object):
def __init__(self, dereferencer, config=None):
self.dereferencer = dereferencer
self.config = config or {}
def create(self, spec_dict, spec_url=''):
if self.config.get('validate_spec', True):
openapi_v3_spec_validator.validate(spec_dict, spec_url=spec_url)
spec_dict_deref = self.dereferencer.dereference(spec_dict)
info_spec = spec_dict_deref.get('info', {})
servers_spec = spec_dict_deref.get('servers', [])
paths = spec_dict_deref.get('paths', {})
components_spec = spec_dict_deref.get('components', {})
info = self.info_factory.create(info_spec)
servers = self.servers_generator.generate(servers_spec)
paths = self.paths_generator.generate(paths)
components = self.components_factory.create(components_spec)
spec = Spec(
info, list(paths), servers=list(servers), components=components)
return spec
@property
@lru_cache()
def schemas_registry(self):
return SchemaRegistry(self.dereferencer)
@property
@lru_cache()
def info_factory(self):
return InfoFactory(self.dereferencer)
@property
@lru_cache()
def servers_generator(self):
return ServersGenerator(self.dereferencer)
@property
@lru_cache()
def paths_generator(self):
return PathsGenerator(self.dereferencer, self.schemas_registry)
@property
@lru_cache()
def components_factory(self):
return ComponentsFactory(self.dereferencer, self.schemas_registry)

View file

@ -0,0 +1,58 @@
# -*- coding: utf-8 -*-
"""OpenAPI core specs models module"""
import logging
from functools import partialmethod
from openapi_core.exceptions import InvalidOperation, InvalidServer
log = logging.getLogger(__name__)
class Spec(object):
"""Represents an OpenAPI Specification for a service."""
def __init__(self, info, paths, servers=None, components=None):
self.info = info
self.paths = paths and dict(paths)
self.servers = servers or []
self.components = components
def __getitem__(self, path_name):
return self.paths[path_name]
@property
def default_url(self):
return self.servers[0].default_url
def get_server(self, full_url_pattern):
for spec_server in self.servers:
if spec_server.default_url in full_url_pattern:
return spec_server
raise InvalidServer(
"Invalid request server {0}".format(full_url_pattern))
def get_server_url(self, index=0):
return self.servers[index].default_url
def get_operation(self, path_pattern, http_method):
try:
return self.paths[path_pattern].operations[http_method]
except KeyError:
raise InvalidOperation(
"Unknown operation path {0} with method {1}".format(
path_pattern, http_method))
def get_schema(self, name):
return self.components.schemas[name]
# operations shortcuts
get = partialmethod(get_operation, http_method='get')
put = partialmethod(get_operation, http_method='put')
post = partialmethod(get_operation, http_method='post')
delete = partialmethod(get_operation, http_method='delete')
options = partialmethod(get_operation, http_method='options')
head = partialmethod(get_operation, http_method='head')
patch = partialmethod(get_operation, http_method='patch')

View file

@ -4,7 +4,7 @@ from openapi_spec_validator.validators import Dereferencer
from openapi_spec_validator import default_handlers
from openapi_core.exceptions import OpenAPIParameterError, OpenAPIBodyError
from openapi_core.specs import SpecFactory
from openapi_core.schema.specs.factories import SpecFactory
from openapi_core.validators import RequestValidator, ResponseValidator

View file

@ -1,116 +0,0 @@
# -*- coding: utf-8 -*-
"""OpenAPI core specs module"""
import logging
from functools import partialmethod, lru_cache
from openapi_spec_validator import openapi_v3_spec_validator
from openapi_core.components import ComponentsFactory
from openapi_core.exceptions import InvalidOperation, InvalidServer
from openapi_core.infos import InfoFactory
from openapi_core.paths import PathsGenerator
from openapi_core.schemas import SchemaRegistry
from openapi_core.servers import ServersGenerator
log = logging.getLogger(__name__)
class Spec(object):
"""Represents an OpenAPI Specification for a service."""
def __init__(self, info, paths, servers=None, components=None):
self.info = info
self.paths = paths and dict(paths)
self.servers = servers or []
self.components = components
def __getitem__(self, path_name):
return self.paths[path_name]
@property
def default_url(self):
return self.servers[0].default_url
def get_server(self, full_url_pattern):
for spec_server in self.servers:
if spec_server.default_url in full_url_pattern:
return spec_server
raise InvalidServer(
"Invalid request server {0}".format(full_url_pattern))
def get_server_url(self, index=0):
return self.servers[index].default_url
def get_operation(self, path_pattern, http_method):
try:
return self.paths[path_pattern].operations[http_method]
except KeyError:
raise InvalidOperation(
"Unknown operation path {0} with method {1}".format(
path_pattern, http_method))
def get_schema(self, name):
return self.components.schemas[name]
# operations shortcuts
get = partialmethod(get_operation, http_method='get')
put = partialmethod(get_operation, http_method='put')
post = partialmethod(get_operation, http_method='post')
delete = partialmethod(get_operation, http_method='delete')
options = partialmethod(get_operation, http_method='options')
head = partialmethod(get_operation, http_method='head')
patch = partialmethod(get_operation, http_method='patch')
class SpecFactory(object):
def __init__(self, dereferencer, config=None):
self.dereferencer = dereferencer
self.config = config or {}
def create(self, spec_dict, spec_url=''):
if self.config.get('validate_spec', True):
openapi_v3_spec_validator.validate(spec_dict, spec_url=spec_url)
spec_dict_deref = self.dereferencer.dereference(spec_dict)
info_spec = spec_dict_deref.get('info', {})
servers_spec = spec_dict_deref.get('servers', [])
paths = spec_dict_deref.get('paths', {})
components_spec = spec_dict_deref.get('components', {})
info = self.info_factory.create(info_spec)
servers = self.servers_generator.generate(servers_spec)
paths = self.paths_generator.generate(paths)
components = self.components_factory.create(components_spec)
spec = Spec(
info, list(paths), servers=list(servers), components=components)
return spec
@property
@lru_cache()
def schemas_registry(self):
return SchemaRegistry(self.dereferencer)
@property
@lru_cache()
def info_factory(self):
return InfoFactory(self.dereferencer)
@property
@lru_cache()
def servers_generator(self):
return ServersGenerator(self.dereferencer)
@property
@lru_cache()
def paths_generator(self):
return PathsGenerator(self.dereferencer, self.schemas_registry)
@property
@lru_cache()
def components_factory(self):
return ComponentsFactory(self.dereferencer, self.schemas_registry)

View file

@ -7,14 +7,14 @@ from openapi_core.exceptions import (
UndefinedSchemaProperty, MissingProperty,
EmptyValue, InvalidMediaTypeValue, InvalidParameterValue,
)
from openapi_core.media_types import MediaType
from openapi_core.operations import Operation
from openapi_core.parameters import Parameter
from openapi_core.paths import Path
from openapi_core.request_bodies import RequestBody
from openapi_core.responses import Response
from openapi_core.schemas import Schema
from openapi_core.servers import Server, ServerVariable
from openapi_core.schema.media_types.models import MediaType
from openapi_core.schema.operations.models import Operation
from openapi_core.schema.parameters.models import Parameter
from openapi_core.schema.paths.models import Path
from openapi_core.schema.request_bodies.models import RequestBody
from openapi_core.schema.responses.models import Response
from openapi_core.schema.schemas.models import Schema
from openapi_core.schema.servers.models import Server, ServerVariable
from openapi_core.shortcuts import create_spec
from openapi_core.validators import RequestValidator, ResponseValidator
from openapi_core.wrappers import MockRequest, MockResponse

View file

@ -1,7 +1,7 @@
import mock
import pytest
from openapi_core.operations import Operation
from openapi_core.schema.operations.models import Operation
class TestSchemas(object):

View file

@ -1,8 +1,8 @@
import pytest
from openapi_core.enums import ParameterStyle
from openapi_core.exceptions import EmptyValue
from openapi_core.parameters import Parameter
from openapi_core.schema.parameters.enums import ParameterStyle
from openapi_core.schema.parameters.models import Parameter
class TestParameterInit(object):

View file

@ -1,7 +1,7 @@
import mock
import pytest
from openapi_core.paths import Path
from openapi_core.schema.paths.models import Path
class TestPaths(object):

View file

@ -1,7 +1,7 @@
import mock
import pytest
from openapi_core.request_bodies import RequestBody
from openapi_core.schema.request_bodies.models import RequestBody
class TestRequestBodies(object):

View file

@ -2,7 +2,7 @@ import mock
import pytest
from openapi_core.exceptions import InvalidValueType, InvalidValue
from openapi_core.schemas import Schema
from openapi_core.schema.schemas.models import Schema
class TestSchemaIteritems(object):

View file

@ -2,8 +2,8 @@ import mock
import pytest
from openapi_core.exceptions import InvalidOperation
from openapi_core.paths import Path
from openapi_core.specs import Spec
from openapi_core.schema.paths.models import Path
from openapi_core.schema.specs.models import Spec
class TestSpecs(object):