OpenAPITools / OpenAPITools/openapi-generator

[BUG] [python] AnyOf Parent class generates empty `from_dict` function.

Open
#19,926 1 comment 1 reaction 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 (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

When generating models with the REF_AS_PARENT_IN_ALLOF normalizer option enabled, the parent model that is extended from will not have its from_dict() function generated correctly. It will be missing any function body, making it impossible for these models to be used in the API routes.

We would expect the parent from_dict function to also be implemented.

For example, When B inherits from A. A is generated as:

# coding: utf-8

"""
    My API

    No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)

    The version of the OpenAPI document: 1.0.0
    Generated by OpenAPI Generator (https://openapi-generator.tech)

    Do not edit the class manually.
"""  # noqa: E501


from __future__ import annotations
import pprint
import re  # noqa: F401
import json

from pydantic import BaseModel, ConfigDict, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from typing import Optional, Set
from typing_extensions import Self

class A(BaseModel):
    """
    A
    """ # noqa: E501
    a_field: Optional[StrictStr] = None
    __properties: ClassVar[List[str]] = ["a_field"]

    model_config = ConfigDict(
        populate_by_name=True,
        validate_assignment=True,
        protected_namespaces=(),
    )


    def to_str(self) -> str:
        """Returns the string representation of the model using alias"""
        return pprint.pformat(self.model_dump(by_alias=True))

    def to_json(self) -> str:
        """Returns the JSON representation of the model using alias"""
        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
        return json.dumps(self.to_dict())

    @classmethod
    def from_json(cls, json_str: str) -> Optional[Self]:
        """Create an instance of A from a JSON string"""
        return cls.from_dict(json.loads(json_str))

    def to_dict(self) -> Dict[str, Any]:
        """Return the dictionary representation of the model using alias.

        This has the following differences from calling pydantic's
        `self.model_dump(by_alias=True)`:

        * `None` is only added to the output dict for nullable fields that
          were set at model initialization. Other fields with value `None`
          are ignored.
        """
        excluded_fields: Set[str] = set([
        ])

        _dict = self.model_dump(
            by_alias=True,
            exclude=excluded_fields,
            exclude_none=True,
        )
        return _dict

    @classmethod
    def from_dict(cls, obj: Dict[str, Any]) -> Optional[Self]:
        """Create an instance of A from a dict"""


The generated model of B will have the correct from_dict function generated.

This issue also shows up with the python-pydantic-v1 generator.

openapi-generator version

7.9.0 & 7.10.0

OpenAPI declaration file content or url
openapi: 3.0.0
info:
  title: My API
  version: 1.0.0

paths: {}

components:
  schemas:
    A:
      type: object
      properties:
        a_field:
          type: string

    B:
      allOf:
        - $ref: '#/components/schemas/A'
        - type: object
          properties:
            b_field:
              type: string

Generation Details

openapi-generator-cli generate -g python -i openapi.yaml --openapi-normalizer 'REFACTOR_ALLOF_WITH_PROPERTIES_ONLY=true,REF_AS_PARENT_IN_ALLOF=true'

Steps to reproduce
Related issues/PRs
Suggest a fix

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 by running the reported openapi-generator-cli command with the supplied OpenAPI declaration and compare the generated from_dict methods for models A and B. Trace the Python and python-pydantic-v1 generator paths, then verify that the parent model's from_dict has a working body in generated output for both generators.

Written by the indexing model from the issue text.

Assessment

Tech stack
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.