Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"--field-constraints" produces extra "RootModel"s that don't get collapsed by "--collapse-root-models" #2120

Open
xyqyear opened this issue Oct 17, 2024 · 0 comments

Comments

@xyqyear
Copy link

xyqyear commented Oct 17, 2024

Describe the bug

Sometimes "--collapse-root-models" works without "--field-constraints" but fails when using it.

I found this when converting docker compose's spec to pydantic v2 model. I've condensed the problematic part as a schema.

To Reproduce

Example schema:

{
    "properties": {
        "service": {
            "id": "#/definitions/service",
            "type": "object",
            "properties": {
                "annotations": {
                    "$ref": "#/definitions/list_or_dict"
                }
            }
        }
    },
    "additionalProperties": false,
    "definitions": {
        "list_or_dict": {
            "oneOf": [
                {
                    "type": "object",
                    "patternProperties": {
                        ".+": {
                            "type": [
                                "string",
                                "number",
                                "boolean",
                                "null"
                            ]
                        }
                    }
                },
                {
                    "type": "array",
                    "items": {
                        "type": "string"
                    }
                }
            ]
        }
    }
}

Used commandline:

datamodel-codegen --input test.json --output-model-type pydantic_v2.BaseModel --field-constraints --collapse-root-models --output test.py

I get:

from __future__ import annotations

from typing import Dict, List, Optional, Union

from pydantic import BaseModel, ConfigDict, RootModel


class ListOrDict1(RootModel[List[str]]):
    root: List[str]


class Service(BaseModel):
    annotations: Optional[
        Union[Dict[str, Optional[Union[str, float, bool]]], ListOrDict1]
    ] = None


class Model(BaseModel):
    model_config = ConfigDict(
        extra="forbid",
    )
    service: Optional[Service] = None

I expect RootModel be collapsed when using "--collapse-root-models".

When I use this command: (without --field-constraints, but with constr)

datamodel-codegen --input test.json --output-model-type pydantic_v2.BaseModel --collapse-root-models --output test.py

It produces the following result:

from __future__ import annotations

from typing import Dict, List, Optional, Union

from pydantic import BaseModel, ConfigDict, constr


class Service(BaseModel):
    annotations: Optional[
        Union[Dict[constr(pattern=r'.+'), Optional[Union[str, float, bool]]], List[str]]
    ] = None


class Model(BaseModel):
    model_config = ConfigDict(
        extra='forbid',
    )
    service: Optional[Service] = None

As you can see, there is no more RootModel. However this is not optimal because pyright doesn't like constr(...) being a type expression.

Version:

  • OS: Debian 12
  • Python version: 3.12.7
  • datamodel-code-generator version: 0.26.2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants
@xyqyear and others