|
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