pydantic / pydantic-settings

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

env_prefix doesn't follow case_sensitive flag in DotEnvSettingsSource #262

Closed appunni-m closed 1 month ago

appunni-m commented 3 months ago
           if not env_used:
                if is_extra_allowed and env_name.startswith(self.env_prefix):
                    # env_prefix should be respected and removed from the env_name
                    normalized_env_name = env_name[len(self.env_prefix) :]
                    data[normalized_env_name] = env_value
                else:
                    data[env_name] = env_value

in class DotEnvSettingsSource(EnvSettingsSource):

env_prefix doesn't follow case_sensitive flag, alias has to be lower case always, as case_insensitive will cause all env var name into lower case, it doesn't do same with env_prefix , as shown in code above

hramezani commented 3 months ago

Please provide more information. Also, it would be great to provide an example that represents your problem. It helps us to find the problem

appunni-m commented 3 months ago
from typing import Dict

from pydantic import Json, Field
from pydantic_settings import BaseSettings

class HttpSettings(BaseSettings):
    base_url: str = Field(alias='BASE_URL')
    headers: Json[Dict[str, str]] = Field(default="{}", alias='HTTP_HEADERS')

if __name__ == "__main__":
    settings = HttpSettings(
      _env_prefix="rather_"
    )

""" .env

RATHER_BASE_URL=http://service.domain.com/api/v1/
RATHER_HTTP_HEADERS={"x-request-id": "default-client-id"}

"""

appunni-m commented 3 months ago
class HttpSettings(LucarioSettings):
    base_url: str = Field(alias='BASE_URL')
    headers: Json[Dict[str, str]] = Field(default="{}", alias='HTTP_HEADERS')

if __name__ == "__main__":
    settings = HttpSettings(
      _env_prefix="RATHER_", _case_sensitive=True
    )

This one works, but _case_sensitive=False is not working. As alias will also validated in case sensitive manner even when _case_sensitive=False

hramezani commented 3 months ago

From the doc:

env_prefix does not apply to fields with alias. It means the environment variable name is the same as field alias:

So, you need to change your example like:

from pydantic import Field, Json
from pydantic_settings import BaseSettings

class HttpSettings(BaseSettings):
    base_url: str = Field(alias='BASE_URL')
    headers: Json[dict[str, str]] = Field(default="{}", alias='HTTP_HEADERS')

if __name__ == "__main__":
    settings = HttpSettings(
      _case_sensitive=True, _env_file='.env'
    )

Then, it works in both sensitive and insensitive cases.