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] Multi-level inheritance not working correctly #1662

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

[BUG][Python] Multi-level inheritance not working correctly #1662

tomghyselinck opened this issue Dec 11, 2018 · 8 comments

Comments

@tomghyselinck
Copy link
Contributor

tomghyselinck commented Dec 11, 2018

Description

The generated Python client does not properly return the final classes when multi-level inheritance is used.

For example:

  • When GET /pet returns any of AngryDog, NiceDog, and FunnyCat object, the Python client will return a Pet object (without all final_type-specific attributes missing).
  • When GET /dog returns any of AngryDog or NiceDog object, the Python client will return a Pet object (without all final_type-specific attributes missing).

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 multi-level-inheritance.yaml in the attached zip-file:
multi-level-inheritance.zip

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

    See also 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 ./multi-level-inheritance/
    java -jar openapi-generator-cli-4.x.jar generate -i ./multi-level-inheritance.yaml -g python -o ./multi-level-inheritance/client/python
    
  2. Start (mocked) server

    python3 -m connexion run --mock=all multi-level-inheritance.yaml
    
  3. Run the client test

    (cd multi-level-inheritance/client/python/ && python3)
    
    import openapi_client
    api = openapi_client.DefaultApi()
    pet = api.pet_get()
    print(type(pet))
    print(pet)
    dog = api.dog_get()
    print(type(dog))
    print(dog)

    Output:

    <class 'openapi_client.models.pet.Pet'>
    {'pet_type': 'NiceDog'}
    <class 'openapi_client.models.dog.Dog'>
    {'doggie_thing': 'Playing with piece of wood'}
    
Related issues/PRs

Similar issues has been seen with CSHARP and Java:

Suggest a fix

When we add an addition discriminator in the Dog schema then GET /dog does properly return either an AngryDog or NiceDog object.

@tomghyselinck
Copy link
Contributor Author

The (post) 4.0.0-beta version of the tool gives us the following error:

wget \
    'https://oss.sonatype.org/content/repositories/snapshots/org/openapitools/openapi-generator-cli/4.0.0-SNAPSHOT/openapi-generator-cli-4.0.0-20190104.042328-150.jar' \
    -O 'openapi-generator-cli-4.x.jar'
rm -rf ./multi-level-inheritance/
java -jar openapi-generator-cli-4.x.jar generate -i ./multi-level-inheritance.yaml -g python -o ./multi-level-inheritance/client/python
[main] WARN  o.o.c.ignore.CodegenIgnoreProcessor - Output directory does not exist, or is inaccessible. No file (.openapi-generator-ignore) will be evaluated.
[main] INFO  o.o.c.languages.PythonClientCodegen - Environment variable PYTHON_POST_PROCESS_FILE not defined so the Python code may not be properly formatted. To define it, try 'export PYTHON_POST_PROCESS_FILE="/usr/local/bin/yapf -i"' (Linux/Mac)
[main] INFO  o.o.c.languages.PythonClientCodegen - NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).
Exception in thread "main" java.lang.RuntimeException: Could not process model 'AngryDog'.Please make sure that your schema is correct!
        at org.openapitools.codegen.DefaultGenerator.generateModels(DefaultGenerator.java:457)
        at org.openapitools.codegen.DefaultGenerator.generate(DefaultGenerator.java:891)
        at org.openapitools.codegen.cmd.Generate.run(Generate.java:354)
        at org.openapitools.codegen.OpenAPIGenerator.main(OpenAPIGenerator.java:62)
