From 5a949f6d8893ffb291b9a02abc0e57967005015f Mon Sep 17 00:00:00 2001 From: Kanna Kim Date: Sat, 29 Aug 2026 21:36:48 -0500 Subject: [PATCH] fix(python-fastapi): omit security imports for unauthenticated APIs --- .../resources/python-fastapi/api.mustache | 6 +++-- .../PythonFastAPIServerCodegenTest.java | 19 ++++++++++++++ .../src/test/resources/bugs/issue_23008.yaml | 26 +++++++++++++++++++ .../src/openapi_server/apis/fake_api.py | 2 -- .../src/openapi_server/apis/pet_api.py | 2 +- .../src/openapi_server/apis/store_api.py | 2 +- .../src/openapi_server/apis/user_api.py | 2 +- 7 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 modules/openapi-generator/src/test/resources/bugs/issue_23008.yaml diff --git a/modules/openapi-generator/src/main/resources/python-fastapi/api.mustache b/modules/openapi-generator/src/main/resources/python-fastapi/api.mustache index 0680d357cda6..7c34ff7bf121 100644 --- a/modules/openapi-generator/src/main/resources/python-fastapi/api.mustache +++ b/modules/openapi-generator/src/main/resources/python-fastapi/api.mustache @@ -22,11 +22,13 @@ from fastapi import ( # noqa: F401 status, ) -from {{modelPackage}}.extra_models import TokenModel # noqa: F401 {{#imports}} {{import}} {{/imports}} -{{#securityImports.0}}from {{packageName}}.security_api import {{#securityImports}}get_token_{{.}}{{^-last}}, {{/-last}}{{/securityImports}}{{/securityImports.0}} +{{#securityImports.0}} +from {{modelPackage}}.extra_models import TokenModel # noqa: F401 +from {{packageName}}.security_api import {{#securityImports}}get_token_{{.}}{{^-last}}, {{/-last}}{{/securityImports}} +{{/securityImports.0}} router = APIRouter() diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonFastAPIServerCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonFastAPIServerCodegenTest.java index 72a330b29b60..7a6a528102d8 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonFastAPIServerCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonFastAPIServerCodegenTest.java @@ -268,4 +268,23 @@ public void testEndpointArgumentCommaStaysOnSameLine() throws IOException { Assert.assertFalse(content.contains("\n,\n"), "comma wrapped onto its own line in: " + api); } + + @Test(description = "security imports are emitted only for APIs with authenticated operations (#23008)") + public void testSecurityImportsRequireAuthenticatedOperations() throws IOException { + final DefaultCodegen unauthenticatedCodegen = new PythonFastAPIServerCodegen(); + final String unauthenticatedOutputPath = generateFiles(unauthenticatedCodegen, "src/test/resources/bugs/issue_23008.yaml"); + final Path unauthenticatedApi = Paths.get(unauthenticatedOutputPath + "src/openapi_server/apis/default_api.py"); + + assertFileExists(unauthenticatedApi); + assertFileNotContains(unauthenticatedApi, "from openapi_server.models.extra_models import TokenModel"); + assertFileNotContains(unauthenticatedApi, "from openapi_server.security_api import"); + + final DefaultCodegen authenticatedCodegen = new PythonFastAPIServerCodegen(); + final String authenticatedOutputPath = generateFiles(authenticatedCodegen, "src/test/resources/3_0/python-fastapi/petstore.yaml"); + final Path authenticatedApi = Paths.get(authenticatedOutputPath + "src/openapi_server/apis/pet_api.py"); + + assertFileExists(authenticatedApi); + assertFileContains(authenticatedApi, "from openapi_server.models.extra_models import TokenModel"); + assertFileContains(authenticatedApi, "from openapi_server.security_api import get_token_"); + } } diff --git a/modules/openapi-generator/src/test/resources/bugs/issue_23008.yaml b/modules/openapi-generator/src/test/resources/bugs/issue_23008.yaml new file mode 100644 index 000000000000..01a77bead2e5 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/bugs/issue_23008.yaml @@ -0,0 +1,26 @@ +openapi: 3.0.3 +info: + title: Supporting-files reproduction + version: 1.0.0 +paths: + /pets: + get: + operationId: listPets + responses: + "200": + description: A list of pets + content: + application/json: + schema: + type: array + items: + $ref: "#/components/schemas/Pet" +components: + schemas: + Pet: + type: object + required: + - name + properties: + name: + type: string diff --git a/samples/server/petstore/python-fastapi/src/openapi_server/apis/fake_api.py b/samples/server/petstore/python-fastapi/src/openapi_server/apis/fake_api.py index 56b3e6e64381..175746812f3d 100644 --- a/samples/server/petstore/python-fastapi/src/openapi_server/apis/fake_api.py +++ b/samples/server/petstore/python-fastapi/src/openapi_server/apis/fake_api.py @@ -22,12 +22,10 @@ status, ) -from openapi_server.models.extra_models import TokenModel # noqa: F401 from pydantic import Field from typing import Any, Optional from typing_extensions import Annotated - router = APIRouter() ns_pkg = openapi_server.impl diff --git a/samples/server/petstore/python-fastapi/src/openapi_server/apis/pet_api.py b/samples/server/petstore/python-fastapi/src/openapi_server/apis/pet_api.py index a550aa7a21d1..76200809cc55 100644 --- a/samples/server/petstore/python-fastapi/src/openapi_server/apis/pet_api.py +++ b/samples/server/petstore/python-fastapi/src/openapi_server/apis/pet_api.py @@ -22,13 +22,13 @@ status, ) -from openapi_server.models.extra_models import TokenModel # noqa: F401 from pydantic import Field, StrictBytes, StrictStr, field_validator from typing import Any, List, Optional, Tuple, Union from typing_extensions import Annotated from openapi_server.models.api_response import ApiResponse from openapi_server.models.pet import Pet from fastapi import File, UploadFile +from openapi_server.models.extra_models import TokenModel # noqa: F401 from openapi_server.security_api import get_token_petstore_auth, get_token_api_key router = APIRouter() diff --git a/samples/server/petstore/python-fastapi/src/openapi_server/apis/store_api.py b/samples/server/petstore/python-fastapi/src/openapi_server/apis/store_api.py index d1882a9005a8..414e5625af96 100644 --- a/samples/server/petstore/python-fastapi/src/openapi_server/apis/store_api.py +++ b/samples/server/petstore/python-fastapi/src/openapi_server/apis/store_api.py @@ -22,11 +22,11 @@ status, ) -from openapi_server.models.extra_models import TokenModel # noqa: F401 from pydantic import Field, StrictInt from typing import Any, Dict from typing_extensions import Annotated from openapi_server.models.order import Order +from openapi_server.models.extra_models import TokenModel # noqa: F401 from openapi_server.security_api import get_token_api_key router = APIRouter() diff --git a/samples/server/petstore/python-fastapi/src/openapi_server/apis/user_api.py b/samples/server/petstore/python-fastapi/src/openapi_server/apis/user_api.py index c000022a85fe..d6466608634a 100644 --- a/samples/server/petstore/python-fastapi/src/openapi_server/apis/user_api.py +++ b/samples/server/petstore/python-fastapi/src/openapi_server/apis/user_api.py @@ -22,11 +22,11 @@ status, ) -from openapi_server.models.extra_models import TokenModel # noqa: F401 from pydantic import Field, StrictStr, field_validator from typing import Any, List from typing_extensions import Annotated from openapi_server.models.user import User +from openapi_server.models.extra_models import TokenModel # noqa: F401 from openapi_server.security_api import get_token_api_key router = APIRouter()