[BUG][PYTHON] adding a requirement on a sibling field in an allOf throws AttributeError on import
Bug Report Checklist
- [x] Have you provided a full/minimal spec to reproduce the issue?
- [x] Have you validated the input using an OpenAPI validator (example)?
- [x] Have you tested with the latest master to confirm the issue still exists?
- [x] Have you searched for related issues/PRs?
- [x] What's the actual output vs expected output?
- [ ] [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description
Adding a requirement on a sibling field in an allOf breaks the model import
openapi-generator version
6.2.0
OpenAPI declaration file content or url
openapi: 3.0.0
info:
title: test
version: 1.0.0
paths:
/:
get:
responses:
200:
description: "OK"
components:
schemas:
Test:
type: object
properties:
test:
type: string
TestRequired:
allOf:
- $ref: '#/components/schemas/Test'
- type: object
required: [test]
properties:
name:
type: string
Generation Details
openapi-generator-cli generate -g python -i test.yaml -o out
Steps to reproduce
Generate the client then try to import the generated "TestRequired" class. It will fail with an Error AttributeError: type object 'properties' has no attribute 'test'
The generated class is the following
# coding: utf-8
"""
test
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) # noqa: E501
The version of the OpenAPI document: 1.0.0
Generated by: https://openapi-generator.tech
"""
from datetime import date, datetime # noqa: F401
import decimal # noqa: F401
import functools # noqa: F401
import io # noqa: F401
import re # noqa: F401
import typing # noqa: F401
import typing_extensions # noqa: F401
import uuid # noqa: F401
import frozendict # noqa: F401
from openapi_client import schemas # noqa: F401
class TestRequired(
schemas.ComposedSchema,
):
"""NOTE: This class is auto generated by OpenAPI Generator.
Ref: https://openapi-generator.tech
Do not edit the class manually.
"""
class MetaOapg:
class all_of_1(
schemas.DictSchema
):
class MetaOapg:
required = {
"test",
}
class properties:
name = schemas.StrSchema
__annotations__ = {
"name": name,
}
test: schemas.AnyTypeSchema
@typing.overload
def __getitem__(self, name: typing_extensions.Literal["name"]) -> MetaOapg.properties.name: ...
@typing.overload
def __getitem__(self, name: str) -> schemas.UnsetAnyTypeSchema: ...
def __getitem__(self, name: typing.Union[typing_extensions.Literal["name", ], str]):
# dict_instance[name] accessor
return super().__getitem__(name)
@typing.overload
def get_item_oapg(self, name: typing_extensions.Literal["name"]) -> typing.Union[MetaOapg.properties.name, schemas.Unset]: ...
@typing.overload
def get_item_oapg(self, name: str) -> typing.Union[schemas.UnsetAnyTypeSchema, schemas.Unset]: ...
def get_item_oapg(self, name: typing.Union[typing_extensions.Literal["name", ], str]):
return super().get_item_oapg(name)
def __new__(
cls,
*args: typing.Union[dict, frozendict.frozendict, ],
test: typing.Union[MetaOapg.properties.test, dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader, ],
name: typing.Union[MetaOapg.properties.name, str, schemas.Unset] = schemas.unset,
_configuration: typing.Optional[schemas.Configuration] = None,
**kwargs: typing.Union[schemas.AnyTypeSchema, dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, None, list, tuple, bytes],
) -> 'all_of_1':
return super().__new__(
cls,
*args,
test=test,
name=name,
_configuration=_configuration,
**kwargs,
)
@classmethod
@functools.lru_cache()
def all_of(cls):
# we need this here to make our import statements work
# we must store _composed_schemas in here so the code is only run
# when we invoke this method. If we kept this at the class
# level we would get an error because the class level
# code would be run when this module is imported, and these composed
# classes don't exist yet because their module has not finished
# loading
return [
Test,
cls.all_of_1,
]
def __new__(
cls,
*args: typing.Union[dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader, ],
_configuration: typing.Optional[schemas.Configuration] = None,
**kwargs: typing.Union[schemas.AnyTypeSchema, dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, None, list, tuple, bytes],
) -> 'TestRequired':
return super().__new__(
cls,
*args,
_configuration=_configuration,
**kwargs,
)
from openapi_client.model.test import Test
the constructor of all_of_1 expects a required test argument whose typing is based on properties which doesn't contain it.
Suggest a fix
Add typing for required parameters not existing in properties as AnyTypeSchema
Thanks for reporting this I will work on a fix for this
Draft fix is being worked in https://github.com/openapi-json-schema-tools/openapi-json-schema-generator/pull/44
This was fixed in the separate repo in https://github.com/openapi-json-schema-tools/openapi-json-schema-generator/pull/44. You can use it from the latest release there if you want.
Here, I will update the python generator in this repo to include this fix before the 6.2.1 release.
What is the relation between this project and openapi-json-schema-generator?
@tnielens please refer to https://github.com/OpenAPITools/openapi-generator/pull/13501#issuecomment-1256170624 for more information.
@vincent-raman is there a regression with my fix?
@wing328 this is a corner case that will probably not work in most other generators because this required property has no property definition so it will not be in required vars. It is handlable if the generators use requiredVarsMap that I made and python uses. That property was added in https://github.com/OpenAPITools/openapi-generator/pull/13117
@vincent-raman is there a regression with my fix?
No, that was a mistake, I removed my comment, sorry. It seems working pretty well