forked from openapi-generators/openapi-python-client
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathresponses.py
More file actions
213 lines (154 loc) · 6.92 KB
/
Copy pathresponses.py
File metadata and controls
213 lines (154 loc) · 6.92 KB
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
from dataclasses import InitVar, dataclass, field
from typing import Any, List, Union
from .. import schema as oai
from .errors import ParseError
from .reference import Reference
@dataclass
class Response:
""" Describes a single response for an endpoint """
status_code: Union[int, str]
@property
def is_error(self) -> bool:
return False
def return_string(self) -> str:
""" How this Response should be represented as a return type """
return "None"
def constructor(self) -> str:
""" How the return value of this response should be constructed """
return "None"
def __gt__(self, other: Any) -> bool:
if isinstance(self, RefResponse):
return True
return False
def __lt__(self, other: Any) -> bool:
if isinstance(self, RefResponse):
return False
return True
@dataclass
class ListRefResponse(Response):
""" Response is a list of some ref schema """
reference: Reference
def return_string(self) -> str:
""" How this Response should be represented as a return type """
return f"List[{self.reference.class_name}]"
def constructor(self) -> str:
""" How the return value of this response should be constructed """
return f"[{self.reference.class_name}.from_dict(item) for item in cast(List[Dict[str, Any]], response.json())]"
@dataclass
class RefResponse(Response):
""" Response is a single ref schema """
reference: Reference
@property
def is_error(self) -> bool:
return self.reference.lookup().is_error
def return_string(self) -> str:
""" How this Response should be represented as a return type """
return self.reference.class_name
def constructor(self) -> str:
""" How the return value of this response should be constructed """
return f"{self.reference.class_name}.from_dict(cast(Dict[str, Any], response.json()))"
def __lt__(self, other: Any) -> bool:
if not isinstance(other, RefResponse):
return NotImplemented
return len(self.reference.class_name) < len(other.reference.class_name)
@dataclass
class ListBasicResponse(Response):
""" Response is a list of some basic type """
openapi_type: InitVar[str]
python_type: str = field(init=False)
def __post_init__(self, openapi_type: str) -> None:
self.python_type = openapi_types_to_python_type_strings[openapi_type]
def return_string(self) -> str:
""" How this Response should be represented as a return type """
return f"List[{self.python_type}]"
def constructor(self) -> str:
""" How the return value of this response should be constructed """
return f"[{self.python_type}(item) for item in cast(List[{self.python_type}], response.json())]"
@dataclass
class UnionResponse(Response):
options: List[Response]
def __post_init__(self) -> None:
self.options = sorted(self.options, reverse=True)
def return_string(self) -> str:
return f'Union[{", ".join(opt.return_string() for opt in self.options)}]'
def constructor(self) -> str:
return f'try_any([{", ".join("lambda: " + opt.constructor() for opt in self.options)}])'
@dataclass
class BasicResponse(Response):
""" Response is a basic type """
openapi_type: InitVar[str]
python_type: str = field(init=False)
def __post_init__(self, openapi_type: str) -> None:
self.python_type = openapi_types_to_python_type_strings[openapi_type]
def return_string(self) -> str:
""" How this Response should be represented as a return type """
return self.python_type
def constructor(self) -> str:
""" How the return value of this response should be constructed """
return f"{self.python_type}(response.text)"
@dataclass
class ObjectResponse(Response):
""" Response is a basic type """
def return_string(self) -> str:
""" How this Response should be represented as a return type """
return 'Dict[str, Any]'
def constructor(self) -> str:
""" How the return value of this response should be constructed """
return 'response.json()'
@dataclass
class BytesResponse(Response):
""" Response is a basic type """
python_type: str = "bytes"
def return_string(self) -> str:
""" How this Response should be represented as a return type """
return self.python_type
def constructor(self) -> str:
""" How the return value of this response should be constructed """
return f"{self.python_type}(response.content)"
openapi_types_to_python_type_strings = {
"string": "str",
"number": "float",
"integer": "int",
"boolean": "bool",
}
def response_from_data(*, status_code: int, data: Union[oai.Response, oai.Reference], base_responses: Any) -> Union[Response, ParseError]:
""" Generate a Response from the OpenAPI dictionary representation of it """
if isinstance(data, oai.Reference):
data = base_responses[Reference.from_ref(data.ref).class_name]
if data.content is None:
return Response(status_code=status_code)
content = data.content
schema_data = None
if "application/json" in content:
schema_data = data.content["application/json"].media_type_schema
elif "application/octet-stream" in content:
return BytesResponse(status_code=status_code)
elif "text/html" in content:
schema_data = data.content["text/html"].media_type_schema
if schema_data is None:
return ParseError(data=data, detail=f"Unsupported content_type {content}")
if isinstance(schema_data, oai.Reference):
return RefResponse(status_code=status_code, reference=Reference.from_ref(schema_data.ref),)
response_type = schema_data.type
if schema_data.anyOf:
options = []
for option in schema_data.anyOf:
if isinstance(option, oai.Reference):
options.append(RefResponse(status_code=status_code, reference=Reference.from_ref(option.ref)))
elif getattr(option, 'type', None) == 'object':
options.append(ObjectResponse(status_code=status_code))
return UnionResponse(status_code, options)
if response_type is None:
breakpoint()
return Response(status_code=status_code)
if response_type == "array" and isinstance(schema_data.items, oai.Reference):
return ListRefResponse(status_code=status_code, reference=Reference.from_ref(schema_data.items.ref),)
if (
response_type == "array"
and isinstance(schema_data.items, oai.Schema)
and schema_data.items.type in openapi_types_to_python_type_strings
):
return ListBasicResponse(status_code=status_code, openapi_type=schema_data.items.type)
if response_type in openapi_types_to_python_type_strings:
return BasicResponse(status_code=status_code, openapi_type=response_type)
return ParseError(data=data, detail=f"Unrecognized type {schema_data.type}")