Skip to content
Open
Show file tree
Hide file tree
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
6 changes: 5 additions & 1 deletion modelopt/torch/opt/config_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,14 +193,18 @@ def _load_raw_config_with_schema(config_file: str | Path | Traversable) -> _RawC
schema = _parse_modelopt_schema(text, config_path)
docs = list(yaml.safe_load_all(text))

if len(docs) == 0 or docs[0] is None:
if len(docs) == 0 or (len(docs) == 1 and docs[0] is None):
return _RawConfig({}, schema=schema, path=config_path)
if len(docs) == 1:
_raw = docs[0]
elif len(docs) == 2:
# Multi-document: first doc is imports/metadata, second is content.
# Merge the imports into the content for downstream resolution.
header, content = docs[0], docs[1]
if header is None:
# An explicit null/empty first document is an empty header, not an
# empty file — the second document still carries the real body.
header = {}
if not isinstance(header, dict):
raise ValueError(
f"Config file {config_path}: first YAML document must be a mapping, "
Expand Down
32 changes: 32 additions & 0 deletions tests/unit/recipe/test_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -1611,6 +1611,38 @@ def test_load_config_multi_doc_null_content(tmp_path):
assert data == {"key": "value"}


def test_load_config_multi_doc_null_header_list_body(tmp_path):
"""Multi-document YAML with a null first doc and a list body keeps the list."""
cfg_file = tmp_path / "null_header_list.yaml"
cfg_file.write_text("null\n---\n- item1\n- item2\n")
data = load_config(cfg_file)
assert data == ["item1", "item2"]


def test_load_config_multi_doc_empty_header_list_body(tmp_path):
"""Multi-document YAML with an empty explicit first doc and a list body keeps the list."""
cfg_file = tmp_path / "empty_header_list.yaml"
cfg_file.write_text("---\n---\n- item1\n")
data = load_config(cfg_file)
assert data == ["item1"]


def test_load_config_multi_doc_null_header_dict_body(tmp_path):
"""Multi-document YAML with a null first doc and a dict body keeps the dict."""
cfg_file = tmp_path / "null_header_dict.yaml"
cfg_file.write_text("~\n---\nkey: value\n")
data = load_config(cfg_file)
assert data == {"key": "value"}


def test_load_config_lone_null_doc(tmp_path):
"""A single explicit null document still loads as an empty dict."""
cfg_file = tmp_path / "lone_null.yaml"
cfg_file.write_text("null\n")
data = load_config(cfg_file)
assert data == {}


def test_load_config_multi_doc_first_not_dict_raises(tmp_path):
"""Multi-document YAML with non-dict first document raises ValueError."""
cfg_file = tmp_path / "bad_multi.yaml"
Expand Down