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

[BUG] [python-fastapi] doesn't support additionalProperties properly #19311

Open
5 of 6 tasks
mgoltzsche opened this issue Aug 6, 2024 · 0 comments · May be fixed by #19312
Open
5 of 6 tasks

[BUG] [python-fastapi] doesn't support additionalProperties properly #19311

mgoltzsche opened this issue Aug 6, 2024 · 0 comments · May be fixed by #19312

Comments

@mgoltzsche
Copy link
Contributor

mgoltzsche commented Aug 6, 2024

Bug Report Checklist

  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • 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?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

The python-fastapi generator generates invalid model code when the model's OpenAPI schema specifies additionalProperties:
It lets the generated model class extend the type of the value of additionalProperties.
Also, it generates an additional_properties dict field to hold the additional properties but the generated to_dict method that would map it to the correct transfer representation is not honoured by pydantic v2 (which supports storing additional properties within the model object's __dict__ when model_config.extra=allow is specified).

For instance currently the generator generates the following model code when given a type ExampleObject that specifies a static name property as well as additionalProperties: {"type": "string"}:

example_object.py
from __future__ import annotations
import pprint
import re  # noqa: F401
import json

from pydantic import ConfigDict, StrictStr
from typing import Any, ClassVar, Dict, List
from example.gen.models.str import str
try:
    from typing import Self
except ImportError:
    from typing_extensions import Self

class ExampleObject(str):
    name: StrictStr
    additional_properties: Dict[str, Any] = {}
    __properties: ClassVar[List[str]] = ["name"]

    model_config = {
        "populate_by_name": True,
        "validate_assignment": True,
        "protected_namespaces": (),
    }


    def to_str(self) -> str:
        ...
    def to_json(self) -> str:
        ...
    @classmethod
    def from_json(cls, json_str: str) -> Self:
        ...
    def to_dict(self) -> Dict[str, Any]:
        ...
    @classmethod
    def from_dict(cls, obj: Dict) -> Self:
        ...

Please note:

  • It lets the model class inherit from str (specified by additionalProperties schema) and import the non-existing package example.gen.models.str.
  • It generated an additional_properties dict in addition to the __dict__ that already holds all model fields dynamically under the hood - the latter should be leveraged and is sufficient.
Expectation

Instead, I'd expect the following:

  • It should not inherit the value type specified within the additionalProperties schema.
  • It should not generate an additional additional_properties dict but leverage the built-in __dict__ which is anyway how pydantic v2 supports additional properties.
openapi-generator version

131fd51 # v7.7.0+patch

OpenAPI declaration file content or url
openapi.yaml with additionalProperties schema
openapi: "3.0.1"

info:
  title: Example API
  description: Example API to test additionalProperties support
  version: 1.0.0

servers:
  - url: /

tags:
  - name: example

paths:
  /example:
    get:
      operationId: example
      summary: Example operation
      description: An operation that returns an object with dynamic properties
      tags:
        - example
      responses:
        '200':
          description: Example object
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ExampleObject'

components:
  schemas:
    ExampleObject:
      type: object
      properties:
        name:
          type: string
      additionalProperties:
        type: string
      required:
        - name
Generation Details

Generate a python server from the previously listed openapi.yaml file using the python-fastapi generator:

openapi-generator generate -i ./openapi.yaml -g python-fastapi -o ./generated --package-name=example.generated -p sourceFolder= -p fastapiImplementationPackage=example.controller
Steps to reproduce
java -jar ./modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -i ./openapi.yaml -g python-fastapi -o ./generated --package-name=example.generated -p sourceFolder= -p fastapiImplementationPackage=example.controller
Related issues/PRs
Suggest a fix
@mgoltzsche mgoltzsche changed the title [BUG] [python-fastapi] [BUG] [python-fastapi] doesn't support additionalProperties properly Aug 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant