datamodel-code-generator
datamodel-code-generator copied to clipboard
Incorrect relative imports when using Modular Schema
Describe the bug When generating models from the openapi specification and when the names of the schemas contain dots, incorrect imports are generated inside init.py for modules that are actually located in the same directory
Only inside init.py the extra dot in the import statement is added. In other generated .py files, imports are generated correct
To Reproduce
Example schema:
{
"openapi": "3.0.2",
"info": {
"title": "Swagger",
"version": "1.0.17"
},
"paths": {
},
"components": {
"schemas": {
"A.B.C": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64",
"example": 10
},
"reference": {
"$ref": "#/components/schemas/A.B.D.E"
}
}
},
"A.B.D.E": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "int64",
"example": 10
}
}
}
}
}
}
Used commandline:
$ datamodel-codegen --input swagger.json --output model --input-file-type openapi
Actual behavior The following file and folder structure was created
.
└── model/
└── A/
├── B/
│ ├── D.py
│ └── __init__.py
└── __init__.py
Code for init.py inside B folder
# generated by datamodel-codegen:
# filename: swagger.json
# timestamp: 2023-10-05T14:48:13+00:00
from __future__ import annotations
from typing import Optional
from pydantic import BaseModel, Field
from .. import D
class C(BaseModel):
id: Optional[int] = Field(None, example=10)
reference: Optional[D.E] = None
There are one extra '.' in 'from .. import D' statement because module D is in the same directory
Trying to use a class from that init.py and getting error
from model.A.B import C
c = C(id=10)
PS C:\Projects\model-test> python .\test.py
Traceback (most recent call last):
File "C:\Projects\model-test\test.py", line 1, in <module>
from model.A.B import C
File "C:\Projects\model-test\model\A\B\__init__.py", line 11, in <module>
from .. import D
ImportError: cannot import name 'D' from 'model.A' (C:\Projects\model-test\model\A\__init__.py)
Expected behavior Relative Import inside init.py should not contain an extra dot in situations where reference to a module in the same directory is used
For init.py code from above it expected to look like this
# generated by datamodel-codegen:
# filename: swagger.json
# timestamp: 2023-10-05T14:48:13+00:00
from __future__ import annotations
from typing import Optional
from pydantic import BaseModel, Field
from . import D
class C(BaseModel):
id: Optional[int] = Field(None, example=10)
reference: Optional[D.E] = None
Version:
- OS: Windows 10
- Python version: 3.10.6
- datamodel-code-generator version: 0.22.0
Additional context I guess such behavior is related to these lines of code in parser/base.py https://github.com/koxudaxi/datamodel-code-generator/blob/60256efafc34377e93640134bbed757e579acfb3/datamodel_code_generator/parser/base.py#L688-L690
Thank you for creating the issue. I'm sorry for my late reply. I found the same issue https://github.com/koxudaxi/datamodel-code-generator/issues/1638
I guess some users use . in schema name. They want to define the schema as a module.
https://github.com/koxudaxi/datamodel-code-generator/blob/979444cdd4cbfbfab489f6f4c9bb09f8eaf8553b/tests/data/openapi/modular.yaml#L243
https://github.com/koxudaxi/datamodel-code-generator/blob/979444cdd4cbfbfab489f6f4c9bb09f8eaf8553b/tests/data/expected/main/main_modular/woo/boo.py#L14
I am considering introducing an option to exclude . from the schema name.
The CLI should Introduce the option as a warning if the model name contains a ..
I think the option is a good solution.
In my case it would be quite enough to exclude . from the title and concat its parts into one PascalCase word to generate just one output file.
But what if it is necessary to maintain a modular structure with all these directories? As I understand, the imports error mentioned in this issue will persist?