From a3e9a2a1eba04d2e94d6bfdc8568af261fce72d2 Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Wed, 5 Aug 2020 10:46:19 -0400 Subject: [PATCH] Add support for YAML documents (#111) --- CHANGELOG.md | 1 + README.md | 2 +- openapi_python_client/__init__.py | 13 ++++++----- tests/test___init__.py | 36 +++++++++++++++---------------- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8502006f8..96c75d15a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 with the pieces it can. - Support for Enums declared in "components/schemas" and references to them (#102). - Generated clients can now be installed via pip (#120). +- Support for YAML OpenAPI documents (#111) ### Internal Changes - Switched OpenAPI document parsing to use Pydantic based on a vendored version of diff --git a/README.md b/README.md index 75a20bb85..d1853b0f1 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ # openapi-python-client Generate modern Python clients from OpenAPI -**This project is still in early development and does not support all OpenAPI features** +**This project is still in development and does not support all OpenAPI features** ## Why This? The Python clients generated by openapi-generator support Python 2 and therefore come with a lot of baggage. This tool diff --git a/openapi_python_client/__init__.py b/openapi_python_client/__init__.py index 540ce7c06..6e33fcd1f 100644 --- a/openapi_python_client/__init__.py +++ b/openapi_python_client/__init__.py @@ -1,7 +1,6 @@ """ Generate modern Python clients from OpenAPI """ from __future__ import annotations -import json import shutil import subprocess import sys @@ -27,7 +26,7 @@ def _get_project_for_url_or_path(url: Optional[str], path: Optional[Path]) -> _Project: - data_dict = _get_json(url=url, path=path) + data_dict = _get_document(url=url, path=path) openapi = GeneratorData.from_dict(data_dict) return _Project(openapi=openapi) @@ -65,18 +64,18 @@ def update_existing_client(*, url: Optional[str], path: Optional[Path]) -> Seque return project.update() -def _get_json(*, url: Optional[str], path: Optional[Path]) -> Dict[str, Any]: - json_bytes: bytes +def _get_document(*, url: Optional[str], path: Optional[Path]) -> Dict[str, Any]: + yaml_bytes: bytes if url is not None and path is not None: raise ValueError("Provide URL or Path, not both.") if url is not None: response = httpx.get(url) - json_bytes = response.content + yaml_bytes = response.content elif path is not None: - json_bytes = path.read_bytes() + yaml_bytes = path.read_bytes() else: raise ValueError("No URL or Path provided") - return json.loads(json_bytes) + return yaml.safe_load(yaml_bytes) class _Project: diff --git a/tests/test___init__.py b/tests/test___init__.py index 57975930a..9a975b7ae 100644 --- a/tests/test___init__.py +++ b/tests/test___init__.py @@ -8,7 +8,7 @@ def test__get_project_for_url_or_path(mocker): data_dict = mocker.MagicMock() - _get_json = mocker.patch("openapi_python_client._get_json", return_value=data_dict) + _get_document = mocker.patch("openapi_python_client._get_document", return_value=data_dict) openapi = mocker.MagicMock() from_dict = mocker.patch("openapi_python_client.parser.GeneratorData.from_dict", return_value=openapi) _Project = mocker.patch("openapi_python_client._Project") @@ -19,7 +19,7 @@ def test__get_project_for_url_or_path(mocker): project = _get_project_for_url_or_path(url=url, path=path) - _get_json.assert_called_once_with(url=url, path=path) + _get_document.assert_called_once_with(url=url, path=path) from_dict.assert_called_once_with(data_dict) _Project.assert_called_once_with(openapi=openapi) assert project == _Project() @@ -58,56 +58,56 @@ def test_update_existing_client(mocker): class TestGetJson: - def test__get_json_no_url_or_path(self, mocker): + def test__get_document_no_url_or_path(self, mocker): get = mocker.patch("httpx.get") Path = mocker.patch("openapi_python_client.Path") - loads = mocker.patch("json.loads") + loads = mocker.patch("yaml.safe_load") - from openapi_python_client import _get_json + from openapi_python_client import _get_document with pytest.raises(ValueError): - _get_json(url=None, path=None) + _get_document(url=None, path=None) get.assert_not_called() Path.assert_not_called() loads.assert_not_called() - def test__get_json_url_and_path(self, mocker): + def test__get_document_url_and_path(self, mocker): get = mocker.patch("httpx.get") Path = mocker.patch("openapi_python_client.Path") - loads = mocker.patch("json.loads") + loads = mocker.patch("yaml.safe_load") - from openapi_python_client import _get_json + from openapi_python_client import _get_document with pytest.raises(ValueError): - _get_json(url=mocker.MagicMock(), path=mocker.MagicMock()) + _get_document(url=mocker.MagicMock(), path=mocker.MagicMock()) get.assert_not_called() Path.assert_not_called() loads.assert_not_called() - def test__get_json_url_no_path(self, mocker): + def test__get_document_url_no_path(self, mocker): get = mocker.patch("httpx.get") Path = mocker.patch("openapi_python_client.Path") - loads = mocker.patch("json.loads") + loads = mocker.patch("yaml.safe_load") - from openapi_python_client import _get_json + from openapi_python_client import _get_document url = mocker.MagicMock() - _get_json(url=url, path=None) + _get_document(url=url, path=None) get.assert_called_once_with(url) Path.assert_not_called() loads.assert_called_once_with(get().content) - def test__get_json_path_no_url(self, mocker): + def test__get_document_path_no_url(self, mocker): get = mocker.patch("httpx.get") - loads = mocker.patch("json.loads") + loads = mocker.patch("yaml.safe_load") - from openapi_python_client import _get_json + from openapi_python_client import _get_document path = mocker.MagicMock() - _get_json(url=None, path=path) + _get_document(url=None, path=path) get.assert_not_called() path.read_bytes.assert_called_once()