Open jjeff07 opened 8 months ago
Thanks @jjeff07 for this feature request.
You are setting explicitly the value for username
in init and it is the correct behavior.
As this is a rare case, I would like not to accept this feature because adding more flags makes the code base complex.
You can implement your custom InitSettingsSource
and have your desired behavior there.
If I am allowed to set _env_ignore_empty=True
to ignore empty environment variables shouldn't there be a way to do it with init args? For example:
import os
import httpx
from pydantic import BaseModel
from pydantic_settings import BaseSettings
os.environ['password'] = 'world'
class Settings(BaseSettings):
url: str
username: str
password: str
class Client(Settings, BaseModel):
def __init__(self, url=None, username=None, password=None):
super().__init__(url=url, username=username, password=password)
self.client = httpx.Client(base_url=self.url, auth=(self.username, self.password))
client = Client(url='google.com', username='Hello')
"""
(<class 'pydantic_core._pydantic_core.ValidationError'>, 1 validation error for Client
password
Input should be a valid string [type=string_type, input_value=None, input_type=NoneType]
For further information visit https://errors.pydantic.dev/2.6/v/string_type, <traceback object at 0x00000226F8500D80>)
"""
You can have your desired behavior like:
from typing import Any, Tuple, Type
from pydantic_settings import BaseSettings, InitSettingsSource, PydanticBaseSettingsSource, SettingsConfigDict
class MyInitSettingsSource(InitSettingsSource):
def __init__(self, settings_cls: type[BaseSettings], init_kwargs: dict[str, Any]):
init_kwargs = {k: v for k, v in init_kwargs.items() if v is not None}
super().__init__(settings_cls, init_kwargs)
class Settings(BaseSettings):
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", extra="allow")
username: str
@classmethod
def settings_customise_sources(
cls,
settings_cls: Type[BaseSettings],
init_settings: PydanticBaseSettingsSource,
env_settings: PydanticBaseSettingsSource,
dotenv_settings: PydanticBaseSettingsSource,
file_secret_settings: PydanticBaseSettingsSource,
) -> Tuple[PydanticBaseSettingsSource, ...]:
return MyInitSettingsSource(settings_cls, init_settings.init_kwargs), env_settings, dotenv_settings, file_secret_settings
settings = Settings(username=None)
It would be nice if there were no Unresolved References though. Probably why I couldn't figure out a solution as there are no documented examples.
I would like to keep the default order of
init_settings
and thenenv_settings
but if I pass None in the init then it will error.Example:
Implementation: