Skip to content

[BUG][PYTHON] Using Openapi 3.0 Inheritance/Polymorphism keywords (allOf, anyOf, oneOf) causes generation of UNKNOWNBASETYPE model. #8892

@danaelhe

Description

@danaelhe

Bug Report Checklist

  • [y] Have you provided a full/minimal spec to reproduce the issue?
  • [y] Have you validated the input using an OpenAPI validator (example)?
  • [y] Have you tested with the latest master to confirm the issue still exists?
  • [y] Have you searched for related issues/PRs?
  • [y] What's the actual output vs expected output?
  • [maybe ] [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

Can’t use allof, anyof, or oneof keywords in request body → Will result in generating "UNKNOWNBASETYPE" which makes that client endpoint unusable. This is specific to Openapi 3.0. In Openapi 2.0 (swagger 2.0) one could get away with using "produces" and "consumes" (kubernetes api uses that) in POST requests. With Openapi 3.0, that has been replaced with requestBody and the use of the inheritance keywords (allOf, anyOf, oneOf). This problem also doesn't seem specific to Python.

The following spec causes the issue:

OpenAPI declaration file content or url
openapi: 3.0.0
info:
  title: Sample API
  version: '2.0'
paths:
  /v2/projects:
    post:
      operationId: create_project
      summary: Create a Project
      description: 'To create a project, send a POST request to `/v2/projects`.'
      tags:
        - Projects
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
              - $ref: '#/components/schemas/project_base'
              required:
              - name
              - purpose
      responses:
        '200':
          description: OK
components:
  schemas:
    project_base:
      type: object
      properties:
        id:
          type: string
          format: uuid
          readOnly: true
          example: 4e1bfbc3
          description: The unique universal identifier of this project.
        name:
          type: string
          maxLength: 175
          example: my-web-api
          description: >-
            The human-readable name for the project. The maximum length is 175
            characters and the name must be unique.
        description:
          type: string
          maxLength: 255
          example: My website API
          description: >-
            The description of the project. The maximum length is 255
            characters.
        purpose:
          type: string
          maxLength: 255
          example: Service or API
Generation Details

Generates a client that imports:
from openapi_client.model.unknownbasetype import UNKNOWNBASETYPE
and uses it in place of the schema described in requestbody (project_base).

If you rework the POST request as such to remove the use of allOf, you are able to create a POST request but you lose the ability to specify which properties are required for that specific endpoint:

paths:
  /v2/projects:
    post:
      operationId: create_project
      summary: Create a Project
      description: 'To create a project, send a POST request to `/v2/projects`.'
      tags:
        - Projects
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/project_base'
      responses:
        '200':
          description: OK

^This will generate the expected import statements in the client:
from openapi_client.model.project_base import ProjectBase

...but you lose the ability to specify which inherited properties are required for that specific endpoint). Also, if you were using oneOf or anyOf, I don't think you'd be able to maintain their behavior with this workaround. I've seen people suggest creating a specific model for each endpoint and specify the required properties there, but that will cause the spec to be super clunky and generate weird model names.

Steps to reproduce

Create a file with the following spec:

openapi: 3.0.0
info:
  title: Sample API
  version: '2.0'
paths:
  /v2/projects:
    post:
      operationId: create_project
      summary: Create a Project
      description: 'To create a project, send a POST request to `/v2/projects`.'
      tags:
        - Projects
      requestBody:
        required: true
        content:
          application/json:
            schema:
              allOf:
              - $ref: '#/components/schemas/project_base'
              required:
              - name
              - purpose
      responses:
        '200':
          description: OK
components:
  schemas:
    project_base:
      type: object
      properties:
        id:
          type: string
          format: uuid
          readOnly: true
          example: 4e1bfbc3
          description: The unique universal identifier of this project.
        name:
          type: string
          maxLength: 175
          example: my-web-api
          description: >-
            The human-readable name for the project. The maximum length is 175
            characters and the name must be unique.
        description:
          type: string
          maxLength: 255
          example: My website API
          description: >-
            The description of the project. The maximum length is 255
            characters.
        purpose:
          type: string
          maxLength: 255
          example: Service or API

run the following:

docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli generate -i/local/projects_allof.yaml -g python -o /local/last-try

Inspect the openapi_client/api/projects_api.py file and see if UNKNOWNBASETYPE is imported and used.

Related issues/PRs

This problem has been described in many issues: #2892 #5903 #7256 #7339. Also not specific to just Python.

openapi-generator version

Openapi 5.0.1, also used the latest master via docker

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions