Add x-nullable to Optional

master
Cristi Vijdea 2019-01-29 08:46:33 +02:00
parent 3806d6efd5
commit 69a1e62ed3
2 changed files with 20 additions and 11 deletions

View File

@ -459,7 +459,7 @@ def get_origin_type(hint_class):
return getattr(hint_class, '__origin__', None) or hint_class return getattr(hint_class, '__origin__', None) or hint_class
def is_origin_type_subclasses(hint_class, check_class): def hint_class_issubclass(hint_class, check_class):
origin_type = get_origin_type(hint_class) origin_type = get_origin_type(hint_class)
return inspect.isclass(origin_type) and issubclass(origin_type, check_class) return inspect.isclass(origin_type) and issubclass(origin_type, check_class)
@ -480,13 +480,13 @@ if typing:
def inspect_collection_hint_class(hint_class): def inspect_collection_hint_class(hint_class):
args = hint_class.__args__ args = hint_class.__args__
child_class = args[0] if args else str child_class = args[0] if args else str
child_type_info = get_basic_type_info_from_hint(child_class) child_type_info = get_basic_type_info_from_hint(child_class) or {'type': openapi.TYPE_STRING}
if not child_type_info:
child_type_info = {'type': openapi.TYPE_STRING}
return OrderedDict([ return OrderedDict([
('type', openapi.TYPE_ARRAY), ('type', openapi.TYPE_ARRAY),
('items', openapi.Items(**child_type_info)), ('items', openapi.Items(**child_type_info)),
]) ])
hinting_type_info.append(((typing.Sequence, typing.AbstractSet), inspect_collection_hint_class)) hinting_type_info.append(((typing.Sequence, typing.AbstractSet), inspect_collection_hint_class))
@ -500,18 +500,24 @@ def get_basic_type_info_from_hint(hint_class):
:rtype: OrderedDict :rtype: OrderedDict
""" """
if typing and get_origin_type(hint_class) == typing.Union: if typing and get_origin_type(hint_class) == typing.Union:
if len(hint_class.__args__) == 2 and hint_class.__args__[1] == type(None): # Optional is implemented as Union[T, None]
if len(hint_class.__args__) == 2 and hint_class.__args__[1] == type(None): # noqa: E721
child_type = hint_class.__args__[0] child_type = hint_class.__args__[0]
return get_basic_type_info_from_hint(child_type) result = get_basic_type_info_from_hint(child_type)
result['x-nullable'] = True
return result
return None return None
for check_class, info in hinting_type_info: for check_class, info in hinting_type_info:
if is_origin_type_subclasses(hint_class, check_class): if hint_class_issubclass(hint_class, check_class):
if callable(info): if callable(info):
return info(hint_class) return info(hint_class)
swagger_type, format = info swagger_type, format = info
if callable(swagger_type): if callable(swagger_type):
swagger_type = swagger_type() swagger_type = swagger_type()
return OrderedDict([ return OrderedDict([
('type', swagger_type), ('type', swagger_type),
('format', format), ('format', format),

View File

@ -11,7 +11,6 @@ try:
except ImportError: except ImportError:
typing = None typing = None
if typing: if typing:
@pytest.mark.parametrize('hint_class, expected_swagger_type_info', [ @pytest.mark.parametrize('hint_class, expected_swagger_type_info', [
(int, {'type': openapi.TYPE_INTEGER, 'format': None}), (int, {'type': openapi.TYPE_INTEGER, 'format': None}),
@ -24,9 +23,13 @@ if typing:
(List[str], {'type': openapi.TYPE_ARRAY, 'items': openapi.Items(openapi.TYPE_STRING)}), (List[str], {'type': openapi.TYPE_ARRAY, 'items': openapi.Items(openapi.TYPE_STRING)}),
(List[bool], {'type': openapi.TYPE_ARRAY, 'items': openapi.Items(openapi.TYPE_BOOLEAN)}), (List[bool], {'type': openapi.TYPE_ARRAY, 'items': openapi.Items(openapi.TYPE_BOOLEAN)}),
(Set[int], {'type': openapi.TYPE_ARRAY, 'items': openapi.Items(openapi.TYPE_INTEGER)}), (Set[int], {'type': openapi.TYPE_ARRAY, 'items': openapi.Items(openapi.TYPE_INTEGER)}),
(Optional[bool], {'type': openapi.TYPE_BOOLEAN, 'format': None}), (Optional[bool], {'type': openapi.TYPE_BOOLEAN, 'format': None, 'x-nullable': True}),
(Optional[List[int]], {'type': openapi.TYPE_ARRAY, 'items': openapi.Items(openapi.TYPE_INTEGER)}), (Optional[List[int]], {
(Union[List[int], type(None)], {'type': openapi.TYPE_ARRAY, 'items': openapi.Items(openapi.TYPE_INTEGER)}), 'type': openapi.TYPE_ARRAY, 'items': openapi.Items(openapi.TYPE_INTEGER), 'x-nullable': True
}),
(Union[List[int], type(None)], {
'type': openapi.TYPE_ARRAY, 'items': openapi.Items(openapi.TYPE_INTEGER), 'x-nullable': True
}),
# Following cases are not 100% correct, but it should work somehow and not crash. # Following cases are not 100% correct, but it should work somehow and not crash.
(Union[int, float], None), (Union[int, float], None),
(List, {'type': openapi.TYPE_ARRAY, 'items': openapi.Items(openapi.TYPE_STRING)}), (List, {'type': openapi.TYPE_ARRAY, 'items': openapi.Items(openapi.TYPE_STRING)}),