codekingpro/portable-devtools
115k
1import abc2import json3from typing import Any, Callable, Dict, List, Optional, Tuple, Type, TypeVar, Union, overload4 5from dataclasses_json.cfg import config, LetterCase6from dataclasses_json.core import (Json, _ExtendedEncoder, _asdict,7 _decode_dataclass)8from dataclasses_json.mm import (JsonData, SchemaType, build_schema)9from dataclasses_json.undefined import Undefined10from dataclasses_json.utils import (_handle_undefined_parameters_safe,11 _undefined_parameter_action_safe)12 13A = TypeVar('A', bound="DataClassJsonMixin")14T = TypeVar('T')15Fields = List[Tuple[str, Any]]16 17 18class DataClassJsonMixin(abc.ABC):19 """20 DataClassJsonMixin is an ABC that functions as a Mixin.21 22 As with other ABCs, it should not be instantiated directly.23 """24 dataclass_json_config: Optional[dict] = None25 26 def to_json(self,27 *,28 skipkeys: bool = False,29 ensure_ascii: bool = True,30 check_circular: bool = True,31 allow_nan: bool = True,32 indent: Optional[Union[int, str]] = None,33 separators: Optional[Tuple[str, str]] = None,34 default: Optional[Callable] = None,35 sort_keys: bool = False,36 **kw) -> str:37 return json.dumps(self.to_dict(encode_json=False),38 cls=_ExtendedEncoder,39 skipkeys=skipkeys,40 ensure_ascii=ensure_ascii,41 check_circular=check_circular,42 allow_nan=allow_nan,43 indent=indent,44 separators=separators,45 default=default,46 sort_keys=sort_keys,47 **kw)48 49 @classmethod50 def from_json(cls: Type[A],51 s: JsonData,52 *,53 parse_float=None,54 parse_int=None,55 parse_constant=None,56 infer_missing=False,57 **kw) -> A:58 kvs = json.loads(s,59 parse_float=parse_float,60 parse_int=parse_int,61 parse_constant=parse_constant,62 **kw)63 return cls.from_dict(kvs, infer_missing=infer_missing)64 65 @classmethod66 def from_dict(cls: Type[A],67 kvs: Json,68 *,69 infer_missing=False) -> A:70 return _decode_dataclass(cls, kvs, infer_missing)71 72 def to_dict(self, encode_json=False) -> Dict[str, Json]:73 return _asdict(self, encode_json=encode_json)74 75 @classmethod76 def schema(cls: Type[A],77 *,78 infer_missing: bool = False,79 only=None,80 exclude=(),81 many: bool = False,82 context=None,83 load_only=(),84 dump_only=(),85 partial: bool = False,86 unknown=None) -> "SchemaType[A]":87 Schema = build_schema(cls, DataClassJsonMixin, infer_missing, partial)88 89 if unknown is None:90 undefined_parameter_action = _undefined_parameter_action_safe(cls)91 if undefined_parameter_action is not None:92 # We can just make use of the same-named mm keywords93 unknown = undefined_parameter_action.name.lower()94 95 return Schema(only=only,96 exclude=exclude,97 many=many,98 context=context,99 load_only=load_only,100 dump_only=dump_only,101 partial=partial,102 unknown=unknown)103 104 105@overload106def dataclass_json(_cls: None = ..., *, letter_case: Optional[LetterCase] = ...,107 undefined: Optional[Union[str, Undefined]] = ...) -> Callable[[Type[T]], Type[T]]: ...108 109 110@overload111def dataclass_json(_cls: Type[T], *, letter_case: Optional[LetterCase] = ...,112 undefined: Optional[Union[str, Undefined]] = ...) -> Type[T]: ...113 114 115def dataclass_json(_cls: Optional[Type[T]] = None, *, letter_case: Optional[LetterCase] = None,116 undefined: Optional[Union[str, Undefined]] = None) -> Union[Callable[[Type[T]], Type[T]], Type[T]]:117 """118 Based on the code in the `dataclasses` module to handle optional-parens119 decorators. See example below:120 121 @dataclass_json122 @dataclass_json(letter_case=LetterCase.CAMEL)123 class Example:124 ...125 """126 127 def wrap(cls: Type[T]) -> Type[T]:128 return _process_class(cls, letter_case, undefined)129 130 if _cls is None:131 return wrap132 return wrap(_cls)133 134 135def _process_class(cls: Type[T], letter_case: Optional[LetterCase],136 undefined: Optional[Union[str, Undefined]]) -> Type[T]:137 if letter_case is not None or undefined is not None:138 cls.dataclass_json_config = config(letter_case=letter_case, # type: ignore[attr-defined]139 undefined=undefined)['dataclasses_json']140 141 cls.to_json = DataClassJsonMixin.to_json # type: ignore[attr-defined]142 # unwrap and rewrap classmethod to tag it to cls rather than the literal143 # DataClassJsonMixin ABC144 cls.from_json = classmethod(DataClassJsonMixin.from_json.__func__) # type: ignore[attr-defined]145 cls.to_dict = DataClassJsonMixin.to_dict # type: ignore[attr-defined]146 cls.from_dict = classmethod(DataClassJsonMixin.from_dict.__func__) # type: ignore[attr-defined]147 cls.schema = classmethod(DataClassJsonMixin.schema.__func__) # type: ignore[attr-defined]148 149 cls.__init__ = _handle_undefined_parameters_safe(cls, kvs=(), # type: ignore[attr-defined,method-assign]150 usage="init")151 # register cls as a virtual subclass of DataClassJsonMixin152 DataClassJsonMixin.register(cls)153 return cls154 