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

Move preferred alias resolution to private method #507

Merged
merged 5 commits into from
Dec 31, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 32 additions & 17 deletions pydantic_settings/sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ def get_field_value(self, field: FieldInfo, field_name: str) -> tuple[Any, str,
field_name: The field name.
Returns:
A tuple contains the key, value and a flag to determine whether value is complex.
A tuple that contains the value, key and a flag to determine whether value is complex.
"""
pass

Expand Down Expand Up @@ -562,12 +562,35 @@ def _replace_env_none_type_values(self, field_value: dict[str, Any]) -> dict[str

return values

def _get_resolved_field_value(self, field: FieldInfo, field_name: str) -> tuple[Any, str, bool]:
"""
Gets the value, the preferred alias key for model creation, and a flag to determine whether value
is complex.
Note:
In V3, this method should either be made public, or, this method should be removed and the
abstract method get_field_value should be updated to include a "use_preferred_alias" flag.
Args:
field: The field.
field_name: The field name.
Returns:
A tuple that contains the value, preferred key and a flag to determine whether value is complex.
"""
field_value, field_key, value_is_complex = self.get_field_value(field, field_name)
if not (value_is_complex or (self.config.get('populate_by_name', False) and (field_key == field_name))):
field_infos = self._extract_field_info(field, field_name)
preferred_key, *_ = field_infos[0]
return field_value, preferred_key, value_is_complex
return field_value, field_key, value_is_complex

def __call__(self) -> dict[str, Any]:
data: dict[str, Any] = {}

for field_name, field in self.settings_cls.model_fields.items():
try:
field_value, field_key, value_is_complex = self.get_field_value(field, field_name)
field_value, field_key, value_is_complex = self._get_resolved_field_value(field, field_name)
except Exception as e:
raise SettingsError(
f'error getting value for field "{field_name}" from source "{self.__class__.__name__}"'
Expand Down Expand Up @@ -675,13 +698,11 @@ def get_field_value(self, field: FieldInfo, field_name: str) -> tuple[Any, str,
field_name: The field name.
Returns:
A tuple contains the key, value if the file exists otherwise `None`, and
A tuple that contains the value (`None` if the file does not exist), key, and
a flag to determine whether value is complex.
"""

field_infos = self._extract_field_info(field, field_name)
preferred_key, *_ = field_infos[0]
for field_key, env_name, value_is_complex in field_infos:
for field_key, env_name, value_is_complex in self._extract_field_info(field, field_name):
# paths reversed to match the last-wins behaviour of `env_file`
for secrets_path in reversed(self.secrets_paths):
path = self.find_case_path(secrets_path, env_name, self.case_sensitive)
Expand All @@ -690,16 +711,14 @@ def get_field_value(self, field: FieldInfo, field_name: str) -> tuple[Any, str,
continue

if path.is_file():
if value_is_complex or (self.config.get('populate_by_name', False) and (field_key == field_name)):
preferred_key = field_key
return path.read_text().strip(), preferred_key, value_is_complex
return path.read_text().strip(), field_key, value_is_complex
else:
warnings.warn(
f'attempted to load secret file "{path}" but found a {path_type_label(path)} instead.',
stacklevel=4,
)

return None, preferred_key, value_is_complex
return None, field_key, value_is_complex

def __repr__(self) -> str:
return f'{self.__class__.__name__}(secrets_dir={self.secrets_dir!r})'
Expand Down Expand Up @@ -742,21 +761,17 @@ def get_field_value(self, field: FieldInfo, field_name: str) -> tuple[Any, str,
field_name: The field name.
Returns:
A tuple contains the key, value if the file exists otherwise `None`, and
A tuple that contains the value (`None` if not found), key, and
a flag to determine whether value is complex.
"""

env_val: str | None = None
field_infos = self._extract_field_info(field, field_name)
preferred_key, *_ = field_infos[0]
for field_key, env_name, value_is_complex in field_infos:
for field_key, env_name, value_is_complex in self._extract_field_info(field, field_name):
env_val = self.env_vars.get(env_name)
if env_val is not None:
if value_is_complex or (self.config.get('populate_by_name', False) and (field_key == field_name)):
preferred_key = field_key
break

return env_val, preferred_key, value_is_complex
return env_val, field_key, value_is_complex

def prepare_field_value(self, field_name: str, field: FieldInfo, value: Any, value_is_complex: bool) -> Any:
"""
Expand Down
Loading