85 lines
1.8 KiB
Python
85 lines
1.8 KiB
Python
# coding: utf-8
|
|
|
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
|
|
|
import inspect
|
|
from copy import deepcopy
|
|
from enum import Enum
|
|
from typing import List, TypeVar
|
|
|
|
import attr
|
|
|
|
T = TypeVar('T')
|
|
|
|
|
|
def to_json(data):
|
|
if not hasattr(data, '__dict__'):
|
|
return data
|
|
|
|
d = {}
|
|
for k, v in data.__dict__.items():
|
|
if hasattr(v, 'json'):
|
|
d[k] = v.json()
|
|
elif isinstance(v, list):
|
|
d[k] = [to_json(i) for i in v]
|
|
elif isinstance(v, dict):
|
|
d[k] = {kk: to_json(vv) for kk, vv in v.items()}
|
|
elif isinstance(v, Enum):
|
|
d[k] = v.value
|
|
else:
|
|
d[k] = v
|
|
|
|
return d
|
|
|
|
|
|
def to_json_decorator(cls):
|
|
cls.json = to_json
|
|
return cls
|
|
|
|
|
|
def make_datatype(t, kwargs):
|
|
"""make_datatype
|
|
|
|
:type t: Type[T]
|
|
:type kwargs: Any
|
|
:rtype: T
|
|
"""
|
|
kwargs = deepcopy(kwargs)
|
|
|
|
if inspect.isclass(t) and issubclass(t, Enum):
|
|
return t(kwargs)
|
|
|
|
if isinstance(kwargs, (int, str, bool)):
|
|
return kwargs
|
|
|
|
if t.__class__ == List.__class__ and isinstance(kwargs, list):
|
|
return [make_datatype(t.__args__[0], i) for i in kwargs]
|
|
|
|
if not hasattr(t, '__attrs_attrs__'):
|
|
return kwargs
|
|
|
|
d = {}
|
|
attr_field = attr.fields(t)
|
|
for att in getattr(t, '__attrs_attrs__', []):
|
|
att_name = att.name
|
|
json_name = getattr(attr_field, att.name).metadata.get('json') or att_name
|
|
att_default = att.default
|
|
att_value = kwargs.get(json_name)
|
|
if att_value:
|
|
d[att_name] = make_datatype(att.type, att_value)
|
|
del kwargs[json_name]
|
|
elif att_default is attr.NOTHING:
|
|
d[att_name] = None
|
|
|
|
return t(**d)
|
|
|
|
|
|
def int_convert_bool(v):
|
|
return bool(v)
|
|
|
|
|
|
def to_lower_converter(s):
|
|
if isinstance(s, str):
|
|
return s.lower()
|
|
return s
|