cdgriffith / Box

Python dictionaries with advanced dot notation access
https://github.com/cdgriffith/Box/wiki
MIT License
2.61k stars 106 forks source link

from_yaml(): Map empty YAML file to empty dict instead of rasing BoxError #177

Closed trallnag closed 3 years ago

trallnag commented 4 years ago

Ruamel YAML will return None if you load an empty file:

  1. Create empty YAML file echo "---" > empty.yml
  2. Run the following:
from ruamel.yaml import YAML
from pathlib import Path

path = Path('/home/jfn/tmp/empty.yml')
yaml = YAML(typ='safe')
data = yaml.load(path)
assert data is None

So when I use the Box function from_yaml() with an empty dict it raises a BoxError.

box.exceptions.BoxError: yaml data not returned as a dictionary but rather a NoneType

    @classmethod
    def from_yaml(
        cls,
        yaml_string: str = None,
        filename: Union[str, PathLike] = None,
        encoding: str = "utf-8",
        errors: str = "strict",
        **kwargs,
    ) -> "Box":
        """
        Transform a yaml object string into a Box object. By default will use SafeLoader.

        :param yaml_string: string to pass to `yaml.load`
        :param filename: filename to open and pass to `yaml.load`
        :param encoding: File encoding
        :param errors: How to handle encoding errors
        :param kwargs: parameters to pass to `Box()` or `yaml.load`
        :return: Box object from yaml data
        """
        box_args = {}
        for arg in kwargs.copy():
            if arg in BOX_PARAMETERS:
                box_args[arg] = kwargs.pop(arg)

        data = _from_yaml(yaml_string=yaml_string, filename=filename, encoding=encoding, errors=errors, **kwargs)
        if not isinstance(data, dict):
>           raise BoxError(f"yaml data not returned as a dictionary but rather a {type(data).__name__}")
E           box.exceptions.BoxError: yaml data not returned as a dictionary but rather a NoneType

It would be nice to return {} instead since I don't think an empty YAML file should lead to an error

trallnag commented 4 years ago

Here is a pytest test:

def test_box_from_empty_yaml_error(tmp_path):
    file_path = tmp_path / "file.yml"
    file_path.write_text("---")

    with pytest.raises(BoxError):
        _ = settings_utils.parse_yamls([file_path.resolve()])
cdgriffith commented 3 years ago

Fixed in https://github.com/cdgriffith/Box/releases/tag/5.3.0