You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
66 lines
2.1 KiB
66 lines
2.1 KiB
from inspect import signature, Parameter |
|
from functools import wraps |
|
from typing import Optional |
|
import re |
|
|
|
|
|
CAMEL_REGEX = re.compile(r'([A-Z])') |
|
UNDERSCORE_REGEX = re.compile(r'_([a-z])') |
|
|
|
def camel_to_underscore(name): |
|
return CAMEL_REGEX.sub(lambda x: '_' + x.group(1).lower(), name) |
|
|
|
def underscore_to_camel(name): |
|
return UNDERSCORE_REGEX.sub(lambda x: x.group(1).upper(), name) |
|
|
|
def is_field_private(field_name: str) -> Optional[str]: |
|
m = re.match(r'_[^(__)]+__', field_name) |
|
return m is not None |
|
|
|
def inited_params(target_init): |
|
target_params = signature(target_init).parameters.values() |
|
if len(target_params) < 1: |
|
raise ValueError('init function mush have at least self parameter') |
|
if len(target_params) == 1: |
|
return target_init |
|
_, *target_params = target_params # we will not use self any more |
|
|
|
@wraps(target_init) |
|
def wrapped_init(wrapped_self, *wrapped_args, **wrapped_kwargs): |
|
for tp in target_params: |
|
if tp.default is Parameter.empty: |
|
continue |
|
setattr(wrapped_self, tp.name, tp.default) |
|
|
|
for tp, v in zip(target_params, wrapped_args): |
|
setattr(wrapped_self, tp.name, v) |
|
|
|
for k, v in wrapped_kwargs.items(): |
|
setattr(wrapped_self, k, v) |
|
|
|
target_init(wrapped_self, *wrapped_args, **wrapped_kwargs) |
|
|
|
return wrapped_init |
|
|
|
def JSONClass(target_class): |
|
|
|
def to_json(self) -> dict: |
|
""" |
|
returns a json representation of the class |
|
where all None - values and private fileds are skipped |
|
""" |
|
return { |
|
underscore_to_camel(k): v for k, v in self.__dict__.items() |
|
if v is not None and not is_field_private(k) |
|
} |
|
|
|
def from_json(json_object: Optional[dict]) -> target_class: |
|
if json_object is None: |
|
json_object = {} |
|
init_object = { camel_to_underscore(k): v for k, v in json_object.items() } |
|
return target_class(**init_object) |
|
|
|
# target_class.__init__ = inited_params(target_class.__init__) |
|
target_class.to_json = to_json |
|
target_class.from_json = from_json |
|
return target_class
|
|
|