diff --git a/modules/openapi-generator/src/main/resources/python-flask/controller.mustache b/modules/openapi-generator/src/main/resources/python-flask/controller.mustache index ad276a661ad..74034f5e869 100644 --- a/modules/openapi-generator/src/main/resources/python-flask/controller.mustache +++ b/modules/openapi-generator/src/main/resources/python-flask/controller.mustache @@ -10,7 +10,7 @@ from {{packageName}} import util {{#operation}} -def {{operationId}}({{#allParams}}{{paramName}}{{^required}}=None{{/required}}{{^-last}}, {{/-last}}{{/allParams}}): # noqa: E501 +def {{operationId}}({{#allParams}}{{^isBodyParam}}{{paramName}}{{/isBodyParam}}{{#isBodyParam}}body{{/isBodyParam}}{{^required}}=None{{/required}}{{^-last}}, {{/-last}}{{/allParams}}): # noqa: E501 """{{summary}}{{^summary}}{{operationId}}{{/summary}} {{notes}} # noqa: E501 @@ -60,6 +60,9 @@ def {{operationId}}({{#allParams}}{{paramName}}{{^required}}=None{{/required}}{{ :rtype: Union[{{returnType}}{{^returnType}}None{{/returnType}}, Tuple[{{returnType}}{{^returnType}}None{{/returnType}}, int], Tuple[{{returnType}}{{^returnType}}None{{/returnType}}, int, Dict[str, str]] """ {{#allParams}} + {{#isBodyParam}} + {{paramName}} = body + {{/isBodyParam}} {{^isContainer}} {{#isDate}} {{paramName}} = util.deserialize_date({{paramName}}) diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonFlaskConnexionServerCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonFlaskConnexionServerCodegenTest.java new file mode 100644 index 00000000000..764b6bf3b17 --- /dev/null +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonFlaskConnexionServerCodegenTest.java @@ -0,0 +1,68 @@ +package org.openapitools.codegen.python; + +import io.swagger.parser.OpenAPIParser; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.parser.core.models.ParseOptions; +import org.openapitools.codegen.*; +import org.openapitools.codegen.languages.PythonFlaskConnexionServerCodegen; +import org.openapitools.codegen.languages.features.CXFServerFeatures; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +import static org.openapitools.codegen.TestUtils.assertFileContains; +import static org.openapitools.codegen.TestUtils.assertFileExists; + +public class PythonFlaskConnexionServerCodegenTest { + + // Helper function, intended to reduce boilerplate + static private String generateFiles(DefaultCodegen codegen, String filePath) throws IOException { + final File output = Files.createTempDirectory("test").toFile().getCanonicalFile(); + output.deleteOnExit(); + final String outputPath = output.getAbsolutePath().replace('\\', '/'); + + codegen.setOutputDir(output.getAbsolutePath()); + codegen.additionalProperties().put(CXFServerFeatures.LOAD_TEST_DATA_FROM_FILE, "true"); + + final ClientOptInput input = new ClientOptInput(); + final OpenAPI openAPI = new OpenAPIParser().readLocation(filePath, null, new ParseOptions()).getOpenAPI(); + input.openAPI(openAPI); + input.config(codegen); + + final DefaultGenerator generator = new DefaultGenerator(); + final List files = generator.opts(input).generate(); + + Assert.assertTrue(files.size() > 0); + return outputPath + "/"; + } + + + @Test(description = "test requestBody") + public void testRequestBody() throws IOException { + final DefaultCodegen codegen = new PythonFlaskConnexionServerCodegen(); + final String outputPath = generateFiles(codegen, "src/test/resources/bugs/issue_1666.yaml"); + + final Path p1 = Paths.get(outputPath + "openapi_server/controllers/test1_controller.py"); + assertFileExists(p1); + assertFileContains(p1, "def not_required(body=None):"); + assertFileContains(p1, "test_request = body"); + + final Path p2 = Paths.get(outputPath + "openapi_server/controllers/test2_controller.py"); + assertFileContains(p2, "def required(body):"); + assertFileContains(p2, "test_request = body"); + + final Path p3 = Paths.get(outputPath + "openapi_server/controllers/test3_controller.py"); + assertFileContains(p3, "def with_path_param(param1, body=None):"); + assertFileContains(p3, "test_request = body"); + + final Path p4 = Paths.get(outputPath + "openapi_server/controllers/test4_controller.py"); + assertFileContains(p4, "def with_path_param_required(param1, body):"); + assertFileContains(p4, "test_request = body"); + } +} diff --git a/modules/openapi-generator/src/test/resources/bugs/issue_1666.yaml b/modules/openapi-generator/src/test/resources/bugs/issue_1666.yaml new file mode 100644 index 00000000000..775e57f80d3 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/bugs/issue_1666.yaml @@ -0,0 +1,83 @@ +openapi: "3.0.3" +info: + title: issue #1666 + version: 1.0.0 +tags: + - name: test1 + - name: test2 + - name: test3 + - name: test4 +paths: + "/not-required": + post: + operationId: notRequired + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TestRequest' + responses: + '200': + description: success + tags: + - test1 + "/required": + post: + operationId: required + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TestRequest' + responses: + '200': + description: success + tags: + - test2 + "/with-path-param/{param1}": + post: + operationId: withPathParam + parameters: + - name: param1 + in: path + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/TestRequest' + responses: + '200': + description: success + tags: + - test3 + "/with-path-param-required/{param1}": + post: + operationId: withPathParamRequired + parameters: + - name: param1 + in: path + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/TestRequest' + responses: + '200': + description: success + tags: + - test4 +components: + schemas: + TestRequest: + type: object + properties: + key1: + type: string diff --git a/samples/server/petstore/python-flask/openapi_server/controllers/pet_controller.py b/samples/server/petstore/python-flask/openapi_server/controllers/pet_controller.py index 6b7d87f1b73..dfc5a025188 100644 --- a/samples/server/petstore/python-flask/openapi_server/controllers/pet_controller.py +++ b/samples/server/petstore/python-flask/openapi_server/controllers/pet_controller.py @@ -8,7 +8,7 @@ from openapi_server.models.pet import Pet # noqa: E501 from openapi_server import util -def add_pet(pet): # noqa: E501 +def add_pet(body): # noqa: E501 """Add a new pet to the store # noqa: E501 @@ -18,6 +18,7 @@ def add_pet(pet): # noqa: E501 :rtype: Union[Pet, Tuple[Pet, int], Tuple[Pet, int, Dict[str, str]] """ + pet = body if connexion.request.is_json: pet = Pet.from_dict(connexion.request.get_json()) # noqa: E501 return 'do some magic!' @@ -77,7 +78,7 @@ def get_pet_by_id(pet_id): # noqa: E501 return 'do some magic!' -def update_pet(pet): # noqa: E501 +def update_pet(body): # noqa: E501 """Update an existing pet # noqa: E501 @@ -87,6 +88,7 @@ def update_pet(pet): # noqa: E501 :rtype: Union[Pet, Tuple[Pet, int], Tuple[Pet, int, Dict[str, str]] """ + pet = body if connexion.request.is_json: pet = Pet.from_dict(connexion.request.get_json()) # noqa: E501 return 'do some magic!' diff --git a/samples/server/petstore/python-flask/openapi_server/controllers/store_controller.py b/samples/server/petstore/python-flask/openapi_server/controllers/store_controller.py index 1782980a90a..27af5fd2513 100644 --- a/samples/server/petstore/python-flask/openapi_server/controllers/store_controller.py +++ b/samples/server/petstore/python-flask/openapi_server/controllers/store_controller.py @@ -44,7 +44,7 @@ def get_order_by_id(order_id): # noqa: E501 return 'do some magic!' -def place_order(order): # noqa: E501 +def place_order(body): # noqa: E501 """Place an order for a pet # noqa: E501 @@ -54,6 +54,7 @@ def place_order(order): # noqa: E501 :rtype: Union[Order, Tuple[Order, int], Tuple[Order, int, Dict[str, str]] """ + order = body if connexion.request.is_json: order = Order.from_dict(connexion.request.get_json()) # noqa: E501 return 'do some magic!' diff --git a/samples/server/petstore/python-flask/openapi_server/controllers/user_controller.py b/samples/server/petstore/python-flask/openapi_server/controllers/user_controller.py index 7510bacdca6..6b318c2cd3e 100644 --- a/samples/server/petstore/python-flask/openapi_server/controllers/user_controller.py +++ b/samples/server/petstore/python-flask/openapi_server/controllers/user_controller.py @@ -7,7 +7,7 @@ from openapi_server.models.user import User # noqa: E501 from openapi_server import util -def create_user(user): # noqa: E501 +def create_user(body): # noqa: E501 """Create user This can only be done by the logged in user. # noqa: E501 @@ -17,12 +17,13 @@ def create_user(user): # noqa: E501 :rtype: Union[None, Tuple[None, int], Tuple[None, int, Dict[str, str]] """ + user = body if connexion.request.is_json: user = User.from_dict(connexion.request.get_json()) # noqa: E501 return 'do some magic!' -def create_users_with_array_input(user): # noqa: E501 +def create_users_with_array_input(body): # noqa: E501 """Creates list of users with given input array # noqa: E501 @@ -32,12 +33,13 @@ def create_users_with_array_input(user): # noqa: E501 :rtype: Union[None, Tuple[None, int], Tuple[None, int, Dict[str, str]] """ + user = body if connexion.request.is_json: user = [User.from_dict(d) for d in connexion.request.get_json()] # noqa: E501 return 'do some magic!' -def create_users_with_list_input(user): # noqa: E501 +def create_users_with_list_input(body): # noqa: E501 """Creates list of users with given input array # noqa: E501 @@ -47,6 +49,7 @@ def create_users_with_list_input(user): # noqa: E501 :rtype: Union[None, Tuple[None, int], Tuple[None, int, Dict[str, str]] """ + user = body if connexion.request.is_json: user = [User.from_dict(d) for d in connexion.request.get_json()] # noqa: E501 return 'do some magic!' @@ -104,7 +107,7 @@ def logout_user(): # noqa: E501 return 'do some magic!' -def update_user(username, user): # noqa: E501 +def update_user(username, body): # noqa: E501 """Updated user This can only be done by the logged in user. # noqa: E501 @@ -116,6 +119,7 @@ def update_user(username, user): # noqa: E501 :rtype: Union[None, Tuple[None, int], Tuple[None, int, Dict[str, str]] """ + user = body if connexion.request.is_json: user = User.from_dict(connexion.request.get_json()) # noqa: E501 return 'do some magic!'