From ea3c22ee283c35671898ed1434abd6875f345f63 Mon Sep 17 00:00:00 2001 From: MoritzWeber Date: Thu, 10 Oct 2024 13:54:41 +0200 Subject: [PATCH] refactor: Disable OpenAPI options via CLI arguments Before, it was inconsistenly handled via environment variables and a postprocess script. --- backend/Makefile | 7 +++- backend/capellacollab/cli/openapi.py | 53 ++++++++++++++++++++++++- backend/capellacollab/core/responses.py | 6 +-- frontend/Makefile | 1 - frontend/postprocess_openapi_schema.py | 32 --------------- 5 files changed, 59 insertions(+), 40 deletions(-) delete mode 100644 frontend/postprocess_openapi_schema.py diff --git a/backend/Makefile b/backend/Makefile index 628b3dd170..1a9e9fc120 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -73,7 +73,12 @@ install: $(VENV)/bin/pip install -e ".[dev]" openapi: - CAPELLACOLLAB_SKIP_OPENAPI_ERROR_RESPONSES=1 $(VENV)/bin/python -m capellacollab.cli openapi generate /tmp/openapi.json + $(VENV)/bin/python \ + -m capellacollab.cli openapi generate \ + --remove-default-keys \ + --remove-min-max-keys \ + --skip-error-responses \ + /tmp/openapi.json dev: database valkey app diff --git a/backend/capellacollab/cli/openapi.py b/backend/capellacollab/cli/openapi.py index b3eb60dd0c..e92636f60a 100644 --- a/backend/capellacollab/cli/openapi.py +++ b/backend/capellacollab/cli/openapi.py @@ -3,8 +3,11 @@ from __future__ import annotations +import copy import json +import os import pathlib +import typing as t import typer @@ -14,10 +17,58 @@ @app.command() def generate( output_file: pathlib.Path, + # For client generation, default keys might blow up the generated code. + remove_default_keys: bool = typer.Option( + default=False, + help=( + "Remove default keys from the schema." + " This might be useful for client generation to reduce verbosity of the generated code." + ), + ), + # Reason for this option is: https://github.com/fastapi/fastapi/issues/240 + remove_min_max_keys: bool = typer.Option( + default=False, + help=( + "Remove the exclusiveMinimum and exclusiveMaximum keys from the schema." + " This improves compatibility with OpenAPI Spec 3.0." + ), + ), + skip_error_responses: bool = typer.Option( + default=False, + help=( + "Skip generation of error responses." + " This might be useful for client generation to reduce verbosity of the generated code." + ), + ), ): """Generate openapi.json and write it to output_file.""" + if skip_error_responses: + os.environ["CAPELLACOLLAB_SKIP_OPENAPI_ERROR_RESPONSES"] = "1" + from capellacollab import __main__ + keys_to_remove = [] + + if remove_default_keys: + keys_to_remove.append("default") + + if remove_min_max_keys: + keys_to_remove.extend(["exclusiveMinimum", "exclusiveMaximum"]) + + schema = __main__.app.openapi() + _remove_keys_from_spec(schema, keys_to_remove) with output_file.open("w") as f: - json.dump(__main__.app.openapi(), f) + json.dump(schema, f) + + +def _remove_keys_from_spec(value: t.Any, keys_to_remove: list[str]): + if isinstance(value, dict): + for k in copy.deepcopy(value): + if k in keys_to_remove: + del value[k] + else: + _remove_keys_from_spec(value[k], keys_to_remove) + elif isinstance(value, list): + for i in value: + _remove_keys_from_spec(i, keys_to_remove) diff --git a/backend/capellacollab/core/responses.py b/backend/capellacollab/core/responses.py index 6485a94f0d..343a8ab856 100644 --- a/backend/capellacollab/core/responses.py +++ b/backend/capellacollab/core/responses.py @@ -47,11 +47,7 @@ def api_exceptions( projects_users_models.ProjectUserPermission | None ) = None, ): - if os.getenv("CAPELLACOLLAB_SKIP_OPENAPI_ERROR_RESPONSES", "").lower() in ( - "1", - "true", - "t", - ): + if os.getenv("CAPELLACOLLAB_SKIP_OPENAPI_ERROR_RESPONSES", "0") == "1": return {} if excs is None: diff --git a/frontend/Makefile b/frontend/Makefile index 49ce0da4ea..3b530e5504 100644 --- a/frontend/Makefile +++ b/frontend/Makefile @@ -30,7 +30,6 @@ snapshots: npx storycap http://localhost:6006 --serverCmd "npm run storybook" --flat openapi: - python postprocess_openapi_schema.py OPENAPI_DIR=$$(mktemp -d) docker run --rm \ -v /tmp/openapi.json:/tmp/openapi.json \ diff --git a/frontend/postprocess_openapi_schema.py b/frontend/postprocess_openapi_schema.py deleted file mode 100644 index b1fa02cbf1..0000000000 --- a/frontend/postprocess_openapi_schema.py +++ /dev/null @@ -1,32 +0,0 @@ -# SPDX-FileCopyrightText: Copyright DB InfraGO AG and contributors -# SPDX-License-Identifier: Apache-2.0 - -"""Due to a bug in the OpenAPI generator, -default keys break the generation of some types. - -To fix it, we remove the default keys from the OpenAPI schema. -""" - -import copy -import json -import pathlib - -PATH_TO_OPENAPI_SCHEMA = pathlib.Path("/tmp/openapi.json") - - -def remove_default_keys(value: dict): - if isinstance(value, dict): - for k in copy.deepcopy(value): - if k == "default": - del value[k] - else: - remove_default_keys(value[k]) - elif isinstance(value, list): - for i in value: - remove_default_keys(i) - - -if __name__ == "__main__": - schema = json.loads(PATH_TO_OPENAPI_SCHEMA.read_text()) - remove_default_keys(schema) - PATH_TO_OPENAPI_SCHEMA.write_text(json.dumps(schema))