Skip to content

Operations fields #169

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
14 changes: 14 additions & 0 deletions openapi_core/schema/external_docs/factories.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""OpenAPI core external docs factories module"""
from openapi_core.schema.external_docs.models import ExternalDocumentation


class ExternalDocumentationFactory(object):

def __init__(self, dereferencer):
self.dereferencer = dereferencer

def create(self, external_doc_spec):
url = external_doc_spec['url']
description = external_doc_spec.get('description')

return ExternalDocumentation(url, description=description)
9 changes: 9 additions & 0 deletions openapi_core/schema/external_docs/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"""OpenAPI core external docs models module"""


class ExternalDocumentation(object):
"""Represents an OpenAPI External Documentation."""

def __init__(self, url, description=None):
self.url = url
self.description = description
43 changes: 42 additions & 1 deletion openapi_core/schema/operations/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@
from openapi_spec_validator.validators import PathItemValidator

from openapi_core.compat import lru_cache
from openapi_core.schema.external_docs.factories import (
ExternalDocumentationFactory,
)
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
from openapi_core.schema.security.factories import SecurityRequirementFactory
from openapi_core.schema.servers.generators import ServersGenerator


class OperationsGenerator(object):
Expand All @@ -32,6 +37,24 @@ def generate(self, path_name, path):
parameters_list)
operation_id = operation_deref.get('operationId')
tags_list = operation_deref.get('tags', [])
summary = operation_deref.get('summary')
description = operation_deref.get('description')
security_requirements_list = operation_deref.get('security', [])
servers_spec = operation_deref.get('servers', [])

servers = self.servers_generator.generate(servers_spec)

security = None
if security_requirements_list:
security = list(map(
self.security_requirement_factory.create,
security_requirements_list))

external_docs = None
if 'externalDocs' in operation_deref:
external_docs_spec = operation_deref.get('externalDocs')
external_docs = self.external_docs_factory.create(
external_docs_spec)

request_body = None
if 'requestBody' in operation_deref:
Expand All @@ -43,8 +66,11 @@ def generate(self, path_name, path):
http_method,
Operation(
http_method, path_name, responses, list(parameters),
summary=summary, description=description,
external_docs=external_docs, security=security,
request_body=request_body, deprecated=deprecated,
operation_id=operation_id, tags=list(tags_list)
operation_id=operation_id, tags=list(tags_list),
servers=servers,
),
)

Expand All @@ -58,7 +84,22 @@ def responses_generator(self):
def parameters_generator(self):
return ParametersGenerator(self.dereferencer, self.schemas_registry)

@property
@lru_cache()
def external_docs_factory(self):
return ExternalDocumentationFactory(self.dereferencer)

@property
@lru_cache()
def request_body_factory(self):
return RequestBodyFactory(self.dereferencer, self.schemas_registry)

@property
@lru_cache()
def security_requirement_factory(self):
return SecurityRequirementFactory(self.dereferencer)

@property
@lru_cache()
def servers_generator(self):
return ServersGenerator(self.dereferencer)
9 changes: 8 additions & 1 deletion openapi_core/schema/operations/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,22 @@ class Operation(object):

def __init__(
self, http_method, path_name, responses, parameters,
request_body=None, deprecated=False, operation_id=None, tags=None):
summary=None, description=None, external_docs=None, security=None,
request_body=None, deprecated=False, operation_id=None, tags=None,
servers=None):
self.http_method = http_method
self.path_name = path_name
self.responses = dict(responses)
self.parameters = dict(parameters)
self.summary = summary
self.description = description
self.external_docs = external_docs
self.security = security
self.request_body = request_body
self.deprecated = deprecated
self.operation_id = operation_id
self.tags = tags
self.servers = servers

def __getitem__(self, name):
return self.parameters[name]
Expand Down
Empty file.
14 changes: 14 additions & 0 deletions openapi_core/schema/security/factories.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""OpenAPI core security factories module"""
from openapi_core.schema.security.models import SecurityRequirement


class SecurityRequirementFactory(object):

def __init__(self, dereferencer):
self.dereferencer = dereferencer

