|
7 | 7 | import httpx
|
8 | 8 | import isort
|
9 | 9 | import orjson
|
| 10 | +import yaml |
10 | 11 | from black import NothingChanged
|
11 | 12 | from httpx import ConnectError
|
12 | 13 | from httpx import ConnectTimeout
|
@@ -45,30 +46,61 @@ def write_code(path: Path, content) -> None:
|
45 | 46 |
|
46 | 47 | def get_open_api(source: Union[str, Path]) -> OpenAPI:
|
47 | 48 | """
|
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 |
51 | 63 | """
|
52 | 64 | try:
|
| 65 | + # Handle remote files |
53 | 66 | if not isinstance(source, Path) and (
|
54 |
| - source.startswith("http://") or source.startswith("https://") |
| 67 | + source.startswith("http://") or source.startswith("https://") |
55 | 68 | ):
|
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)) |
57 | 75 |
|
| 76 | + # Handle local files |
58 | 77 | with open(source, "r") as f:
|
59 | 78 | 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 | + |
61 | 93 | except FileNotFoundError:
|
62 | 94 | 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." |
64 | 96 | )
|
65 | 97 | raise
|
66 | 98 | except (ConnectError, ConnectTimeout):
|
67 | 99 | click.echo(f"Could not connect to {source}.")
|
68 | 100 | raise ConnectError(f"Could not connect to {source}.") from None
|
69 |
| - except (ValidationError, orjson.JSONDecodeError): |
| 101 | + except ValidationError: |
70 | 102 | 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." |
72 | 104 | )
|
73 | 105 | raise
|
74 | 106 |
|
|
0 commit comments