Skip to content

Commit 95d9104

Browse files
Merge pull request #78 from MarcoMuellner/67-support-reading-yaml-openapi-files
feat: Allowing yaml as a format.
2 parents 14583c6 + 05e3dec commit 95d9104

File tree

2 files changed

+60
-9
lines changed

2 files changed

+60
-9
lines changed

src/openapi_python_generator/generate_data.py

+41-9
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import httpx
88
import isort
99
import orjson
10+
import yaml
1011
from black import NothingChanged
1112
from httpx import ConnectError
1213
from httpx import ConnectTimeout
@@ -45,30 +46,61 @@ def write_code(path: Path, content) -> None:
4546

4647
def get_open_api(source: Union[str, Path]) -> OpenAPI:
4748
"""
48-
Tries to fetch the openapi.json file from the web or load from a local file. Returns the according OpenAPI object.
49-
:param source:
50-
:return:
49+
Tries to fetch the openapi specification file from the web or load from a local file.
50+
Supports both JSON and YAML formats. Returns the according OpenAPI object.
51+
52+
Args:
53+
source: URL or file path to the OpenAPI specification
54+
55+
Returns:
56+
OpenAPI: Parsed OpenAPI specification object
57+
58+
Raises:
59+
FileNotFoundError: If the specified file cannot be found
60+
ConnectError: If the URL cannot be accessed
61+
ValidationError: If the specification is invalid
62+
JSONDecodeError/YAMLError: If the file cannot be parsed
5163
"""
5264
try:
65+
# Handle remote files
5366
if not isinstance(source, Path) and (
54-
source.startswith("http://") or source.startswith("https://")
67+
source.startswith("http://") or source.startswith("https://")
5568
):
56-
return OpenAPI(**orjson.loads(httpx.get(source).text))
69+
content = httpx.get(source).text
70+
# Try JSON first, then YAML for remote files
71+
try:
72+
return OpenAPI(**orjson.loads(content))
73+
except orjson.JSONDecodeError:
74+
return OpenAPI(**yaml.safe_load(content))
5775

76+
# Handle local files
5877
with open(source, "r") as f:
5978
file_content = f.read()
60-
return OpenAPI(**orjson.loads(file_content))
79+
80+
# Try JSON first
81+
try:
82+
return OpenAPI(**orjson.loads(file_content))
83+
except orjson.JSONDecodeError:
84+
# If JSON fails, try YAML
85+
try:
86+
return OpenAPI(**yaml.safe_load(file_content))
87+
except yaml.YAMLError as e:
88+
click.echo(
89+
f"File {source} is neither a valid JSON nor YAML file: {str(e)}"
90+
)
91+
raise
92+
6193
except FileNotFoundError:
6294
click.echo(
63-
f"File {source} not found. Please make sure to pass the path to the OpenAPI 3.0 specification."
95+
f"File {source} not found. Please make sure to pass the path to the OpenAPI specification."
6496
)
6597
raise
6698
except (ConnectError, ConnectTimeout):
6799
click.echo(f"Could not connect to {source}.")
68100
raise ConnectError(f"Could not connect to {source}.") from None
69-
except (ValidationError, orjson.JSONDecodeError):
101+
except ValidationError:
70102
click.echo(
71-
f"File {source} is not a valid OpenAPI 3.0 specification, or there may be a problem with your JSON."
103+
f"File {source} is not a valid OpenAPI 3.0 specification."
72104
)
73105
raise
74106

tests/test_generate_data.py

+19
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import shutil
22

33
import pytest
4+
import yaml
45
from httpx import ConnectError
6+
from orjson import orjson
57
from pydantic import ValidationError
68

79
from openapi_python_generator.common import HTTPLibrary
@@ -16,14 +18,31 @@
1618

1719

1820
def test_get_open_api(model_data):
21+
# Test JSON file
1922
assert get_open_api(test_data_path) == model_data
2023

24+
# Create YAML version of the test file
25+
yaml_path = test_data_path.with_suffix('.yaml')
26+
with open(test_data_path) as f:
27+
json_content = orjson.loads(f.read())
28+
with open(yaml_path, 'w') as f:
29+
yaml.dump(json_content, f)
30+
31+
# Test YAML file
32+
assert get_open_api(yaml_path) == model_data
33+
34+
# Cleanup YAML file
35+
yaml_path.unlink()
36+
37+
# Test remote file failure
2138
with pytest.raises(ConnectError):
2239
assert get_open_api("http://localhost:8080/api/openapi.json")
2340

41+
# Test invalid OpenAPI spec
2442
with pytest.raises(ValidationError):
2543
assert get_open_api(test_data_folder / "failing_api.json")
2644

45+
# Test non-existent file
2746
with pytest.raises(FileNotFoundError):
2847
assert get_open_api(test_data_folder / "file_does_not_exist.json")
2948

0 commit comments

Comments
 (0)