From a5975ef18e047479fc987c1c54f59d080e17b9e8 Mon Sep 17 00:00:00 2001 From: 0xMattijs Date: Fri, 3 May 2024 20:36:13 +0200 Subject: [PATCH] Fix the post processing of enums in the Python generator, such that it uses the proper variable namesfrom x-enum-varnames Remove sample --- .../languages/AbstractPythonCodegen.java | 5 +++- ...ith-fake-endpoints-models-for-testing.yaml | 29 +++++++++++++++++++ .../petstore/python-aiohttp/docs/EnumTest.md | 2 ++ .../petstore_api/models/enum_test.py | 26 ++++++++++++++++- .../docs/EnumTest.md | 2 ++ .../petstore_api/models/enum_test.py | 26 ++++++++++++++++- .../python-pydantic-v1/docs/EnumTest.md | 2 ++ .../petstore_api/models/enum_test.py | 26 ++++++++++++++++- .../client/petstore/python/docs/EnumTest.md | 2 ++ .../python/petstore_api/models/enum_test.py | 26 ++++++++++++++++- 10 files changed, 141 insertions(+), 5 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonCodegen.java index 7808c7ffb29a..36b74be9578b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonCodegen.java @@ -992,7 +992,10 @@ private ModelsMap postProcessModelsMap(ModelsMap objs) { enumVars.put("name", toEnumVariableName((String) enumVars.get("value"), "str")); } else { model.vendorExtensions.putIfAbsent("x-py-enum-type", "int"); - enumVars.put("name", toEnumVariableName((String) enumVars.get("value"), "int")); + // Do not overwrite the variable name if already set through x-enum-varnames + if (model.vendorExtensions.get("x-enum-varnames") == null) { + enumVars.put("name", toEnumVariableName((String) enumVars.get("value"), "int")); + } } } } diff --git a/modules/openapi-generator/src/test/resources/3_0/python/petstore-with-fake-endpoints-models-for-testing.yaml b/modules/openapi-generator/src/test/resources/3_0/python/petstore-with-fake-endpoints-models-for-testing.yaml index f092a7acc6e9..7f5925943583 100644 --- a/modules/openapi-generator/src/test/resources/3_0/python/petstore-with-fake-endpoints-models-for-testing.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/python/petstore-with-fake-endpoints-models-for-testing.yaml @@ -2060,6 +2060,35 @@ components: enum: - 1.1 - -1.2 + enum_number_vendor_ext: + type: integer + format: int32 + enum: + - 42 + - 18 + - 56 + x-enum-descriptions: + - 'Description for 42' + - 'Description for 18' + - 'Description for 56' + x-enum-varnames: + - FortyTwo + - Eigtheen + - FiftySix + enum_string_vendor_ext: + type: string + enum: + - FOO + - Bar + - baz + x-enum-descriptions: + - 'Description for FOO' + - 'Description for Bar' + - 'Description for baz' + x-enum-varnames: + - FOOVar + - BarVar + - bazVar outerEnum: $ref: '#/components/schemas/OuterEnum' outerEnumInteger: diff --git a/samples/openapi3/client/petstore/python-aiohttp/docs/EnumTest.md b/samples/openapi3/client/petstore/python-aiohttp/docs/EnumTest.md index d875c67604cf..dd37f9cc7b4c 100644 --- a/samples/openapi3/client/petstore/python-aiohttp/docs/EnumTest.md +++ b/samples/openapi3/client/petstore/python-aiohttp/docs/EnumTest.md @@ -10,6 +10,8 @@ Name | Type | Description | Notes **enum_integer_default** | **int** | | [optional] [default to 5] **enum_integer** | **int** | | [optional] **enum_number** | **float** | | [optional] +**enum_number_vendor_ext** | **int** | | [optional] +**enum_string_vendor_ext** | **str** | | [optional] **outer_enum** | [**OuterEnum**](OuterEnum.md) | | [optional] **outer_enum_integer** | [**OuterEnumInteger**](OuterEnumInteger.md) | | [optional] **outer_enum_default_value** | [**OuterEnumDefaultValue**](OuterEnumDefaultValue.md) | | [optional] diff --git a/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/enum_test.py b/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/enum_test.py index 820879b30e4a..1e65d8a80185 100644 --- a/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/enum_test.py +++ b/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/enum_test.py @@ -35,11 +35,13 @@ class EnumTest(BaseModel): enum_integer_default: Optional[StrictInt] = 5 enum_integer: Optional[StrictInt] = None enum_number: Optional[float] = None + enum_number_vendor_ext: Optional[StrictInt] = None + enum_string_vendor_ext: Optional[StrictStr] = None outer_enum: Optional[OuterEnum] = Field(default=None, alias="outerEnum") outer_enum_integer: Optional[OuterEnumInteger] = Field(default=None, alias="outerEnumInteger") outer_enum_default_value: Optional[OuterEnumDefaultValue] = Field(default=None, alias="outerEnumDefaultValue") outer_enum_integer_default_value: Optional[OuterEnumIntegerDefaultValue] = Field(default=None, alias="outerEnumIntegerDefaultValue") - __properties: ClassVar[List[str]] = ["enum_string", "enum_string_required", "enum_integer_default", "enum_integer", "enum_number", "outerEnum", "outerEnumInteger", "outerEnumDefaultValue", "outerEnumIntegerDefaultValue"] + __properties: ClassVar[List[str]] = ["enum_string", "enum_string_required", "enum_integer_default", "enum_integer", "enum_number", "enum_number_vendor_ext", "enum_string_vendor_ext", "outerEnum", "outerEnumInteger", "outerEnumDefaultValue", "outerEnumIntegerDefaultValue"] @field_validator('enum_string') def enum_string_validate_enum(cls, value): @@ -88,6 +90,26 @@ def enum_number_validate_enum(cls, value): raise ValueError("must be one of enum values (1.1, -1.2)") return value + @field_validator('enum_number_vendor_ext') + def enum_number_vendor_ext_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in set([42, 18, 56]): + raise ValueError("must be one of enum values (42, 18, 56)") + return value + + @field_validator('enum_string_vendor_ext') + def enum_string_vendor_ext_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in set(['FOO', 'Bar', 'baz']): + raise ValueError("must be one of enum values ('FOO', 'Bar', 'baz')") + return value + model_config = ConfigDict( populate_by_name=True, validate_assignment=True, @@ -149,6 +171,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "enum_integer_default": obj.get("enum_integer_default") if obj.get("enum_integer_default") is not None else 5, "enum_integer": obj.get("enum_integer"), "enum_number": obj.get("enum_number"), + "enum_number_vendor_ext": obj.get("enum_number_vendor_ext"), + "enum_string_vendor_ext": obj.get("enum_string_vendor_ext"), "outerEnum": obj.get("outerEnum"), "outerEnumInteger": obj.get("outerEnumInteger"), "outerEnumDefaultValue": obj.get("outerEnumDefaultValue"), diff --git a/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/docs/EnumTest.md b/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/docs/EnumTest.md index 6dee11438f2d..15d7a6539f94 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/docs/EnumTest.md +++ b/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/docs/EnumTest.md @@ -9,6 +9,8 @@ Name | Type | Description | Notes **enum_integer_default** | **int** | | [optional] [default to 5] **enum_integer** | **int** | | [optional] **enum_number** | **float** | | [optional] +**enum_number_vendor_ext** | **int** | | [optional] +**enum_string_vendor_ext** | **str** | | [optional] **outer_enum** | [**OuterEnum**](OuterEnum.md) | | [optional] **outer_enum_integer** | [**OuterEnumInteger**](OuterEnumInteger.md) | | [optional] **outer_enum_default_value** | [**OuterEnumDefaultValue**](OuterEnumDefaultValue.md) | | [optional] diff --git a/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/enum_test.py b/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/enum_test.py index 5630ebfa1a30..66c688f9f484 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/enum_test.py +++ b/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/enum_test.py @@ -34,11 +34,13 @@ class EnumTest(BaseModel): enum_integer_default: Optional[StrictInt] = 5 enum_integer: Optional[StrictInt] = None enum_number: Optional[float] = None + enum_number_vendor_ext: Optional[StrictInt] = None + enum_string_vendor_ext: Optional[StrictStr] = None outer_enum: Optional[OuterEnum] = Field(default=None, alias="outerEnum") outer_enum_integer: Optional[OuterEnumInteger] = Field(default=None, alias="outerEnumInteger") outer_enum_default_value: Optional[OuterEnumDefaultValue] = Field(default=None, alias="outerEnumDefaultValue") outer_enum_integer_default_value: Optional[OuterEnumIntegerDefaultValue] = Field(default=None, alias="outerEnumIntegerDefaultValue") - __properties = ["enum_string", "enum_string_required", "enum_integer_default", "enum_integer", "enum_number", "outerEnum", "outerEnumInteger", "outerEnumDefaultValue", "outerEnumIntegerDefaultValue"] + __properties = ["enum_string", "enum_string_required", "enum_integer_default", "enum_integer", "enum_number", "enum_number_vendor_ext", "enum_string_vendor_ext", "outerEnum", "outerEnumInteger", "outerEnumDefaultValue", "outerEnumIntegerDefaultValue"] @validator('enum_string') def enum_string_validate_enum(cls, value): @@ -87,6 +89,26 @@ def enum_number_validate_enum(cls, value): raise ValueError("must be one of enum values (1.1, -1.2)") return value + @validator('enum_number_vendor_ext') + def enum_number_vendor_ext_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in (42, 18, 56): + raise ValueError("must be one of enum values (42, 18, 56)") + return value + + @validator('enum_string_vendor_ext') + def enum_string_vendor_ext_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in ('FOO', 'Bar', 'baz'): + raise ValueError("must be one of enum values ('FOO', 'Bar', 'baz')") + return value + class Config: """Pydantic configuration""" allow_population_by_field_name = True @@ -133,6 +155,8 @@ def from_dict(cls, obj: dict) -> EnumTest: "enum_integer_default": obj.get("enum_integer_default") if obj.get("enum_integer_default") is not None else 5, "enum_integer": obj.get("enum_integer"), "enum_number": obj.get("enum_number"), + "enum_number_vendor_ext": obj.get("enum_number_vendor_ext"), + "enum_string_vendor_ext": obj.get("enum_string_vendor_ext"), "outer_enum": obj.get("outerEnum"), "outer_enum_integer": obj.get("outerEnumInteger"), "outer_enum_default_value": obj.get("outerEnumDefaultValue"), diff --git a/samples/openapi3/client/petstore/python-pydantic-v1/docs/EnumTest.md b/samples/openapi3/client/petstore/python-pydantic-v1/docs/EnumTest.md index 6dee11438f2d..15d7a6539f94 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1/docs/EnumTest.md +++ b/samples/openapi3/client/petstore/python-pydantic-v1/docs/EnumTest.md @@ -9,6 +9,8 @@ Name | Type | Description | Notes **enum_integer_default** | **int** | | [optional] [default to 5] **enum_integer** | **int** | | [optional] **enum_number** | **float** | | [optional] +**enum_number_vendor_ext** | **int** | | [optional] +**enum_string_vendor_ext** | **str** | | [optional] **outer_enum** | [**OuterEnum**](OuterEnum.md) | | [optional] **outer_enum_integer** | [**OuterEnumInteger**](OuterEnumInteger.md) | | [optional] **outer_enum_default_value** | [**OuterEnumDefaultValue**](OuterEnumDefaultValue.md) | | [optional] diff --git a/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/enum_test.py b/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/enum_test.py index 7595ca667389..a04be47a43fb 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/enum_test.py +++ b/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/enum_test.py @@ -34,12 +34,14 @@ class EnumTest(BaseModel): enum_integer_default: Optional[StrictInt] = 5 enum_integer: Optional[StrictInt] = None enum_number: Optional[StrictFloat] = None + enum_number_vendor_ext: Optional[StrictInt] = None + enum_string_vendor_ext: Optional[StrictStr] = None outer_enum: Optional[OuterEnum] = Field(default=None, alias="outerEnum") outer_enum_integer: Optional[OuterEnumInteger] = Field(default=None, alias="outerEnumInteger") outer_enum_default_value: Optional[OuterEnumDefaultValue] = Field(default=None, alias="outerEnumDefaultValue") outer_enum_integer_default_value: Optional[OuterEnumIntegerDefaultValue] = Field(default=None, alias="outerEnumIntegerDefaultValue") additional_properties: Dict[str, Any] = {} - __properties = ["enum_string", "enum_string_required", "enum_integer_default", "enum_integer", "enum_number", "outerEnum", "outerEnumInteger", "outerEnumDefaultValue", "outerEnumIntegerDefaultValue"] + __properties = ["enum_string", "enum_string_required", "enum_integer_default", "enum_integer", "enum_number", "enum_number_vendor_ext", "enum_string_vendor_ext", "outerEnum", "outerEnumInteger", "outerEnumDefaultValue", "outerEnumIntegerDefaultValue"] @validator('enum_string') def enum_string_validate_enum(cls, value): @@ -88,6 +90,26 @@ def enum_number_validate_enum(cls, value): raise ValueError("must be one of enum values (1.1, -1.2)") return value + @validator('enum_number_vendor_ext') + def enum_number_vendor_ext_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in (42, 18, 56): + raise ValueError("must be one of enum values (42, 18, 56)") + return value + + @validator('enum_string_vendor_ext') + def enum_string_vendor_ext_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in ('FOO', 'Bar', 'baz'): + raise ValueError("must be one of enum values ('FOO', 'Bar', 'baz')") + return value + class Config: """Pydantic configuration""" allow_population_by_field_name = True @@ -140,6 +162,8 @@ def from_dict(cls, obj: dict) -> EnumTest: "enum_integer_default": obj.get("enum_integer_default") if obj.get("enum_integer_default") is not None else 5, "enum_integer": obj.get("enum_integer"), "enum_number": obj.get("enum_number"), + "enum_number_vendor_ext": obj.get("enum_number_vendor_ext"), + "enum_string_vendor_ext": obj.get("enum_string_vendor_ext"), "outer_enum": obj.get("outerEnum"), "outer_enum_integer": obj.get("outerEnumInteger"), "outer_enum_default_value": obj.get("outerEnumDefaultValue"), diff --git a/samples/openapi3/client/petstore/python/docs/EnumTest.md b/samples/openapi3/client/petstore/python/docs/EnumTest.md index d875c67604cf..dd37f9cc7b4c 100644 --- a/samples/openapi3/client/petstore/python/docs/EnumTest.md +++ b/samples/openapi3/client/petstore/python/docs/EnumTest.md @@ -10,6 +10,8 @@ Name | Type | Description | Notes **enum_integer_default** | **int** | | [optional] [default to 5] **enum_integer** | **int** | | [optional] **enum_number** | **float** | | [optional] +**enum_number_vendor_ext** | **int** | | [optional] +**enum_string_vendor_ext** | **str** | | [optional] **outer_enum** | [**OuterEnum**](OuterEnum.md) | | [optional] **outer_enum_integer** | [**OuterEnumInteger**](OuterEnumInteger.md) | | [optional] **outer_enum_default_value** | [**OuterEnumDefaultValue**](OuterEnumDefaultValue.md) | | [optional] diff --git a/samples/openapi3/client/petstore/python/petstore_api/models/enum_test.py b/samples/openapi3/client/petstore/python/petstore_api/models/enum_test.py index 0472b7b29813..bd4e77461346 100644 --- a/samples/openapi3/client/petstore/python/petstore_api/models/enum_test.py +++ b/samples/openapi3/client/petstore/python/petstore_api/models/enum_test.py @@ -35,12 +35,14 @@ class EnumTest(BaseModel): enum_integer_default: Optional[StrictInt] = 5 enum_integer: Optional[StrictInt] = None enum_number: Optional[StrictFloat] = None + enum_number_vendor_ext: Optional[StrictInt] = None + enum_string_vendor_ext: Optional[StrictStr] = None outer_enum: Optional[OuterEnum] = Field(default=None, alias="outerEnum") outer_enum_integer: Optional[OuterEnumInteger] = Field(default=None, alias="outerEnumInteger") outer_enum_default_value: Optional[OuterEnumDefaultValue] = Field(default=None, alias="outerEnumDefaultValue") outer_enum_integer_default_value: Optional[OuterEnumIntegerDefaultValue] = Field(default=None, alias="outerEnumIntegerDefaultValue") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["enum_string", "enum_string_required", "enum_integer_default", "enum_integer", "enum_number", "outerEnum", "outerEnumInteger", "outerEnumDefaultValue", "outerEnumIntegerDefaultValue"] + __properties: ClassVar[List[str]] = ["enum_string", "enum_string_required", "enum_integer_default", "enum_integer", "enum_number", "enum_number_vendor_ext", "enum_string_vendor_ext", "outerEnum", "outerEnumInteger", "outerEnumDefaultValue", "outerEnumIntegerDefaultValue"] @field_validator('enum_string') def enum_string_validate_enum(cls, value): @@ -89,6 +91,26 @@ def enum_number_validate_enum(cls, value): raise ValueError("must be one of enum values (1.1, -1.2)") return value + @field_validator('enum_number_vendor_ext') + def enum_number_vendor_ext_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in set([42, 18, 56]): + raise ValueError("must be one of enum values (42, 18, 56)") + return value + + @field_validator('enum_string_vendor_ext') + def enum_string_vendor_ext_validate_enum(cls, value): + """Validates the enum""" + if value is None: + return value + + if value not in set(['FOO', 'Bar', 'baz']): + raise ValueError("must be one of enum values ('FOO', 'Bar', 'baz')") + return value + model_config = ConfigDict( populate_by_name=True, validate_assignment=True, @@ -157,6 +179,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "enum_integer_default": obj.get("enum_integer_default") if obj.get("enum_integer_default") is not None else 5, "enum_integer": obj.get("enum_integer"), "enum_number": obj.get("enum_number"), + "enum_number_vendor_ext": obj.get("enum_number_vendor_ext"), + "enum_string_vendor_ext": obj.get("enum_string_vendor_ext"), "outerEnum": obj.get("outerEnum"), "outerEnumInteger": obj.get("outerEnumInteger"), "outerEnumDefaultValue": obj.get("outerEnumDefaultValue"),