Caused by: java.lang.RuntimeException: Please report the issue: Cannot process Composed Schema in addProperties: class ComposedSchema {
    class Schema {
        title: null
        multipleOf: null
        maximum: null
        exclusiveMaximum: null
        minimum: null
        exclusiveMinimum: null
        maxLength: null
        minLength: null
        pattern: null
        maxItems: null
        minItems: null
        uniqueItems: null
        maxProperties: null
        minProperties: null
        required: null
        type: null
        not: null
        properties: null
        additionalProperties: null
        description: null
        format: null
        $ref: null
        nullable: null
        readOnly: null
        writeOnly: null
        example: null
        externalDocs: null
        deprecated: null
        discriminator: null
        xml: null
    }
    allOf: [class Schema {
        title: null
        multipleOf: null
        maximum: null
        exclusiveMaximum: null
        minimum: null
        exclusiveMinimum: null
        maxLength: null
        minLength: null
        pattern: null
        maxItems: null
        minItems: null
        uniqueItems: null
        maxProperties: null
        minProperties: null
        required: null
        type: null
        not: null
        properties: null
        additionalProperties: null
        description: null
        format: null
        $ref: #/components/schemas/Pet
        nullable: null
        readOnly: null
        writeOnly: null
        example: null
        externalDocs: null
        deprecated: null
        discriminator: null
        xml: null
    }, class ObjectSchema {
        class Schema {
            title: null
            multipleOf: null
            maximum: null
            exclusiveMaximum: null
            minimum: null
            exclusiveMinimum: null
            maxLength: null
            minLength: null
            pattern: null
            maxItems: null
            minItems: null
            uniqueItems: null
            maxProperties: null
            minProperties: null
            required: null
            type: null
            not: null
            properties: {doggieThing=class StringSchema {
                class Schema {
                    title: null
                    multipleOf: null
                    maximum: null
                    exclusiveMaximum: null
                    minimum: null
                    exclusiveMinimum: null
                    maxLength: null
                    minLength: null
                    pattern: null
                    maxItems: null
                    minItems: null
                    uniqueItems: null
                    maxProperties: null
                    minProperties: null
                    required: null
                    type: null
                    not: null
                    properties: null
                    additionalProperties: null
                    description: null
                    format: null
                    $ref: null
                    nullable: null
                    readOnly: null
                    writeOnly: null
                    example: null
                    externalDocs: null
                    deprecated: null
                    discriminator: null
                    xml: null
                }
                type: string
                _default: null
                _enum: null
            }}
            additionalProperties: null
            description: null
            format: null
            $ref: null
            nullable: null
            readOnly: null
            writeOnly: null
            example: null
            externalDocs: null
            deprecated: null
            discriminator: null
            xml: null
        }
        type: object
        defaultObject: null
    }]
    anyOf: null
    oneOf: null
}
        at org.openapitools.codegen.DefaultCodegen.addProperties(DefaultCodegen.java:1866)
        at org.openapitools.codegen.DefaultCodegen.fromModel(DefaultCodegen.java:1732)
        at org.openapitools.codegen.DefaultGenerator.processModels(DefaultGenerator.java:1133)
        at org.openapitools.codegen.DefaultGenerator.generateModels(DefaultGenerator.java:452)
        ... 3 more

@tomghyselinck
Copy link
Contributor Author

This may be related to #583?

@tomghyselinck
Copy link
Contributor Author

@ericraymond : @wing328 is working on a fix in #1842

@tomghyselinck
Copy link
Contributor Author

See also #1663 (comment) for a related issue where we can't use the discriminator.propertyName from a parent object.

@rienafairefr
Copy link
Contributor

I think the python code for discriminator in model.mustache isn't using the OAS3 values correctly, it's only using the OAS2, using a special vendor extension x-discriminator-value:

discriminator_value_class_map = {
        {{#children}}'{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}': '{{{classname}}}'{{^-last}},

I've worked on related stuff in #2121 , but it was for composed schemas without discriminator. I encountered this issue and I've pushed #2170, which seem to work even for oneOf/anyOf inheritance. Can you check that one out if it fixes your issue ?

@tomghyselinck
Copy link
Contributor Author

Hi @rienafairefr,

Sorry for the late reply.

I am testing out your PRs. It looks like there is something odd going on with allOf inheritance and member fields.

I already made some comments on #2121 and #2170.

With best regards,
Tom.

@gvanderpol
Copy link

gvanderpol commented Oct 2, 2019

@tomghyselinck @rienafairefr

We are also facing issues with our Python model generation when there is an 'allOf' reference in the swagger JSON file. The issues are similar to what is described above (empty models in our case). The openapi generator used is v4.1.2.

We are wondering what the status is to fix this for the Python client generation? We actually need this functionality pretty bad.

@spacether
Copy link
Contributor

This looks like this is working with the composition features that have existed since 2019.
Please see the tests in #5341

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

4 participants