Skip to content

Commit 5d83373

Browse files
refactor: centralize definition of Python vendor extensions (#23898)
1 parent f00a7df commit 5d83373

4 files changed

Lines changed: 62 additions & 48 deletions

File tree

modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,7 @@ public static enum ENUM_PROPERTY_NAMING_TYPE {camelCase, PascalCase, snake_case,
487487
public static final String X_NULLABLE_TYPE = "x-nullable-type";
488488
public static final String X_CSHARP_VALUE_TYPE = "x-csharp-value-type";
489489
public static final String X_REGEX = "x-regex";
490+
public static final String X_PATTERN = "x-pattern";
490491
public static final String X_MODIFIERS = "x-modifiers";
491492
public static final String X_MODIFIER_PREFIX = "x-modifier-";
492493
public static final String X_MODEL_IS_MUTABLE = "x-model-is-mutable";
@@ -504,4 +505,17 @@ public static enum ENUM_PROPERTY_NAMING_TYPE {camelCase, PascalCase, snake_case,
504505
public static final String X_NULLABLE = "x-nullable";
505506
public static final String X_ENUM_VARNAMES = "x-enum-varnames";
506507
public static final String X_ENUM_DESCRIPTIONS = "x-enum-descriptions";
508+
public static final String X_PY_TYPING = "x-py-typing";
509+
public static final String X_PY_EXAMPLE = "x-py-example";
510+
public static final String X_PY_EXAMPLE_IMPORT = "x-py-example-import";
511+
public static final String X_PY_FASTAPI_EXAMPLE = "x-py-fastapi-example";
512+
public static final String X_PY_NAME = "x-py-name";
513+
public static final String X_PY_ENUM_TYPE = "x-py-enum-type";
514+
public static final String X_PY_READONLY = "x-py-readonly";
515+
public static final String X_PY_MODEL_IMPORTS = "x-py-model-imports";
516+
public static final String X_PY_OTHER_IMPORTS = "x-py-other-imports";
517+
public static final String X_PY_POSTPONED_MODEL_IMPORTS = "x-py-postponed-model-imports";
518+
public static final String X_PY_TYPING_IMPORTS = "x-py-typing-imports";
519+
public static final String X_PY_PYDANTIC_IMPORTS = "x-py-pydantic-imports";
520+
public static final String X_PY_DATETIME_IMPORTS = "x-py-datetime-imports";
507521
}

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonCodegen.java

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -635,16 +635,16 @@ public void setParameterExampleValue(CodegenParameter codegenParameter, Paramete
635635

636636
if (parameter.getExample() != null) {
637637
codegenParameter.example = parameter.getExample().toString();
638-
codegenParameter.vendorExtensions.put("x-py-example", toPythonLiteral(parameter.getExample()));
638+
codegenParameter.vendorExtensions.put(X_PY_EXAMPLE, toPythonLiteral(parameter.getExample()));
639639
} else if (parameter.getExamples() != null && !parameter.getExamples().isEmpty()) {
640640
Example example = parameter.getExamples().values().iterator().next();
641641
if (example.getValue() != null) {
642642
codegenParameter.example = example.getValue().toString();
643-
codegenParameter.vendorExtensions.put("x-py-example", toPythonLiteral(example.getValue()));
643+
codegenParameter.vendorExtensions.put(X_PY_EXAMPLE, toPythonLiteral(example.getValue()));
644644
}
645645
} else if (schema != null && schema.getExample() != null) {
646646
codegenParameter.example = schema.getExample().toString();
647-
codegenParameter.vendorExtensions.put("x-py-example", toPythonLiteral(schema.getExample()));
647+
codegenParameter.vendorExtensions.put(X_PY_EXAMPLE, toPythonLiteral(schema.getExample()));
648648
}
649649

650650
setParameterExampleValue(codegenParameter);
@@ -1040,13 +1040,13 @@ private ModelsMap postProcessModelsMap(ModelsMap objs) {
10401040
}
10411041

10421042
String typing = pydantic.generatePythonType(cp);
1043-
cp.vendorExtensions.put("x-py-typing", typing);
1043+
cp.vendorExtensions.put(X_PY_TYPING, typing);
10441044

10451045
// setup x-py-name for each oneOf/anyOf schema
10461046
if (!model.oneOf.isEmpty()) { // oneOf
1047-
cp.vendorExtensions.put("x-py-name", String.format(Locale.ROOT, "oneof_schema_%d_validator", property_count++));
1047+
cp.vendorExtensions.put(X_PY_NAME, String.format(Locale.ROOT, "oneof_schema_%d_validator", property_count++));
10481048
} else if (!model.anyOf.isEmpty()) { // anyOf
1049-
cp.vendorExtensions.put("x-py-name", String.format(Locale.ROOT, "anyof_schema_%d_validator", property_count++));
1049+
cp.vendorExtensions.put(X_PY_NAME, String.format(Locale.ROOT, "anyof_schema_%d_validator", property_count++));
10501050
}
10511051
}
10521052

@@ -1061,13 +1061,13 @@ private ModelsMap postProcessModelsMap(ModelsMap objs) {
10611061
if (model.isEnum) {
10621062
for (Map<String, Object> enumVars : (List<Map<String, Object>>) model.getAllowableValues().get("enumVars")) {
10631063
if ((Boolean) enumVars.get("isString")) {
1064-
model.vendorExtensions.putIfAbsent("x-py-enum-type", "str");
1064+
model.vendorExtensions.putIfAbsent(X_PY_ENUM_TYPE, "str");
10651065
// Do not overwrite the variable name if already set through x-enum-varnames
10661066
if (model.vendorExtensions.get(X_ENUM_VARNAMES) == null) {
10671067
enumVars.put("name", toEnumVariableName((String) enumVars.get("value"), "str"));
10681068
}
10691069
} else {
1070-
model.vendorExtensions.putIfAbsent("x-py-enum-type", "int");
1070+
model.vendorExtensions.putIfAbsent(X_PY_ENUM_TYPE, "int");
10711071
// Do not overwrite the variable name if already set through x-enum-varnames
10721072
if (model.vendorExtensions.get(X_ENUM_VARNAMES) == null) {
10731073
enumVars.put("name", toEnumVariableName((String) enumVars.get("value"), "int"));
@@ -1077,7 +1077,7 @@ private ModelsMap postProcessModelsMap(ModelsMap objs) {
10771077
}
10781078

10791079
// set the extensions if the key is absent
1080-
model.getVendorExtensions().putIfAbsent("x-py-readonly", readOnlyFields);
1080+
model.getVendorExtensions().putIfAbsent(X_PY_READONLY, readOnlyFields);
10811081

10821082
// remove the items of postponedModelImports in modelImports to avoid circular imports error
10831083
if (!modelImports.isEmpty() && !postponedModelImports.isEmpty()) {
@@ -1096,12 +1096,12 @@ private ModelsMap postProcessModelsMap(ModelsMap objs) {
10961096
}
10971097

10981098
if (!modelsToImport.isEmpty()) {
1099-
model.getVendorExtensions().putIfAbsent("x-py-model-imports", modelsToImport);
1099+
model.getVendorExtensions().putIfAbsent(X_PY_MODEL_IMPORTS, modelsToImport);
11001100
}
11011101
}
11021102

11031103
if (!moduleImports.isEmpty()) {
1104-
model.getVendorExtensions().putIfAbsent("x-py-other-imports", moduleImports.exports());
1104+
model.getVendorExtensions().putIfAbsent(X_PY_OTHER_IMPORTS, moduleImports.exports());
11051105
}
11061106

11071107

@@ -1115,7 +1115,7 @@ private ModelsMap postProcessModelsMap(ModelsMap objs) {
11151115
modelsToImport.add("from " + packageName + ".models." + underscore(modelImport) + " import " + modelImport);
11161116
}
11171117

1118-
model.getVendorExtensions().putIfAbsent("x-py-postponed-model-imports", modelsToImport);
1118+
model.getVendorExtensions().putIfAbsent(X_PY_POSTPONED_MODEL_IMPORTS, modelsToImport);
11191119
}
11201120
}
11211121

@@ -1326,7 +1326,7 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
13261326
null
13271327
);
13281328
String typing = pydantic.generatePythonType(cp);
1329-
cp.vendorExtensions.put("x-py-typing", typing);
1329+
cp.vendorExtensions.put(X_PY_TYPING, typing);
13301330
}
13311331

13321332
// update typing import for operation return type
@@ -1367,7 +1367,7 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
13671367
for (String exampleImport : exampleImports) {
13681368
imports.add("from " + packageName + ".models." + underscore(exampleImport) + " import " + exampleImport);
13691369
}
1370-
operation.vendorExtensions.put("x-py-example-import", imports);
1370+
operation.vendorExtensions.put(X_PY_EXAMPLE_IMPORT, imports);
13711371
}
13721372

13731373
if (!postponedExampleImports.isEmpty()) {
@@ -1376,7 +1376,7 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
13761376
imports.add("from " + packageName + ".models." + underscore(exampleImport) + " import "
13771377
+ exampleImport);
13781378
}
1379-
operation.vendorExtensions.put("x-py-example-import", imports);
1379+
operation.vendorExtensions.put(X_PY_EXAMPLE_IMPORT, imports);
13801380
}
13811381

13821382
// Remove constant params from allParams list and add to constantParams
@@ -1462,7 +1462,7 @@ public void postProcessPattern(String pattern, Map<String, Object> vendorExtensi
14621462
}
14631463

14641464
vendorExtensions.put(X_REGEX, regex.replace("\"", "\\\""));
1465-
vendorExtensions.put("x-pattern", pattern.replace("\"", "\\\""));
1465+
vendorExtensions.put(X_PATTERN, pattern.replace("\"", "\\\""));
14661466
vendorExtensions.put(X_MODIFIERS, modifiers);
14671467
}
14681468
}

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonPydanticV1Codegen.java

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@
3939
import java.util.regex.Pattern;
4040
import java.util.stream.Collectors;
4141

