allow omitting read-only properties in requests #1161
Closed
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 withreadOnly: 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 inproperty_from_data
after building the property. (The same is true ofdescription
andexample
, 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 forto_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 toto_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 inmodel.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 withproperty.python_name
— so you can't have a collision between, for instance, our local variablefield_dict
and a property with the same name. I would've liked to do something similar infrom_dict
, but that would be harder because the variable naming logic for that is spread out through many templates.