OpenAPITools / OpenAPITools/openapi-generator

[BUG][PYTHON] SDK generating on [ allOf, oneOf, anyOf ] not supported for items:

Open
#22,260 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Issue: Bug
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

Bug Report Checklist
  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
Description

The described issue is not supported for: [ allOf, oneOf, anyOf ] within items:

  1. allOf
      allOf:
        - $ref: '#/components/schemas/CreateItemA'
        - $ref: '#/components/schemas/CreateItemB'
  1. oneOf
      oneOf:
        - $ref: '#/components/schemas/CreateItemA'
        - $ref: '#/components/schemas/CreateItemB'
  1. anyOf
      anyOf:
        - $ref: '#/components/schemas/CreateItemA'
        - $ref: '#/components/schemas/CreateItemB'
      discriminator:
        propertyName: type
        mapping:
          a: '#/components/schemas/CreateItemA'
          b: '#/components/schemas/CreateItemB'
  • allOf supported [ not within items: ]
openapi: 3.0.3
...
paths:
  /path:
    post:
      ...
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/CreateItem'
      responses:
        '200':
          description: OK
components:
  schemas:
    CreateItem:
      allOf:
        - $ref: '#/components/schemas/CreateItemA'
        - $ref: '#/components/schemas/CreateItemB'
...
  • [] allOf NOT supported [within items: ]
openapi: 3.0.3
...
paths:
  /path:
    post:
      ...
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              items:
                $ref: '#/components/schemas/CreateItem'
      responses:
        '200':
          description: OK
components:
  schemas:
    CreateItem:
      allOf:
        - $ref: '#/components/schemas/CreateItemA'
        - $ref: '#/components/schemas/CreateItemB'
...
openapi-generator version

v7.16.0

OpenAPI declaration file content
openapi: 3.0.3
info:
  title: Public API
  version: 1.0.0
paths:
  /path:
    post:
      summary: Create
      operationId: createItems
      description: |
        Create items
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              items:
                $ref: '#/components/schemas/CreateItem'
      responses:
        '200':
          description: OK
components:
  schemas:
    CreateItem:
      allOf:
        - $ref: '#/components/schemas/CreateItemA'
        - $ref: '#/components/schemas/CreateItemB'
    CreateItemA:
      type: object
      title: Create Item A
      properties:
        type:
          type: string
          default: a
        a:
          type: string
      required:
        - type
    CreateItemB:
      type: object
      title: Create Item B
      properties:
        type:
          type: string
          default: b
        b:
          type: string
      required:
        - type
        - b
Generation Details
docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli:v7.16.0 generate -i /local/openapi.yaml -g python -o /local/test_client
Steps to reproduce

The result with the BUG:

...
            schema:
              items:
                $ref: '#/components/schemas/CreateItem'
...
# /local/test_client/api/default_api.py

class DefaultApi:
    """NOTE: This class is auto generated by OpenAPI Generator
    Ref: https://openapi-generator.tech

    Do not edit the class manually.
    """

    def __init__(self, api_client=None) -> None:
        if api_client is None:
            api_client = ApiClient.get_default()
        self.api_client = api_client


    @validate_call
    def create_items(
        self,
        _request_timeout: Union[
            None,
            Annotated[StrictFloat, Field(gt=0)],
            Tuple[
                Annotated[StrictFloat, Field(gt=0)],
                Annotated[StrictFloat, Field(gt=0)]
            ]
        ] = None,
        _request_auth: Optional[Dict[StrictStr, Any]] = None,
        _content_type: Optional[StrictStr] = None,
        _headers: Optional[Dict[StrictStr, Any]] = None,
        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
    ) -> None:
        """Create

        Create items 

        :param _request_timeout: timeout setting for this request. If one
                                 number provided, it will be total request
                                 timeout. It can also be a pair (tuple) of
                                 (connection, read) timeouts.
        :type _request_timeout: int, tuple(int, int), optional
        :param _request_auth: set to override the auth_settings for an a single
                              request; this effectively ignores the
                              authentication in the spec for a single request.
        :type _request_auth: dict, optional
        :param _content_type: force content-type for the request.
        :type _content_type: str, Optional
        :param _headers: set to override the headers for a single
                         request; this effectively ignores the headers
                         in the spec for a single request.
        :type _headers: dict, optional
        :param _host_index: set to override the host_index for a single
                            request; this effectively ignores the host_index
                            in the spec for a single request.
        :type _host_index: int, optional
        :return: Returns the result object.
        """ # noqa: E501
...

Against supported allOf [ not within items: ]
Expected result should be similar to:

...
            schema:
              $ref: '#/components/schemas/CreateItem'
...

Result:

# /local/test_client/api/default_api.py

class DefaultApi:
    """NOTE: This class is auto generated by OpenAPI Generator
    Ref: https://openapi-generator.tech

    Do not edit the class manually.
    """

    def __init__(self, api_client=None) -> None:
        if api_client is None:
            api_client = ApiClient.get_default()
        self.api_client = api_client


    @validate_call
    def create_items(
        self,
        type: StrictStr,
        b: StrictStr,
        a: Optional[StrictStr] = None,
        _request_timeout: Union[
            None,
            Annotated[StrictFloat, Field(gt=0)],
            Tuple[
                Annotated[StrictFloat, Field(gt=0)],
                Annotated[StrictFloat, Field(gt=0)]
            ]
        ] = None,
        _request_auth: Optional[Dict[StrictStr, Any]] = None,
        _content_type: Optional[StrictStr] = None,
        _headers: Optional[Dict[StrictStr, Any]] = None,
        _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
    ) -> None:
        """Create

        Create items 

        :param type: (required)
        :type type: str
        :param b: (required)
        :type b: str
        :param a:
        :type a: str
        :param _request_timeout: timeout setting for this request. If one
                                 number provided, it will be total request
                                 timeout. It can also be a pair (tuple) of
                                 (connection, read) timeouts.
        :type _request_timeout: int, tuple(int, int), optional
        :param _request_auth: set to override the auth_settings for an a single
                              request; this effectively ignores the
                              authentication in the spec for a single request.
        :type _request_auth: dict, optional
        :param _content_type: force content-type for the request.
        :type _content_type: str, Optional
        :param _headers: set to override the headers for a single
                         request; this effectively ignores the headers
                         in the spec for a single request.
        :type _headers: dict, optional
        :param _host_index: set to override the host_index for a single
                            request; this effectively ignores the host_index
                            in the spec for a single request.
        :type _host_index: int, optional
        :return: Returns the result object.
        """ # noqa: E501

        _param = self._create_items_serialize(
            type=type,
            b=b,
            a=a,
            _request_auth=_request_auth,
            _content_type=_content_type,
            _headers=_headers,
            _host_index=_host_index
        )
...
Suggest a fix

Add support for [ allOf, oneOf, anyOf ] on items:

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the provided openapi.yaml and reproduce the issue using the Docker generation command for the Python client. Compare the generated default_api.py for schemas using allOf, oneOf, and anyOf under items: with the supported non-items case. Done means the generated method exposes the composed item fields consistently for all three constructs.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, openapi, python
Domain
api, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.