Skip to content

Commit 0ea364b

Browse files
authored
feat(models): add example scenario mapping (#198)
Expose the grouping of example models into scenarios
1 parent 6a1eb74 commit 0ea364b

4 files changed

Lines changed: 421 additions & 14 deletions

File tree

autotest/test_models.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ def test_models(model_name, files):
3535
assert any(Path(f).name == "mfsim.nam" for f in files)
3636

3737

38+
@pytest.mark.parametrize("example_name, model_names", models.get_examples().items())
39+
def test_get_examples(example_name, model_names):
40+
assert example_name in models.EXAMPLES
41+
for model_name in model_names:
42+
assert model_name in models.MODELMAP
43+
44+
3845
@pytest.mark.parametrize("model_name, files", list(islice(MODELMAP.items(), TAKE)))
3946
def test_copy_to(model_name, files, tmp_path):
4047
workspace = models.copy_to(tmp_path, model_name)

modflow_devtools/make_registry.py

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99
from modflow_devtools.misc import get_model_paths
1010
from modflow_devtools.models import BASE_URL
1111

12-
REGISTRY_PATH = Path(__file__).parent / "registry" / "registry.toml"
12+
REGISTRY_DIR = Path(__file__).parent / "registry"
13+
REGISTRY_PATH = REGISTRY_DIR / "registry.toml"
14+
MODELMAP_PATH = REGISTRY_DIR / "models.toml"
15+
EXAMPLES_PATH = REGISTRY_DIR / "examples.toml"
1316

1417

1518
def _sha256(path: Path) -> str:
@@ -28,21 +31,16 @@ def _sha256(path: Path) -> str:
2831

2932
def write_registry(
3033
path: str | PathLike,
31-
registry_path: str | PathLike,
3234
url: str,
3335
append: bool = False,
3436
):
3537
path = Path(path).expanduser().absolute()
36-
registry_path = Path(registry_path).expanduser().absolute()
37-
modelmap_path = registry_path.parent / "models.toml"
38-
3938
if not path.is_dir():
4039
raise NotADirectoryError(f"Path {path} is not a directory.")
41-
if not registry_path.exists():
42-
registry_path.parent.mkdir(parents=True, exist_ok=True)
4340

4441
registry: dict[str, dict[str, str | None]] = {}
4542
modelmap: dict[str, list[str]] = {}
43+
examples: dict[str, list[str]] = {}
4644
exclude = [".DS_Store", "compare"]
4745
if is_zip := url.endswith((".zip", ".tar")):
4846
registry[url.rpartition("/")[2]] = {"hash": None, "url": url}
@@ -60,10 +58,13 @@ def _find_examples_dir(p):
6058
# then the model names could correspond directly to directory names.
6159
model_path = model_path.expanduser().absolute()
6260
base_path = _find_examples_dir(model_path) if is_zip else path
63-
model_name = (
64-
str(model_path.relative_to(base_path)).replace("/", "_").replace("-", "_")
65-
)
61+
rel_path = model_path.relative_to(base_path)
62+
model_name = str(rel_path).replace("/", "_").replace("-", "_")
6663
modelmap[model_name] = []
64+
if is_zip:
65+
if rel_path.parts[0] not in examples:
66+
examples[rel_path.parts[0]] = []
67+
examples[rel_path.parts[0]].append(model_name)
6768
for p in model_path.glob("*"):
6869
if not p.is_file() or any(e in p.name for e in exclude):
6970
continue
@@ -85,15 +86,19 @@ def drop_none_or_empty(path, key, value):
8586
return False
8687
return True
8788

88-
with registry_path.open("ab+" if append else "wb") as registry_file:
89+
REGISTRY_DIR.mkdir(parents=True, exist_ok=True)
90+
with REGISTRY_PATH.open("ab+" if append else "wb") as registry_file:
8991
tomli.dump(
9092
remap(dict(sorted(registry.items())), visit=drop_none_or_empty),
9193
registry_file,
9294
)
9395

94-
with modelmap_path.open("ab+" if append else "wb") as modelmap_file:
96+
with MODELMAP_PATH.open("ab+" if append else "wb") as modelmap_file:
9597
tomli.dump(dict(sorted(modelmap.items())), modelmap_file)
9698

99+
with EXAMPLES_PATH.open("ab+" if append else "wb") as examples_file:
100+
tomli.dump(dict(sorted(examples.items())), examples_file)
101+
97102

98103
if __name__ == "__main__":
99104
parser = argparse.ArgumentParser(description="Make a registry of example models.")
@@ -113,4 +118,4 @@ def drop_none_or_empty(path, key, value):
113118
args = parser.parse_args()
114119
path = Path(args.path)
115120
url = args.url if args.url else BASE_URL
116-
write_registry(path=path, registry_path=REGISTRY_PATH, url=url, append=args.append)
121+
write_registry(path=path, url=url, append=args.append)

modflow_devtools/models.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
REGISTRY_ANCHOR = f"{modflow_devtools.__name__}.registry"
1919
REGISTRY_FILE_NAME = "registry.toml"
2020
MODELMAP_FILE_NAME = "models.toml"
21+
EXAMPLES_FILE_NAME = "examples.toml"
2122

2223
# the mf6 examples release is our base url
2324
BASE_URL = "https://github.com/MODFLOW-ORG/modflow6-examples/releases/download/current"
@@ -26,7 +27,8 @@
2627
# set up the pooch
2728
FETCHERS = {}
2829
REGISTRY: dict[str, str] = {}
29-
MODELMAP: dict[str, list[Path]] = {}
30+
MODELMAP: dict[str, list[str]] = {}
31+
EXAMPLES: dict[str, list[str]] = {}
3032
POOCH = pooch.create(
3133
path=pooch.os_cache(modflow_devtools.__name__.replace("_", "-")),
3234
base_url=BASE_URL,
@@ -86,6 +88,22 @@ def _fetch_zip(zip_name):
8688
)
8789

8890

91+
try:
92+
with pkg_resources.open_binary(
93+
REGISTRY_ANCHOR, EXAMPLES_FILE_NAME
94+
) as examples_file:
95+
EXAMPLES = tomli.load(examples_file)
96+
except: # noqa: E722
97+
warn(
98+
f"No examples file '{EXAMPLES_FILE_NAME}' "
99+
f"in module '{REGISTRY_ANCHOR}' resources"
100+
)
101+
102+
103+
def get_examples() -> dict[str, list[str]]:
104+
return EXAMPLES
105+
106+
89107
def get_registry() -> dict[str, str]:
90108
return POOCH.registry
91109

0 commit comments

Comments
 (0)