Пример #1
0
 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
Пример #2
0
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
Пример #3
0
 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
Пример #4
0
 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
Пример #5
0
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)