Skip to content
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 omitting read-only properties in requests #1161

Closed

Conversation

eli-bl
Copy link
Collaborator

@eli-bl eli-bl commented Nov 8, 2024

The client generator has so far ignored the readOnly attribute in schemas.

OpenAPI leaves the definition of this attribute somewhat vague: readOnly: true indicates that the server does not allow updates to this property in a request... but some servers might interpret that to mean that the property can be present in the request as long as its value is the same as a previous value, while others might not allow it to be present in the request at all.

This PR adds support for the latter case. If you set skip_sending_read_only_properties: true in your configuration, then any property with readOnly: true will be omitted from a schema if and only if it's being serialized inside a request body. This applies to both the request body schema itself, and any nested object schemas within it.

It touches a lot of files, but most of them are generated test code; the implementation is fairly simple.

First, we need to capture the readOnly attribute in parsing. Any property can be read-only, and since we're not using subclasses, this means adding the attribute to every __Property class. But we don't need logic to set it in every class, since there's nothing type-specific about it; we can just set it in property_from_data after building the property. (The same is true of description and example, so I considered refactoring to get those out of the builder methods, but that would blow up the scope of the PR.)

Now, how do we know when to_dict is being called for a request body, instead of in any other context? It would be undesirable for to_dict to always drop read-only properties, since an application could plausibly be using it for other purposes (like to store the output of a query). At first I thought of adding an optional parameter to to_dict—either just a "skip_read_only", or a more general "serialization context" object for future extensibility. Unfortunately, due to the many interactions between templates, this was impractical: the code that would be passing the parameter and the code that would be receiving it are in different templates, so if one of those is overridden with a custom template that doesn't have these changes, things would break.

So I went with a hacky solution: set the "this is a request body" mode globally. I used threading.local so it's thread-safe.

Also, while I was adding the extra to_dict logic in model.py.jinja, I saw an opportunity to clean up the output a bit. The logic is now more concise and, maybe more importantly, it no longer names temporary variables with property.python_name— so you can't have a collision between, for instance, our local variable field_dict and a property with the same name. I would've liked to do something similar in from_dict, but that would be harder because the variable naming logic for that is spread out through many templates.

@eli-bl eli-bl force-pushed the skip-read-only-properties branch from 90fded8 to b4dd779 Compare November 8, 2024 17:28
@eli-bl eli-bl marked this pull request as ready for review November 8, 2024 23:07
@eli-bl
Copy link
Collaborator Author

eli-bl commented Nov 12, 2024

Hmm... I'm closing this for now. In the specific use case that I had in mind, I'm not sure it would actually solve the problem (it turned out the server-side implementation was inconsistent, so omitting all read-only properties could break a different set of endpoints), and this is an area of OpenAPI that's so vaguely defined that people probably have a lot of different requirements and assumptions.

@eli-bl eli-bl closed this Nov 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant