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

Field alias AttributeError: 'AliasChoices' object has no attribute 'lower' - CliSettingsSource #303

Closed
SantiagoG opened this issue Jun 6, 2024 · 3 comments · Fixed by #305
Assignees
Labels
bug Something isn't working

Comments

@SantiagoG
Copy link

Description

Field aliases fail when subclassing a model with BaseSettings and using AliasChoices.

Pytest output
/usr/local/lib/python3.11/dist-packages/pydantic_settings/main.py:141: in __init__
    **__pydantic_self__._settings_build_values(
/usr/local/lib/python3.11/dist-packages/pydantic_settings/main.py:260: in _settings_build_values
    CliSettingsSource(
/usr/local/lib/python3.11/dist-packages/pydantic_settings/sources.py:902: in __init__
    self._connect_root_parser(
/usr/local/lib/python3.11/dist-packages/pydantic_settings/sources.py:1236: in _connect_root_parser
    self._add_parser_args(
/usr/local/lib/python3.11/dist-packages/pydantic_settings/sources.py:1255: in _add_parser_args
    for field_name, resolved_name, field_info in self._sort_arg_fields(model):
/usr/local/lib/python3.11/dist-packages/pydantic_settings/sources.py:1154: in _sort_arg_fields
    resolved_name = resolved_name.lower() if not self.case_sensitive else resolved_name
E   AttributeError: 'AliasChoices' object has no attribute 'lower'\

self = EnvSettingsSource(env_nested_delimiter='.', env_prefix_len=0), model = <class 'test_pydantic-settings.test_settings.<locals>.Check'>
    def _sort_arg_fields(self, model: type[BaseModel]) -> list[tuple[str, str, FieldInfo]]:
        positional_args, subcommand_args, optional_args = [], [], []
        fields = model.__pydantic_fields__ if is_pydantic_dataclass(model) else model.model_fields
        for field_name, field_info in fields.items():
            resolved_name = field_name if field_info.alias is None else field_info.alias
>           resolved_name = resolved_name.lower() if not self.case_sensitive else resolved_name
E           AttributeError: 'AliasChoices' object has no attribute 'lower'

Example Code

import pytest

from pydantic import AliasChoices, Field
# from pydantic import BaseModel
from pydantic_settings import BaseSettings


def test_settings():
    class Check(BaseSettings):
    # class Check(BaseModel):  # This works
        field: str = Field(
            "foo",
            alias=AliasChoices(
                "ALIAS_NAME"
            )
        )

    assert Check().field == 'foo'
    assert Check(ALIAS_NAME="bar").field == 'bar'

Expect

For this test to pass with BaseSettings as it does so with BaseModel.

Platform: Ubuntu 22.04.4 LTS (Jammy Jellyfish)
Python version: Python 3.11.9 (main, Apr  6 2024, 17:59:24) [GCC 11.4.0]

pydantic           2.7.3
pydantic_core      2.18.4
pydantic-settings  2.3.0
@hramezani
Copy link
Member

hramezani commented Jun 6, 2024

Thanks @SantiagoG for reporting this.

This is probably related to pydantic-settings new CLI source.

@kschwab Could you please take a look at this? this shouldn't happen because the code does not enable the CLI source and we mentioned in the doc

To enable CLI parsing, we simply set the `cli_parse_args` flag to a valid value, which retains similar conotations as
defined in `argparse`.

Probably we need to check cli_parse_args soon and return fast in CliSettingsSource.__init__ or even don't initialize it

@hramezani hramezani added bug Something isn't working and removed unconfirmed labels Jun 6, 2024
@kschwab
Copy link
Contributor

kschwab commented Jun 6, 2024

@hramezani yes agreed. It's currently getting initialized; we can move it to only initialize if parsing is necessary.

The above is also a bug in CliSettingsSource related to AliasChoices which we can address separately.

@hramezani
Copy link
Member

hramezani commented Jun 11, 2024

the fix has been released in new pydantic-settings 2.3.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants