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

validate_assignment=True and using a stricter __pydantic_extra__ goes wrong. #10054

Open
1 task done
0Hughman0 opened this issue Aug 5, 2024 · 8 comments
Open
1 task done
Labels
bug V2 Bug related to Pydantic V2

Comments

@0Hughman0
Copy link

0Hughman0 commented Aug 5, 2024

Initial Checks

  • I confirm that I'm using Pydantic V2

Description

When defining a model which has a restriction on __pydantic_extra__, used in conjunction with validate_assignment, assignment of extra attributes causes strange things to happen to __pydantic_extra__ i.e. __pydantic_extra__ is put inside __pydantic_extra__.

The logic that seems to sort out putting extra values into the right place is here:

https://github.com/aaraney/pydantic/blob/91c2bf19f61c610165de72262f723d6f2b233d28/pydantic/main.py#L737-L742

But it appears that prior to that, because validating_assignment=True, we send the new values off to __pydantic_validator__ to to do the validation and setting, where presumably the issue lies.

Or maybe I'm getting muddled up and this is all fine.

Many thanks for the useful library.

Example Code

from typing import Dict
from pydantic import BaseModel, ConfigDict


class Model(BaseModel):
    __pydantic_extra__: Dict[str, int] = {}
    model_config = ConfigDict(extra="allow", 
                              validate_assignment=True)

m = Model()
m.a = 1

assert m.__pydantic_extra__ == {'a': 1}
# Fails as somehow, __pydantic_extra__ = {'__pydantic_extra__': {}, 'a': 1}

Python, Pydantic & OS Version

pydantic version: 2.8.2
        pydantic-core version: 2.20.1
          pydantic-core build: profile=release pgo=true
                 install path: C:\Users\ramme\AppData\Local\pypoetry\Cache\virtualenvs\cassini-UvyUbc-F-py3.8\Lib\site-packages\pydantic
               python version: 3.8.18 (default, Sep 11 2023, 13:47:48) [MSC v.1916 64 bit (AMD64)]
                     platform: Windows-10-10.0.19045-SP0
             related packages: mypy-1.11.0 typing_extensions-4.12.2
                       commit: unknown
@0Hughman0 0Hughman0 added bug V2 Bug related to Pydantic V2 pending Awaiting a response / confirmation labels Aug 5, 2024
@Viicos Viicos removed the pending Awaiting a response / confirmation label Aug 5, 2024
@Viicos
Copy link
Member

Viicos commented Aug 5, 2024

Definitely looks like a bug. Seems like the following code is at play:

https://github.com/pydantic/pydantic-core/blob/a65f3272f002c7663c368aa4708ca706547e3bdb/src/validators/model.rs#L209-L215

@Viicos
Copy link
Member

Viicos commented Aug 5, 2024

You can however omit the = {} assignment to __pydantic_extra__, it will fix your issue.

@0Hughman0
Copy link
Author

Thank you.

I'm really not familiar with pydantic's internals so this all seems very strange to me!

May be worth pointing out that the error persists if one uses the suggested form of __pydantic_extra__ from the docs:

https://docs.pydantic.dev/latest/concepts/models/#extra-fields

i.e.

class Model(BaseModel):
    __pydantic_extra__: Dict[str, int] = Field(init=False)
    model_config = ConfigDict(extra="allow", 
                              validate_assignment=True)

m = Model()
m.a = 1

assert m.__pydantic_extra__ == {'a': 1}
# also fails

@sydney-runkle
Copy link
Member

Hmm, I'm not so convinced this is a bug. This is the behavior I'd expect - a is not defined on the original model, so shouldn't we consider it an extra attribute?

@Viicos
Copy link
Member

Viicos commented Aug 5, 2024

@sydney-runkle the issue is regarding __pydantic_extra__ being set inside __pydantic_extra__ itself

@sydney-runkle
Copy link
Member

Ah yes, that's not right...

@sydney-runkle
Copy link
Member

I presume we can just add an exclusionary rule for that case

@sydney-runkle
Copy link
Member

Just a side note, this is semi related: #9672. We could potentially tackle these at the same time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug V2 Bug related to Pydantic V2
Projects
None yet
Development

No branches or pull requests

3 participants