42-
import static org.openapitools.codegen.CodegenConstants.X_MODIFIERS;
43-
import static org.openapitools.codegen.CodegenConstants.X_REGEX;
42+
import static org.openapitools.codegen.CodegenConstants.*;
4443
import static org.openapitools.codegen.utils.StringUtils.*;
4544

4645
public abstract class AbstractPythonPydanticV1Codegen extends DefaultCodegen implements CodegenConfig {
@@ -948,13 +947,13 @@ private ModelsMap postProcessModelsMap(ModelsMap objs) {
948947
fieldCustomization = "Field(...)";
949948
}
950949

951-
cp.vendorExtensions.put("x-py-typing", typing + " = " + fieldCustomization);
950+
cp.vendorExtensions.put(X_PY_TYPING, typing + " = " + fieldCustomization);
952951

953952
// setup x-py-name for each oneOf/anyOf schema
954953
if (!model.oneOf.isEmpty()) { // oneOf
955-
cp.vendorExtensions.put("x-py-name", String.format(Locale.ROOT, "oneof_schema_%d_validator", property_count++));
954+
cp.vendorExtensions.put(X_PY_NAME, String.format(Locale.ROOT, "oneof_schema_%d_validator", property_count++));
956955
} else if (!model.anyOf.isEmpty()) { // anyOf
957-
cp.vendorExtensions.put("x-py-name", String.format(Locale.ROOT, "anyof_schema_%d_validator", property_count++));
956+
cp.vendorExtensions.put(X_PY_NAME, String.format(Locale.ROOT, "anyof_schema_%d_validator", property_count++));
958957
}
959958
}
960959

