def default(self, o) -> JSON: result: JSON if _isinstance_safe(o, Collection): if _isinstance_safe(o, Mapping): result = dict(o) else: result = list(o) elif _isinstance_safe(o, datetime): result = o.timestamp() elif _isinstance_safe(o, UUID): result = str(o) else: result = json.JSONEncoder.default(self, o) return result
def _override(obj, attr): overrides = _overrides(obj) def o(k, v): if v is None: return None if k in overrides and getattr(overrides[k], attr) is not None: return getattr(overrides[k], attr)(v) return v override_kvs = {} as_dict = _asdict(obj) # if as_dict returns anything else # than dict we just want to return # a value here as it is not iterable. if not isinstance(as_dict, dict): return obj for k, v in as_dict.items(): this_obj = getattr(obj, k) if _isinstance_safe(this_obj, (list, tuple)): override_kvs[k] = [_override(o, attr) for o in this_obj] elif is_dataclass(this_obj): override_kvs[k] = _override(this_obj, attr) else: override_kvs[k] = o(k, v) return override_kvs
def default(self, o) -> Json: result: Json if _isinstance_safe(o, Collection): if _isinstance_safe(o, Mapping): result = dict(o) else: result = list(o) elif _isinstance_safe(o, datetime): result = o.timestamp() elif _isinstance_safe(o, timedelta): result = o.total_seconds() elif _isinstance_safe(o, UUID): result = str(o) elif _isinstance_safe(o, Enum): result = o.value elif _isinstance_safe(o, Decimal): result = str(o) else: result = json.JSONEncoder.default(self, o) return result
def default(self, o) -> JSON: result: JSON if _isinstance_safe(o, Collection): if _isinstance_safe(o, Mapping): result = dict(o) else: result = list(o) elif _isinstance_safe(o, datetime): result = o.isoformat() elif _isinstance_safe(o, UUID): result = str(o) elif _isinstance_safe(o, Decimal): result = str(o) elif _isinstance_safe(o, Enum): result = o.value elif _is_dataclass_instance(o): result = asdict(o) else: result = json.JSONEncoder.default(self, o) return result
def _decode_dataclass(cls, kvs, infer_missing): if _isinstance_safe(kvs, cls): return kvs overrides = _user_overrides_or_exts(cls) kvs = {} if kvs is None and infer_missing else kvs field_names = [field.name for field in fields(cls)] decode_names = _decode_letter_case_overrides(field_names, overrides) kvs = {decode_names.get(k, k): v for k, v in kvs.items()} missing_fields = {field for field in fields(cls) if field.name not in kvs} for field in missing_fields: if field.default is not MISSING: kvs[field.name] = field.default elif field.default_factory is not MISSING: kvs[field.name] = field.default_factory() elif infer_missing: kvs[field.name] = None # Perform undefined parameter action kvs = _handle_undefined_parameters_safe(cls, kvs, usage="from") init_kwargs = {} types = get_type_hints(cls) for field in fields(cls): # The field should be skipped from being added # to init_kwargs as it's not intended as a constructor argument. if not field.init: continue field_value = kvs[field.name] field_type = types[field.name] if field_value is None and not _is_optional(field_type): warning = (f"value of non-optional type {field.name} detected " f"when decoding {cls.__name__}") if infer_missing: warnings.warn( f"Missing {warning} and was defaulted to None by " f"infer_missing=True. " f"Set infer_missing=False (the default) to prevent this " f"behavior.", RuntimeWarning) else: warnings.warn(f"`NoneType` object {warning}.", RuntimeWarning) init_kwargs[field.name] = field_value continue while True: if not _is_new_type(field_type): break field_type = field_type.__supertype__ if (field.name in overrides and overrides[field.name].decoder is not None): # FIXME hack if field_type is type(field_value): init_kwargs[field.name] = field_value else: init_kwargs[field.name] = overrides[field.name].decoder( field_value) elif is_dataclass(field_type): # FIXME this is a band-aid to deal with the value already being # serialized when handling nested marshmallow schema # proper fix is to investigate the marshmallow schema generation # code if is_dataclass(field_value): value = field_value else: value = _decode_dataclass(field_type, field_value, infer_missing) init_kwargs[field.name] = value elif _is_supported_generic(field_type) and field_type != str: init_kwargs[field.name] = _decode_generic(field_type, field_value, infer_missing) else: init_kwargs[field.name] = _support_extended_types( field_type, field_value) return cls(**init_kwargs)