-
-
Notifications
You must be signed in to change notification settings - Fork 6.7k
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
[Python] add additionalProperties support, Option2 #2049
[Python] add additionalProperties support, Option2 #2049
Conversation
passed_type = self.recursive_type(value) | ||
if type(name) != str: | ||
raise TypeError('Variable name must be type string and %s was not' % name) | ||
elif passed_type != required_type and check_type: |
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.
Thank you very much for creating this pull request! I'm the author of #2028 and #2029 and I think the solution you have here is cleaner and more robust.
Just one minor issue I've noticed so far. I tested it with my use case of
additionalProperties:
type: "object"
which caused this error to be raised when doing model["foo"] = "bar"
with ValueError: Variable value must be type object but you passed in str
. It looks like the type checking isn't taking into account subclasses. I would really appreciate if you could address this use case. I would be happy to test for you as well.
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.
Hi Ivan. You're welcome. Thank you for yours. We both had the same idea to add a dict to store the values, this pull request just implemented it as a general case. Thanks for the heads up about that failing case. To fix it, I will add more samples. For the example you gave the code was right to raise an error, because you should have passed in:
model["foo"] = {"some_var": "bar"}
But the error message was wrong in the type that it was demanding. It should have wanted a dict rather than an object. We collapse complex schema types down elsewhere, so I will find that code and use it.
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.
The intent of additionalProperties with type object is that any value, regardless of type, is accepted. Upon review of the OpenAPI spec I should be using additionalProperties: true
to represent that intent (source: https://swagger.io/docs/specification/data-models/dictionaries/). I will try this case out for us.
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.
When additionalProperties: true
is used, the codegen treats it as if additionalProperties
is not enabled. I suspect that the fact that its type isn't defined causes it to be ignored.
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.
Ivan, what does inspecting the values in the openapi spec show when we set additionalProperties to either of the below values?
- additionalProperties: true
- additionalProperties: {}
If we see it in those results, we can handle it in the java code.
One can inspect the values in the openapi spec with the below line:
java -DdebugOpenAPI -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -t modules/openapi-generator/src/main/resources/python -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g python -o samples/client/petstore/python -DpackageName=petstore_api
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.
Ivan I am figuring out how to add this empty object -> all types.
This is also complicated by the fact that any type can have nullable set to true, which would mean that we could accept types like (string) (string OR None) or all the way up to (string, boolean, integer, float, list, dict, None).
For now I will leave nullable out because it is a 3.0 spec feature.
We still will have cases were "str|bool|int|float|list|dict" would be the type or you could have that nested as the innermost value in a nested list or dict schema, like:
dict(str, dict(str, str|bool|int|float|list|dict))
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.
@wing328 @ivan-gomes I am still working on this. Please refrain from merging until I have updated this PR. My update will include the type=object additionalProperties feature.
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.
Roger. Please let me know if there is anything I can do to help.
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.
@ivan-gomes will do.
Still to do is:
- Ensure deserialization works w/ tests (only file tests remaining)
- Fix the other language tests that I broke by changing the additionalpropertiesclass property names
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.
@wing328 @ivan-gomes I am nearing completion on this task.
To get this feature to work I added typing of all parameters and discriminators using real python classes and type checking. Soon I will get this PR submitted.
This is a big change and I welcome all feedback and discussion on it.
3f6d7b8
to
3901164
Compare
…er a variable name
…s on all model parameters
…use in model.to_dict and serialization
…aises ApiTypeError, openapi3 python nullable class tests added
… and code, partial work on api_client deserialization
…pi_client, tests not passing yet
Ran it against the API spec that caused me to create the issue, and it works great! Thanks so much for your effort. My humble opinion is that the changes involved are quite interconnected and trying to retroactively decouple them into separate PRs would be significant work with little practical purpose. |
Per a discussion with @wing328 this PR is a bit big. I will break it up to smaller pieces for ease of review. |
Hi @spacether, I have made some additional changes to make things work for (multi-level) inheritance: I use this in combination with #2170 to also make the With best regards, |
Thanks for doing that @tomghyselinck Can you explain how you can use vars rather than allvars in the model mustache file for allof models? |
Hi @spacether, Thank you for your quick response. Regarding the
|
Hi @spacether, I just want to let you know that there is still a problem with deserializing I have a quick and dirty workaround: There are two alternative workarounds (or solutions?) in this commit:
Both alternative changes trigger a warning With best regards, |
Thanks @tomghyselinck Or maybe we should keep enum only classes like shown here: https://docs.python.org/3/library/enum.html Some non-object models are:
Are we able to tell the difference between the three above 3 options from the current debugged model description? |
Thank you for the explanation. (I intended to ask if #1991 was the solution for this, but my comment was already in the air 🙂) |
Break out PR-statuses:
|
Hey @spacether! This is exactly the functionality I'm looking for in the codegen tools for the python client. I have a model defined with a couple of rigid properties, and then want to be able to support additional properties of a certain type. If that's not possible, then aliasing a |
Hey @mvrderese this PR is being broken up into smaller pieces so it is easier to review. I would welcome some help. If you want to collaborate please shoot me an email through the link at the bottom of my page here https://spacether.github.io/ |
Hi @spacether. Can we get an update on where we are on this feature? It addresses the last blocker I have on migrating a project to openapi-generator. |
Hey @ivan-gomes I am still working on this.
|
public String getTypeString(Schema p, String prefix, String suffix) { | ||
// this is used to set dataType, which defines a python tuple of classes | ||
String typeSuffix = suffix; | ||
if (suffix == ")") { |
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.
Please use ")".equals(suffix)
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.
Updated per feedback here https://github.com/spacether/openapi-generator/tree/issue_1991_uses_class_types
return prefix + "[" + getTypeString(inner, "(", ")") + "]" + typeSuffix; | ||
} | ||
String baseType = getSimpleTypeDeclaration(p); | ||
if (baseType == "file") { |
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.
There's no file
type in OAS v3 as it has been replaced by "type: string, format: binary".
What about using ModelUtils.isBinarySchema
to check 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.
This code only exists to handle v2 file schemas, so applying it to ModelUtils.isBinarySchema would target a different use case than we want. I am replacing this with ModelUtils.isFileSchema(p) here https://github.com/spacether/openapi-generator/tree/issue_1991_uses_class_types
|
||
@Override | ||
public String toInstantiationType(Schema property) { | ||
if (property instanceof ArraySchema || property instanceof MapSchema || property.getAdditionalProperties() != null) { |
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.
Please use ModelUtils.isArraySchema instead of property instanceof ArraySchema
. Same for the map schema check using instanceof at the moment.
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.
Implemented this feedback here https://github.com/spacether/openapi-generator/tree/issue_1991_uses_class_types
Unable to get necessary reviews and approvals on this PR and feature break out PRs. |
That is a real shame considering this is a very painful bug and you put a lot of work into fixing it. Is there anything that can be done? Tagging @wing328 for feedback as well. |
This is something that I really wanted to complete. |
The code in this PR was merged into master in the new generator python-experimental |
PR checklist
./bin/
to update Petstore sample so that CIs can verify the change. (For instance, only need to run./bin/{LANG}-petstore.sh
and./bin/security/{LANG}-petstore.sh
if updating the {LANG} (e.g. php, ruby, python, etc) code generator or {LANG} client's mustache templates). Windows batch files can be found in.\bin\windows\
.master
,. Default:3.4.x
,4.0.x
master
.@taxpon (2017/07) @frol (2017/07) @mbohlool (2017/07) @cbornet (2017/09) @kenjones-cisco (2017/11) @tomplus (2018/10) @Jyhess (2019/01)
Description of the PR
Issues that will be closed if this is merged:
New Changes
Breaking Changes:
Note:
This is an alternative solution to this PR: #2029