@@ -969,21 +968,21 @@ private ModelsMap postProcessModelsMap(ModelsMap objs) {
969968
if (model.isEnum) {
970969
for (Map<String, Object> enumVars : (List<Map<String, Object>>) model.getAllowableValues().get("enumVars")) {
971970
if ((Boolean) enumVars.get("isString")) {
972-
model.vendorExtensions.putIfAbsent("x-py-enum-type", "str");
971+
model.vendorExtensions.putIfAbsent(X_PY_ENUM_TYPE, "str");
973972
// update `name`, e.g.
974973
enumVars.put("name", toEnumVariableName((String) enumVars.get("value"), "str"));
975974
} else {
976-
model.vendorExtensions.putIfAbsent("x-py-enum-type", "int");
975+
model.vendorExtensions.putIfAbsent(X_PY_ENUM_TYPE, "int");
977976
enumVars.put("name", toEnumVariableName((String) enumVars.get("value"), "int"));
978977
}
979978
}
980979
}
981980

982981
// set the extensions if the key is absent
983-
model.getVendorExtensions().putIfAbsent("x-py-typing-imports", typingImports);
984-
model.getVendorExtensions().putIfAbsent("x-py-pydantic-imports", pydanticImports);
985-
model.getVendorExtensions().putIfAbsent("x-py-datetime-imports", datetimeImports);
986-
model.getVendorExtensions().putIfAbsent("x-py-readonly", readOnlyFields);
982+
model.getVendorExtensions().putIfAbsent(X_PY_TYPING_IMPORTS, typingImports);
983+
model.getVendorExtensions().putIfAbsent(X_PY_PYDANTIC_IMPORTS, pydanticImports);
984+
model.getVendorExtensions().putIfAbsent(X_PY_DATETIME_IMPORTS, datetimeImports);
985+
model.getVendorExtensions().putIfAbsent(X_PY_READONLY, readOnlyFields);
987986

988987
// remove the items of postponedModelImports in modelImports to avoid circular imports error
989988
if (!modelImports.isEmpty() && !postponedModelImports.isEmpty()) {
@@ -1001,7 +1000,7 @@ private ModelsMap postProcessModelsMap(ModelsMap objs) {
10011000
modelsToImport.add("from " + packageName + ".models." + underscore(modelImport) + " import " + modelImport);
10021001
}
10031002

1004-
model.getVendorExtensions().putIfAbsent("x-py-model-imports", modelsToImport);
1003+
model.getVendorExtensions().putIfAbsent(X_PY_MODEL_IMPORTS, modelsToImport);
10051004
}
10061005

10071006
if (!postponedModelImports.isEmpty()) {
@@ -1014,7 +1013,7 @@ private ModelsMap postProcessModelsMap(ModelsMap objs) {
10141013
modelsToImport.add("from " + packageName + ".models." + underscore(modelImport) + " import " + modelImport);
10151014
}
10161015

1017-
model.getVendorExtensions().putIfAbsent("x-py-postponed-model-imports", modelsToImport);
1016+
model.getVendorExtensions().putIfAbsent(X_PY_POSTPONED_MODEL_IMPORTS, modelsToImport);
10181017
}
10191018

10201019
}
@@ -1789,9 +1788,9 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
17891788
}
17901789

