pydantic / pydantic-core

Core validation logic for pydantic written in rust
MIT License
1.39k stars 232 forks source link

Different behavior for `extra_behavior` and `config.extra_fields_behavior` #1243

Open sydney-runkle opened 6 months ago

sydney-runkle commented 6 months ago

See https://github.com/pydantic/pydantic-core/pull/1236#issuecomment-2012366184 for a more in depth description :)

sydney-runkle commented 1 month ago

The problem here being that these two different ways of specifying extra_behavior result in different results:

from pydantic_core import core_schema, SchemaValidator, SchemaSerializer

class Parent:
    x: int

class Other(Parent):
    y: str

Parent.__pydantic_core_schema__ = core_schema.model_schema(
    Parent,
    core_schema.model_fields_schema(
        {
            'x': core_schema.model_field(core_schema.int_schema()),
        }
    ),
    extra_behavior='allow',
    # config=core_schema.CoreConfig(extra_behavior='allow'),
)
Parent.__pydantic_validator__ = SchemaValidator(Parent.__pydantic_core_schema__)
Parent.__pydantic_serializer__ = SchemaSerializer(Parent.__pydantic_core_schema__)

Other.__pydantic_core_schema__ = core_schema.model_schema(
    Other,
    core_schema.model_fields_schema(
        {
            'x': core_schema.model_field(core_schema.int_schema()),
            'y': core_schema.model_field(core_schema.str_schema()),
        }
    ),
    extra_behavior='forbid',
    # config=core_schema.CoreConfig(extra_behavior='forbid'),
)
Other.__pydantic_validator__ = SchemaValidator(Other.__pydantic_core_schema__)
Other.__pydantic_serializer__ = SchemaSerializer(Other.__pydantic_core_schema__)

other = Other.__pydantic_validator__.validate_python({'x': 1, 'y': 'some string'})
assert Parent.__pydantic_serializer__.to_python(other) == {'x': 1}
sydney-runkle commented 1 month ago

So, the problem is resolved here if you set extra_behavior on both the model and model_fields schemas - should that be the case, or should the model schema push down that setting?

cc @davidhewitt