def create(self, security_requirement_spec):
name = next(iter(security_requirement_spec))
scope_names = security_requirement_spec[name]

return SecurityRequirement(name, scope_names=scope_names)
9 changes: 9 additions & 0 deletions openapi_core/schema/security/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"""OpenAPI core security models module"""


class SecurityRequirement(object):
"""Represents an OpenAPI Security Requirement."""

def __init__(self, name, scope_names=None):
self.name = name
self.scope_names = scope_names or []
6 changes: 2 additions & 4 deletions openapi_core/schema/servers/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,16 @@ def __init__(self, dereferencer):

def generate(self, servers_spec):
servers_deref = self.dereferencer.dereference(servers_spec)
if not servers_deref:
yield Server('/')
return
for server_spec in servers_deref:
url = server_spec['url']
variables_spec = server_spec.get('variables', {})
description = server_spec.get('description')

variables = None
if variables_spec:
variables = self.variables_generator.generate(variables_spec)

yield Server(url, variables=variables)
yield Server(url, variables=variables, description=description)

@property
@lru_cache()
Expand Down
3 changes: 2 additions & 1 deletion openapi_core/schema/servers/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@

class Server(object):

def __init__(self, url, variables=None):
def __init__(self, url, variables=None, description=None):
self.url = url
self.variables = variables and dict(variables) or {}
self.description = description

@property
def default_url(self):
Expand Down
5 changes: 5 additions & 0 deletions openapi_core/schema/specs/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ def create(self, spec_dict, spec_url=''):
paths = spec_dict_deref.get('paths', {})
components_spec = spec_dict_deref.get('components', {})

if not servers_spec:
servers_spec = [
{'url': '/'},
]

info = self.info_factory.create(info_spec)
servers = self.servers_generator.generate(servers_spec)
paths = self.paths_generator.generate(paths)
Expand Down
13 changes: 13 additions & 0 deletions tests/integration/data/v3.0/petstore.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,19 @@ paths:
$ref: "#/components/responses/PetsResponse"
post:
summary: Create a pet
description: Creates new pet entry
externalDocs:
url: https://example.com
description: Find more info here
security:
- petstore_auth:
- write:pets
- read:pets
servers:
- url: https://development.gigantic-server.com/v1
description: Development server
- url: https://staging.gigantic-server.com/v1
description: Staging server
operationId: createPets
tags:
- pets
Expand Down
37 changes: 37 additions & 0 deletions tests/integration/schema/test_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
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.security.models import SecurityRequirement
from openapi_core.schema.servers.models import Server, ServerVariable
from openapi_core.shortcuts import create_spec
from openapi_core.validation.request.validators import RequestValidator
Expand Down Expand Up @@ -79,6 +80,42 @@ def test_spec(self, spec, spec_dict):
assert operation.http_method == http_method
assert operation.operation_id is not None
assert operation.tags == operation_spec['tags']
assert operation.summary == operation_spec.get('summary')
assert operation.description == operation_spec.get(
'description')

ext_docs_spec = operation_spec.get('externalDocs')
if ext_docs_spec:
ext_docs = operation.external_docs
assert ext_docs.url == ext_docs_spec['url']
assert ext_docs.description == ext_docs_spec.get(
'description')

security_spec = operation_spec.get('security')
if security_spec:
for idx, sec_req in enumerate(operation.security):
assert type(sec_req) == SecurityRequirement
sec_req_spec = security_spec[idx]
sec_req_nam = next(iter(sec_req_spec))
assert sec_req.name == sec_req_nam
assert sec_req.scope_names == sec_req_spec[sec_req_nam]

servers_spec = operation_spec.get('servers', [])
for idx, server in enumerate(operation.servers):
assert type(server) == Server

server_spec = servers_spec[idx]
assert server.url == server_spec['url']
assert server.default_url == server_spec['url']
assert server.description == server_spec.get('description')

for variable_name, variable in iteritems(server.variables):
assert type(variable) == ServerVariable
assert variable.name == variable_name

variable_spec = server_spec['variables'][variable_name]
assert variable.default == variable_spec['default']
assert variable.enum == variable_spec.get('enum')

responses_spec = operation_spec.get('responses')

Expand Down