11from dataclasses import dataclass
2- from typing import Optional , List , Dict , Union
2+ from typing import Optional , List , Dict , Union , ClassVar
3+ import stringcase
34
45
56@dataclass
@@ -9,6 +10,14 @@ class Property:
910 name : str
1011 required : bool
1112
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+
1221
1322@dataclass
1423class StringProperty (Property ):
@@ -18,41 +27,82 @@ class StringProperty(Property):
1827 default : Optional [str ] = None
1928 pattern : Optional [str ] = None
2029
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+
2139
2240@dataclass
2341class DateTimeProperty (Property ):
2442 """ A property of type datetime.datetime """
43+ _type_string : ClassVar [str ] = "datetime"
2544
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 ()} "
2748
2849
2950@dataclass
3051class FloatProperty (Property ):
3152 """ A property of type float """
3253
3354 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 ()} "
3463
3564
3665@dataclass
3766class IntProperty (Property ):
3867 """ A property of type int """
3968
4069 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 ()} "
4178
4279
4380@dataclass
4481class BooleanProperty (Property ):
4582 """ Property for bool """
83+ _type_string : ClassVar [str ] = "bool"
4684
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 ()} "
4888
4989
5090@dataclass
5191class ListProperty (Property ):
5292 """ Property for list """
5393
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 ()} "
56106
57107
58108@dataclass
@@ -61,22 +111,59 @@ class EnumProperty(Property):
61111
62112 values : List [str ]
63113
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+
64125
65126@dataclass
66127class RefProperty (Property ):
67128 """ A property which refers to another Schema """
68129
69130 ref : str
70131
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+
71142
72143@dataclass
73144class DictProperty (Property ):
74145 """ Property that is a general Dict """
75146
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+
76162
77163def property_from_dict (
78164 name : str , required : bool , data : Dict [str , Union [float , int , str , List [str ], Dict [str , str ]]]
79165) -> Property :
166+ """ Generate a Property from the OpenAPI dictionary representation of it """
80167 if "enum" in data :
81168 return EnumProperty (name = name , required = required , values = data ["enum" ],)
82169 if "$ref" in data :
@@ -99,7 +186,10 @@ def property_from_dict(
99186 ref = None
100187 if "$ref" in data ["items" ]:
101188 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 )
103193 elif data ["type" ] == "object" :
104194 return DictProperty (name = name , required = required ,)
105195 raise ValueError (f"Did not recognize type of { data } " )
0 commit comments