Skip to content

Commit 6c0eaae

Browse files
wip
1 parent 9f9b40c commit 6c0eaae

5 files changed

Lines changed: 121 additions & 50 deletions

File tree

docs/source/tutorials/downloadable_example.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ title: Downloadable samples
44

55
# Downloadable samples
66

7+
## First retrieval
8+
79
Retrieving sample examples is as easy as:
810

911
```python
@@ -13,4 +15,8 @@ print(AVAILABLE_EXAMPLES)
1315
print("samples.vki_ls59:", samples.vki_ls59)
1416
```
1517

16-
The first call to `samples.vki_ls59` triggers a download and takes a few seconds, whereas subsequent calls are instantaneous because they reuse the cached sample.
18+
The first call to `samples.vki_ls59` triggers a download and takes a few seconds.
19+
20+
## Cached retrieval
21+
22+
Subsequent calls are instantaneous because they reuse the cached sample.

examples/downloadable_example/__init__.py

Whitespace-only changes.

examples/downloadable_example/sample_example.py

Lines changed: 0 additions & 49 deletions
This file was deleted.

tests/cli/test_plaidcheck.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,26 @@ def test_check_dataset_missing_infos(tmp_path: Path, dataset_name: str) -> None:
7070
assert any(msg.code == "MISSING_PATH" for msg in report.messages)
7171

7272

73+
@pytest.mark.parametrize("dataset_name", _REFERENCE_DATASETS)
74+
def test_check_dataset_missing_required_layout_after_valid_infos(
75+
tmp_path: Path, dataset_name: str
76+
) -> None:
77+
"""Missing layout file (other than infos.yaml) should short-circuit checks."""
78+
dataset_path = _copy_reference_dataset(tmp_path, dataset_name)
79+
if dataset_name == "dataset_cgns":
80+
# CGNS backend only requires infos.yaml + data/.
81+
shutil.rmtree(dataset_path / "data")
82+
else:
83+
(dataset_path / "variable_schema.yaml").unlink()
84+
85+
report = check_dataset(dataset_path)
86+
87+
assert report.has_errors()
88+
assert any(msg.code == "MISSING_PATH" for msg in report.messages)
89+
# The early return on missing layout means we never reach init-related codes.
90+
assert not any(msg.code == "DATASET_INIT_ERROR" for msg in report.messages)
91+
92+
7393
@pytest.mark.parametrize("dataset_name", _REFERENCE_DATASETS)
7494
def test_check_dataset_rejects_extra_infos_key(
7595
tmp_path: Path, dataset_name: str
@@ -643,6 +663,35 @@ def test_check_dataset_sample_conversion_error(tmp_path: Path, monkeypatch) -> N
643663
assert any(msg.code == "SAMPLE_CONVERSION_ERROR" for msg in report.messages)
644664

645665

666+
def test_check_dataset_init_keyerror_reported_as_missing_split(
667+
tmp_path: Path, monkeypatch
668+
) -> None:
669+
"""KeyError raised by `init_from_disk` should map to NUM_SAMPLES_MISSING_SPLIT."""
670+
dataset = _make_minimal_layout(tmp_path)
671+
672+
monkeypatch.setattr(
673+
plaidcheck,
674+
"load_infos_from_disk",
675+
lambda path: _infos({"train": 1}), # noqa: ARG005
676+
)
677+
monkeypatch.setattr(
678+
plaidcheck,
679+
"load_metadata_from_disk",
680+
lambda path: ({"train": {}}, {"Var": {}}, {"train": {}}, None), # noqa: ARG005
681+
)
682+
683+
def _raise_key_error(path): # noqa: ARG001
684+
raise KeyError("ghost_split")
685+
686+
monkeypatch.setattr(plaidcheck, "init_from_disk", _raise_key_error)
687+
688+
report = check_dataset(dataset)
689+
690+
assert any(msg.code == "NUM_SAMPLES_MISSING_SPLIT" for msg in report.messages)
691+
assert any("ghost_split" in msg.message for msg in report.messages)
692+
assert not any(msg.code == "DATASET_INIT_ERROR" for msg in report.messages)
693+
694+
646695
def test_check_dataset_missing_num_samples_split_is_clear(
647696
tmp_path: Path, monkeypatch
648697
) -> None:
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
"""Tests for `plaid.storage.common.writer` validation paths."""
2+
3+
from pathlib import Path
4+
5+
import pytest
6+
7+
from plaid.problem_definition import ProblemDefinition
8+
from plaid.storage.common.writer import save_problem_definitions_to_disk
9+
10+
11+
def _make_pb_def() -> ProblemDefinition:
12+
return ProblemDefinition(
13+
input_features=["Global/in"],
14+
output_features=["Global/out"],
15+
train_split={"train": [0]},
16+
test_split={"test": [0]},
17+
)
18+
19+
20+
def test_save_problem_definitions_to_disk_rejects_non_dict_non_pbdef(
21+
tmp_path: Path,
22+
) -> None:
23+
"""Passing a non-dict, non-ProblemDefinition value should raise TypeError."""
24+
with pytest.raises(TypeError, match=r"dict\[str, ProblemDefinition\]"):
25+
save_problem_definitions_to_disk(tmp_path, [("name", _make_pb_def())]) # type: ignore[arg-type]
26+
27+
28+
def test_save_problem_definitions_to_disk_rejects_non_string_identifier(
29+
tmp_path: Path,
30+
) -> None:
31+
"""Non-string / empty identifiers should raise TypeError."""
32+
pb_def = _make_pb_def()
33+
with pytest.raises(TypeError, match="non-empty strings"):
34+
save_problem_definitions_to_disk(tmp_path, {123: pb_def}) # type: ignore[dict-item]
35+
with pytest.raises(TypeError, match="non-empty strings"):
36+
save_problem_definitions_to_disk(tmp_path, {"": pb_def})
37+
38+
39+
def test_save_problem_definitions_to_disk_rejects_non_pbdef_value(
40+
tmp_path: Path,
41+
) -> None:
42+
"""Non-ProblemDefinition values should raise TypeError."""
43+
with pytest.raises(TypeError, match="ProblemDefinition instances"):
44+
save_problem_definitions_to_disk(tmp_path, {"pb": "not a pb_def"}) # type: ignore[dict-item]
45+
46+
47+
def test_save_problem_definitions_to_disk_rejects_bare_pbdef(tmp_path: Path) -> None:
48+
"""Passing a bare ProblemDefinition (not wrapped in a dict) should raise."""
49+
with pytest.raises(TypeError, match="use the dictionary key as the problem"):
50+
save_problem_definitions_to_disk(tmp_path, _make_pb_def()) # type: ignore[arg-type]
51+
52+
53+
def test_save_problem_definitions_to_disk_writes_each_definition(
54+
tmp_path: Path,
55+
) -> None:
56+
"""Happy path: each ProblemDefinition is delegated to its `save_to_file`."""
57+
pb_defs = {"pb_a": _make_pb_def(), "pb_b": _make_pb_def()}
58+
59+
save_problem_definitions_to_disk(tmp_path, pb_defs)
60+
61+
target_dir = tmp_path / "problem_definitions"
62+
assert target_dir.is_dir()
63+
# ProblemDefinition.save_to_file serialises each definition as a YAML file.
64+
assert (target_dir / "pb_a.yaml").is_file()
65+
assert (target_dir / "pb_b.yaml").is_file()

0 commit comments

Comments
 (0)