[BUG] [Python] Model initialization does not accept iterable postitional arguments
Created by: ckoegel
Bug Report Checklist
-
Have you provided a full/minimal spec to reproduce the issue? -
Have you validated the input using an OpenAPI validator (example)? -
Have you tested with the latest master to confirm the issue still exists? -
Have you searched for related issues/PRs? -
What's the actual output vs expected output? -
[Optional] Sponsorship to speed up the bug fix or feature request (example)
Description
When generating models from openapi schemas, these objects do not accept iterable objects for initializing new instances. The init
function accepts both *args
and **kwargs
, but the file invalid_pos_args.mustache
causes an ApiTypeError
if any *args
are passed in.
openapi-generator version
0.5.3
OpenAPI declaration file content or url
https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/resources/python/model_templates/invalid_pos_args.mustache https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/resources/python/model_templates/model_normal.mustache
Generation Details
using the spec at https://github.com/Bandwidth/api-docs/blob/main/site/specs-source/messaging.json and generating using openapi-generator-cli generate -g python -i messaging.json -o ./msg-test
allows for viewing the generated SDK,
Steps to reproduce
After generating, attempting to create a BandwidthCallbackMessage by passing in a dict, ex: BandwidthCallbackMessage(my_dict)
causes the ApiTypeError "Invalid positional arguments...". This can be avoided by using **kwargs
, ex: BandwidthCallbackMessage(**my_dict)
, but since the message attribute is also an object (BandwidthMessage), the same issue arises, nested in the creation of BandwidthCallbackMessage, and the error is thrown anyway.
Related issues/PRs
None
Suggest a fix
By creating the instance of BandwidthCallbackMessage using BandwidthCallbackMessage(**my_dict), and then putting the code below inside the for var_name, var_vlaue in kwargs.items():
loop inside the init function of the generated model file, I was able to generate both objects successfully.
if var_name not in self.attribute_map and \
self._configuration is not None and \
self._configuration.discard_unknown_keys and \
self.additional_properties_type is None:
# discard variable.
continue
if var_name == "message":
setattr(self, var_name, BandwidthMessage(**var_value))
else:
setattr(self, var_name, var_value)
if var_name in self.read_only_vars:
raise ApiAttributeError(f"`{var_name}` is a read-only attribute. Use `from_openapi_data` to instantiate "
f"class with read only attributes.")
This solution is honestly horrendous and only works for this very specific use case, but shows that it can be done. I will be attempting to modify the logic inside the if args:
statement in the same file to recursively check for objects in the args field and convert them to kwargs to be set normally. This solution should allow for a much more standardized solution to the issue. I'll be making a PR with my progress on this.