mirror of
https://github.com/correl/tornado-openapi3.git
synced 2024-12-27 11:09:53 +00:00
Allow overriding of spec as a dictionary
This commit is contained in:
parent
3a622e0306
commit
7a8f195712
7 changed files with 120 additions and 85 deletions
|
@ -29,10 +29,15 @@ author = "Correl Roush"
|
|||
# ones.
|
||||
extensions = [
|
||||
"sphinx.ext.autodoc",
|
||||
"sphinx.ext.intersphinx",
|
||||
"sphinx_rtd_theme",
|
||||
]
|
||||
|
||||
autodoc_member_order = "groupwise"
|
||||
autodoc_member_order = "bysource"
|
||||
intersphinx_mapping = {
|
||||
"python": ("https://docs.python.org/3", None),
|
||||
"tornado": ("https://tornado.readthedocs.org/", None),
|
||||
}
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ["_templates"]
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
Handling Incoming Requests
|
||||
==========================
|
||||
|
||||
OpenAPIRequestHandler extends Tornado's RequestHandler class, providing
|
||||
validation of incoming requests and translating errors into appropriate HTTP
|
||||
responses.
|
||||
|
||||
.. automodule:: tornado_openapi3.handler
|
||||
:members:
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
Testing API Responses
|
||||
=====================
|
||||
|
||||
AsyncOpenAPITestCase extends Tornado's AsyncHTTPTestCase class, providing
|
||||
validation of the responses from your application and raising errors in tests.
|
||||
|
||||
.. automodule:: tornado_openapi3.testing
|
||||
:members:
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import json
|
||||
import unittest.mock
|
||||
|
||||
from openapi_core import create_spec # type: ignore
|
||||
from openapi_core.exceptions import OpenAPIError # type: ignore
|
||||
import tornado.httpclient # type: ignore
|
||||
import tornado.web # type: ignore
|
||||
|
@ -11,60 +10,56 @@ from tornado_openapi3.handler import OpenAPIRequestHandler
|
|||
|
||||
|
||||
class ResourceHandler(OpenAPIRequestHandler):
|
||||
spec = create_spec(
|
||||
{
|
||||
"openapi": "3.0.0",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.0.0",
|
||||
spec_dict = {
|
||||
"openapi": "3.0.0",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.0.0",
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"resource": {
|
||||
"type": "object",
|
||||
"properties": {"name": {"type": "string"}},
|
||||
"required": ["name"],
|
||||
},
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"resource": {
|
||||
"type": "object",
|
||||
"properties": {"name": {"type": "string"}},
|
||||
"required": ["name"],
|
||||
"securitySchemes": {
|
||||
"basicAuth": {
|
||||
"type": "http",
|
||||
"scheme": "bearer",
|
||||
}
|
||||
},
|
||||
},
|
||||
"security": [{"basicAuth": []}],
|
||||
"paths": {
|
||||
"/resource": {
|
||||
"post": {
|
||||
"requestBody": {
|
||||
"required": True,
|
||||
"content": {
|
||||
"application/vnd.example.resource+json": {
|
||||
"schema": {"$ref": "#/components/schemas/resource"},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
"securitySchemes": {
|
||||
"basicAuth": {
|
||||
"type": "http",
|
||||
"scheme": "bearer",
|
||||
}
|
||||
},
|
||||
},
|
||||
"security": [{"basicAuth": []}],
|
||||
"paths": {
|
||||
"/resource": {
|
||||
"post": {
|
||||
"requestBody": {
|
||||
"required": True,
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success",
|
||||
"content": {
|
||||
"application/vnd.example.resource+json": {
|
||||
"schema": {"$ref": "#/components/schemas/resource"},
|
||||
}
|
||||
},
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success",
|
||||
"content": {
|
||||
"application/vnd.example.resource+json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/resource"
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
"401": {
|
||||
"description": "Missing or invalid credentials",
|
||||
},
|
||||
"401": {
|
||||
"description": "Missing or invalid credentials",
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
}
|
||||
custom_media_type_deserializers = {
|
||||
"application/vnd.example.resource+json": json.loads,
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import json
|
||||
|
||||
from openapi_core import create_spec # type: ignore
|
||||
from openapi_core.schema.responses.exceptions import InvalidResponse # type: ignore
|
||||
import tornado.web # type: ignore
|
||||
|
||||
|
@ -11,31 +10,29 @@ from tornado_openapi3.testing import AsyncOpenAPITestCase
|
|||
def spec(responses: dict = dict()) -> dict:
|
||||
if not responses:
|
||||
responses = {"200": {"description": "Success"}}
|
||||
return create_spec(
|
||||
{
|
||||
"openapi": "3.0.0",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.0.0",
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"resource": {
|
||||
"type": "object",
|
||||
"properties": {"name": {"type": "string"}},
|
||||
"required": ["name"],
|
||||
},
|
||||
return {
|
||||
"openapi": "3.0.0",
|
||||
"info": {
|
||||
"title": "Test API",
|
||||
"version": "1.0.0",
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"resource": {
|
||||
"type": "object",
|
||||
"properties": {"name": {"type": "string"}},
|
||||
"required": ["name"],
|
||||
},
|
||||
},
|
||||
"paths": {
|
||||
"/resource": {
|
||||
"get": {
|
||||
"responses": responses,
|
||||
}
|
||||
},
|
||||
"paths": {
|
||||
"/resource": {
|
||||
"get": {
|
||||
"responses": responses,
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class TestTestCase(AsyncOpenAPITestCase):
|
||||
|
@ -54,7 +51,7 @@ class TestTestCase(AsyncOpenAPITestCase):
|
|||
|
||||
|
||||
class BaseTestCase(AsyncOpenAPITestCase):
|
||||
spec = spec()
|
||||
spec_dict = spec()
|
||||
custom_media_type_deserializers = {
|
||||
"application/vnd.example.resource+json": json.loads,
|
||||
}
|
||||
|
@ -76,7 +73,7 @@ class BaseTestCase(AsyncOpenAPITestCase):
|
|||
|
||||
|
||||
class SuccessTests(BaseTestCase):
|
||||
spec = spec(
|
||||
spec_dict = spec(
|
||||
responses={
|
||||
"200": {
|
||||
"description": "Success",
|
||||
|
@ -99,7 +96,7 @@ class SuccessTests(BaseTestCase):
|
|||
|
||||
|
||||
class IncorrectResponseTests(BaseTestCase):
|
||||
spec = spec(responses={"200": {"description": "Success"}})
|
||||
spec_dict = spec(responses={"200": {"description": "Success"}})
|
||||
|
||||
async def get(self, handler: tornado.web.RequestHandler) -> None:
|
||||
handler.set_status(400)
|
||||
|
@ -111,7 +108,7 @@ class IncorrectResponseTests(BaseTestCase):
|
|||
|
||||
|
||||
class RaiseErrorTests(BaseTestCase):
|
||||
spec = spec(
|
||||
spec_dict = spec(
|
||||
responses={
|
||||
"500": {
|
||||
"description": "An error has occurred.",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import asyncio
|
||||
import logging
|
||||
|
||||
from openapi_core import create_spec # type: ignore
|
||||
from openapi_core.exceptions import OpenAPIError # type: ignore
|
||||
from openapi_core.deserializing.exceptions import DeserializeError # type: ignore
|
||||
from openapi_core.schema.specs.models import Spec # type: ignore
|
||||
|
@ -21,16 +22,38 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
|
||||
class OpenAPIRequestHandler(tornado.web.RequestHandler):
|
||||
"""Base class for HTTP request handlers.
|
||||
|
||||
A request handler extending :py:class:`tornado.web.RequestHandler` providing
|
||||
OpenAPI spec validation on incoming requests and translating errors into
|
||||
appropriate HTTP responses.
|
||||
|
||||
"""
|
||||
|
||||
@property
|
||||
def spec(self) -> Spec:
|
||||
"""The OpenAPI 3 specification.
|
||||
def spec_dict(self) -> dict:
|
||||
"""The OpenAPI 3 specification
|
||||
|
||||
Override this in your request handlers to load or define your OpenAPI 3
|
||||
spec.
|
||||
|
||||
:rtype: dict
|
||||
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
@property
|
||||
def spec(self) -> Spec:
|
||||
"""The OpenAPI 3 specification.
|
||||
|
||||
Override this in your request handlers to customize how your OpenAPI 3
|
||||
spec is loaded and validated.
|
||||
|
||||
:rtype: :py:class:`openapi_core.schema.specs.model.Spec`
|
||||
|
||||
"""
|
||||
return create_spec(self.spec_dict, validate_spec=False)
|
||||
|
||||
@property
|
||||
def custom_media_type_deserializers(self) -> dict:
|
||||
"""A dictionary mapping media types to deserializing functions.
|
||||
|
|
|
@ -3,20 +3,42 @@ from typing import Any
|
|||
import tornado.httpclient # type: ignore
|
||||
import tornado.testing # type: ignore
|
||||
|
||||
from openapi_core import create_spec # type: ignore
|
||||
from openapi_core.schema.specs.models import Spec # type: ignore
|
||||
from tornado_openapi3.responses import ResponseValidator
|
||||
|
||||
|
||||
class AsyncOpenAPITestCase(tornado.testing.AsyncHTTPTestCase):
|
||||
"""A test case that starts up an HTTP server.
|
||||
|
||||
An async test case extending :py:class:`tornado.testing.AsyncHTTPTestCase`,
|
||||
providing OpenAPI spec validation on the responses from your application and
|
||||
raising errors in tests.
|
||||
|
||||
"""
|
||||
|
||||
@property
|
||||
def spec_dict(self) -> dict:
|
||||
"""The OpenAPI 3 specification
|
||||
|
||||
Override this in your test cases to load or define your OpenAPI 3 spec.
|
||||
|
||||
:rtype: dict
|
||||
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
@property
|
||||
def spec(self) -> Spec:
|
||||
"""The OpenAPI 3 specification.
|
||||
|
||||
Override this in your request handlers to load or define your OpenAPI 3
|
||||
spec.
|
||||
Override this in your test cases to customize how your OpenAPI 3 spec is
|
||||
loaded and validated.
|
||||
|
||||
:rtype: :py:class:`openapi_core.schema.specs.model.Spec`
|
||||
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
return create_spec(self.spec_dict)
|
||||
|
||||
@property
|
||||
def custom_media_type_deserializers(self) -> dict:
|
||||
|
|
Loading…
Reference in a new issue