17911790
if ("Field()".equals(fieldCustomization)) {
1792-
param.vendorExtensions.put("x-py-typing", typing);
1791+
param.vendorExtensions.put(X_PY_TYPING, typing);
17931792
} else {
1794-
param.vendorExtensions.put("x-py-typing", String.format(Locale.ROOT, "Annotated[%s, %s]", typing, fieldCustomization));
1793+
param.vendorExtensions.put(X_PY_TYPING, String.format(Locale.ROOT, "Annotated[%s, %s]", typing, fieldCustomization));
17951794
importAnnotated = true;
17961795
}
17971796
}
@@ -1809,7 +1808,7 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
18091808
for (String exampleImport : exampleImports) {
18101809
imports.add("from " + packageName + ".models." + underscore(exampleImport) + " import " + exampleImport);
18111810
}
1812-
operation.vendorExtensions.put("x-py-example-import", imports);
1811+
operation.vendorExtensions.put(X_PY_EXAMPLE_IMPORT, imports);
18131812
}
18141813

18151814
if (!postponedExampleImports.isEmpty()) {
@@ -1818,7 +1817,7 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
18181817
imports.add("from " + packageName + ".models." + underscore(exampleImport) + " import "
18191818
+ exampleImport);
18201819
}
1821-
operation.vendorExtensions.put("x-py-example-import", imports);
1820+
operation.vendorExtensions.put(X_PY_EXAMPLE_IMPORT, imports);
18221821
}
18231822
}
18241823

@@ -1918,7 +1917,7 @@ public void postProcessPattern(String pattern, Map<String, Object> vendorExtensi
19181917
}
19191918

19201919
vendorExtensions.put(X_REGEX, regex.replace("\"", "\\\""));
1921-
vendorExtensions.put("x-pattern", pattern.replace("\"", "\\\""));
1920+
vendorExtensions.put(X_PATTERN, pattern.replace("\"", "\\\""));
19221921
vendorExtensions.put(X_MODIFIERS, modifiers);
19231922
}
19241923
}

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PythonFastAPIServerCodegen.java

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import java.io.File;
4242
import java.util.*;
4343

