Description
First of all, I want to thank all contributors!
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
If a property has an enum setting and is not nullable, API gets 500 error.
requestBody:
content:
application/json:
schema:
type: object
properties:
foo_id:
type: string
enum:
- 'foo'
- 'bar'
openapi-generator version
6.2.0
OpenAPI declaration file content or url
openapi: 3.0.0
info:
description: Appreciate so much contributors
version: 1.0.0
title: Hello OpenAPI
contact:
email: [email protected]
tags:
- name: Tag
description: the Tag
paths:
/foobar/{foo_id}:
get:
tags:
- Tag
summary: foo
description: bar
operationId: foobar_get
parameters:
- in: path
name: foo_id
schema:
type: string
enum:
- 'foo'
- 'bar'
required: true
responses:
'200':
description: foobar
/foobar:
post:
tags:
- Tag
summary: foo
description: bar
operationId: foobar_post
requestBody:
content:
application/json:
schema:
type: object
properties:
foo_id:
type: string
enum:
- 'foo'
- 'bar'
responses:
'200':
description: foobar
Generation Details
openapi-generator generate -i swagger-build.yaml -g python-flask
Python 3.8.12
Steps to reproduce
- Make a parameter with an enum and not nullable in RequestBody
- Generate stub server
- Post a correct param to the API
- Got 500 error
Related issues/PRs
Suggest a fix
It worked in my 5.3.1 generator.
I think the problem is in __init__
function in Autogenerated Model class.
In 5.3.1, member variables in the init function were private (like self._foobar
) but public (self.foobar
) in 6.2.0.
This change causes a problem.
The setter is called forcibly when assigning some variable to a public member like as following sample:
class Foo():
def __init__(self, foo_id=None):
self.foo_id = foo_id ## Setter called (6.2.0)
self._foo_id = foo_id ## Setter doesn't call (5.3.1)
@property
def foo_id(self):
return self._foo_id
@foo.setter
def foo_id(self, foo_id):
print('Setter called')
self._foo_id = foo_id
The detailed problem is in the deserialize_model function that excuted by using `Model.from_dict() function.
def deserialize_model(data, klass):
"""Deserializes list or dict to model.
:param data: dict, list.
:type data: dict | list
:param klass: class literal.
:return: model object.
"""
instance = klass()
if not instance.openapi_types:
return data
for attr, attr_type in six.iteritems(instance.openapi_types):
if data is not None \
and instance.attribute_map[attr] in data \
and isinstance(data, (list, dict)):
value = data[instance.attribute_map[attr]]
setattr(instance, attr, _deserialize(value, attr_type))
return instance
The class is called without any parameters in instance = klass()
and will cause a 500.
In this moment, the param is None and raise ValueError.
Invalid value for `foo_id` (None), must be one of ['foo', 'bar']
I understand the problem, ... but I don't know how it should be so I cannot make any PR.
I'm using nullable: true
setting for the workaround this time.