-
Notifications
You must be signed in to change notification settings - Fork 153
Support oneOfs & anyOfs in operation request & response schema #701
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
Support oneOfs & anyOfs in operation request & response schema #701
Conversation
c87efb9 to
0a04571
Compare
| if properties is None: | ||
| return args | ||
|
|
||
| for k, v in properties.items(): | ||
| if v.type == "object" and not v.readOnly and v.properties: | ||
| # nested objects receive a prefix and are otherwise parsed normally | ||
| pref = prefix + "." + k if prefix else k | ||
|
|
||
| args += _parse_request_model( | ||
| v, | ||
| prefix=pref, | ||
| parent=parent, | ||
| # NOTE: We do not increment the depth because dicts do not have | ||
| # parent arguments. | ||
| depth=depth, | ||
| ) | ||
| elif ( | ||
| v.type == "array" | ||
| and v.items | ||
| and v.items.type == "object" | ||
| and v.extensions.get("linode-cli-format") != "json" | ||
| ): | ||
| # handle lists of objects as a special case, where each property | ||
| # of the object in the list is its own argument | ||
| pref = prefix + "." + k if prefix else k | ||
|
|
||
| # Support specifying this list as JSON | ||
| args.append( | ||
| OpenAPIRequestArg( | ||
| k, | ||
| v.items, | ||
| False, | ||
| prefix=prefix, | ||
| is_parent=True, | ||
| parent=parent, | ||
| # NOTE: We do not increment the depth because dicts do not have | ||
| # parent arguments. | ||
| depth=depth, | ||
| ) | ||
| elif ( | ||
| v.type == "array" | ||
| and v.items | ||
| and v.items.type == "object" | ||
| and v.extensions.get("linode-cli-format") != "json" | ||
| ): | ||
| # handle lists of objects as a special case, where each property | ||
| # of the object in the list is its own argument | ||
| pref = prefix + "." + k if prefix else k | ||
|
|
||
| # Support specifying this list as JSON | ||
| args.append( | ||
| OpenAPIRequestArg( | ||
| k, | ||
| v.items, | ||
| False, | ||
| prefix=prefix, | ||
| is_parent=True, | ||
| parent=parent, | ||
| depth=depth, | ||
| ) | ||
| ) | ||
| ) | ||
|
|
||
| args += _parse_request_model( | ||
| v.items, | ||
| prefix=pref, | ||
| parent=pref, | ||
| depth=depth + 1, | ||
| ) | ||
| else: | ||
| # required fields are defined in the schema above the property, so | ||
| # we have to check here if required fields are defined/if this key | ||
| # is among them and pass it into the OpenAPIRequestArg class. | ||
| required = False | ||
| if schema.required: | ||
| required = k in schema.required | ||
| args.append( | ||
| OpenAPIRequestArg( | ||
| k, | ||
| v, | ||
| required, | ||
| prefix=prefix, | ||
| parent=parent, | ||
| depth=depth, | ||
| ) | ||
| args += _parse_request_model( | ||
| v.items, | ||
| prefix=pref, | ||
| parent=pref, | ||
| depth=depth + 1, | ||
| ) | ||
| else: | ||
| # required fields are defined in the schema above the property, so | ||
| # we have to check here if required fields are defined/if this key | ||
| # is among them and pass it into the OpenAPIRequestArg class. | ||
| required = False | ||
| if schema.required: | ||
| required = k in schema.required | ||
| args.append( | ||
| OpenAPIRequestArg( | ||
| k, | ||
| v, | ||
| required, | ||
| prefix=prefix, | ||
| parent=parent, | ||
| depth=depth, | ||
| ) | ||
| ) | ||
|
|
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 logic is all the same, I just replaced the wrapping if statement with a guard clause
| if ( | ||
| v.type == "object" | ||
| and not v.readOnly | ||
| and len(_aggregate_schema_properties(v)[0]) > 0 |
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 is necessary to account for nested anyOfs and oneOfs.
jriddle-linode
left a comment
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.
Working locally, looks good to me!
zliang-akamai
left a comment
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.
Tested and looks good to me!
📝 Description
This pull request adds support for parsing OpenAPI oneOfs and anyOfs in both the request and response schema for operations.
Additionally, this PR adds support for rendering each root-level request oneOf separate section in the generated command help pages.
✔️ How to Test
The following test steps assume you have pulled down this pull request locally and run the following command:
make SPEC='https://gist.githubusercontent.com/lgarber-akamai/07485a643e8329a5c16bec775e8066c4/raw/56f4491ba6e239c9cad736f05ff2d1ab0608098c/openapi.json' installNOTE: The overridden specification is necessary because the currently published OpenAPI specification does not yet make use of oneOfs.
Unit Testing
Integration Testing
Manual Testing
nodebalancers config-createcommand:MYIDHEREwith the ID of the newly created NodeBalancer:📷 Preview
Improved Help Page