1
1
from dataclasses import dataclass
2
- from typing import Optional , List , Dict , Union
2
+ from typing import Optional , List , Dict , Union , ClassVar
3
+ import stringcase
3
4
4
5
5
6
@dataclass
@@ -9,6 +10,14 @@ class Property:
9
10
name : str
10
11
required : bool
11
12
13
+ _type_string : ClassVar [str ]
14
+
15
+ def get_type_string (self ):
16
+ """ Get a string representation of type that should be used when declaring this property """
17
+ if self .required :
18
+ return self ._type_string
19
+ return f"Optional[{ self ._type_string } ]"
20
+
12
21
13
22
@dataclass
14
23
class StringProperty (Property ):
@@ -18,41 +27,82 @@ class StringProperty(Property):
18
27
default : Optional [str ] = None
19
28
pattern : Optional [str ] = None
20
29
30
+ _type_string : ClassVar [str ] = "str"
31
+
32
+ def to_string (self ) -> str :
33
+ """ How this should be declared in a dataclass """
34
+ if self .default :
35
+ return f"{ self .name } : { self .get_type_string ()} = { self .default } "
36
+ else :
37
+ return f"{ self .name } : { self .get_type_string ()} "
38
+
21
39
22
40
@dataclass
23
41
class DateTimeProperty (Property ):
24
42
""" A property of type datetime.datetime """
43
+ _type_string : ClassVar [str ] = "datetime"
25
44
26
- pass
45
+ def to_string (self ) -> str :
46
+ """ How this should be declared in a dataclass """
47
+ return f"{ self .name } : { self .get_type_string ()} "
27
48
28
49
29
50
@dataclass
30
51
class FloatProperty (Property ):
31
52
""" A property of type float """
32
53
33
54
default : Optional [float ] = None
55
+ _type_string : ClassVar [str ] = "float"
56
+
57
+ def to_string (self ) -> str :
58
+ """ How this should be declared in a dataclass """
59
+ if self .default :
60
+ return f"{ self .name } : { self .get_type_string ()} = { self .default } "
61
+ else :
62
+ return f"{ self .name } : { self .get_type_string ()} "
34
63
35
64
36
65
@dataclass
37
66
class IntProperty (Property ):
38
67
""" A property of type int """
39
68
40
69
default : Optional [int ] = None
70
+ _type_string : ClassVar [str ] = "int"
71
+
72
+ def to_string (self ) -> str :
73
+ """ How this should be declared in a dataclass """
74
+ if self .default :
75
+ return f"{ self .name } : { self .get_type_string ()} = { self .default } "
76
+ else :
77
+ return f"{ self .name } : { self .get_type_string ()} "
41
78
42
79
43
80
@dataclass
44
81
class BooleanProperty (Property ):
45
82
""" Property for bool """
83
+ _type_string : ClassVar [str ] = "bool"
46
84
47
- pass
85
+ def to_string (self ) -> str :
86
+ """ How this should be declared in a dataclass """
87
+ return f"{ self .name } : { self .get_type_string ()} "
48
88
49
89
50
90
@dataclass
51
91
class ListProperty (Property ):
52
92
""" Property for list """
53
93
54
- type : Optional [str ] = None
55
- ref : Optional [str ] = None
94
+ type : Optional [str ]
95
+ ref : Optional [str ]
96
+
97
+ def get_type_string (self ):
98
+ """ Get a string representation of type that should be used when declaring this property """
99
+ if self .required :
100
+ return f"List[{ self .type } ]"
101
+ return f"Optional[List[{ self .type } ]]"
102
+
103
+ def to_string (self ) -> str :
104
+ """ How this should be declared in a dataclass """
105
+ return f"{ self .name } : { self .get_type_string ()} "
56
106
57
107
58
108
@dataclass
@@ -61,22 +111,59 @@ class EnumProperty(Property):
61
111
62
112
values : List [str ]
63
113
114
+ def get_type_string (self ):
115
+ """ Get a string representation of type that should be used when declaring this property """
116
+ class_name = stringcase .pascalcase (self .name )
117
+ if self .required :
118
+ return class_name
119
+ return f"Optional[{ class_name } ]"
120
+
121
+ def to_string (self ) -> str :
122
+ """ How this should be declared in a dataclass """
123
+ return f"{ self .name } : { self .get_type_string ()} "
124
+
64
125
65
126
@dataclass
66
127
class RefProperty (Property ):
67
128
""" A property which refers to another Schema """
68
129
69
130
ref : str
70
131
132
+ def get_type_string (self ):
133
+ """ Get a string representation of type that should be used when declaring this property """
134
+ if self .required :
135
+ return self .ref
136
+ return f"Optional[{ self .ref } ]"
137
+
138
+ def to_string (self ) -> str :
139
+ """ How this should be declared in a dataclass """
140
+ return f"{ self .name } : { self .get_type_string ()} "
141
+
71
142
72
143
@dataclass
73
144
class DictProperty (Property ):
74
145
""" Property that is a general Dict """
75
146
147
+ _type_string : ClassVar [str ] = "Dict"
148
+
149
+ def to_string (self ) -> str :
150
+ """ How this should be declared in a dataclass """
151
+ return f"{ self .name } : { self .get_type_string ()} "
152
+
153
+
154
+ _openapi_types_to_python_type_strings = {
155
+ "string" : "str" ,
156
+ "number" : "float" ,
157
+ "integer" : "int" ,
158
+ "boolean" : "bool" ,
159
+ "object" : "Dict" ,
160
+ }
161
+
76
162
77
163
def property_from_dict (
78
164
name : str , required : bool , data : Dict [str , Union [float , int , str , List [str ], Dict [str , str ]]]
79
165
) -> Property :
166
+ """ Generate a Property from the OpenAPI dictionary representation of it """
80
167
if "enum" in data :
81
168
return EnumProperty (name = name , required = required , values = data ["enum" ],)
82
169
if "$ref" in data :
@@ -99,7 +186,10 @@ def property_from_dict(
99
186
ref = None
100
187
if "$ref" in data ["items" ]:
101
188
ref = data ["items" ]["$ref" ].split ("/" )[- 1 ]
102
- return ListProperty (name = name , required = required , type = data ["items" ].get ("type" ), ref = ref ,)
189
+ _type = None
190
+ if "type" in data ["items" ]:
191
+ _type = _openapi_types_to_python_type_strings [data ["items" ]["type" ]]
192
+ return ListProperty (name = name , required = required , type = _type , ref = ref )
103
193
elif data ["type" ] == "object" :
104
194
return DictProperty (name = name , required = required ,)
105
195
raise ValueError (f"Did not recognize type of { data } " )
0 commit comments