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

[BUG][Python] oneOf (with multi-level inheritance) misses code generation #1663

Closed
tomghyselinck opened this issue Dec 11, 2018 · 4 comments
Closed

Comments

@tomghyselinck
Copy link
Contributor

Description

As a workaround for #1662 I was trying to use oneOf, listing the first-level inheritance objects instead of the base type.

Unfortunately, this shows pops up another related issue:

The generated code wants to resolve an OneOfDog object, but it looks like it is not generated anywhere.

Please note that you can also see that the member fields of the Pet and Dog parent object are missing in the AngryDog (cfr. #453).

openapi-generator version

I used OpenAPI generator CLI version 4.0.0-SNAPSHOT:
https://oss.sonatype.org/content/repositories/snapshots/org/openapitools/openapi-generator-cli/4.0.0-SNAPSHOT/openapi-generator-cli-4.0.0-20181210.103357-85.jar

OpenAPI declaration file content or url

See oneOf-multi-level-inheritance.yaml in the attached zip-file:
oneOf-multi-level-inheritance.zip

Command line used for generation
java -jar openapi-generator-cli-4.x.jar generate -i ./oneOf-multi-level-inheritance.yaml -g python -o ./oneOf-multi-level-inheritance/client/python
Steps to reproduce
  1. Generate client code

    See also oneOf-multi-level-inheritance.sh.

    wget \
        'https://oss.sonatype.org/content/repositories/snapshots/org/openapitools/openapi-generator-cli/4.0.0-SNAPSHOT/openapi-generator-cli-4.0.0-20181210.103357-85.jar' \
        -O 'openapi-generator-cli-4.x.jar'
    rm -rf ./oneOf-multi-level-inheritance/
    java -jar openapi-generator-cli-4.x.jar generate -i ./oneOf-multi-level-inheritance.yaml -g python -o ./oneOf-multi-level-inheritance/client/python
    
  2. Start (mocked) server

    python3 -m connexion run --mock=all oneOf-multi-level-inheritance.yaml

  3. Run the client test

    (cd multi-level-inheritance/client/python/ && python3)

    import openapi_client
    api = openapi_client.DefaultApi()
    dog = api.dog_get()
    print(type(dog))
    print(dog)
    pet = api.pet_get()
    print(type(pet))
    print(pet)

    Output:

    <class 'openapi_client.models.angry_dog.AngryDog'>
    {'byting': True}
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/oneOf-multi-level-inheritance/client/python/openapi_client/api/default_api.py", line 138, in pet_get
        (data) = self.pet_get_with_http_info(**kwargs)  # noqa: E501
      File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/oneOf-multi-level-inheritance/client/python/openapi_client/api/default_api.py", line 205, in pet_get_with_http_info
        collection_formats=collection_formats)
      File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/oneOf-multi-level-inheritance/client/python/openapi_client/api_client.py", line 335, in call_api
     _preload_content, _request_timeout)
      File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/oneOf-multi-level-inheritance/client/python/openapi_client/api_client.py", line 174, in __call_api
        return_data = self.deserialize(response_data, response_type)
      File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/oneOf-multi-level-inheritance/client/python/openapi_client/api_client.py", line 246, in deserialize
        return self.__deserialize(data, response_type)
      File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/oneOf-multi-level-inheritance/client/python/openapi_client/api_client.py", line 274, in __deserialize
     klass = getattr(openapi_client.models, klass)
    AttributeError: module 'openapi_client.models' has no attribute 'OneOfDog'
    
Related issues/PRs
Suggest a fix

I have no clue here (yet)

@Funghorn
Copy link

Funghorn commented Jan 26, 2019

Are there currently any workarounds for this? If not for 3rd spec, then maybe for the 2nd (without using oneOf, since, afaik, it is not supported).
UPDATE: found solution for 2nd spec - use model inheritance (stackoverflow).

@tomghyselinck
Copy link
Contributor Author

@wing328 Since #1664 and/or #1842 I see some improvement but the Python client models still miss the parent properties which gives me some issues when trying to return an object of a type "in the middle of the type hierarchy" (e.g. Dog in the attached project):

  • The member fields of the parent object(s) are always missing: (Bird, Cat, Dog miss petThing from the Pet base/parent object, AngryDog etc. miss all members from Dog and Pet object, ...)
  • The discriminator does not work when returning a sub-level object (e.g. Dog)
  • When trying to fix above by duplicating the discriminator at the sub-level object (e.g. Dog), we get a python KeyError
    Workaround we currently use is to add another (different) discriminator at the sub-level object (e.g. Cat).

