pydantic / pydantic-settings

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

Crash when `YamlConfigSettingsSource` file contains no items #329

Closed darrenburns closed 3 months ago

darrenburns commented 3 months ago

Hi,

I'm trying to use a yaml file as a settings source, and an exception is being raised when the file contains no items.

This does not occur with the toml settings source.

Here's an example:

from typing import Type
from pydantic import Field
from pydantic_settings import (
    BaseSettings,
    PydanticBaseSettingsSource,
    SettingsConfigDict,
    YamlConfigSettingsSource,
)

class Settings(BaseSettings):
    model_config = SettingsConfigDict(
        extra="allow",
        yaml_file="config.yaml",
    )

    @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 (
            init_settings,
            YamlConfigSettingsSource(settings_cls),
            env_settings,
            dotenv_settings,
            file_secret_settings,
        )

settings = Settings()

The file config.yaml is completely empty.

This crashes with the following exception:

Traceback (most recent call last):
  File "/Users/darrenburns/code/posting/.venv/bin/posting", line 5, in <module>
    from posting.__main__ import cli
  File "/Users/darrenburns/code/posting/src/posting/__main__.py", line 6, in <module>
    from posting.app import Posting
  File "/Users/darrenburns/code/posting/src/posting/app.py", line 35, in <module>
    from posting.config import Settings
  File "/Users/darrenburns/code/posting/src/posting/config.py", line 45, in <module>
    settings = Settings()
               ^^^^^^^^^^
  File "/Users/darrenburns/code/posting/.venv/lib/python3.11/site-packages/pydantic_settings/main.py", line 141, in __init__
    **__pydantic_self__._settings_build_values(
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/darrenburns/code/posting/.venv/lib/python3.11/site-packages/pydantic_settings/main.py", line 284, in _settings_build_values
    sources = self.settings_customise_sources(
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/darrenburns/code/posting/src/posting/config.py", line 38, in settings_customise_sources
    YamlConfigSettingsSource(settings_cls),
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/darrenburns/code/posting/.venv/lib/python3.11/site-packages/pydantic_settings/sources.py", line 1673, in __init__
    self.yaml_data = self._read_files(self.yaml_file_path)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/darrenburns/code/posting/.venv/lib/python3.11/site-packages/pydantic_settings/sources.py", line 1555, in _read_files
    vars.update(self._read_file(file_path))
TypeError: 'NoneType' object is not iterable

Versions:

pydantic==2.7.3
pydantic-core==2.18.4
pydantic-settings==2.3.4
hramezani commented 3 months ago

Thanks @darrenburns for reporting this.

I created https://github.com/pydantic/pydantic-settings/pull/330 as a fix

darrenburns commented 3 months ago

Thanks @hramezani!