-
-
Notifications
You must be signed in to change notification settings - Fork 227
fix: Allow None in enum properties #512
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
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 = None In 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] = UNSET In 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:
- null The 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:
- null NullEnum 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.