-
-
Notifications
You must be signed in to change notification settings - Fork 227
feat: add literal_enums setting to produce Literal[...] instead of enum classes. #1114
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
This looks great, thanks! Also related is #1076, though that one didn't provide a config option and didn't use the literals in the endpoint code, just added it as an additional generated piece. I think I like this approach better—where the style is selected and only one or the other is generated, rather than both. I guess we'll need another new snapshot test for this style—probably a brand new OpenAPI document rather than keeping another variant of the massive I do think the more granular controls could also be good in the future. Someone might like to generate most of their enums as enum classes, but then opt in to Literal for a few that can't map well. |
This PR also unblocked our generation of:
which errors with:
Thanks! |
@dbanty I think this should be ready to merge so long as you're happy with how I implemented it. Fixing the various type errors in the generated code uncovered quite a few bugs in my code and a possibility of non-deterministic output due to ruff making different choices depending on the ordering of imports when one of them is unused. I added a parse-time check that the value is in the enum so that it will be equally as strict as regular enums. |
I merged in main and have |
Ok, now I've actually tested with Python 3.8 and fixed the last few usages typing features that are only available from Python 3.10. Everything should pass this time. |
I know I'm commenting a bit late, but... I'm trying to understand the decision to make this a whole new class, instead of adding an attribute to |
@eli-bl I didn't think very hard about this at the time because I wasn't yet thinking about contributing it upstream. If I remember correctly, the main reason I didn't use At the end of the day, I've spent about as much time as I can justify on getting this upstreamed. If someone wants to take it in a different direction I won't be offended but I don't have time to make a big change like unifying the two classes. Either way, I would really like for this feature to be accepted in some form! |
@dbanty Test coverage is now 100% except the |
This is just #1114 but with some docs & changeset --------- Co-authored-by: Eitan Mosenkis <[email protected]> Co-authored-by: Eitan Mosenkis <[email protected]> Co-authored-by: Dylan Anthony <[email protected]>
Thank you so much for this! I had to update a snapshot and I added a mention to the readme both over in #1142—which is merged! This fixes an issue that's clearly bumped into a lot given the number of attempts at solving it 😅. |
> [!IMPORTANT] > Merging this pull request will create this release ## Features - update Ruff to >=0.2,<0.8 (#1137) - Add UUID string format. Thanks @estyrke! (#1140) - Support OpenAPI 3.1 prefixItems property for arrays. Thanks @estyrke! (#1141) ### Add `literal_enums` config setting Instead of the default `Enum` classes for enums, you can now generate `Literal` sets wherever `enum` appears in the OpenAPI spec by setting `literal_enums: true` in your config file. ```yaml literal_enums: true ``` Thanks to @emosenkis for PR #1114 closes #587, #725, #1076, and probably many more. Thanks also to @eli-bl, @expobrain, @theorm, @chrisguillory, and anyone else who helped getting to this design! ## Fixes - Typo in docstring (#1128) ### Use literal value instead of `HTTPStatus` enum when checking response statuses Python 3.13 renamed some of the `HTTPStatus` enum members, which means clients generated with Python 3.13 may not work with older versions of Python. This change stops using the `HTTPStatus` enum directly when checking response statuses. Statuses will still be checked for validity at generation time, and transformed into `HTTPStatus` _after_ being checked at runtime. This may cause some linters to complain. Co-authored-by: knope-bot[bot] <152252888+knope-bot[bot]@users.noreply.github.com>
While attempting to generate a client for https://api.railz.ai/swagger/v2, I ran into duplicate enum values. I tried using the fixes from #725 and #1095 but neither was sufficient because while some duplicates result from case insensitivity, others result from characters (e.g.
+
) that are stripped when generating the Python name for the value. Allowing enums to be implemented asLiteral
s provides a good alternative that should result in more readable code when an API defines enums that really are a collection of possible values not amenable to representation as a Python enum.This solution works for me and if you're amenable to the idea, I can add tests, etc. to get it ready for merging. Down the line, I can imagine allowing more configuration options, such as using literal enums only for int enums, only for enums with duplicate values, or only for enums that match a regex but I don't know if you're interested in allowing that sort of granular configuration of generated types.