Skip to content
Merged
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
20 changes: 20 additions & 0 deletions src/datasight/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,11 @@ def load_example_queries(path: str | None, project_dir: str) -> list[dict[str, A
except yaml.YAMLError as e:
logger.warning(f"Failed to parse {path}: {e}")
return []
if data is None:
# Empty or comment-only YAML — yaml.safe_load returns None.
# `datasight generate` writes such scaffolds when nothing is detected,
# so treat this as an empty config rather than warning on every load.
return []
if not isinstance(data, list):
logger.warning(f"Expected a list in {path}, got {type(data).__name__}")
return []
Expand Down Expand Up @@ -300,6 +305,11 @@ def load_measure_overrides(path: str | None, project_dir: str) -> list[dict[str,
except yaml.YAMLError as e:
logger.warning(f"Failed to parse {path}: {e}")
return []
if data is None:
# Empty or comment-only YAML — yaml.safe_load returns None.
# `datasight generate` writes such scaffolds when nothing is detected,
# so treat this as an empty config rather than warning on every load.
return []
if not isinstance(data, list):
logger.warning(f"Expected a list in {path}, got {type(data).__name__}")
return []
Expand Down Expand Up @@ -436,6 +446,11 @@ def load_time_series_config(path: str | None, project_dir: str) -> list[dict[str
except yaml.YAMLError as e:
logger.warning(f"Failed to parse {path}: {e}")
return []
if data is None:
# Empty or comment-only YAML — yaml.safe_load returns None.
# `datasight generate` writes such scaffolds when nothing is detected,
# so treat this as an empty config rather than warning on every load.
return []
if not isinstance(data, list):
logger.warning(f"Expected a list in {path}, got {type(data).__name__}")
return []
Expand Down Expand Up @@ -490,6 +505,11 @@ def load_joins_config(path: str | None, project_dir: str) -> list[dict[str, Any]
except yaml.YAMLError as e:
logger.warning(f"Failed to parse {path}: {e}")
return []
if data is None:
# Empty or comment-only YAML — yaml.safe_load returns None.
# `datasight generate` writes such scaffolds when nothing is detected,
# so treat this as an empty config rather than warning on every load.
return []
if not isinstance(data, list):
logger.warning(f"Expected a list in {path}, got {type(data).__name__}")
return []
Expand Down
3 changes: 3 additions & 0 deletions src/datasight/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ def load_validation_config(
except yaml.YAMLError as e:
logger.warning(f"Failed to parse {path}: {e}")
return []
if data is None:
# Empty or comment-only YAML — yaml.safe_load returns None.
return []
if not isinstance(data, list):
logger.warning(f"Expected a list in {path}, got {type(data).__name__}")
return []
Expand Down
31 changes: 30 additions & 1 deletion tests/test_config_extra.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,10 +253,39 @@ def test_load_time_series_config_invalid_yaml(tmp_path):
assert load_time_series_config(None, str(tmp_path)) == []


def _capture_loguru_warnings():
"""Datasight uses loguru, which bypasses pytest's caplog by default."""
from loguru import logger as _logger

captured: list[str] = []
sink_id = _logger.add(lambda msg: captured.append(str(msg)), level="WARNING")
return captured, lambda: _logger.remove(sink_id)


def test_load_time_series_config_non_list(tmp_path):
p = tmp_path / "time_series.yaml"
p.write_text("foo: bar\n", encoding="utf-8")
assert load_time_series_config(None, str(tmp_path)) == []
captured, cleanup = _capture_loguru_warnings()
try:
assert load_time_series_config(None, str(tmp_path)) == []
finally:
cleanup()
# Genuine wrong-shape input still warns.
assert any("Expected a list" in line for line in captured)


def test_load_time_series_config_comment_only_is_silent(tmp_path):
"""An all-comments scaffold (what `datasight generate` writes when it
finds no timestamp candidates) parses to None — treat as empty silently
rather than warning on every load."""
p = tmp_path / "time_series.yaml"
p.write_text("# datasight time series declarations\n# nothing detected\n", encoding="utf-8")
captured, cleanup = _capture_loguru_warnings()
try:
assert load_time_series_config(None, str(tmp_path)) == []
finally:
cleanup()
assert not any("Expected a list" in line for line in captured)


def test_load_time_series_config_valid_and_invalid_entries(tmp_path):
Expand Down
Loading