openapi-generators / openapi-generators/openapi-python-client
from_dict raises when nullable ref is set to None
Ninguém assumiu esta issue ainda.
- Linguagem predominante
- Python
- Estrelas
- 2k
- Forks
- 293
- Merge médio
- 34min
- PRs com merge (30d)
- 1
Descrição
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)
Guia de contribuição
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Direção de pesquisa
Comece inspecionando os arquivos gerados myapp_client/models/my_object.py e my_child_object.py, especialmente o caminho from_dict mostrado no relatório, e então rastreie qual código do gerador o produz. Compare o tratamento de escalares nullable com o tratamento de $ref nullable. Está concluído quando from_dict aceitar um valor None para myRef sem chamar MyChildObject.from_dict(None), preservando o comportamento de UNSET.
Escrita pelo modelo de indexação a partir do texto da issue.
Avaliação
- Stack de tecnologia
- openapi, python
- Domínio
- tooling
- Tipo de issue
- Bug
- Dificuldade
- 4/5
- Tempo estimado
- 3-5 dias
- Status de atividade
- Estagnada
- Clareza
- Razoavelmente clara
- Facilidade para iniciantes
- 35/100