forked from loafle/openapi-generator-original
Autoset constants (Required fields having single valid enum value) (#16761)
* Autoset constants (Required fields having single valid enum value) Python Implementation of #16547 * Fixing ``PythonClientCodegenTest.testHandleConstantParams`` for Windows platform.
This commit is contained in:
parent
8bb473316e
commit
2f214ee6c6
@ -43,6 +43,8 @@ public class CodegenConstants {
|
|||||||
public static final String API_SUFFIX = "apiSuffix";
|
public static final String API_SUFFIX = "apiSuffix";
|
||||||
public static final String API_SUFFIX_DESC = "suffix for api classes";
|
public static final String API_SUFFIX_DESC = "suffix for api classes";
|
||||||
|
|
||||||
|
public static final String AUTOSET_CONSTANTS = "autosetConstants";
|
||||||
|
|
||||||
public static final String MODEL_PACKAGE = "modelPackage";
|
public static final String MODEL_PACKAGE = "modelPackage";
|
||||||
public static final String MODEL_PACKAGE_DESC = "package for generated models";
|
public static final String MODEL_PACKAGE_DESC = "package for generated models";
|
||||||
|
|
||||||
|
@ -304,6 +304,9 @@ public class DefaultCodegen implements CodegenConfig {
|
|||||||
|
|
||||||
protected boolean addSuffixToDuplicateOperationNicknames = true;
|
protected boolean addSuffixToDuplicateOperationNicknames = true;
|
||||||
|
|
||||||
|
// Whether to automatically hardcode params that are considered Constants by OpenAPI Spec
|
||||||
|
protected boolean autosetConstants = false;
|
||||||
|
|
||||||
public boolean getAddSuffixToDuplicateOperationNicknames() {
|
public boolean getAddSuffixToDuplicateOperationNicknames() {
|
||||||
return addSuffixToDuplicateOperationNicknames;
|
return addSuffixToDuplicateOperationNicknames;
|
||||||
}
|
}
|
||||||
@ -427,6 +430,10 @@ public class DefaultCodegen implements CodegenConfig {
|
|||||||
this.setEnumUnknownDefaultCase(Boolean.parseBoolean(additionalProperties
|
this.setEnumUnknownDefaultCase(Boolean.parseBoolean(additionalProperties
|
||||||
.get(CodegenConstants.ENUM_UNKNOWN_DEFAULT_CASE).toString()));
|
.get(CodegenConstants.ENUM_UNKNOWN_DEFAULT_CASE).toString()));
|
||||||
}
|
}
|
||||||
|
if (additionalProperties.containsKey(CodegenConstants.AUTOSET_CONSTANTS)) {
|
||||||
|
this.setAutosetConstants(
|
||||||
|
Boolean.parseBoolean(additionalProperties.get(CodegenConstants.AUTOSET_CONSTANTS).toString()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
@ -8282,4 +8289,47 @@ public class DefaultCodegen implements CodegenConfig {
|
|||||||
throw new IllegalArgumentException("Invalid schema type; type must be Boolean or Schema");
|
throw new IllegalArgumentException("Invalid schema type; type must be Boolean or Schema");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAutosetConstants(boolean autosetConstants) {
|
||||||
|
this.autosetConstants = autosetConstants;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method removes all constant Query, Header and Cookie Params from allParams and sets them as constantParams in the CodegenOperation.
|
||||||
|
* The definition of constant is single valued required enum params.
|
||||||
|
* The constantParams in the the generated code should be hardcoded to the constantValue if autosetConstants feature is enabled.
|
||||||
|
*
|
||||||
|
* @param operation - operation to be processed
|
||||||
|
*/
|
||||||
|
protected void handleConstantParams(CodegenOperation operation) {
|
||||||
|
if (!autosetConstants || operation.allParams.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final ArrayList<CodegenParameter> copy = new ArrayList<>(operation.allParams);
|
||||||
|
// Remove all params from Params, Non constant params will be added back later.
|
||||||
|
operation.allParams.clear();
|
||||||
|
|
||||||
|
// Finds all constant params, removes them from allParams and adds them to constant params.
|
||||||
|
// Also, adds back non constant params to allParams.
|
||||||
|
for (CodegenParameter p : copy) {
|
||||||
|
if (p.isEnum && p.required && p._enum != null && p._enum.size() == 1) {
|
||||||
|
// Add to constantParams for use in the code generation templates.
|
||||||
|
operation.constantParams.add(p);
|
||||||
|
if(p.isQueryParam) {
|
||||||
|
operation.queryParams.removeIf(param -> param.baseName.equals(p.baseName));
|
||||||
|
}
|
||||||
|
if(p.isHeaderParam) {
|
||||||
|
operation.headerParams.removeIf(param -> param.baseName.equals(p.baseName));
|
||||||
|
}
|
||||||
|
if(p.isCookieParam) {
|
||||||
|
operation.cookieParams.removeIf(param -> param.baseName.equals(p.baseName));
|
||||||
|
}
|
||||||
|
LOGGER.info("Update operation [{}]. Remove parameter [{}] because it can only have a fixed value of [{}]", operation.operationId, p.baseName, p._enum.get(0));
|
||||||
|
} else {
|
||||||
|
// Add back to allParams as the param is not a constant.
|
||||||
|
operation.allParams.add(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
operation.hasParams = !operation.allParams.isEmpty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,6 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
|
|||||||
public static final String TEST_OUTPUT = "testOutput";
|
public static final String TEST_OUTPUT = "testOutput";
|
||||||
public static final String IMPLICIT_HEADERS = "implicitHeaders";
|
public static final String IMPLICIT_HEADERS = "implicitHeaders";
|
||||||
public static final String IMPLICIT_HEADERS_REGEX = "implicitHeadersRegex";
|
public static final String IMPLICIT_HEADERS_REGEX = "implicitHeadersRegex";
|
||||||
public static final String AUTOSET_CONSTANTS = "autosetConstants";
|
|
||||||
public static final String JAVAX_PACKAGE = "javaxPackage";
|
public static final String JAVAX_PACKAGE = "javaxPackage";
|
||||||
public static final String USE_JAKARTA_EE = "useJakartaEe";
|
public static final String USE_JAKARTA_EE = "useJakartaEe";
|
||||||
public static final String CONTAINER_DEFAULT_TO_NULL = "containerDefaultToNull";
|
public static final String CONTAINER_DEFAULT_TO_NULL = "containerDefaultToNull";
|
||||||
@ -136,7 +135,6 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
|
|||||||
protected AnnotationLibrary annotationLibrary;
|
protected AnnotationLibrary annotationLibrary;
|
||||||
protected boolean implicitHeaders = false;
|
protected boolean implicitHeaders = false;
|
||||||
protected String implicitHeadersRegex = null;
|
protected String implicitHeadersRegex = null;
|
||||||
protected boolean autosetConstants = false;
|
|
||||||
protected boolean camelCaseDollarSign = false;
|
protected boolean camelCaseDollarSign = false;
|
||||||
protected boolean useJakartaEe = false;
|
protected boolean useJakartaEe = false;
|
||||||
protected boolean containerDefaultToNull = false;
|
protected boolean containerDefaultToNull = false;
|
||||||
@ -558,10 +556,6 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
|
|||||||
this.setImplicitHeadersRegex(additionalProperties.get(IMPLICIT_HEADERS_REGEX).toString());
|
this.setImplicitHeadersRegex(additionalProperties.get(IMPLICIT_HEADERS_REGEX).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (additionalProperties.containsKey(AUTOSET_CONSTANTS)) {
|
|
||||||
this.setAutosetConstants(Boolean.parseBoolean(additionalProperties.get(AUTOSET_CONSTANTS).toString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (additionalProperties.containsKey(CAMEL_CASE_DOLLAR_SIGN)) {
|
if (additionalProperties.containsKey(CAMEL_CASE_DOLLAR_SIGN)) {
|
||||||
this.setCamelCaseDollarSign(Boolean.parseBoolean(additionalProperties.get(CAMEL_CASE_DOLLAR_SIGN).toString()));
|
this.setCamelCaseDollarSign(Boolean.parseBoolean(additionalProperties.get(CAMEL_CASE_DOLLAR_SIGN).toString()));
|
||||||
}
|
}
|
||||||
@ -2052,10 +2046,6 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
|
|||||||
this.implicitHeadersRegex = implicitHeadersRegex;
|
this.implicitHeadersRegex = implicitHeadersRegex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAutosetConstants(boolean autosetConstants) {
|
|
||||||
this.autosetConstants = autosetConstants;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCamelCaseDollarSign(boolean camelCaseDollarSign) {
|
public void setCamelCaseDollarSign(boolean camelCaseDollarSign) {
|
||||||
this.camelCaseDollarSign = camelCaseDollarSign;
|
this.camelCaseDollarSign = camelCaseDollarSign;
|
||||||
}
|
}
|
||||||
@ -2293,46 +2283,7 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
|
|||||||
}
|
}
|
||||||
operation.hasParams = !operation.allParams.isEmpty();
|
operation.hasParams = !operation.allParams.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method removes all constant Query, Header and Cookie Params from allParams and sets them as constantParams in the CodegenOperation.
|
|
||||||
* The definition of constant is single valued required enum params.
|
|
||||||
* The constantParams in the the generated code should be hardcoded to the constantValue if autosetConstants feature is enabled.
|
|
||||||
*
|
|
||||||
* @param operation - operation to be processed
|
|
||||||
*/
|
|
||||||
protected void handleConstantParams(CodegenOperation operation) {
|
|
||||||
if (!autosetConstants || operation.allParams.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final ArrayList<CodegenParameter> copy = new ArrayList<>(operation.allParams);
|
|
||||||
// Remove all params from Params, Non constant params will be added back later.
|
|
||||||
operation.allParams.clear();
|
|
||||||
|
|
||||||
// Finds all constant params, removes them from allParams and adds them to constant params.
|
|
||||||
// Also, adds back non constant params to allParams.
|
|
||||||
for (CodegenParameter p : copy) {
|
|
||||||
if (p.isEnum && p.required && p._enum != null && p._enum.size() == 1) {
|
|
||||||
// Add to constantParams for use in the code generation templates.
|
|
||||||
operation.constantParams.add(p);
|
|
||||||
if(p.isQueryParam) {
|
|
||||||
operation.queryParams.removeIf(param -> param.baseName.equals(p.baseName));
|
|
||||||
}
|
|
||||||
if(p.isHeaderParam) {
|
|
||||||
operation.headerParams.removeIf(param -> param.baseName.equals(p.baseName));
|
|
||||||
}
|
|
||||||
if(p.isCookieParam) {
|
|
||||||
operation.cookieParams.removeIf(param -> param.baseName.equals(p.baseName));
|
|
||||||
}
|
|
||||||
LOGGER.info("Update operation [{}]. Remove parameter [{}] because it can only have a fixed value of [{}]", operation.operationId, p.baseName, p._enum.get(0));
|
|
||||||
} else {
|
|
||||||
// Add back to allParams as the param is not a constant.
|
|
||||||
operation.allParams.add(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
operation.hasParams = !operation.allParams.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean shouldBeImplicitHeader(CodegenParameter parameter) {
|
private boolean shouldBeImplicitHeader(CodegenParameter parameter) {
|
||||||
return StringUtils.isNotBlank(implicitHeadersRegex) && parameter.baseName.matches(implicitHeadersRegex);
|
return StringUtils.isNotBlank(implicitHeadersRegex) && parameter.baseName.matches(implicitHeadersRegex);
|
||||||
}
|
}
|
||||||
|
@ -1281,6 +1281,9 @@ public abstract class AbstractPythonCodegen extends DefaultCodegen implements Co
|
|||||||
}
|
}
|
||||||
operation.vendorExtensions.put("x-py-example-import", imports);
|
operation.vendorExtensions.put("x-py-example-import", imports);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove constant params from allParams list and add to constantParams
|
||||||
|
handleConstantParams(operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Map<String, String>> newImports = new ArrayList<>();
|
List<Map<String, String>> newImports = new ArrayList<>();
|
||||||
|
@ -227,6 +227,13 @@ class {{classname}}:
|
|||||||
{{/isArray}}
|
{{/isArray}}
|
||||||
|
|
||||||
{{/queryParams}}
|
{{/queryParams}}
|
||||||
|
{{#constantParams}}
|
||||||
|
{{#isQueryParam}}
|
||||||
|
# Set client side default value of Query Param "{{baseName}}".
|
||||||
|
_query_params['{{baseName}}'] = {{#_enum}}'{{{.}}}'{{/_enum}}
|
||||||
|
|
||||||
|
{{/isQueryParam}}
|
||||||
|
{{/constantParams}}
|
||||||
# process the header parameters
|
# process the header parameters
|
||||||
_header_params = dict(_params.get('_headers', {}))
|
_header_params = dict(_params.get('_headers', {}))
|
||||||
{{#headerParams}}
|
{{#headerParams}}
|
||||||
@ -237,6 +244,13 @@ class {{classname}}:
|
|||||||
{{/isArray}}
|
{{/isArray}}
|
||||||
|
|
||||||
{{/headerParams}}
|
{{/headerParams}}
|
||||||
|
{{#constantParams}}
|
||||||
|
{{#isHeaderParam}}
|
||||||
|
# Set client side default value of Header Param "{{baseName}}".
|
||||||
|
_header_params['{{baseName}}'] = {{#_enum}}'{{{.}}}'{{/_enum}}
|
||||||
|
|
||||||
|
{{/isHeaderParam}}
|
||||||
|
{{/constantParams}}
|
||||||
# process the form parameters
|
# process the form parameters
|
||||||
_form_params: List[Tuple[str, str]] = []
|
_form_params: List[Tuple[str, str]] = []
|
||||||
_files: Dict[str, str] = {}
|
_files: Dict[str, str] = {}
|
||||||
|
@ -2673,6 +2673,7 @@ public class JavaClientCodegenTest {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testHandleConstantParams() throws IOException {
|
public void testHandleConstantParams() throws IOException {
|
||||||
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
|
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
|
||||||
output.deleteOnExit();
|
output.deleteOnExit();
|
||||||
@ -2682,7 +2683,7 @@ public class JavaClientCodegenTest {
|
|||||||
clientOptInput.openAPI(openAPI);
|
clientOptInput.openAPI(openAPI);
|
||||||
JavaClientCodegen javaClientCodegen = new JavaClientCodegen();
|
JavaClientCodegen javaClientCodegen = new JavaClientCodegen();
|
||||||
javaClientCodegen.setOutputDir(output.getAbsolutePath());
|
javaClientCodegen.setOutputDir(output.getAbsolutePath());
|
||||||
javaClientCodegen.additionalProperties().put(JavaClientCodegen.AUTOSET_CONSTANTS, "true");
|
javaClientCodegen.additionalProperties().put(CodegenConstants.AUTOSET_CONSTANTS, "true");
|
||||||
javaClientCodegen.setAutosetConstants(true);
|
javaClientCodegen.setAutosetConstants(true);
|
||||||
clientOptInput.config(javaClientCodegen);
|
clientOptInput.config(javaClientCodegen);
|
||||||
defaultGenerator.opts(clientOptInput);
|
defaultGenerator.opts(clientOptInput);
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
package org.openapitools.codegen.python;
|
package org.openapitools.codegen.python;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import io.swagger.parser.OpenAPIParser;
|
import io.swagger.parser.OpenAPIParser;
|
||||||
import io.swagger.v3.oas.models.OpenAPI;
|
import io.swagger.v3.oas.models.OpenAPI;
|
||||||
@ -30,6 +31,7 @@ import org.openapitools.codegen.languages.features.CXFServerFeatures;
|
|||||||
import static org.openapitools.codegen.TestUtils.assertFileContains;
|
import static org.openapitools.codegen.TestUtils.assertFileContains;
|
||||||
import static org.openapitools.codegen.TestUtils.assertFileExists;
|
import static org.openapitools.codegen.TestUtils.assertFileExists;
|
||||||
import org.openapitools.codegen.TestUtils;
|
import org.openapitools.codegen.TestUtils;
|
||||||
|
import org.openapitools.codegen.java.assertions.JavaFileAssert;
|
||||||
import org.testng.Assert;
|
import org.testng.Assert;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -40,6 +42,9 @@ import java.nio.file.Path;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class PythonClientCodegenTest {
|
public class PythonClientCodegenTest {
|
||||||
|
|
||||||
@ -501,4 +506,28 @@ public class PythonClientCodegenTest {
|
|||||||
CodegenProperty property = vars.get(0);
|
CodegenProperty property = vars.get(0);
|
||||||
Assert.assertEquals(property.name, "dollar_value");
|
Assert.assertEquals(property.name, "dollar_value");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHandleConstantParams() throws IOException {
|
||||||
|
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
|
||||||
|
output.deleteOnExit();
|
||||||
|
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/java/autoset_constant.yaml");
|
||||||
|
final DefaultGenerator defaultGenerator = new DefaultGenerator();
|
||||||
|
final ClientOptInput clientOptInput = new ClientOptInput();
|
||||||
|
clientOptInput.openAPI(openAPI);
|
||||||
|
PythonClientCodegen pythonClientCodegen = new PythonClientCodegen();
|
||||||
|
pythonClientCodegen.setOutputDir(output.getAbsolutePath());
|
||||||
|
pythonClientCodegen.additionalProperties().put(CodegenConstants.AUTOSET_CONSTANTS, "true");
|
||||||
|
pythonClientCodegen.setAutosetConstants(true);
|
||||||
|
clientOptInput.config(pythonClientCodegen);
|
||||||
|
defaultGenerator.opts(clientOptInput);
|
||||||
|
|
||||||
|
Map<String, File> files = defaultGenerator.generate().stream()
|
||||||
|
.collect(Collectors.toMap(File::getPath, Function.identity()));
|
||||||
|
|
||||||
|
File apiFile = files
|
||||||
|
.get(Paths.get(output.getAbsolutePath(), "openapi_client", "api", "hello_example_api.py").toString());
|
||||||
|
assertNotNull(apiFile);
|
||||||
|
assertFileContains(apiFile.toPath(), "_header_params['X-CUSTOM_CONSTANT_HEADER'] = 'CONSTANT_VALUE'");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user