-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathdataclasses.py
76 lines (66 loc) · 3.03 KB
/
dataclasses.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
from inspect import isclass
from typing import List, Tuple
from .base import GenericModelCodeGenerator, KWAGRS_TEMPLATE, METADATA_FIELD_NAME, sort_kwargs, template
from ..dynamic_typing import (DDict, DList, DOptional, ImportPathList, MetaData, ModelMeta, StringSerializable)
DEFAULT_ORDER = (
("default", "default_factory"),
"*",
("metadata",)
)
class DataclassModelCodeGenerator(GenericModelCodeGenerator):
DC_DECORATOR = template(f"dataclass{{% if kwargs %}}({KWAGRS_TEMPLATE}){{% endif %}}")
DC_FIELD = template(f"field({KWAGRS_TEMPLATE})")
def __init__(self, model: ModelMeta, meta=False, dataclass_kwargs: dict = None, **kwargs):
"""
:param model: ModelMeta instance
:param meta: Enable generation of metadata as attrib argument
:param dataclass_kwargs: kwargs for @dataclass() decorators
:param kwargs:
"""
super().__init__(model, **kwargs)
self.no_meta = not meta
self.dataclass_kwargs = dataclass_kwargs or {}
@property
def decorators(self) -> Tuple[ImportPathList, List[str]]:
imports, decorators = super().decorators
imports.append(('dataclasses', ['dataclass', 'field']))
decorators.insert(0, self.DC_DECORATOR.render(kwargs=self.dataclass_kwargs))
return imports, decorators
def field_data(self, name: str, meta: MetaData, optional: bool) -> Tuple[ImportPathList, dict]:
"""
Form field data for template
:param name: Original field name
:param meta: Field metadata
:param optional: Is field optional
:return: imports, field data
"""
imports, data = super().field_data(name, meta, optional)
body_kwargs = {}
if optional:
meta: DOptional
if isinstance(meta.type, DList):
body_kwargs["default_factory"] = "list"
elif isinstance(meta.type, DDict):
body_kwargs["default_factory"] = "dict"
else:
body_kwargs["default"] = "None"
if isclass(meta.type) and issubclass(meta.type, StringSerializable):
pass
elif isclass(meta) and issubclass(meta, StringSerializable):
pass
if not self.no_meta and name != data["name"]:
body_kwargs["metadata"] = {METADATA_FIELD_NAME: name}
if len(body_kwargs) == 1 and next(iter(body_kwargs.keys())) == "default":
data["body"] = body_kwargs["default"]
elif body_kwargs:
data["body"] = self.DC_FIELD.render(kwargs=sort_kwargs(body_kwargs, DEFAULT_ORDER))
return imports, data
@property
def convert_strings_kwargs(self) -> Tuple[ImportPathList, dict]:
"""
:return: Imports and Dict with kw-arguments for `json_to_models.models.string_converters.convert_strings` decorator.
"""
imports, kwargs = super().convert_strings_kwargs
imports.append(('json_to_models.models', ['ClassType']))
kwargs["class_type"] = 'ClassType.Dataclass'
return imports, kwargs