OpenAPITools / OpenAPITools/openapi-generator
[PYTHON]: Bug or not bug ? Using allOf for inheritance generate bad imports
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 26.8k
- Forks
- 7.7k
- PR merge metrics
- PR metrics pending
Description
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
- Why the first syntax break the imports ? Is the syntax wrong ?
- 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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the test.yaml schema and reproduce the output using the documented openapi-generator-cli python-flask command. Compare generated imports and model types for the two allOf forms, then inspect the generator behavior that resolves oneOf inside array items. Done means the valid schema form produces resolvable imports and the generated type reflects the referenced schemas without invalid names.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- flask, openapi, python
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100