Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ COERCION_INDEX_BY_TYPE = {
ModelComposed: 0,
ModelNormal: 1,
ModelSimple: 2,
none_type: 3,
none_type: 3, # The type of 'None'.
list: 4,
dict: 5,
float: 6,
Expand All @@ -83,7 +83,8 @@ COERCION_INDEX_BY_TYPE = {
datetime: 9,
date: 10,
str: 11,
file_type: 12,
file_type: 12, # 'file_type' is an alias for the built-in 'file' or 'io.IOBase' type.
object: 13, # The 'type' attribute is not specified in the OAS schema.
Copy link
Contributor

@spacether spacether Apr 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sebastien-rosset can we discuss this over Skype?
I am concerned with doing it this way because many python classes inherit from the object type. So if we did it this way, it would allow in a ton of other class instances that we shouldn't like set, tuple, and arbitrary other classes.
Swagger/Openapi only allows specific types (string, int, float, dict, list, bytes, datetime, date, file_type, none_type)
My preference would be to instead convert these any type classes in python into a composed schema where it oneOf allows any type. As an added benefit, this could maybe be used to verify that we can have oneOf models with simple or complex types, which I'm not sure we can do.
Things like:
oneOf:

  • string
  • Pet

What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sebastien-rosset can we discuss this over Skype?
I am concerned with doing it this way because many python classes inherit from the object type. So if we did it this way, it would allow in a ton of other class instances that we shouldn't like set, tuple, and arbitrary other classes.
Swagger/Openapi only allows specific types (string, int, float, dict, list, bytes, datetime, date, file_type, none_type)
My preference would be to instead convert these any type classes in python into a composed schema where it oneOf allows any type. As an added benefit, this could maybe be used to verify that we can have oneOf models with simple or complex types, which I'm not sure we can do.
Things like:
oneOf:

  • string
  • Pet

What do you think?

Yes I think that makes sense. Currently, when the type is "any", the generated openapi_types() function has a dict of properties to set of allowed types, and the allowed type is "object". That currently causes a runtime exception. So instead of having "object" in the list, we would enumerate all possible types: str, bool, date, datetime, dict, float, int, list

}

# these are used to limit what type conversions we try to do
Expand Down Expand Up @@ -134,7 +135,12 @@ COERCIBLE_TYPE_PAIRS = {
(str, date),
# (int, str),
# (float, str),
(str, file_type)
(str, file_type),
(dict, object),
(list, object),
(str, object),
(int, object),
(float, object),
),
}

Expand Down Expand Up @@ -352,11 +358,11 @@ def order_response_types(required_types):

Args:
required_types (list/tuple): collection of classes or instance of
list or dict with classs information inside it
list or dict with class information inside it.

Returns:
(list): coercion order sorted collection of classes or instance
of list or dict with classs information inside it
of list or dict with class information inside it.
"""

def index_getter(class_or_instance):
Expand All @@ -373,7 +379,9 @@ def order_response_types(required_types):
elif (inspect.isclass(class_or_instance)
and issubclass(class_or_instance, ModelSimple)):
return COERCION_INDEX_BY_TYPE[ModelSimple]
return COERCION_INDEX_BY_TYPE[class_or_instance]
elif class_or_instance in COERCION_INDEX_BY_TYPE:
return COERCION_INDEX_BY_TYPE[class_or_instance]
raise ApiValueError("Unsupported type: %s" % class_or_instance)

sorted_types = sorted(
required_types,
Expand All @@ -391,7 +399,7 @@ def remove_uncoercible(required_types_classes, current_item, from_server,
these should be ordered by COERCION_INDEX_BY_TYPE
from_server (bool): a boolean of whether the data is from the server
if false, the data is from the client
current_item (any): the current item to be converted
current_item (any): the current item (input data) to be converted

Keyword Args:
must_convert (bool): if True the item to convert is of the wrong
Expand Down Expand Up @@ -692,6 +700,8 @@ def attempt_convert_item(input_value, valid_classes, path_to_item,
configuration, from_server)
elif valid_class == file_type:
return deserialize_file(input_value, configuration)
elif valid_class == object:
return input_value
return deserialize_primitive(input_value, valid_class,
path_to_item)
except (ApiTypeError, ApiValueError, ApiKeyError) as conversion_exc:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ def __eq__(self, other):
ModelComposed: 0,
ModelNormal: 1,
ModelSimple: 2,
none_type: 3,
none_type: 3, # The type of 'None'.
list: 4,
dict: 5,
float: 6,
Expand All @@ -339,7 +339,8 @@ def __eq__(self, other):
datetime: 9,
date: 10,
str: 11,
file_type: 12,
file_type: 12, # 'file_type' is an alias for the built-in 'file' or 'io.IOBase' type.
object: 13, # The 'type' attribute is not specified in the OAS schema.
}

# these are used to limit what type conversions we try to do
Expand Down Expand Up @@ -390,7 +391,12 @@ def __eq__(self, other):
(str, date),
# (int, str),
# (float, str),
(str, file_type)
(str, file_type),
(dict, object),
(list, object),
(str, object),
(int, object),
(float, object),
),
}

Expand Down Expand Up @@ -608,11 +614,11 @@ def order_response_types(required_types):

Args:
required_types (list/tuple): collection of classes or instance of
list or dict with classs information inside it
list or dict with class information inside it.

Returns:
(list): coercion order sorted collection of classes or instance
of list or dict with classs information inside it
of list or dict with class information inside it.
"""

