def _from_dict_set_value(self, fname, ftype, metadata, alias=None): self.add_line(f"value = d.get('{alias or fname}', MISSING)") self.add_line("if value is None:") with self.indent(): self.add_line(f"kwargs['{fname}'] = None") if self.defaults[fname] is MISSING: self.add_line("elif value is MISSING:") with self.indent(): self.add_line(f"raise MissingField('{fname}'," f"{type_name(ftype)},cls)") self.add_line("else:") with self.indent(): unpacked_value = self._unpack_field_value( fname=fname, ftype=ftype, parent=self.cls, metadata=metadata, ) self.add_line("try:") with self.indent(): self.add_line(f"kwargs['{fname}'] = {unpacked_value}") self.add_line("except Exception as e:") with self.indent(): field_type = type_name(ftype) self.add_line(f"raise InvalidFieldValue('{fname}'," f"{field_type},value,cls)") else: self.add_line("elif value is not MISSING:") with self.indent(): unpacked_value = self._unpack_field_value( fname=fname, ftype=ftype, parent=self.cls, metadata=metadata, ) self.add_line("try:") with self.indent(): self.add_line(f"kwargs['{fname}'] = {unpacked_value}") self.add_line("except Exception as e:") with self.indent(): field_type = type_name(ftype) self.add_line(f"raise InvalidFieldValue('{fname}'," f"{field_type},value,cls)")
def holder_class_name(self): return type_name(self.holder_class)
def field_type_name(self): return type_name(self.field_type)
def get_declared_hook(self, method_name: str): if not hasattr(self.cls, method_name): return cls = get_class_that_define_method(method_name, self.cls) if type_name(cls) != DataClassDictMixinPath: return cls.__dict__[method_name]
def add_from_dict(self) -> None: self.reset() self.add_line("@classmethod") self.add_line( "def from_dict(cls, d, use_bytes=False, use_enum=False, " "use_datetime=False):" ) with self.indent(): pre_deserialize = self.get_declared_hook(__PRE_DESERIALIZE__) if pre_deserialize: if not isinstance(pre_deserialize, classmethod): raise BadHookSignature( f"`{__PRE_DESERIALIZE__}` must be a class method with " f"Callable[[Dict[Any, Any]], Dict[Any, Any]] signature" ) else: self.add_line(f"d = cls.{__PRE_DESERIALIZE__}(d)") self.add_line("try:") with self.indent(): self.add_line("kwargs = {}") for fname, ftype in self.field_types.items(): metadata = self.metadatas.get(fname) self._add_type_modules(ftype) self.add_line(f"value = d.get('{fname}', MISSING)") self.add_line("if value is None:") with self.indent(): self.add_line(f"kwargs['{fname}'] = None") self.add_line("else:") with self.indent(): if self.defaults[fname] is MISSING: self.add_line("if value is MISSING:") with self.indent(): self.add_line( f"raise MissingField('{fname}'," f"{type_name(ftype)},cls)" ) self.add_line("else:") with self.indent(): unpacked_value = self._unpack_field_value( fname=fname, ftype=ftype, parent=self.cls, metadata=metadata, ) self.add_line("try:") with self.indent(): self.add_line( f"kwargs['{fname}'] = {unpacked_value}" ) self.add_line("except Exception as e:") with self.indent(): field_type = type_name(ftype) self.add_line( f"raise InvalidFieldValue('{fname}'," f"{field_type},value,cls)" ) else: self.add_line("if value is not MISSING:") with self.indent(): unpacked_value = self._unpack_field_value( fname=fname, ftype=ftype, parent=self.cls, metadata=metadata, ) self.add_line("try:") with self.indent(): self.add_line( f"kwargs['{fname}'] = {unpacked_value}" ) self.add_line("except Exception as e:") with self.indent(): field_type = type_name(ftype) self.add_line( f"raise InvalidFieldValue('{fname}'," f"{field_type},value,cls)" ) self.add_line("except AttributeError:") with self.indent(): self.add_line("if not isinstance(d, dict):") with self.indent(): self.add_line( f"raise ValueError('Argument for " f"{type_name(self.cls)}.from_dict method " f"should be a dict instance') from None" ) self.add_line("else:") with self.indent(): self.add_line("raise") post_deserialize = self.get_declared_hook(__POST_DESERIALIZE__) if post_deserialize: if not isinstance(post_deserialize, classmethod): raise BadHookSignature( f"`{__POST_DESERIALIZE__}` must be a class method " f"with Callable[[{type_name(self.cls)}], " f"{type_name(self.cls)}] signature" ) else: self.add_line( f"return cls.{__POST_DESERIALIZE__}(cls(**kwargs))" ) else: self.add_line("return cls(**kwargs)") self.add_line("setattr(cls, 'from_dict', from_dict)") self.compile()