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

[PYTHON]: Bug or not bug ? Using allOf for inheritance generate bad imports #18966

Open
VBA-N7 opened this issue Jun 18, 2024 · 2 comments
Open

Comments

@VBA-N7
Copy link

VBA-N7 commented Jun 18, 2024

Hi,
I'm not sure what i will describe is a bug; I prefer to give you some clues and have a little chat before openning a bug.

Context:
I fetch a swagger generated from one of my colleagues who is using Swashbuckle and the inheritance for the Dog schema use the following syntax:

openapi: 3.0.1
info:
  title: title
  version: 1.0.0
paths: {}
components:
  schemas:
    Dog:
      type: object
      allOf:
        - $ref: '#/components/schemas/Animal'
      properties:
        food_eaten:
          type: array
          items:
            oneOf:
              - $ref: '#/components/schemas/Treat'

    Animal:
      type: object

    Treat:
      type: object

When generate python flask server, the imports are kinda broken.
docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli:v7.6.0 generate -i /local/test.yaml -g python-flask -o /local/dist

from datetime import date, datetime  # noqa: F401

from typing import List, Dict  # noqa: F401

from openapi_server.models.base_model import Model
from openapi_server.models.one_ofobject import OneOfobject
from openapi_server import util

from openapi_server.models.one_ofobject import OneOfobject  # noqa: E501

class Dog(Model):
    """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

    Do not edit the class manually.
    """

    def __init__(self, food_eaten=None):  # noqa: E501
        """Dog - a model defined in OpenAPI

        :param food_eaten: The food_eaten of this Dog.  # noqa: E501
        :type food_eaten: List[OneOfobject]
        """
        self.openapi_types = {
            'food_eaten': List[OneOfobject]
        }

        self.attribute_map = {
            'food_eaten': 'food_eaten'
        }

        self._food_eaten = food_eaten

    @classmethod
    def from_dict(cls, dikt) -> 'Dog':
        """Returns the dict as a model

        :param dikt: A dict.
        :type: dict
        :return: The Dog of this Dog.  # noqa: E501
        :rtype: Dog
        """
        return util.deserialize_model(dikt, cls)

    @property
    def food_eaten(self) -> List[OneOfobject]:
        """Gets the food_eaten of this Dog.


        :return: The food_eaten of this Dog.
        :rtype: List[OneOfobject]
        """
        return self._food_eaten

    @food_eaten.setter
    def food_eaten(self, food_eaten: List[OneOfobject]):
        """Sets the food_eaten of this Dog.


        :param food_eaten: The food_eaten of this Dog.
        :type food_eaten: List[OneOfobject]
        """

        self._food_eaten = food_eaten

I saw on swagger.io that the syntax of allOf should be the following one:

openapi: 3.0.1
info:
  title: title
  version: 1.0.0
paths: {}
components:
  schemas:
    Dog:
      type: object
      allOf:
        - $ref: '#/components/schemas/Animal'
        - type: object
          properties:
            food_eaten:
              type: array
              items:
                oneOf:
                  - $ref: '#/components/schemas/Treat'

    Animal:
      type: object

    Treat:
      type: object

When i'm using this one, the imports are correct (working):

from datetime import date, datetime  # noqa: F401

from typing import List, Dict  # noqa: F401

from openapi_server.models.base_model import Model
from openapi_server.models.dog_all_of_food_eaten import DogAllOfFoodEaten
from openapi_server import util

from openapi_server.models.dog_all_of_food_eaten import DogAllOfFoodEaten  # noqa: E501

class Dog(Model):
    """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

    Do not edit the class manually.
    """

    def __init__(self, food_eaten=None):  # noqa: E501
        """Dog - a model defined in OpenAPI

        :param food_eaten: The food_eaten of this Dog.  # noqa: E501
        :type food_eaten: List[DogAllOfFoodEaten]
        """
        self.openapi_types = {
            'food_eaten': List[DogAllOfFoodEaten]
        }

        self.attribute_map = {
            'food_eaten': 'food_eaten'
        }

        self._food_eaten = food_eaten

    @classmethod
    def from_dict(cls, dikt) -> 'Dog':
        """Returns the dict as a model

        :param dikt: A dict.
        :type: dict
        :return: The Dog of this Dog.  # noqa: E501
        :rtype: Dog
        """
        return util.deserialize_model(dikt, cls)

    @property
    def food_eaten(self) -> List[DogAllOfFoodEaten]:
        """Gets the food_eaten of this Dog.


        :return: The food_eaten of this Dog.
        :rtype: List[DogAllOfFoodEaten]
        """
        return self._food_eaten

    @food_eaten.setter
    def food_eaten(self, food_eaten: List[DogAllOfFoodEaten]):
        """Sets the food_eaten of this Dog.


        :param food_eaten: The food_eaten of this Dog.
        :type food_eaten: List[DogAllOfFoodEaten]
        """

        self._food_eaten = food_eaten
  1. Why the first syntax break the imports ? Is the syntax wrong ?
  2. When im using the second syntax, i dont understand why it is generating a DogAllOfFoodEaten.

Actual:

        self.openapi_types = {
            'food_eaten': List[DogAllOfFoodEaten]
        }

Expected:

        self.openapi_types = {
            'food_eaten': List[Treat | DogBiscuit | SomethingElse]
        }

Thanks for all you have done so far. I really appreciate it.
Have a good day.

@VBA-N7 VBA-N7 changed the title [PYTHON]: Using allOf for inheritance generate bad imports [PYTHON]: Bug or not bug ? Using allOf for inheritance generate bad imports Jun 18, 2024
@wing328
Copy link
Member

wing328 commented Jun 18, 2024

https://github.com/openapitools/openapi-generator/blob/master/docs/customization.md#openapi-normalizer

can you please enabled the normalizer rule REFACTOR_ALLOF_WITH_PROPERTIES_ONLY?

            oneOf:
             - $ref: '#/components/schemas/Treat'

this is an inline schema so it will be created as a model separately

@VBA-N7
Copy link
Author

VBA-N7 commented Jun 18, 2024

Thanks @wing328 for your help, it works !

Could you please indicate me if it is a normal behavior ?

  1. When im using the second syntax, i dont understand why it is generating a DogAllOfFoodEaten.

Actual:

        self.openapi_types = {
            'food_eaten': List[DogAllOfFoodEaten]
        }

Expected:

        self.openapi_types = {
            'food_eaten': List[Treat | DogBiscuit | SomethingElse]
        }

Thanks !

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

2 participants