- Sponsor
-
Notifications
You must be signed in to change notification settings - Fork 227
Allow case sensitive enum values #725
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
Allow case sensitive enum values #725
Conversation
Codecov Report
@@ Coverage Diff @@
## main #725 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 49 49
Lines 1971 1976 +5
=========================================
+ Hits 1971 1976 +5
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
openapi_python_client/utils.py
Outdated
@@ -66,10 +66,19 @@ def fix_reserved_words(value: str) -> str: | |||
return value | |||
|
|||
|
|||
def case_insensitive_snake_case(value: str) -> str: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be called case_sensitive_snake_case
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, fixed
I had submitted #1095 before seeing that this fixes the same issue. I've closed mine, but it did include one other change that I think might be good to add to this PR: skipping duplicate values. It is totally valid in OpenAPI (though pointless) to have a list of enum values like |
Also, if I understand correctly, the only reason this PR is flagged as "breaking" is the change to the prefix logic (VALUE_, LITERAL_). I agree with the rationale behind that change, but to avoid unnecessarily breaking people's code that is relying on the current behavior, maybe it would be best to make that part an opt-in via a config option? |
63859f4
to
bd77766
Compare
bd77766
to
5560f54
Compare
@eli-bl about your comments above:
|
I see the new config option, but it looks to me like you're only using it to control the new case-sensitivity behavior. The other new behavior you added was using (Btw, you've added me as a reviewer but I'm not a maintainer of the repo, just someone else who has submitted PRs; I commented on this one because I had started working on the same thing before I saw yours) |
And... at the risk of being nitpicky and overthinking things, I do have some other thoughts about the VALUE_ vs. LITERAL_ thing. First, I do think that it should be a config option because it's a breaking change... but it really doesn't have anything to do with case-sensitivity. It's just that you happened to implement it in the same PR. If I were someone trying to use the generator and having this Second, although your decision to use I don't feel super strongly about this, and I'm guessing that "string property whose allowable values all start with digits" is not a very common pattern anyway, but if you think I have a point, one way you could address it would be something like:
So, this would be a bigger breaking change in the sense that my Of course none of these approaches can really avoid all collisions, since someone could have actual enum values that are equal to ps. There's also a way that you could avoid having to have a config option for the case-sensitivity part: turn on the case-sensitive enum behavior only if you detect that there would be conflicts otherwise. That is, take a pass through the list and see if there are any pairs like |
> [!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>
Superceded by #1114, which I think will add enough flexibility for anyone who needs it. Thanks for this early version! |
How to judge "enough flexibility" is subjective of course, but for what it's worth, here are two counter-arguments for why #1114 could still be desirable.
|
Totally fair, and ideally we could enhance this option to be applicable to individual enums, rather than only globally. Maybe a match on $ref would be enough?
Unfortunately it's not possible to render every OpenAPI document into idiomatic Python. For example, enum variants should, idiomatically, be screaming snake case. But obviously that auto-conversion doesn't always work. It's possible we could allow one-off variant name overrides in another separate config so that folks can produce idiomatic Python values. Ideally, they'd also be able to use this to explain to consumers why "A" is different than "a". |
Sure, I get that. OpenAPI doesn't align smoothly with Python or lots of other languages, and the generator can't be expected to cover every use case in a way that'll please everyone. And the literal enum option is useful. I should've made it clearer that what I'm arguing for is just a little more granularity in this feature. That was brought up early on, but then your latest comment suggested that just being able to turn it on or off globally was enough flexibility... so what I was getting at was that a lot of people have gotten used to using the formal enum class pattern, and I would find it hard to explain to them why they have to stop using it for 99% of my API because there is 1% that it wouldn't be a good fit for. |
Added setting
case_sensitive_enums
to allow case sensitive enum values in the generated code.This solve the issue in #587 .
Also, to avoid collisions, changes the prefix for values not starting with alphanumeric characters from
VALUE_
toLITERAL_
.How could it happen
Consider the case
[1, "1bc"]
, the previous code would assign the enumVALUE_1
to the first item (aka theVALUE_
prefix plus the int value of the item) and the same enumVALUE_1
for the second item (the prefixVALUE_
plus the position of the non-alphanumeric value in the list).The new code avoids that and use different prefixes for integer values (
VALUE_{value}
) and string starting with non-alphanumeric characters (LITERAL_{sanitised_value}
).