datamodel-code-generator
datamodel-code-generator copied to clipboard
AttributeError: 'NoneType' object has no attribute 'is_list'
Describe the bug
Fail to generate python code with an array of $ref from an allof, an AttributeError has been raised by the lib.
If this is not a bug, please let me know if I'm doing something wrong.
To Reproduce
Example schema:
PetOpts:
type: string
ProjectedPet:
type: object
properties:
id:
type: integer
format: int64
name:
type: string
tag:
type: string
opts:
type: array
items:
$ref: "#/components/schemas/PetOpts"
Pet:
allOf:
- $ref: "#/components/schemas/ProjectedPet"
required:
- id
- name
- opts
Used commandline:
datamodel-codegen --input api.yaml --output model.py --input-file-type openapi --use-annotated --collapse-root-models --use-standard-collections --capitalize-enum-members --target-python-version 3.10 --output-model-type pydantic_v2.BaseModel
Actual behavior
AttributeError: 'NoneType' object has no attribute 'is_list'
Expected behavior
class ProjectedPet(BaseModel):
id: Optional[int] = None
name: Optional[str] = None
tag: Optional[str] = None
opts: Optional[list[str]] = None
class Pet(ProjectedPet):
id: int
name: str
opts: list[str]
Version:
- OS: MacOS 14.6.1
- Python version: 3.11
- datamodel-code-generator version: 0.25.9
Additional context
The traceback
Traceback (most recent call last):
File "/Users/user/work/issue-datamodel-code-generator/.venv/lib/python3.11/site-packages/datamodel_code_generator/__main__.py", line 445, in main
generate(
File "/Users/user/work/issue-datamodel-code-generator/.venv/lib/python3.11/site-packages/datamodel_code_generator/__init__.py", line 473, in generate
results = parser.parse()
^^^^^^^^^^^^^^
File "/Users/user/work/issue-datamodel-code-generator/.venv/lib/python3.11/site-packages/datamodel_code_generator/parser/base.py", line 1366, in parse
self.__collapse_root_models(
File "/Users/user/work/issue-datamodel-code-generator/.venv/lib/python3.11/site-packages/datamodel_code_generator/parser/base.py", line 1015, in __collapse_root_models
elif data_type.parent.is_list:
^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'is_list'
Pet:
allOf:
- $ref: "#/components/schemas/ProjectedPet"
- type: object
required:
- id
- name
- opts
I'm getting the same error with version 0.26.5 and openapi spec https://docs.shipstation.com/_spec/openapi.json?download
$ datamodel-codegen --input ./api_model/openapi-v2-20250131.json --output-model-type pydantic_v2.BaseModel --snake-case-field --allow-extra-fields --use-standard-collections --use-union-operator --force-optional --allow-population-by-field-name --target-python-version=3.11 --collapse-root-models --use-schema-description --capitalise-enum-members --enable-version-header --use-annotated --output-datetime-class datetime
The input file type was determined to be: openapi
This can be specified explicitly with the `--input-file-type` option.
/home/vscode/.local/share/virtualenvs/virtualenv-S6O_fdF0/lib/python3.12/site-packages/datamodel_code_generator/parser/jsonschema.py:341: UserWarning: format of 'url' not understood for 'string' - using default
warn(f'format of {format__!r} not understood for {type_!r} - using default')
Traceback (most recent call last):
File "/home/vscode/.local/share/virtualenvs/virtualenv-S6O_fdF0/lib/python3.12/site-packages/datamodel_code_generator/__main__.py", line 494, in main
generate(
File "/home/vscode/.local/share/virtualenvs/virtualenv-S6O_fdF0/lib/python3.12/site-packages/datamodel_code_generator/__init__.py", line 507, in generate
results = parser.parse()
^^^^^^^^^^^^^^
File "/home/vscode/.local/share/virtualenvs/virtualenv-S6O_fdF0/lib/python3.12/site-packages/datamodel_code_generator/parser/base.py", line 1415, in parse
self.__collapse_root_models(
File "/home/vscode/.local/share/virtualenvs/virtualenv-S6O_fdF0/lib/python3.12/site-packages/datamodel_code_generator/parser/base.py", line 1064, in __collapse_root_models
elif data_type.parent.is_list:
^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'is_list'
As a quick "hack", I edited file datamodel_code_generator/parser/base.py
I changed line 1065 from
elif data_type.parent.is_list:
to
elif data_type.parent and data_type.parent.is_list:
The openapi file now gets converted without an error, it seems correct but I won't know for certain until try to use it.
...
ok, it didn't quite work. There's a custom type that's used in multiple places in this openapi spec file as a list
e.g.
label_ids: Annotated[
list[SeId],
Field(description="An array of the label ids used in this manifest."),
]
My code change causes the type SeId to not render. My workaround for that was to run datamodel-codegen again, without --collapse-root-models, then copy the definition of SeId from that generated python file into the 'broken' file.
class SeId(RootModel[str | None]):
model_config = ConfigDict(
populate_by_name=True,
)
root: Annotated[
str | None,
Field(
description='A string that uniquely identifies a ShipStation resource, such as a carrier, label, shipment, etc.',
examples=['se-28529731'],
max_length=25,
min_length=1,
pattern='^se(-[a-z0-9]+)+$',
title='se_id',
),
] = None
Now pylint pretty much only complains about Unnecessary pass statement, e.g.
class ShippingAddressTo(Address, PartialShippingAddressTo):
pass
model_config = ConfigDict(
extra='allow',
populate_by_name=True,
)
This also occurs with the unmodified base.py .
PR welcome.