def index_getter(class_or_instance):
Expand All @@ -629,7 +635,9 @@ def index_getter(class_or_instance):
elif (inspect.isclass(class_or_instance)
and issubclass(class_or_instance, ModelSimple)):
return COERCION_INDEX_BY_TYPE[ModelSimple]
return COERCION_INDEX_BY_TYPE[class_or_instance]
elif class_or_instance in COERCION_INDEX_BY_TYPE:
return COERCION_INDEX_BY_TYPE[class_or_instance]
raise ApiValueError("Unsupported type: %s" % class_or_instance)

sorted_types = sorted(
required_types,
Expand All @@ -647,7 +655,7 @@ def remove_uncoercible(required_types_classes, current_item, from_server,
these should be ordered by COERCION_INDEX_BY_TYPE
from_server (bool): a boolean of whether the data is from the server
if false, the data is from the client
current_item (any): the current item to be converted
current_item (any): the current item (input data) to be converted

Keyword Args:
must_convert (bool): if True the item to convert is of the wrong
Expand Down Expand Up @@ -948,6 +956,8 @@ def attempt_convert_item(input_value, valid_classes, path_to_item,
configuration, from_server)
elif valid_class == file_type:
return deserialize_file(input_value, configuration)
elif valid_class == object:
return input_value
return deserialize_primitive(input_value, valid_class,
path_to_item)
except (ApiTypeError, ApiValueError, ApiKeyError) as conversion_exc:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ def __eq__(self, other):
ModelComposed: 0,
ModelNormal: 1,
ModelSimple: 2,
none_type: 3,
none_type: 3, # The type of 'None'.
list: 4,
dict: 5,
float: 6,
Expand All @@ -339,7 +339,8 @@ def __eq__(self, other):
datetime: 9,
date: 10,
str: 11,
file_type: 12,
file_type: 12, # 'file_type' is an alias for the built-in 'file' or 'io.IOBase' type.
object: 13, # The 'type' attribute is not specified in the OAS schema.
}

# these are used to limit what type conversions we try to do
Expand Down Expand Up @@ -390,7 +391,12 @@ def __eq__(self, other):
(str, date),
# (int, str),
# (float, str),
(str, file_type)
(str, file_type),
(dict, object),
(list, object),
(str, object),
(int, object),
(float, object),
),
}

Expand Down Expand Up @@ -608,11 +614,11 @@ def order_response_types(required_types):

Args:
required_types (list/tuple): collection of classes or instance of
list or dict with classs information inside it
list or dict with class information inside it.

Returns:
(list): coercion order sorted collection of classes or instance
of list or dict with classs information inside it
of list or dict with class information inside it.
"""

def index_getter(class_or_instance):
Expand All @@ -629,7 +635,9 @@ def index_getter(class_or_instance):
elif (inspect.isclass(class_or_instance)
and issubclass(class_or_instance, ModelSimple)):
return COERCION_INDEX_BY_TYPE[ModelSimple]
return COERCION_INDEX_BY_TYPE[class_or_instance]
elif class_or_instance in COERCION_INDEX_BY_TYPE:
return COERCION_INDEX_BY_TYPE[class_or_instance]
raise ApiValueError("Unsupported type: %s" % class_or_instance)

sorted_types = sorted(
required_types,
Expand All @@ -647,7 +655,7 @@ def remove_uncoercible(required_types_classes, current_item, from_server,
these should be ordered by COERCION_INDEX_BY_TYPE
from_server (bool): a boolean of whether the data is from the server
if false, the data is from the client
current_item (any): the current item to be converted
current_item (any): the current item (input data) to be converted

Keyword Args:
must_convert (bool): if True the item to convert is of the wrong
Expand Down Expand Up @@ -948,6 +956,8 @@ def attempt_convert_item(input_value, valid_classes, path_to_item,
configuration, from_server)
elif valid_class == file_type:
return deserialize_file(input_value, configuration)
elif valid_class == object:
return input_value
return deserialize_primitive(input_value, valid_class,
path_to_item)
except (ApiTypeError, ApiValueError, ApiKeyError) as conversion_exc:
Expand Down