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

Error with --allow-extra-fields on Root Models #2169

Open
felix2246 opened this issue Nov 15, 2024 · 0 comments
Open

Error with --allow-extra-fields on Root Models #2169

felix2246 opened this issue Nov 15, 2024 · 0 comments

Comments

@felix2246
Copy link

felix2246 commented Nov 15, 2024

Hello,
I think this is a bug, but I'm not sure. Maybe I am missing something and the mistake is on my side.
Apologies in advance.

Describe the bug
When I generate my pydantic validators from a json schema and try to import the model class, I get this error:
PydanticUserError: RootModel does not support setting model_config['extra']

I enabled the --allow-extra-fields option. Apparently, this is not allowed for root models.

I import the class like this:

from EmailValidator import EmailValidator

To Reproduce

Example schema:

{
  "$ref": "#/definitions/EmailValidator",
  "definitions": {
    "EmailValidator": {
      "type": "object",
      "properties": {
        "createdAt": {
          "type": "string",
          "format": "date-time"
        },
        "updatedAt": {
          "$ref": "#/definitions/EmailValidator/properties/createdAt"
        },
        "createdBy": {
          "type": "string",
          "minLength": 1
        },
        "state": {
          "type": "string",
          "enum": [
            "draft",
            "scheduled",
            "sending",
            "sent",
            "failed"
          ],
          "default": "draft"
        },
        "sendTime": {
          "$ref": "#/definitions/EmailValidator/properties/createdAt"
        },
        "sendTo": {
          "type": "object",
          "properties": {
            "included": {
              "type": "array",
              "minItems": 1,
              "maxItems": 1,
              "items": [
                {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "enum": [
                        "AI",
                        "ALL_PROFILES"
                      ]
                    }
                  },
                  "required": [
                    "type"
                  ],
                  "additionalProperties": false
                }
              ]
            },
            "excluded": {
              "type": "array",
              "minItems": 0,
              "maxItems": 0,
              "items": []
            }
          },
          "required": [
            "included",
            "excluded"
          ],
          "additionalProperties": false
        },
        "generatedName": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "klaviyoImported": {
          "type": "object",
          "properties": {
            "campaignId": {
              "type": "string",
              "minLength": 1
            },
            "name": {
              "type": "string",
              "minLength": 1
            }
          },
          "required": [
            "campaignId",
            "name"
          ],
          "additionalProperties": false
        },
        "klaviyoCampaignId": {
          "type": "string",
          "minLength": 1
        },
        "stats": {
          "type": "object",
          "properties": {
            "recipients": {
              "type": "integer",
              "minimum": 0
            },
            "opens": {
              "type": "integer",
              "minimum": 0
            },
            "clicks": {
              "type": "integer",
              "minimum": 0
            },
            "revenue": {
              "type": "number",
              "minimum": 0
            },
            "bounces": {
              "type": "integer",
              "minimum": 0
            },
            "mark_as_spam": {
              "type": "integer",
              "minimum": 0
            },
            "unsubscribes": {
              "type": "integer",
              "minimum": 0
            },
            "orders": {
              "type": "integer",
              "minimum": 0,
              "default": 1
            },
            "linkClicks": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "count": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "url_offset": {
                    "type": "integer",
                    "minimum": 0
                  }
                },
                "required": [
                  "url",
                  "count"
                ],
                "additionalProperties": false
              },
              "default": []
            }
          },
          "required": [
            "recipients",
            "opens",
            "clicks",
            "revenue",
            "bounces",
            "mark_as_spam",
            "unsubscribes"
          ],
          "additionalProperties": false
        }
      },
      "additionalProperties": false
    }
  },
  "$schema": "http://json-schema.org/draft-07/schema#"
}

Used commandline:

$ datamodel-codegen --input schema/validatorSchemas --output cron/process-campaigns-and-flows/core/validators --output-model-type=pydantic_v2.BaseModel --target-python-version=3.11 --enum-field-as-literal=all --allow-extra-fields --use-annotated

That's the generated model file:

# generated by datamodel-codegen:
#   filename:  EmailValidator.json
#   timestamp: 2024-11-15T02:41:14+00:00

from __future__ import annotations

from datetime import datetime
from typing import Annotated, List, Literal, Optional

from pydantic import AnyUrl, BaseModel, ConfigDict, Field, RootModel


class IncludedItem(BaseModel):
    model_config = ConfigDict(
        extra="allow",
    )
    type: Literal["AI", "ALL_PROFILES"]


class SendTo(BaseModel):
    model_config = ConfigDict(
        extra="allow",
    )
    included: Annotated[List[IncludedItem], Field(max_length=1, min_length=1)]
    excluded: Annotated[List, Field(max_length=0, min_length=0)]


class KlaviyoImported(BaseModel):
    model_config = ConfigDict(
        extra="allow",
    )
    campaignId: Annotated[str, Field(min_length=1)]
    name: Annotated[str, Field(min_length=1)]


class LinkClick(BaseModel):
    model_config = ConfigDict(
        extra="allow",
    )
    url: AnyUrl
    count: Annotated[int, Field(ge=0)]
    url_offset: Annotated[Optional[int], Field(ge=0)] = None


class Stats(BaseModel):
    model_config = ConfigDict(
        extra="allow",
    )
    recipients: Annotated[int, Field(ge=0)]
    opens: Annotated[int, Field(ge=0)]
    clicks: Annotated[int, Field(ge=0)]
    revenue: Annotated[float, Field(ge=0.0)]
    bounces: Annotated[int, Field(ge=0)]
    mark_as_spam: Annotated[int, Field(ge=0)]
    unsubscribes: Annotated[int, Field(ge=0)]
    orders: Annotated[Optional[int], Field(ge=0)] = 1
    linkClicks: Optional[List[LinkClick]] = []


class CreatedAt(RootModel[datetime]):
    model_config = ConfigDict(
        extra="allow",
    )
    root: datetime


class EmailValidator(BaseModel):
    model_config = ConfigDict(
        extra="allow",
    )
    createdAt: Optional[datetime] = None
    updatedAt: Optional[CreatedAt] = None
    createdBy: Annotated[Optional[str], Field(min_length=1)] = None
    state: Optional[Literal["draft", "scheduled", "sending", "sent", "failed"]] = (
        "draft"
    )
    sendTime: Optional[CreatedAt] = None
    sendTo: Optional[SendTo] = None
    generatedName: Annotated[Optional[str], Field(max_length=255, min_length=1)] = None
    klaviyoImported: Optional[KlaviyoImported] = None
    klaviyoCampaignId: Annotated[Optional[str], Field(min_length=1)] = None
    stats: Optional[Stats] = None


class Model(RootModel[EmailValidator]):
    root: EmailValidator

Expected behavior
Import the model without error

Version:

  • OS: Microsoft Windows [Version 10.0.22631.4169]
  • Python version: 3.11.0
  • datamodel-code-generator version: 0.26.3
@felix2246 felix2246 changed the title Error with extra=allow config on Root Models Error with --allow-extra-fields on Root Models Nov 15, 2024
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

1 participant