openapi-generators / openapi-generators/openapi-python-client
from_dict raises when nullable ref is set to None
还没有人认领这个 Issue。
- 主要语言
- Python
- 星标
- 2k
- 派生
- 293
- 平均合并
- 34 分钟
- 30 天内合并 PR
- 1
描述
Describe the bug
from_dict when we set a nullable field ref to None. This behavior:
- differs from class constructor which accepts
Noneref fields - differs from others fields :
from_dictacceptnullablestring,object,array, etc to be set to None
To Reproduce
Steps to reproduce the behavior:
- take the following swagger:
components:
schemas:
MyObject:
properties:
myId:
title: MyId
type: string
nullable: true
myArray:
title: MyArray
type: array
nullable: true
items:
type: string
myString:
title: MyString
type: string
nullable: true
myObject:
title: myObject
type: object
nullable: true
myRef:
$ref: '#/components/schemas/MyChildObject'
nullable: true
required:
- myId
title: MyObject
type: object
MyChildObject:
properties:
aField:
items:
type: string
nullable: true
title: AField
type: array
title: MyChildObject
type: object
info:
title: myapp
version: 1.9.4a5
openapi: 3.0.2
paths:
/myroute:
get:
parameters:
requestBody:
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/MyChildObject'
description: Successful Response
- generate the client from this swagger
- run the following code snippet:
from myapp_client.models import MyObject, MyChildObject
MyObject(my_id="id", my_object=None, my_array=None, my_string=None, my_ref=None) # pass
MyObject.from_dict({"myId":"id", "myObject": None, "myArray": None, "myString": None, "myRef": None}) # raise
MyObject.from_dict({"myId":"id", "myObject": None, "myArray": None, "myString": None}) # pass
- See error
In [1]: from myapp_client.models import MyObject, MyChildObject
In [2]: MyObject(my_id="id", my_object=None, my_array=None, my_string=None, my_ref=None)
Out[2]: MyObject(my_id='id', my_array=None, my_string=None, my_object=None, my_ref=None, additional_properties={})
In [3]: MyObject.from_dict({"myId":"id", "myObject": None, "myArray": None, "myString": None, "myRef": None})
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In [3], line 1
----> 1 MyObject.from_dict({"myId":"id", "myObject": None, "myArray": None, "myString": None, "myRef": None})
File ~/CF/amp-client/myapp-client/myapp_client/models/my_object.py:89, in MyObject.from_dict(cls, src_dict)
87 my_ref = UNSET
88 else:
---> 89 my_ref = MyChildObject.from_dict(_my_ref)
91 my_object = cls(
92 my_id=my_id,
93 my_array=my_array,
(...)
96 my_ref=my_ref,
97 )
99 my_object.additional_properties = d
File ~/CF/amp-client/myapp-client/myapp_client/models/my_child_object.py:38, in MyChildObject.from_dict(cls, src_dict)
36 @classmethod
37 def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
---> 38 d = src_dict.copy()
39 a_field = cast(List[str], d.pop("aField", UNSET))
41 my_child_object = cls(
42 a_field=a_field,
43 )
AttributeError: 'NoneType' object has no attribute 'copy'
In [4]: MyObject.from_dict({"myId":"id", "myObject": None, "myArray": None, "myString": None})
Out[4]: MyObject(my_id='id', my_array=None, my_string=None, my_object=None, my_ref=<myapp_client.types.Unset object at 0x7f9f73a4f8e0>, additional_properties={})
In [5]: MyObject.from_dict({"myId":"id", "myObject": None, "myArray": None, "myString": None})
Expected behavior
We expect MyObject.from_dict({"myId":"id", "myObject": None, "myArray": None, "myString": None, "myRef": None}) to run without errors.
Some debug
having a look in the debugger, it raises there::
_my_ref = d.pop("myRef", UNSET)
my_ref: Union[Unset, MyChildObject]
if isinstance(_my_ref, Unset):
my_ref = UNSET
else:
-> my_ref = MyChildObject.from_dict(_my_ref)
The code generated should rather look like:
_my_ref = d.pop("myRef", UNSET)
my_ref: Union[Unset, None, MyChildObject]
if _my_ref is None:
my_ref = None
elif isinstance(_my_ref, Unset):
my_ref = UNSET
else:
my_ref = MyChildObject.from_dict(_my_ref)
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
调研方向
首先检查生成的 myapp_client/models/my_object.py 和 my_child_object.py,尤其是报告中所示的 from_dict 路径,然后追踪生成它的生成器代码。比较 nullable 标量的处理方式与 nullable $ref 的处理方式。当 from_dict 接受 myRef 的 None 值而不调用 MyChildObject.from_dict(None),同时保留 UNSET 行为时,即表示完成。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- openapi, python
- 领域
- tooling
- Issue 类型
- 缺陷
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 活跃度
- 停滞
- 描述清晰度
- 基本清楚
- 新手友好度
- 35/100