Skip to content

Client generation error when primitive types precede object types in a required oneOf / anyOf union #603

Closed
@jselig-rigetti

Description

@jselig-rigetti

The first clause of the to_dict method uses elif instead of if when a model's required property is a oneOf or anyOf union with primitive-type members ordered before object-type members, resulting in a syntax error.

In the mean time, a workaround may be to sort primitive-type members below object-type members as long as each group's members has their ordering maintained among themselves.

Source of issue:

{% if loop.first and property.required and not property.nullable %}{# No if UNSET or if None statement before this #}
if isinstance({{ source }}, {{ inner_property.get_instance_type_string() }}):
{% elif not loop.last or ns.contains_properties_without_transform %}
elif isinstance({{ source }}, {{ inner_property.get_instance_type_string() }}):

Resulting error:

$ openapi-python-client generate --path schema-required-union-ordering.yaml --fail-on-warning
Generating schema-required-union-ordering-client
Error(s) encountered while generating, client was not created

black failed

reformatted schema_required_union_ordering_client/api/__init__.py
reformatted schema_required_union_ordering_client/__init__.py
error: cannot format schema_required_union_ordering_client/models/get_response_200.py: Cannot parse: 23:8:         elif isinstance(self.a, GetResponse200AType1):
reformatted schema_required_union_ordering_client/types.py
reformatted schema_required_union_ordering_client/models/get_response_200a_type_1.py
reformatted schema_required_union_ordering_client/client.py
reformatted schema_required_union_ordering_client/api/default/get.py

Oh no! 💥 💔 💥
6 files reformatted, 2 files left unchanged, 1 file failed to reformat.

Using an example schema-required-union-ordering.yaml file:

openapi: 3.0.2
info:
  title: schema-required-union-ordering
  version: 1.0.0

paths:
  /:
    get:
      description: Test
      responses:
        '200':
          description: Test
          content:
            application/json:
              schema:
                type: object
                required:
                  - a
                properties:
                  a:
                    oneOf: # same error for `anyOf`
                    - type: string
                    - type: object

The problematic schema_required_union_ordering_client/models/get_response_200.py file:

from typing import Any, BinaryIO, Dict, List, Optional, TextIO, Tuple, Type, TypeVar, Union, cast

import attr

from ..models.get_response_200a_type_1 import GetResponse200AType1
from ..types import UNSET, Unset

T = TypeVar("T", bound="GetResponse200")

@attr.s(auto_attribs=True)
class GetResponse200:
    """
    Attributes:
        a (Union[GetResponse200AType1, str]):
    """

    a: Union[GetResponse200AType1, str]
    additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict)


    def to_dict(self) -> Dict[str, Any]:
        
        elif isinstance(self.a, GetResponse200AType1):
            a = self.a.to_dict()

        else:
            a = self.a



        field_dict: Dict[str, Any] = {}
        field_dict.update(self.additional_properties)
        field_dict.update({
            "a": a,
        })

        return field_dict



    @classmethod
    def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
        d = src_dict.copy()
        def _parse_a(data: object) -> Union[GetResponse200AType1, str]:
            try:
                if not isinstance(data, dict):
                    raise TypeError()
                a_type_1 = GetResponse200AType1.from_dict(data)



                return a_type_1
            except: # noqa: E722
                pass
            return cast(Union[GetResponse200AType1, str], data)

        a = _parse_a(d.pop("a"))


        get_response_200 = cls(
            a=a,
        )

        get_response_200.additional_properties = d
        return get_response_200

    @property
    def additional_keys(self) -> List[str]:
        return list(self.additional_properties.keys())

    def __getitem__(self, key: str) -> Any:
        return self.additional_properties[key]

    def __setitem__(self, key: str, value: Any) -> None:
        self.additional_properties[key] = value

    def __delitem__(self, key: str) -> None:
        del self.additional_properties[key]

    def __contains__(self, key: str) -> bool:
        return key in self.additional_properties

Versions

  • Python: 3.7.12
  • openapi-python-client: 0.11.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    🐞bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions