-
Notifications
You must be signed in to change notification settings - Fork 35
fixing #37 issue support of definitions for nested objects #38
base: master
Are you sure you want to change the base?
Changes from 4 commits
97724ae
a67ba3a
2391f78
aea9c8c
5a7bb2a
532bfbd
5be9182
fec8d0e
4152782
09a0648
cd49ed4
56dea30
2efbdcc
44ebcbe
836aa93
efd7516
cb565a3
ca20480
84a1d7b
34d9cd5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
import coreschema | ||
from collections import OrderedDict | ||
from coreapi.document import Field | ||
from coreapi.compat import urlparse | ||
from openapi_codec.utils import get_method, get_encoding, get_location, get_links_from_document | ||
|
||
|
@@ -23,15 +24,61 @@ def generate_swagger_object(document): | |
swagger['schemes'] = [parsed_url.scheme] | ||
|
||
swagger['paths'] = _get_paths_object(document) | ||
swagger['definitions'] = _get_definitions(document) | ||
|
||
return swagger | ||
|
||
|
||
def _get_definitions(document): | ||
|
||
definitions = OrderedDict() | ||
links = _get_links(document) | ||
|
||
def get_field_def_data(field_item, defs): | ||
|
||
definition_data = { | ||
'type': 'object', | ||
'properties': {} | ||
} | ||
|
||
if isinstance(field_item, coreschema.Object): | ||
props = field_item.properties | ||
else: | ||
props = field_item.schema.properties | ||
|
||
for f_name, f_schema in iter(props.items()): | ||
|
||
if _get_field_type(f_schema) is 'object': | ||
defs[f_name] = get_field_def_data(f_schema, defs) | ||
definition_data['properties'][f_name] = { | ||
'$ref': '#/definitions/{}'.format(f_name) | ||
} | ||
else: | ||
definition_data['properties'][f_name] = { | ||
'type': _get_field_type(f_schema), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i suppose it needs something like elif _get_field_type(f_schema) == 'array':
_item_name = '{}_item'.format(f_name)
defs[_item_name] = get_field_def_data(f_schema.items, defs)
definition_data['properties'][f_name] = {
'type': 'array',
'items': {'$ref': '#/definitions/{}'.format(_item_name)}
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The usage of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes. name clashes shoudl be a problem in all of this PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, let me figure that out. I thought it was useful and nobody even start it, but as soon I did it turns out everyone, but me knows how to do it better =) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @xxmatyuk No offense =), I tried 2 other PRs for the same issue, and yours is still the best although still not quite ready. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @tuffnatty no problems, that was looong hard day) I'm willing to fix it, so stay tuned. And yeah, thanks ) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @tuky @tuffnatty There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Say e.g. you have 4 serializers in 2 different files: class AuthorSerializer(Serializer):
name = CharField()
class Song(Serializer):
author = AuthorSerializer()
co_authors = AuthorSerializer(many=True) class AuthorSerializer(Serializer):
birthday = DateField()
class Song(Serializer):
author = AuthorSerializer() The 2 different There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @tuky, thanks a lot! I wrote a test, reproduced the clash, working on fix. |
||
'description': '' | ||
} | ||
|
||
return definition_data | ||
|
||
for _, link, _ in links: | ||
for field in link.fields: | ||
field_type = _get_field_type(field) | ||
if field_type == 'object': | ||
definitions[field.name] = get_field_def_data(field, definitions) | ||
|
||
if field_type == 'array': | ||
item_name = '{}_item'.format(field.name) | ||
definitions[item_name] = get_field_def_data(field.schema.items, definitions) | ||
|
||
return definitions | ||
|
||
|
||
def _add_tag_prefix(item): | ||
operation_id, link, tags = item | ||
if tags: | ||
operation_id = tags[0] + '_' + operation_id | ||
return (operation_id, link, tags) | ||
return operation_id, link, tags | ||
|
||
|
||
def _get_links(document): | ||
|
@@ -114,8 +161,10 @@ def _get_field_type(field): | |
# Deprecated | ||
return field.type | ||
|
||
if field.schema is None: | ||
return 'string' | ||
if isinstance(field, Field): | ||
cls = field.schema.__class__ | ||
else: | ||
cls = field.__class__ | ||
|
||
return { | ||
coreschema.String: 'string', | ||
|
@@ -124,7 +173,7 @@ def _get_field_type(field): | |
coreschema.Boolean: 'boolean', | ||
coreschema.Array: 'array', | ||
coreschema.Object: 'object', | ||
}.get(field.schema.__class__, 'string') | ||
}.get(cls, 'string') | ||
|
||
|
||
def _get_parameters(link, encoding): | ||
|
@@ -160,8 +209,14 @@ def _get_parameters(link, encoding): | |
'description': field_description, | ||
'type': field_type, | ||
} | ||
|
||
if field_type == 'array': | ||
schema_property['items'] = {'type': 'string'} | ||
item_name = '{}_item'.format(field.name) | ||
schema_property['items'] = {'$ref': '#/definitions/{}'.format(item_name)} | ||
|
||
if field_type == 'object': | ||
schema_property = {'$ref': '#/definitions/{}'.format(field.name)} | ||
|
||
properties[field.name] = schema_property | ||
if field.required: | ||
required.append(field.name) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since the recursion can also be an array of "simple" types, i would also suggest to add here: