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
3 changes: 2 additions & 1 deletion flopy4/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,9 @@ def _write_contract(outdir: Path, mf6_version: str) -> None:
is_branch = not effective_version[0].isdigit() if effective_version else True
_populate_remote_cache(registry, release_id, force=args.force or is_branch)

dfns_spec = registry.spec(schema_version=_DFN_SCHEMA_VERSION)
make(
dfndir=registry.cache_path if isinstance(registry, RemoteDfnRegistry) else registry.path,
dfns=dfns_spec,
outdir=_MF6_ROOT,
existing_only=not args.all_packages,
makedirs=args.all_packages,
Expand Down
21 changes: 14 additions & 7 deletions flopy4/mf6/utils/codegen/dfn2py.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
from os import PathLike
from pathlib import Path

import modflow_devtools.dfn as dfn

from flopy4.mf6.utils.codegen.make import make_modules

_PROJ_ROOT = Path(__file__).parents[4].expanduser().resolve()
Expand Down Expand Up @@ -41,18 +39,22 @@


def make(
dfndir: str | PathLike,
dfns: dict,
outdir: str | PathLike = _MF6_ROOT,
developmode: bool = False,
makedirs: bool = False,
existing_only: bool = False,
verbose: bool = False,
):
"""Generate an MF6 module from DFNs."""
dfndir = Path(dfndir).expanduser().resolve()
"""Generate an MF6 module from DFNs.

Parameters
----------
dfns :
Pre-loaded DFN dict, e.g. from a registry's `spec()` call.
"""
outdir = Path(outdir).expanduser().resolve()
outdir.mkdir(exist_ok=True, parents=True)
dfns = dfn.Dfn.load_all(dfndir, schema_version="2.0.0.dev1")
components = make_modules(
dfns=dfns,
outdir=outdir,
Expand Down Expand Up @@ -99,9 +101,14 @@ def cli_main() -> None:
parser.add_argument("--verbose", action="store_true")
args = parser.parse_args()

from modflow_devtools.dfns import LocalDfnRegistry

registry = LocalDfnRegistry(path=Path(args.dfndir))
dfns = registry.spec(schema_version="2.0.0.dev1")

try:
make(
dfndir=args.dfndir,
dfns=dfns,
outdir=args.outdir,
developmode=args.developmode,
makedirs=args.makedirs,
Expand Down
12 changes: 2 additions & 10 deletions flopy4/mf6/utils/codegen/make.py
Original file line number Diff line number Diff line change
Expand Up @@ -1101,8 +1101,7 @@ def make_module(spec: ComponentSpec, env: jinja2.Environment, verbose: bool = Fa

def make_modules(
*,
dfns: dict[str, "Dfn"] | None = None,
dfndir: PathLike | None = None,
dfns: dict[str, "Dfn"],
outdir: PathLike,
developmode: bool = False,
skip: set[str] | None = None,
Expand All @@ -1115,10 +1114,7 @@ def make_modules(
Parameters
----------
dfns :
Pre-loaded DFN dict from a registry's spec() call. Takes precedence
over dfndir when both are provided.
dfndir :
Directory containing DFN files. Used only when dfns is not provided.
Pre-loaded DFN dict, e.g. from a registry's spec() call.
outdir :
Root output directory for generated Python files.
developmode :
Expand All @@ -1137,10 +1133,6 @@ def make_modules(
list[ComponentSpec]
Specs for all components that were generated.
"""
if dfns is None:
if dfndir is None:
raise ValueError("Provide either 'dfns' or 'dfndir'.")
dfns = Dfn.load_all(Path(dfndir), schema_version="2.0.0.dev1")
outdir = Path(outdir)
skip = skip or set()
env = _get_env()
Expand Down
24 changes: 12 additions & 12 deletions test/mf6/test_mf6_codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -684,12 +684,12 @@ def test_npf_compound_records_expanded(all_dfns):


# Layer 3: End-to-end generation
def test_simple_tier_generates_importable_files(dfn_path, tmp_path, all_dfns):
def test_simple_tier_generates_importable_files(tmp_path, all_dfns):
"""Run make_all() and verify each simple-tier file is importable with the right class."""
(tmp_path / "gwf").mkdir()

skip = {n for n in all_dfns if n not in SIMPLE_TIER}
specs = make_modules(dfndir=dfn_path, outdir=tmp_path, skip=skip)
specs = make_modules(dfns=all_dfns, outdir=tmp_path, skip=skip)

generated = {s.dfn_name: s for s in specs}

Expand Down Expand Up @@ -722,12 +722,12 @@ def test_simple_tier_generates_importable_files(dfn_path, tmp_path, all_dfns):
assert hasattr(mod, expected_class), f"Class {expected_class} not found in {spec.outpath}"


def test_solution_tier_generates_importable_files(dfn_path, tmp_path, all_dfns):
def test_solution_tier_generates_importable_files(tmp_path, all_dfns):
"""Run make_all() and verify each solution-tier file is importable with Solution base."""
from flopy4.mf6.solution import Solution

skip = {n for n in all_dfns if n not in SOLUTION_TIER}
specs = make_modules(dfndir=dfn_path, outdir=tmp_path, skip=skip)
specs = make_modules(dfns=all_dfns, outdir=tmp_path, skip=skip)

generated = {s.dfn_name: s for s in specs}

Expand Down Expand Up @@ -780,14 +780,14 @@ def _load_class_from_spec(spec, mod_name: str, expected_class: str):
del sys.modules[key]


def test_transport_tier_generates_importable_files(dfn_path, tmp_path, all_dfns):
def test_transport_tier_generates_importable_files(tmp_path, all_dfns):
"""gwt-disv, gwt-ist, gwe-disv generate importable Package subclasses."""
for subdir in ("gwt", "gwe"):
(tmp_path / subdir).mkdir()

target = {n for n in TRANSPORT_TIER if n in all_dfns}
skip = {n for n in all_dfns if n not in target}
specs = make_modules(dfndir=dfn_path, outdir=tmp_path, skip=skip)
specs = make_modules(dfns=all_dfns, outdir=tmp_path, skip=skip)
generated = {s.dfn_name: s for s in specs}

from flopy4.mf6.package import Package
Expand All @@ -802,14 +802,14 @@ def test_transport_tier_generates_importable_files(dfn_path, tmp_path, all_dfns)
assert issubclass(cls, Package)


def test_oc_tier_generates_importable_files(dfn_path, tmp_path, all_dfns):
def test_oc_tier_generates_importable_files(tmp_path, all_dfns):
"""gwt-oc, gwe-oc, prt-oc generate importable Package subclasses with OC period fields."""
for subdir in ("gwt", "gwe", "prt"):
(tmp_path / subdir).mkdir()

target = {n for n in OC_TIER if n in all_dfns}
skip = {n for n in all_dfns if n not in target}
specs = make_modules(dfndir=dfn_path, outdir=tmp_path, skip=skip)
specs = make_modules(dfns=all_dfns, outdir=tmp_path, skip=skip)
generated = {s.dfn_name: s for s in specs}

from flopy4.mf6.package import Package
Expand All @@ -827,13 +827,13 @@ def test_oc_tier_generates_importable_files(dfn_path, tmp_path, all_dfns):
assert oc_fields, f"{dfn_name} should have save_/print_ period fields"


def test_utl_tier_generates_importable_files(dfn_path, tmp_path, all_dfns):
def test_utl_tier_generates_importable_files(tmp_path, all_dfns):
"""utl-* packages generate importable Package subclasses (including utl-tas inner classes)."""
(tmp_path / "utl").mkdir()

target = {n for n in UTL_TIER if n in all_dfns}
skip = {n for n in all_dfns if n not in target}
specs = make_modules(dfndir=dfn_path, outdir=tmp_path, makedirs=True, skip=skip)
specs = make_modules(dfns=all_dfns, outdir=tmp_path, makedirs=True, skip=skip)
generated = {s.dfn_name: s for s in specs}

from flopy4.mf6.package import Package
Expand All @@ -848,13 +848,13 @@ def test_utl_tier_generates_importable_files(dfn_path, tmp_path, all_dfns):
assert issubclass(cls, Package)


def test_exg_tier_generates_importable_files(dfn_path, tmp_path, all_dfns):
def test_exg_tier_generates_importable_files(tmp_path, all_dfns):
"""exg-* packages generate importable Package subclasses (including 0-field pass-only)."""
(tmp_path / "exg").mkdir()

target = {n for n in EXG_TIER if n in all_dfns}
skip = {n for n in all_dfns if n not in target}
specs = make_modules(dfndir=dfn_path, outdir=tmp_path, makedirs=True, skip=skip)
specs = make_modules(dfns=all_dfns, outdir=tmp_path, makedirs=True, skip=skip)
generated = {s.dfn_name: s for s in specs}

from flopy4.mf6.package import Package
Expand Down
Loading