44+
import static org.openapitools.codegen.CodegenConstants.*;
4445
import static org.openapitools.codegen.utils.StringUtils.underscore;
4546

4647
/**
@@ -284,13 +285,13 @@ private boolean overrideFileFormParamTyping(CodegenOperation operation) {
284285
boolean changed = false;
285286
for (CodegenParameter param : operation.allParams) {
286287
if (param.isFormParam && param.isFile) {
287-
param.vendorExtensions.put("x-py-typing", param.required ? "UploadFile" : "Optional[UploadFile]");
288+
param.vendorExtensions.put(X_PY_TYPING, param.required ? "UploadFile" : "Optional[UploadFile]");
288289
changed = true;
289290
}
290291
}
291292
for (CodegenParameter param : operation.formParams) {
292293
if (param.isFile) {
293-
param.vendorExtensions.put("x-py-typing", param.required ? "UploadFile" : "Optional[UploadFile]");
294+
param.vendorExtensions.put(X_PY_TYPING, param.required ? "UploadFile" : "Optional[UploadFile]");
294295
}
295296
}
296297
return changed;
@@ -397,35 +398,35 @@ private Operation findOpenAPIOperation(CodegenOperation operation) {
397398
}
398399

399400
private void clearBodyParamExample(CodegenOperation operation) {
400-
operation.bodyParam.vendorExtensions.remove("x-py-example");
401-
operation.bodyParam.vendorExtensions.remove("x-py-fastapi-example");
401+
operation.bodyParam.vendorExtensions.remove(X_PY_EXAMPLE);
402+
operation.bodyParam.vendorExtensions.remove(X_PY_FASTAPI_EXAMPLE);
402403
for (CodegenParameter param : operation.allParams) {
403404
if (param.isBodyParam || Objects.equals(param.paramName, operation.bodyParam.paramName)) {
404-
param.vendorExtensions.remove("x-py-example");
405-
param.vendorExtensions.remove("x-py-fastapi-example");
405+
param.vendorExtensions.remove(X_PY_EXAMPLE);
406+
param.vendorExtensions.remove(X_PY_FASTAPI_EXAMPLE);
406407
}
407408
}
408409
for (CodegenParameter param : operation.bodyParams) {
409410
if (param.isBodyParam || Objects.equals(param.paramName, operation.bodyParam.paramName)) {
410-
param.vendorExtensions.remove("x-py-example");
411-
param.vendorExtensions.remove("x-py-fastapi-example");
411+
param.vendorExtensions.remove(X_PY_EXAMPLE);
412+
param.vendorExtensions.remove(X_PY_FASTAPI_EXAMPLE);
412413
}
413414
}
414415
}
415416

416417
private void setBodyParamExample(CodegenOperation operation, String example) {
417-
operation.bodyParam.vendorExtensions.remove("x-py-example");
418-
operation.bodyParam.vendorExtensions.put("x-py-fastapi-example", example);
418+
operation.bodyParam.vendorExtensions.remove(X_PY_EXAMPLE);
419+
operation.bodyParam.vendorExtensions.put(X_PY_FASTAPI_EXAMPLE, example);
419420
for (CodegenParameter param : operation.allParams) {
420421
if (param.isBodyParam || Objects.equals(param.paramName, operation.bodyParam.paramName)) {
421-
param.vendorExtensions.remove("x-py-example");
422-
param.vendorExtensions.put("x-py-fastapi-example", example);
422+
param.vendorExtensions.remove(X_PY_EXAMPLE);
423+
param.vendorExtensions.put(X_PY_FASTAPI_EXAMPLE, example);
423424
}
424425
}
425426
for (CodegenParameter param : operation.bodyParams) {
426427
if (param.isBodyParam || Objects.equals(param.paramName, operation.bodyParam.paramName)) {
427-
param.vendorExtensions.remove("x-py-example");
428-
param.vendorExtensions.put("x-py-fastapi-example", example);
428+
param.vendorExtensions.remove(X_PY_EXAMPLE);
429+
param.vendorExtensions.put(X_PY_FASTAPI_EXAMPLE, example);
429430
}
430431
}
431432
}

0 commit comments

Comments
 (0)