add support for marking Swagger paths deprecated

This commit is contained in:
Ryan Petrello 2018-02-02 15:04:34 -05:00
parent ac7c5f8648
commit 10974159b5
No known key found for this signature in database
GPG Key ID: F2AA5F2122351777
2 changed files with 28 additions and 11 deletions

View File

@ -1,3 +1,4 @@
import json
import warnings
from coreapi.document import Object, Link
@ -25,6 +26,8 @@ class AutoSchema(DRFAuthSchema):
'generated for {} {}.'
.format(self.view.__class__.__name__, method, path))
link.__dict__['deprecated'] = getattr(self.view, 'deprecated', False)
# auto-generate a topic/tag for the serializer based on its model
if hasattr(self.view, 'swagger_topic'):
link.__dict__['topic'] = str(self.view.swagger_topic).title()
@ -62,6 +65,9 @@ class SwaggerSchemaView(APIView):
urlconf=None
)
schema = generator.get_schema(request=request)
# python core-api doesn't support the deprecation yet, so track it
# ourselves and return it in a response header
_deprecated = []
# By default, DRF OpenAPI serialization places all endpoints in
# a single node based on their root path (/api). Instead, we want to
@ -75,6 +81,11 @@ class SwaggerSchemaView(APIView):
if topic:
schema._data.setdefault(topic, Object())
schema._data[topic]._data[path] = node
if isinstance(action, Object):
for link in action.links.values():
if link.deprecated:
_deprecated.append(link.url)
elif isinstance(node, Link):
topic = getattr(node, 'topic', None)
if topic:
@ -86,4 +97,7 @@ class SwaggerSchemaView(APIView):
'The schema generator did not return a schema Document'
)
return Response(schema)
return Response(
schema,
headers={'X-Deprecated-Paths': json.dumps(_deprecated)}
)

View File

@ -42,27 +42,27 @@ class TestSwaggerGeneration():
url = drf_reverse('api:swagger_view') + '?format=openapi'
response = get(url, user=admin)
data = generate_swagger_object(response.data)
if response.has_header('X-Deprecated-Paths'):
data['deprecated_paths'] = json.loads(response['X-Deprecated-Paths'])
data.update(response.accepted_renderer.get_customizations() or {})
self.__class__.JSON = data
def _lookup_display_name(self, method, path):
return path
def test_transform_metadata(self, release):
"""
This test takes the JSON output from the swagger endpoint and applies
various transformations to it.
"""
self.__class__.JSON['info']['version'] = release
self.__class__.JSON['host'] = None
self.__class__.JSON['schemes'] = ['https']
self.__class__.JSON['produces'] = ['application/json']
self.__class__.JSON['consumes'] = ['application/json']
JSON = self.__class__.JSON
JSON['info']['version'] = release
JSON['host'] = None
JSON['schemes'] = ['https']
JSON['produces'] = ['application/json']
JSON['consumes'] = ['application/json']
# Inject a top-level description into the OpenAPI document
if os.path.exists(description_file):
with open(description_file, 'r') as f:
self.__class__.JSON['info']['description'] = f.read()
JSON['info']['description'] = f.read()
# Write tags in the order we want them sorted
if os.path.exists(config_file):
@ -72,9 +72,10 @@ class TestSwaggerGeneration():
tag = {'name': category['name']}
if 'description' in category:
tag['description'] = category['description']
self.__class__.JSON.setdefault('tags', []).append(tag)
JSON.setdefault('tags', []).append(tag)
revised_paths = {}
deprecated_paths = JSON.pop('deprecated_paths', [])
for path, node in self.__class__.JSON['paths'].items():
# change {version} in paths to the actual default API version (e.g., v2)
revised_paths[path.replace(
@ -82,6 +83,8 @@ class TestSwaggerGeneration():
settings.REST_FRAMEWORK['DEFAULT_VERSION']
)] = node
for method in node:
if path in deprecated_paths:
node[method]['deprecated'] = True
if 'description' in node[method]:
# Pop off the first line and use that as the summary
lines = node[method]['description'].splitlines()