Skip to content

Model Validator (before) does not receive alias in inputΒ #696

@RafaelWO

Description

@RafaelWO

I recently upgraded pydantic-settings (2.6.1 -> 2.11.0) and now have the following issue. I have a settings class with fields that have a validation_alias using AliasChoices. I want to use the aliases to deprecate an old field name without breaking changes. Therefore, I added model_validator that checks if old field names are supplied and issues a warning.

# file: alias.py
import warnings
from typing import Any

from pydantic import AliasChoices, Field, model_validator
from pydantic_settings import BaseSettings


class Settings(BaseSettings):
    NAME: str = Field(
        default="",
        validation_alias=AliasChoices("NAME", "OLD_NAME"),
    )
    VALUE: str = Field(
        default="",
        validation_alias=AliasChoices("VALUE", "OLD_VALUE"),
    )

    @model_validator(mode="before")
    def check_for_deprecated_attributes(cls, data: Any) -> Any:
        if isinstance(data, dict):
            print("DEBUG: data", data)
            old_keys = {k for k in data.keys() if k.startswith("OLD_")}
            if old_keys:
                warnings.warn(
                    "The config attributes starting with 'OLD_' are deprecated and will be removed in the"
                    " future. Please remove the prefix 'OLD_'."
                    f" The following deprecated attributes were set: {old_keys!r}",
                    DeprecationWarning,
                    stacklevel=4,
                )
        return data

if __name__ == "__main__":
    settings = Settings(OLD_NAME="foo")

If I run python -Wd alias.py, I get:

DEBUG: data {'NAME': 'foo'}

I.e., the before-validator already receives the "resolved" field name.

But I would expect the following (which works with v2.6.1):

DEBUG: data {'OLD_NAME': 'foo'}
/home/rafael/alias.py:35: DeprecationWarning: The config attributes starting with 'OLD_' are deprecated and will be removed in the future. Please remove the prefix 'OLD_'. The following deprecated attributes were set: {'OLD_NAME'}
  settings = Settings(OLD_NAME="foo")

I don't know whether this is a regression or the new behavior is expected.

Thanks for your feedback! πŸ™‚

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions