pydantic / pydantic-settings

Settings management using pydantic
https://docs.pydantic.dev/latest/usage/pydantic_settings/
MIT License
633 stars 66 forks source link

context not passed to field validators #407

Closed aidanmontare-fed closed 1 month ago

aidanmontare-fed commented 1 month ago

moving here from #pydantic/pydantic#10418

Initial Checks

Description

Hi there! It appears that the context arg that can be passed to model_validate does not work when using Pydantic Settings, when it does work using a regular Pydantic model.

Example Code

Python 3.12.6 (main, Sep 13 2024, 19:07:08) [GCC 11.4.0]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.27.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: from pydantic_settings import *

In [2]: from pydantic import *

In [3]: class Settings(BaseSettings):
   ...:     text: str
   ...:     @field_validator('text')
   ...:     @classmethod
   ...:     def test_validator(cls, v: str, info: ValidationInfo):
   ...:         context = info.context
   ...:         print(f'{context=}')
   ...:         if context:
   ...:             print('have context')
   ...:         return v
   ...:

In [4]: Settings.model_validate({'text': 'foo bar'})
context=None
Out[4]: Settings(text='foo bar')

In [5]: Settings.model_validate({'text': 'foo bar'}, context={'biz': 'baz'}) # can't see context
context=None
Out[5]: Settings(text='foo bar')

In [6]: class Model(BaseModel):
   ...:     text: str
   ...:     @field_validator('text')
   ...:     @classmethod
   ...:     def test_validator(cls, v: str, info: ValidationInfo):
   ...:         context = info.context
   ...:         print(f'{context=}')
   ...:         if context:
   ...:             print('have context')
   ...:         return v
   ...:

In [7]: Model.model_validate({'text': 'foo bar'})
context=None
Out[7]: Model(text='foo bar')

In [8]: Model.model_validate({'text': 'foo bar'}, context={'biz': 'baz'}) # but this one does
context={'biz': 'baz'}
have context
Out[8]: Model(text='foo bar')

In [9]:

Python, Pydantic & OS Version

pydantic version: 2.9.1
        pydantic-core version: 2.23.3
          pydantic-core build: profile=release pgo=false
                 install path: /home/aam7/.pyenv/versions/3.12.6/envs/bug/lib/python3.12/site-packages/pydantic
               python version: 3.12.6 (main, Sep 13 2024, 19:07:08) [GCC 11.4.0]
                     platform: Linux-5.15.153.1-microsoft-standard-WSL2-x86_64-with-glibc2.35
             related packages: typing_extensions-4.12.2 pydantic-settings-2.5.2
                       commit: unknown
hramezani commented 1 month ago

Thanks @aidanmontare-fed for reporting this bug. I will prepare a fix.

hramezani commented 1 month ago

@aidanmontare-fed I created https://github.com/pydantic/pydantic-settings/pull/417 to fix the problem.

Could you please confirm?

aidanmontare-fed commented 1 month ago

@hramezani just checked it out and it works great! Thanks so much!

hramezani commented 1 month ago

Thanks @aidanmontare-fed for reporting the bug and confirming the fix.

The fix will be available in the next release!

hramezani commented 1 week ago

@aidanmontare-fed I have to revert the fix. Actually, the issue is related to pydantic https://github.com/pydantic/pydantic/issues/10062

The fix that I did caused a lot of issues for current users and had to be reverted. Here are some of the issues:

class Settings(BaseSettings):
    text: str

    def __init__(self, **data):
        super().__init__(**data)

    __init__.__pydantic_base_init__ = True

    @field_validator('text')
    @classmethod
    def test_validator(cls, v: str, info: ValidationInfo):
        context = info.context
        print(f'{context=}')
        if context:
            print('have context')
        return v

Settings.model_validate({'text': 'foo bar'}, context={'biz': 'baz'})