How to test:

  1. Generate the Python client code:

    ./python-multi-level-inheritance.sh
    
  2. Start the (mocked) server

    python3 -m connexion run --mock all --verbose --port 8080 python-multi-level-inheritance.yaml
    
  3. Run some Python client tests:

    (cd python-multi-level-inheritance/ && python3)
    
>>> import openapi_client
>>> client_api = openapi_client.DefaultApi()
>>> b = client_api.bird_get()
>>> type(b)
<class 'openapi_client.models.bird.Bird'>
>>> dir(b)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_birdie_thing', 'attribute_map', 'birdie_thing', 'discriminator', 'openapi_types', 'to_dict', 'to_str']
>>> c = client_api.cat_get()
>>> type(c)
<class 'openapi_client.models.funny_cat.FunnyCat'>
>>> dir(c)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_hopping_around', 'attribute_map', 'discriminator', 'hopping_around', 'openapi_types', 'to_dict', 'to_str']
>>> d = client_api.dog_get()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/python-multi-level-inheritance/openapi_client/api/default_api.py", line 229, in dog_get
    (data) = self.dog_get_with_http_info(**kwargs)  # noqa: E501
  File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/python-multi-level-inheritance/openapi_client/api/default_api.py", line 297, in dog_get_with_http_info
    collection_formats=collection_formats)
  File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/python-multi-level-inheritance/openapi_client/api_client.py", line 339, in call_api
    _preload_content, _request_timeout, _host)
  File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/python-multi-level-inheritance/openapi_client/api_client.py", line 178, in __call_api
    return_data = self.deserialize(response_data, response_type)
  File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/python-multi-level-inheritance/openapi_client/api_client.py", line 250, in deserialize
    return self.__deserialize(data, response_type)
  File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/python-multi-level-inheritance/openapi_client/api_client.py", line 289, in __deserialize
    return self.__deserialize_model(data, klass)
  File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/python-multi-level-inheritance/openapi_client/api_client.py", line 637, in __deserialize_model
    klass_name = instance.get_real_child_model(data)
  File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/python-multi-level-inheritance/openapi_client/models/dog.py", line 78, in get_real_child_model
    discriminator_key = self.attribute_map[self.discriminator]
KeyError: 'pettype'
>>> p = client_api.pet_get()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/python-multi-level-inheritance/openapi_client/api/default_api.py", line 316, in pet_get
    (data) = self.pet_get_with_http_info(**kwargs)  # noqa: E501
  File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/python-multi-level-inheritance/openapi_client/api/default_api.py", line 383, in pet_get_with_http_info
    collection_formats=collection_formats)
  File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/python-multi-level-inheritance/openapi_client/api_client.py", line 339, in call_api
    _preload_content, _request_timeout, _host)
  File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/python-multi-level-inheritance/openapi_client/api_client.py", line 178, in __call_api
    return_data = self.deserialize(response_data, response_type)
  File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/python-multi-level-inheritance/openapi_client/api_client.py", line 250, in deserialize
    return self.__deserialize(data, response_type)
  File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/python-multi-level-inheritance/openapi_client/api_client.py", line 289, in __deserialize
    return self.__deserialize_model(data, klass)
  File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/python-multi-level-inheritance/openapi_client/api_client.py", line 639, in __deserialize_model
    instance = self.__deserialize(data, klass_name)
  File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/python-multi-level-inheritance/openapi_client/api_client.py", line 289, in __deserialize
    return self.__deserialize_model(data, klass)
  File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/python-multi-level-inheritance/openapi_client/api_client.py", line 637, in __deserialize_model
    klass_name = instance.get_real_child_model(data)
  File "/home/tom/programming/XRA-31/components/software/1.x-sc_qam/xra31api-rest/issues/python-multi-level-inheritance/openapi_client/models/dog.py", line 78, in get_real_child_model
    discriminator_key = self.attribute_map[self.discriminator]
KeyError: 'pettype'

Is there already any PR in progress which will fix this?

@tomghyselinck
Copy link
Contributor Author

Forgot attachment for previous comment:
python-multi-level-inheritance.zip

@spacether
Copy link
Contributor

This should be resolved by #5341
If it is not, can you re-open it and describe the payload that the server is sending back?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants