Skip to content

Commit 87105b3

Browse files
committed
Refactor Reference
1 parent 96f004e commit 87105b3

File tree

9 files changed

+55
-35
lines changed

9 files changed

+55
-35
lines changed

openapi_python_client/openapi_parser/openapi.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def parse_request_form_body(body: Dict[str, Any], /) -> Optional[Reference]:
6767
body_content = body["content"]
6868
form_body = body_content.get("application/x-www-form-urlencoded")
6969
if form_body:
70-
return Reference(form_body["schema"]["$ref"])
70+
return Reference.from_ref(form_body["schema"]["$ref"])
7171
return None
7272

7373
@staticmethod
@@ -168,7 +168,7 @@ def from_dict(d: Dict[str, Any], /) -> Schema:
168168
if isinstance(p, (ListProperty, RefProperty, EnumProperty)) and p.reference:
169169
relative_imports.add(import_string_from_reference(p.reference))
170170
schema = Schema(
171-
reference=Reference(d["title"]),
171+
reference=Reference.from_ref(d["title"]),
172172
required_properties=required_properties,
173173
optional_properties=optional_properties,
174174
relative_imports=relative_imports,

openapi_python_client/openapi_parser/properties.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ class EnumProperty(Property):
122122
reference: Reference = field(init=False)
123123

124124
def __post_init__(self) -> None:
125-
self.reference = Reference(self.name)
125+
self.reference = Reference.from_ref(self.name)
126126
inverse_values = {v: k for k, v in self.values.items()}
127127
if self.default is not None:
128128
self.default = f"{self.reference.class_name}.{inverse_values[self.default]}"
@@ -203,7 +203,7 @@ def property_from_dict(name: str, required: bool, data: Dict[str, Any]) -> Prope
203203
default=data.get("default"),
204204
)
205205
if "$ref" in data:
206-
return RefProperty(name=name, required=required, reference=Reference(data["$ref"]), default=None)
206+
return RefProperty(name=name, required=required, reference=Reference.from_ref(data["$ref"]), default=None)
207207
if data["type"] == "string":
208208
if "format" not in data:
209209
return StringProperty(
@@ -220,7 +220,7 @@ def property_from_dict(name: str, required: bool, data: Dict[str, Any]) -> Prope
220220
elif data["type"] == "array":
221221
reference = None
222222
if "$ref" in data["items"]:
223-
reference = Reference(data["items"]["$ref"])
223+
reference = Reference.from_ref(data["items"]["$ref"])
224224
_type = None
225225
if "type" in data["items"]:
226226
_type = _openapi_types_to_python_type_strings[data["items"]["type"]]
Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
1+
""" A Reference is ultimately a Class which will be in models, usually defined in a body input or return type """
2+
3+
from __future__ import annotations
4+
5+
from dataclasses import dataclass
6+
17
import stringcase
28

39

10+
@dataclass
411
class Reference:
512
""" A reference to a class which will be in models """
613

7-
def __init__(self, ref: str):
8-
ref_value = ref.split("/")[-1] # get the #/schemas/blahblah part off
9-
self.class_name: str = stringcase.pascalcase(ref_value)
10-
self.module_name: str = stringcase.snakecase(ref_value)
14+
class_name: str
15+
module_name: str
16+
17+
@staticmethod
18+
def from_ref(ref: str) -> Reference:
19+
""" Get a Reference from the openapi #/schemas/blahblah string """
20+
ref_value = ref.split("/")[-1]
21+
return Reference(class_name=stringcase.pascalcase(ref_value), module_name=stringcase.snakecase(ref_value),)

openapi_python_client/openapi_parser/responses.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,11 @@ def response_from_dict(*, status_code: int, data: _ResponseDict) -> Response:
9595
schema_data = data["content"][content_type]["schema"]
9696

9797
if "$ref" in schema_data:
98-
return RefResponse(status_code=status_code, reference=Reference(schema_data["$ref"]),)
98+
return RefResponse(status_code=status_code, reference=Reference.from_ref(schema_data["$ref"]),)
9999
if "type" not in schema_data:
100100
return Response(status_code=status_code)
101101
if schema_data["type"] == "array":
102-
return ListRefResponse(status_code=status_code, reference=Reference(schema_data["items"]["$ref"]),)
102+
return ListRefResponse(status_code=status_code, reference=Reference.from_ref(schema_data["items"]["$ref"]),)
103103
if schema_data["type"] == "string":
104104
return StringResponse(status_code=status_code)
105105
raise ValueError(f"Cannot parse response of type {schema_data['type']}")

tests/test_end_to_end/test_end_to_end.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ def test_end_to_end(capsys):
3030
gm_path = Path(__file__).parent / "golden-master"
3131
output_path = Path.cwd() / "my-test-api-client"
3232

33-
runner.invoke(app, ["generate", f"--path={openapi_path}"])
33+
result = runner.invoke(app, ["generate", f"--path={openapi_path}"])
3434

35+
if result.exit_code != 0:
36+
raise result.exception
3537
_compare_directories(gm_path, output_path)
3638
shutil.rmtree(output_path)

tests/test_openapi_parser/test_openapi.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,14 +159,14 @@ def test_from_dict(self, mocker):
159159
property_from_dict = mocker.patch(
160160
f"{MODULE_NAME}.property_from_dict", side_effect=[required_property, optional_property]
161161
)
162-
Reference = mocker.patch(f"{MODULE_NAME}.Reference")
162+
from_ref = mocker.patch(f"{MODULE_NAME}.Reference.from_ref")
163163
import_string_from_reference = mocker.patch(f"{MODULE_NAME}.import_string_from_reference")
164164

165165
from openapi_python_client.openapi_parser.openapi import Schema
166166

167167
result = Schema.from_dict(in_data)
168168

169-
Reference.assert_called_once_with(in_data["title"])
169+
from_ref.assert_called_once_with(in_data["title"])
170170
property_from_dict.assert_has_calls(
171171
[
172172
mocker.call(name="RequiredEnum", required=True, data=in_data["properties"]["RequiredEnum"]),
@@ -175,7 +175,7 @@ def test_from_dict(self, mocker):
175175
)
176176
import_string_from_reference.assert_called_once_with(required_property.reference)
177177
assert result == Schema(
178-
reference=Reference(),
178+
reference=from_ref(),
179179
required_properties=[required_property],
180180
optional_properties=[optional_property],
181181
relative_imports={import_string_from_reference()},
@@ -187,14 +187,14 @@ class TestEndpoint:
187187
def test_parse_request_form_body(self, mocker):
188188
ref = mocker.MagicMock()
189189
body = {"content": {"application/x-www-form-urlencoded": {"schema": {"$ref": ref}}}}
190-
Reference = mocker.patch(f"{MODULE_NAME}.Reference")
190+
from_ref = mocker.patch(f"{MODULE_NAME}.Reference.from_ref")
191191

192192
from openapi_python_client.openapi_parser.openapi import Endpoint
193193

194194
result = Endpoint.parse_request_form_body(body)
195195

196-
Reference.assert_called_once_with(ref)
197-
assert result == Reference()
196+
from_ref.assert_called_once_with(ref)
197+
assert result == from_ref()
198198

199199
def test_parse_request_form_body_no_data(self):
200200
body = {"content": {}}

tests/test_openapi_parser/test_properties.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -100,20 +100,20 @@ class TestEnumProperty:
100100
def test___post_init__(self, mocker):
101101
name = mocker.MagicMock()
102102
fake_reference = mocker.MagicMock(class_name="MyTestEnum")
103-
Reference = mocker.patch(f"{MODULE_NAME}.Reference", return_value=fake_reference)
103+
from_ref = mocker.patch(f"{MODULE_NAME}.Reference.from_ref", return_value=fake_reference)
104104

105105
from openapi_python_client.openapi_parser.properties import EnumProperty
106106

107107
enum_property = EnumProperty(
108108
name=name, required=True, default="second", values={"FIRST": "first", "SECOND": "second"}
109109
)
110110

111-
Reference.assert_called_once_with(name)
111+
from_ref.assert_called_once_with(name)
112112
assert enum_property.default == "MyTestEnum.SECOND"
113113

114114
def test_get_type_string(self, mocker):
115115
fake_reference = mocker.MagicMock(class_name="MyTestEnum")
116-
mocker.patch(f"{MODULE_NAME}.Reference", return_value=fake_reference)
116+
mocker.patch(f"{MODULE_NAME}.Reference.from_ref", return_value=fake_reference)
117117

118118
from openapi_python_client.openapi_parser.properties import EnumProperty
119119

@@ -125,7 +125,7 @@ def test_get_type_string(self, mocker):
125125

126126
def test_transform(self, mocker):
127127
name = mocker.MagicMock()
128-
mocker.patch(f"{MODULE_NAME}.Reference")
128+
mocker.patch(f"{MODULE_NAME}.Reference.from_ref")
129129

130130
from openapi_python_client.openapi_parser.properties import EnumProperty
131131

@@ -135,7 +135,7 @@ def test_transform(self, mocker):
135135

136136
def test_constructor_from_dict(self, mocker):
137137
fake_reference = mocker.MagicMock(class_name="MyTestEnum")
138-
mocker.patch(f"{MODULE_NAME}.Reference", return_value=fake_reference)
138+
mocker.patch(f"{MODULE_NAME}.Reference.from_ref", return_value=fake_reference)
139139

140140
from openapi_python_client.openapi_parser.properties import EnumProperty
141141

@@ -217,15 +217,15 @@ def test_property_from_dict_ref(self, mocker):
217217
data = {
218218
"$ref": mocker.MagicMock(),
219219
}
220-
Reference = mocker.patch(f"{MODULE_NAME}.Reference")
220+
from_ref = mocker.patch(f"{MODULE_NAME}.Reference.from_ref")
221221
RefProperty = mocker.patch(f"{MODULE_NAME}.RefProperty")
222222

223223
from openapi_python_client.openapi_parser.properties import property_from_dict
224224

225225
p = property_from_dict(name=name, required=required, data=data)
226226

227-
Reference.assert_called_once_with(data["$ref"])
228-
RefProperty.assert_called_once_with(name=name, required=required, reference=Reference(), default=None)
227+
from_ref.assert_called_once_with(data["$ref"])
228+
RefProperty.assert_called_once_with(name=name, required=required, reference=from_ref(), default=None)
229229
assert p == RefProperty()
230230

231231
def test_property_from_dict_string_no_format(self, mocker):
@@ -335,15 +335,15 @@ def test_property_from_dict_ref_array(self, mocker):
335335
"items": {"$ref": ref},
336336
}
337337
ListProperty = mocker.patch(f"{MODULE_NAME}.ListProperty")
338-
Reference = mocker.patch(f"{MODULE_NAME}.Reference")
338+
from_ref = mocker.patch(f"{MODULE_NAME}.Reference.from_ref")
339339

340340
from openapi_python_client.openapi_parser.properties import property_from_dict
341341

342342
p = property_from_dict(name=name, required=required, data=data)
343343

344-
Reference.assert_called_once_with(ref)
344+
from_ref.assert_called_once_with(ref)
345345
ListProperty.assert_called_once_with(
346-
name=name, required=required, default=None, type=None, reference=Reference()
346+
name=name, required=required, default=None, type=None, reference=from_ref()
347347
)
348348
assert p == ListProperty()
349349

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
def test_from_ref():
2+
from openapi_python_client.openapi_parser.reference import Reference
3+
4+
r = Reference.from_ref("#/components/schemas/PingResponse")
5+
6+
assert r.class_name == "PingResponse"
7+
assert r.module_name == "ping_response"

tests/test_openapi_parser/test_responses.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,14 @@ def test_response_from_dict_ref(self, mocker):
8484
ref = mocker.MagicMock()
8585
status_code = mocker.MagicMock(autospec=int)
8686
data = {"content": {"application/json": {"schema": {"$ref": ref}}}}
87-
Reference = mocker.patch(f"{MODULE_NAME}.Reference")
87+
from_ref = mocker.patch(f"{MODULE_NAME}.Reference.from_ref")
8888
RefResponse = mocker.patch(f"{MODULE_NAME}.RefResponse")
8989
from openapi_python_client.openapi_parser.responses import response_from_dict
9090

9191
response = response_from_dict(status_code=status_code, data=data)
9292

93-
Reference.assert_called_once_with(ref)
94-
RefResponse.assert_called_once_with(status_code=status_code, reference=Reference())
93+
from_ref.assert_called_once_with(ref)
94+
RefResponse.assert_called_once_with(status_code=status_code, reference=from_ref())
9595
assert response == RefResponse()
9696

9797
def test_response_from_dict_empty(self, mocker):
@@ -109,14 +109,14 @@ def test_response_from_dict_array(self, mocker):
109109
ref = mocker.MagicMock()
110110
status_code = mocker.MagicMock(autospec=int)
111111
data = {"content": {"application/json": {"schema": {"type": "array", "items": {"$ref": ref}}}}}
112-
Reference = mocker.patch(f"{MODULE_NAME}.Reference")
112+
from_ref = mocker.patch(f"{MODULE_NAME}.Reference.from_ref")
113113
ListRefResponse = mocker.patch(f"{MODULE_NAME}.ListRefResponse")
114114
from openapi_python_client.openapi_parser.responses import response_from_dict
115115

116116
response = response_from_dict(status_code=status_code, data=data)
117117

118-
Reference.assert_called_once_with(ref)
119-
ListRefResponse.assert_called_once_with(status_code=status_code, reference=Reference())
118+
from_ref.assert_called_once_with(ref)
119+
ListRefResponse.assert_called_once_with(status_code=status_code, reference=from_ref())
120120
assert response == ListRefResponse()
121121

122122
def test_response_from_dict_string(self, mocker):

0 commit comments

Comments
 (0)