Spaces:
Running
Running
import datetime | |
import logging | |
import re | |
import omagent_core.engine.http.models as http_models | |
import six | |
from omagent_core.engine.configuration.configuration import Configuration | |
from omagent_core.engine.http import rest | |
from requests.structures import CaseInsensitiveDict | |
logger = logging.getLogger(Configuration.get_logging_formatted_name(__name__)) | |
class ObjectMapper(object): | |
PRIMITIVE_TYPES = (float, bool, bytes, six.text_type) + six.integer_types | |
NATIVE_TYPES_MAPPING = { | |
"int": int, | |
"long": int if six.PY3 else long, # noqa: F821 | |
"float": float, | |
"str": str, | |
"bool": bool, | |
"date": datetime.date, | |
"datetime": datetime.datetime, | |
"object": object, | |
} | |
def to_json(self, obj): | |
if obj is None: | |
return None | |
elif isinstance(obj, self.PRIMITIVE_TYPES): | |
return obj | |
elif isinstance(obj, list): | |
return [self.to_json(sub_obj) for sub_obj in obj] | |
elif isinstance(obj, tuple): | |
return tuple(self.to_json(sub_obj) for sub_obj in obj) | |
elif isinstance(obj, (datetime.datetime, datetime.date)): | |
return obj.isoformat() | |
if isinstance(obj, dict) or isinstance(obj, CaseInsensitiveDict): | |
obj_dict = obj | |
else: | |
# Convert model obj to dict except | |
# attributes `swagger_types`, `attribute_map` | |
# and attributes which value is not None. | |
# Convert attribute name to json key in | |
# model definition for request. | |
if hasattr(obj, "attribute_map") and hasattr(obj, "swagger_types"): | |
obj_dict = { | |
obj.attribute_map[attr]: getattr(obj, attr) | |
for attr, _ in six.iteritems(obj.swagger_types) | |
if getattr(obj, attr) is not None | |
} | |
else: | |
obj_dict = { | |
name: getattr(obj, name) | |
for name in vars(obj) | |
if getattr(obj, name) is not None | |
} | |
return {key: self.to_json(val) for key, val in six.iteritems(obj_dict)} | |
def from_json(self, data, klass): | |
return self.__deserialize(data, klass) | |
def __deserialize(self, data, klass): | |
if data is None: | |
return None | |
if type(klass) == str: | |
if klass.startswith("list["): | |
sub_kls = re.match(r"list\[(.*)\]", klass).group(1) | |
return [self.__deserialize(sub_data, sub_kls) for sub_data in data] | |
if klass.startswith("dict("): | |
sub_kls = re.match(r"dict\(([^,]*), (.*)\)", klass).group(2) | |
return { | |
k: self.__deserialize(v, sub_kls) for k, v in six.iteritems(data) | |
} | |
# convert str to class | |
if klass in self.NATIVE_TYPES_MAPPING: | |
klass = self.NATIVE_TYPES_MAPPING[klass] | |
else: | |
klass = getattr(http_models, klass) | |
if klass in self.PRIMITIVE_TYPES: | |
return self.__deserialize_primitive(data, klass) | |
elif klass == object: | |
return self.__deserialize_object(data) | |
elif klass == datetime.date: | |
return self.__deserialize_date(data) | |
elif klass == datetime.datetime: | |
return self.__deserialize_datatime(data) | |
else: | |
return self.__deserialize_model(data, klass) | |
def __deserialize_primitive(self, data, klass): | |
"""Deserializes string to primitive type. | |
:param data: str. | |
:param klass: class literal. | |
:return: int, long, float, str, bool. | |
""" | |
try: | |
if klass == str and type(data) == bytes: | |
return self.__deserialize_bytes_to_str(data) | |
return klass(data) | |
except UnicodeEncodeError: | |
return six.text_type(data) | |
except TypeError: | |
return data | |
def __deserialize_bytes_to_str(self, data): | |
return data.decode("utf-8") | |
def __deserialize_object(self, value): | |
"""Return a original value. | |
:return: object. | |
""" | |
return value | |
def __deserialize_date(self, string): | |
"""Deserializes string to date. | |
:param string: str. | |
:return: date. | |
""" | |
try: | |
from dateutil.parser import parse | |
return parse(string).date() | |
except ImportError: | |
return string | |
except ValueError: | |
raise rest.ApiException( | |
status=0, reason="Failed to parse `{0}` as date object".format(string) | |
) | |
def __deserialize_datatime(self, string): | |
"""Deserializes string to datetime. | |
The string should be in iso8601 datetime format. | |
:param string: str. | |
:return: datetime. | |
""" | |
try: | |
from dateutil.parser import parse | |
return parse(string) | |
except ImportError: | |
return string | |
except ValueError: | |
raise rest.ApiException( | |
status=0, | |
reason=("Failed to parse `{0}` as datetime object".format(string)), | |
) | |
def __hasattr(self, object, name): | |
return name in object.__class__.__dict__ | |
def __deserialize_model(self, data, klass): | |
if not klass.swagger_types and not self.__hasattr( | |
klass, "get_real_child_model" | |
): | |
return data | |
kwargs = {} | |
if klass.swagger_types is not None: | |
for attr, attr_type in six.iteritems(klass.swagger_types): | |
if ( | |
data is not None | |
and klass.attribute_map[attr] in data | |
and isinstance(data, (list, dict)) | |
): | |
value = data[klass.attribute_map[attr]] | |
kwargs[attr] = self.__deserialize(value, attr_type) | |
instance = klass(**kwargs) | |
if ( | |
isinstance(instance, dict) | |
and klass.swagger_types is not None | |
and isinstance(data, dict) | |
): | |
for key, value in data.items(): | |
if key not in klass.swagger_types: | |
instance[key] = value | |
if self.__hasattr(instance, "get_real_child_model"): | |
klass_name = instance.get_real_child_model(data) | |
if klass_name: | |
instance = self.__deserialize(data, klass_name) | |
return instance | |