|
| 1 | +import argparse |
| 2 | +import hashlib |
| 3 | +from pathlib import Path |
| 4 | + |
| 5 | +import tomli_w as tomli |
| 6 | + |
| 7 | +from modflow_devtools.misc import get_model_paths |
| 8 | + |
| 9 | +REPO_OWNER = "MODFLOW-ORG" |
| 10 | +REPO_NAME = "modflow-devtools" |
| 11 | +REPO_REF = "develop" |
| 12 | +PROJ_ROOT = Path(__file__).parents[1] |
| 13 | +DATA_RELPATH = "data" |
| 14 | +DATA_PATH = PROJ_ROOT / REPO_NAME / DATA_RELPATH |
| 15 | +REGISTRY_PATH = DATA_PATH / "registry.txt" |
| 16 | +MODELS_PATH = DATA_PATH / "models.toml" |
| 17 | +BASE_URL = f"https://github.com/{REPO_OWNER}/{REPO_NAME}/raw/{REPO_REF}/{DATA_RELPATH}/" |
| 18 | + |
| 19 | + |
| 20 | +def _sha256(path: Path) -> str: |
| 21 | + """ |
| 22 | + Compute the SHA256 hash of the given file. |
| 23 | + Reference: https://stackoverflow.com/a/44873382/6514033 |
| 24 | + """ |
| 25 | + h = hashlib.sha256() |
| 26 | + b = bytearray(128 * 1024) |
| 27 | + mv = memoryview(b) |
| 28 | + with path.open("rb", buffering=0) as f: |
| 29 | + for n in iter(lambda: f.readinto(mv), 0): |
| 30 | + h.update(mv[:n]) |
| 31 | + return h.hexdigest() |
| 32 | + |
| 33 | + |
| 34 | +def write_registry( |
| 35 | + path: Path, registry_path: Path, base_url: str, append: bool = False |
| 36 | +): |
| 37 | + if not registry_path.exists(): |
| 38 | + registry_path.parent.mkdir(parents=True, exist_ok=True) |
| 39 | + |
| 40 | + models = {} |
| 41 | + exclude = [".DS_Store"] |
| 42 | + with registry_path.open("a+" if append else "w") as f: |
| 43 | + if not path.is_dir(): |
| 44 | + raise NotADirectoryError(f"Path {path} is not a directory.") |
| 45 | + for mp in get_model_paths(path): |
| 46 | + for p in mp.rglob("*"): |
| 47 | + if "compare" in str(p): |
| 48 | + continue |
| 49 | + if p.is_file() and not any(e in p.name for e in exclude): |
| 50 | + relpath = p.relative_to(path) |
| 51 | + name = str(relpath).replace("/", "_").replace("-", "_") |
| 52 | + hash = _sha256(p) |
| 53 | + url = f"{base_url}/{relpath!s}" |
| 54 | + line = f"{name} {hash} {url}" |
| 55 | + f.write(line + "\n") |
| 56 | + key = str(relpath.parent).replace("/", "_").replace("-", "_") |
| 57 | + if key not in models: |
| 58 | + models[key] = [] |
| 59 | + models[key].append(name) |
| 60 | + |
| 61 | + models_path = registry_path.parent / "models.toml" |
| 62 | + with models_path.open("ab+" if append else "wb") as mf: |
| 63 | + tomli.dump(models, mf) |
| 64 | + |
| 65 | + |
| 66 | +if __name__ == "__main__": |
| 67 | + parser = argparse.ArgumentParser(description="Convert DFN files to TOML.") |
| 68 | + parser.add_argument( |
| 69 | + "--path", |
| 70 | + "-p", |
| 71 | + type=str, |
| 72 | + help="Directory containing model directories.", |
| 73 | + ) |
| 74 | + parser.add_argument( |
| 75 | + "--append", |
| 76 | + "-a", |
| 77 | + action="store_true", |
| 78 | + help="Append to the registry file instead of overwriting.", |
| 79 | + ) |
| 80 | + parser.add_argument( |
| 81 | + "--base-url", |
| 82 | + "-b", |
| 83 | + type=str, |
| 84 | + help="Base URL for the registry file.", |
| 85 | + ) |
| 86 | + args = parser.parse_args() |
| 87 | + path = Path(args.path) if args.path else DATA_PATH |
| 88 | + base_url = args.base_url if args.base_url else BASE_URL |
| 89 | + |
| 90 | + write_registry(path, REGISTRY_PATH, base_url, args.append) |
0 commit comments