From 30c1dc9ac3238fbbf51b744f3e86f3c24b06d2c0 Mon Sep 17 00:00:00 2001 From: aduoge <53458900+aduoge@users.noreply.github.com> Date: Tue, 3 Nov 2026 22:48:41 +0800 Subject: [PATCH] fix(config): handle empty config.yaml files yaml.safe_load returns None for an empty file, a comment-only file or a bare document marker. set_envs passed that to flatten_dict, which failed with AttributeError, and since veadk.config calls set_envs at import time, importing veadk failed whenever such a config.yaml was found. Treat a None document as an empty mapping. --- tests/utils/test_empty_config.py | 39 ++++++++++++++++++++++++++++++++ veadk/utils/misc.py | 2 ++ 2 files changed, 41 insertions(+) create mode 100644 tests/utils/test_empty_config.py diff --git a/tests/utils/test_empty_config.py b/tests/utils/test_empty_config.py new file mode 100644 index 000000000..4f8ae7768 --- /dev/null +++ b/tests/utils/test_empty_config.py @@ -0,0 +1,39 @@ +# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Regression tests for empty YAML configuration files.""" + +import pytest + +from veadk.utils.misc import set_envs + + +@pytest.mark.parametrize( + "content", ["", "# Configuration is supplied by environment.\n", "---\n"] +) +def test_set_envs_accepts_empty_yaml(tmp_path, content): + path = tmp_path / "config.yaml" + path.write_text(content, encoding="utf-8") + + assert set_envs(str(path)) == ({}, {}) + + +def test_set_envs_keeps_nested_config_and_environment_precedence(tmp_path, monkeypatch): + path = tmp_path / "config.yaml" + path.write_text("scout_regression:\n option: configured\n", encoding="utf-8") + monkeypatch.setenv("SCOUT_REGRESSION_OPTION", "environment") + + config, environments = set_envs(str(path)) + + assert config == {"scout_regression": {"option": "configured"}} + assert environments == {"SCOUT_REGRESSION_OPTION": "environment"} diff --git a/veadk/utils/misc.py b/veadk/utils/misc.py index cbde5763a..111aecffa 100644 --- a/veadk/utils/misc.py +++ b/veadk/utils/misc.py @@ -136,6 +136,8 @@ def set_envs(config_yaml_path: str, env_from_dotenv: dict = None) -> tuple[dict, with open(config_yaml_path, "r", encoding="utf-8") as yaml_file: config_dict = safe_load(yaml_file) + if config_dict is None: + config_dict = {} flatten_config_dict = flatten_dict(config_dict) config_upper_map = {k.upper(): v for k, v in flatten_config_dict.items()}