Allow overriding of spec as a dictionary

This commit is contained in:
Correl Roush 2021-03-05 15:23:23 -05:00
parent 3a622e0306
commit 7a8f195712
7 changed files with 120 additions and 85 deletions

View file

@ -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"]

View file

@ -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:

View file

@ -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:

View file

@ -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,8 +10,7 @@ from tornado_openapi3.handler import OpenAPIRequestHandler
class ResourceHandler(OpenAPIRequestHandler):
spec = create_spec(
{
spec_dict = {
"openapi": "3.0.0",
"info": {
"title": "Test API",
@ -50,9 +48,7 @@ class ResourceHandler(OpenAPIRequestHandler):
"description": "Success",
"content": {
"application/vnd.example.resource+json": {
"schema": {
"$ref": "#/components/schemas/resource"
},
"schema": {"$ref": "#/components/schemas/resource"},
}
},
},
@ -64,7 +60,6 @@ class ResourceHandler(OpenAPIRequestHandler):
}
},
}
)
custom_media_type_deserializers = {
"application/vnd.example.resource+json": json.loads,
}

View file

@ -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,8 +10,7 @@ from tornado_openapi3.testing import AsyncOpenAPITestCase
def spec(responses: dict = dict()) -> dict:
if not responses:
responses = {"200": {"description": "Success"}}
return create_spec(
{
return {
"openapi": "3.0.0",
"info": {
"title": "Test API",
@ -35,7 +33,6 @@ def spec(responses: dict = dict()) -> dict:
}
},
}
)
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.",

View file

@ -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.

View file

@ -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: