1111)
1212
1313
14+ def f (self ):
15+ for name in ('' ,):
16+ t = self .__annotations__ [name ]
17+ setattr (self , name , t .to_internal_value (getattr (self , name )))
18+
19+
20+ def dataclass_post_init_converters (str_fields : List [str ]):
21+ """
22+ Method factory. Return post_init method to convert string into StringSerializable types
23+ To override generated __post_init__ you can call it directly:
24+
25+ >>> def __post_init__(self):
26+ ... dataclass_post_init_converters(['a', 'b'])(self)
27+
28+ :param str_fields: names of StringSerializable fields
29+ :return: __post_init__ method
30+ """
31+
32+ def __post_init__ (self ):
33+ for name in (str_fields ):
34+ t = self .__annotations__ [name ]
35+ setattr (self , name , t .to_internal_value (getattr (self , name )))
36+
37+ return __post_init__
38+
39+
40+ def convert_strings (str_fields : List [str ]):
41+ """
42+ Decorator factory. Set up `__post_init__` method to convert strings fields values into StringSerializable types
43+
44+ :param str_fields: names of StringSerializable fields
45+ :return: Class decorator
46+ """
47+
48+ def decorator (cls ):
49+ if hasattr (cls , '__post__init__' ):
50+ old_fn = cls .__post__init__
51+
52+ def __post__init__ (self , * args , ** kwargs ):
53+ dataclass_post_init_converters (str_fields )(self )
54+ old_fn (self , * args , ** kwargs )
55+
56+ setattr (cls , '__post_init__' , __post__init__ )
57+ else :
58+ setattr (cls , '__post_init__' , dataclass_post_init_converters (str_fields ))
59+
60+ return cls
61+
62+ return decorator
63+
64+
1465class DataclassModelCodeGenerator (GenericModelCodeGenerator ):
15- DC_DECORATOR = template ("dataclass"
16- "{% if kwargs %}"
17- f"({ KWAGRS_TEMPLATE } )"
18- "{% endif %}" )
66+ DC_DECORATOR = template (f"dataclass{{% if kwargs %}}({ KWAGRS_TEMPLATE } ){{% endif %}}" )
67+ DC_CONVERT_DECORATOR = template ("convert_strings({{ str_fields }})" )
1968 DC_FIELD = template (f"field({ KWAGRS_TEMPLATE } )" )
2069
2170 def __init__ (self , model : ModelMeta , meta = False , post_init_converters = False , dataclass_kwargs : dict = None ,
@@ -32,21 +81,17 @@ def __init__(self, model: ModelMeta, meta=False, post_init_converters=False, dat
3281 self .no_meta = not meta
3382 self .dataclass_kwargs = dataclass_kwargs or {}
3483
35- def generate (self , nested_classes : List [str ] = None ) -> Tuple [ImportPathList , str ]:
36- """
37- :param nested_classes: list of strings that contains classes code
38- :return: list of import data, class code
39- """
40- imports , code = super ().generate (nested_classes )
41- imports .append (('dataclasses' , ['dataclass, field' ]))
42- return imports , code
43-
4484 @property
45- def decorators (self ) -> List [str ]:
46- """
47- :return: List of decorators code (without @)
48- """
49- return [self .DC_DECORATOR .render (kwargs = self .dataclass_kwargs )]
85+ def decorators (self ) -> Tuple [ImportPathList , List [str ]]:
86+ imports = [('dataclasses' , ['dataclass' , 'field' ])]
87+ decorators = [self .DC_DECORATOR .render (kwargs = self .dataclass_kwargs )]
88+ if self .post_init_converters :
89+ str_fields = [self .convert_field_name (name ) for name , t in self .model .type .items ()
90+ if isclass (t ) and issubclass (t , StringSerializable )]
91+ if str_fields :
92+ imports .append (('json_to_models.models.dataclasses' , ['dataclass_post_init_converters' ]))
93+ decorators .append (self .DC_CONVERT_DECORATOR .render (str_fields = str_fields ))
94+ return imports , decorators
5095
5196 def field_data (self , name : str , meta : MetaData , optional : bool ) -> Tuple [ImportPathList , dict ]:
5297 """
0 commit comments