Skip to content

Commit 7350069

Browse files
committed
loader: support json and yaml separately
json is not exactly a subset of yaml, as yaml do not support tabs there are maybe other subtleties, so we just use content-type to figure out how to parse Signed-off-by: Pierre Tardy <[email protected]>
1 parent 46fce48 commit 7350069

File tree

2 files changed

+40
-6
lines changed

2 files changed

+40
-6
lines changed

Diff for: openapi_python_client/__init__.py

+19-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
""" Generate modern Python clients from OpenAPI """
22

3+
import json
4+
import mimetypes
35
import shutil
46
import subprocess
57
import sys
@@ -369,13 +371,26 @@ def _get_document(*, url: Optional[str], path: Optional[Path]) -> Union[Dict[str
369371
try:
370372
response = httpx.get(url)
371373
yaml_bytes = response.content
374+
if "content-type" in response.headers:
375+
content_type = response.headers["content-type"].split(";")[0]
376+
else:
377+
content_type = mimetypes.guess_type(url, strict=True)[0]
378+
372379
except (httpx.HTTPError, httpcore.NetworkError):
373380
return GeneratorError(header="Could not get OpenAPI document from provided URL")
374381
elif path is not None:
375382
yaml_bytes = path.read_bytes()
383+
content_type = mimetypes.guess_type(path.as_uri(), strict=True)[0]
384+
376385
else:
377386
return GeneratorError(header="No URL or Path provided")
378-
try:
379-
return yaml.safe_load(yaml_bytes)
380-
except yaml.YAMLError:
381-
return GeneratorError(header="Invalid YAML from provided source")
387+
if content_type == "application/json":
388+
try:
389+
return json.loads(yaml_bytes.decode())
390+
except yaml.JSONDecodeError as e:
391+
return GeneratorError(header="Invalid JSON from provided source: {}".format(str(e)))
392+
else:
393+
try:
394+
return yaml.safe_load(yaml_bytes)
395+
except yaml.YAMLError as e:
396+
return GeneratorError(header="Invalid YAML from provided source: {}".format(str(e)))

Diff for: tests/test___init__.py

+21-2
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ def test__get_document_path_no_url(self, mocker):
218218

219219
def test__get_document_bad_yaml(self, mocker):
220220
get = mocker.patch("httpx.get")
221-
loads = mocker.patch("yaml.safe_load", side_effect=yaml.YAMLError)
221+
loads = mocker.patch("yaml.safe_load", side_effect=yaml.YAMLError("error line 2"))
222222

223223
from openapi_python_client import _get_document
224224

@@ -228,7 +228,26 @@ def test__get_document_bad_yaml(self, mocker):
228228
get.assert_not_called()
229229
path.read_bytes.assert_called_once()
230230
loads.assert_called_once_with(path.read_bytes())
231-
assert result == GeneratorError(header="Invalid YAML from provided source")
231+
assert result == GeneratorError(header="Invalid YAML from provided source: error line 2")
232+
233+
def test__get_document_json(self, mocker):
234+
class FakeResponse:
235+
content = b'{\n\t"foo": "bar"}'
236+
headers = {"content-type": "application/json; encoding=utf8"}
237+
238+
get = mocker.patch("httpx.get", return_value=FakeResponse())
239+
yaml_loads = mocker.patch("yaml.safe_load")
240+
json_result = mocker.MagicMock()
241+
json_loads = mocker.patch("json.loads", return_value=json_result)
242+
243+
from openapi_python_client import _get_document
244+
245+
url = mocker.MagicMock()
246+
result = _get_document(url=url, path=None)
247+
248+
get.assert_called_once()
249+
json_loads.assert_called_once_with(FakeResponse.content.decode())
250+
assert result == json_result
232251

233252

234253
def make_project(**kwargs):

0 commit comments

Comments
 (0)