fix: Allow None in enum properties#512
fix: Allow None in enum properties#512juspence wants to merge 2 commits intoopenapi-generators:mainfrom juspence:main
Conversation
Needed for some OpenAPI schemas generated by django-rest-framework / drf-spectacular.
|
Thanks for throwing this together. Could you create an e2e test so we can see how this looks with generated code? Instructions are in the CONTRIBUTING.md. I'm worried that the output will confuse type checkers if it's something like: class SomeEnum(str, Enum):
VALUE = "VALUE"
NONE = NoneIn which case, a better approach might be to ignore the None as an Enum value and instead force the property to be Nullable. So you'd get something like this: class ObjThatUsesEnum:
enum_prop: Optional[SomeEnum]And then users would input |
|
Sure, I can throw a test together hopefully tomorrow. I did test the new code with our OpenAPI schema that was breaking before. Now it generates code like below: from enum import Enum
class NullEnum(str, Enum):
VALUE_0 = "None"
def __str__(self) -> str:
return str(self.value)And then the fields that use this enum look like below: field_name: Union[BlankEnum, FieldNameEnum, None, NullEnum, Unset] = UNSETIn our case Django is auto-generating an enum with only one possible value (null / None). I think this is because we have null=True, blank=True on certain model fields. So we end up with NullEnum (only supported value is null) to handle a model field that's null, and BlankEnum (only supported value is "") to handle a model field that's blank. The fact these appear at all is probably a bug in drf-spectacular that autogenerates the OpenAPI schema, but for now I think we're stuck with it. Details from #504: Client generation fails if an enum like below is present in the generated OpenAPI schema. NullEnum:
enum:
- nullThe context here is that we have a Django model with char / text fields that have null=True, blank=True set. We use Django Rest Framework / drf-spectacular to generate an OpenAPI schema from our models and REST API endpoints. This generated schema automatically includes logic like below: ModelName:
type: object
description: ModelName serializer
properties:
field_name:
nullable: true
oneOf:
- $ref: '#/components/schemas/FieldNameEnum'
- $ref: '#/components/schemas/BlankEnum'
- $ref: '#/components/schemas/NullEnum'FieldNameEnum, BlankEnum, and NullEnum are like below: FieldNameEnum:
enum:
- stringvalue1
- stringvalue2
type: string
BlankEnum:
enum:
- ''
NullEnum:
enum:
- nullNullEnum accepts a literal null / None, not a string "null" (it's not a string enum). |
|
Interesting, the generated code you put above has the string "None" which wouldn't be the valid value it's expecting I think. |
For enums which only allow None, add new null_enum.py.jinja template For enums with mixed values, add logic to remove None from list Mark enum property as nullable if None isn't the only value Add tests for enums with mixed values and only null values TODO: Make the type checker stop failing, but PTO next week
|
@dbanty For our use case, we have enums with only 1 value, a literal None. So we can't remove this value and make the enum optional. I also added tests, which generate the right code as far as I can tell, but the type checker is reporting an error somewhere. I will be on PTO next week so I ran out of time to get that fixed. |
|
Thanks for all the work on this @juspence! I'm finishing it off in #516 by fixing some tests and simplifying the implementation a bit (I think). Instead of generating an enum with only one |
Needed for some OpenAPI schemas generated by django-rest-framework / drf-spectacular.