Skip to content

Commit 2dd65bf

Browse files
authored
fix(dfn): restore old dfn2toml logic (#299)
Forgot to split out a separate copy of the TOML conversion script in #271. This makes 1.9.0 breaking, unfortunately. Will need to make a patch release and exclude 1.9.0 from downstream dependencies. Two versions of this script can live side by side for now, until the modflow_devtools.dfns module is properly released with 2.x.
1 parent 0a6ae5d commit 2dd65bf

3 files changed

Lines changed: 141 additions & 96 deletions

File tree

autotest/test_dfns.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
import pytest
55
from packaging.version import Version
66

7-
from modflow_devtools.dfn2toml import convert, is_valid
87
from modflow_devtools.dfns import Dfn, _load_common, load, load_flat
8+
from modflow_devtools.dfns.dfn2toml import convert, is_valid
99
from modflow_devtools.dfns.fetch import fetch_dfns
1010
from modflow_devtools.dfns.schema.v1 import FieldV1
1111
from modflow_devtools.dfns.schema.v2 import FieldV2
1212
from modflow_devtools.markers import requires_pkg
1313

1414
PROJ_ROOT = Path(__file__).parents[1]
15-
DFN_DIR = PROJ_ROOT / "autotest" / "temp" / "dfn"
15+
DFN_DIR = PROJ_ROOT / "autotest" / "temp" / "dfns"
1616
TOML_DIR = DFN_DIR / "toml"
1717
SPEC_DIRS = {1: DFN_DIR, 2: TOML_DIR}
1818
MF6_OWNER = "MODFLOW-ORG"

modflow_devtools/dfn2toml.py

Lines changed: 14 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,126 +1,46 @@
11
"""Convert DFNs to TOML."""
22

33
import argparse
4-
import sys
5-
import textwrap
6-
from dataclasses import asdict
74
from os import PathLike
85
from pathlib import Path
96

107
import tomli_w as tomli
118
from boltons.iterutils import remap
129

13-
from modflow_devtools.dfns import Dfn, is_valid, load, load_flat, map, to_flat, to_tree
14-
from modflow_devtools.dfns.schema.block import block_sort_key
15-
from modflow_devtools.misc import drop_none_or_empty
10+
from modflow_devtools.dfn import Dfn
1611

1712
# mypy: ignore-errors
1813

1914

20-
def convert(inpath: PathLike, outdir: PathLike, schema_version: str = "2") -> None:
21-
"""
22-
Convert DFN files in `inpath` to TOML files in `outdir`.
23-
By default, convert the definitions to schema version 2.
24-
"""
25-
inpath = Path(inpath).expanduser().absolute()
15+
def convert(indir: PathLike, outdir: PathLike):
16+
indir = Path(indir).expanduser().absolute()
2617
outdir = Path(outdir).expanduser().absolute()
2718
outdir.mkdir(exist_ok=True, parents=True)
19+
for dfn in Dfn.load_all(indir).values():
20+
with Path.open(outdir / f"{dfn['name']}.toml", "wb") as f:
2821

29-
if inpath.is_file():
30-
if inpath.name == "common.dfn":
31-
raise ValueError("Cannot convert common.dfn as a standalone file")
22+
def drop_none_or_empty(path, key, value):
23+
if value is None or value == "" or value == [] or value == {}:
24+
return False
25+
return True
3226

33-
common_path = inpath.parent / "common.dfn"
34-
if common_path.exists():
35-
with common_path.open() as f:
36-
from modflow_devtools.dfn import parse_dfn
37-
38-
common, _ = parse_dfn(f)
39-
else:
40-
common = {}
41-
42-
with inpath.open() as f:
43-
dfn = load(f, name=inpath.stem, common=common, format="dfn")
44-
45-
dfn = map(dfn, schema_version=schema_version)
46-
_convert(dfn, outdir / f"{inpath.stem}.toml")
47-
else:
48-
dfns = {
49-
name: map(dfn, schema_version=schema_version) for name, dfn in load_flat(inpath).items()
50-
}
51-
tree = to_tree(dfns)
52-
flat = to_flat(tree)
53-
for dfn_name, dfn in flat.items():
54-
_convert(dfn, outdir / f"{dfn_name}.toml")
55-
56-
57-
def _convert(dfn: Dfn, outpath: Path) -> None:
58-
with Path.open(outpath, "wb") as f:
59-
# TODO if we start using c/attrs, swap out
60-
# all this for a custom unstructuring hook
61-
dfn_dict = asdict(dfn)
62-
dfn_dict["schema_version"] = str(dfn_dict["schema_version"])
63-
if blocks := dfn_dict.pop("blocks", None):
64-
for block_name, block_fields in blocks.items():
65-
if block_name not in dfn_dict:
66-
dfn_dict[block_name] = {}
67-
for field_name, field_data in block_fields.items():
68-
dfn_dict[block_name][field_name] = field_data
69-
70-
tomli.dump(
71-
dict(
72-
sorted(
73-
remap(dfn_dict, visit=drop_none_or_empty).items(),
74-
key=block_sort_key,
75-
)
76-
),
77-
f,
78-
)
27+
tomli.dump(remap(dfn, visit=drop_none_or_empty), f)
7928

8029

8130
if __name__ == "__main__":
82-
"""
83-
Convert DFN files in the original format and schema version 1
84-
to TOML files, by default also converting to schema version 2.
85-
"""
31+
"""Convert DFN files to TOML."""
8632

87-
parser = argparse.ArgumentParser(
88-
description="Convert DFN files to TOML.",
89-
epilog=textwrap.dedent(
90-
"""\
91-
Convert DFN files in the original format and schema version 1
92-
to TOML files, by default also converting to schema version 2.
93-
"""
94-
),
95-
)
33+
parser = argparse.ArgumentParser(description="Convert DFN files to TOML.")
9634
parser.add_argument(
9735
"--indir",
9836
"-i",
9937
type=str,
100-
help="Directory containing DFN files, or a single DFN file.",
38+
help="Directory containing DFN files.",
10139
)
10240
parser.add_argument(
10341
"--outdir",
10442
"-o",
10543
help="Output directory.",
10644
)
107-
parser.add_argument(
108-
"--schema-version",
109-
"-s",
110-
type=str,
111-
default="2",
112-
help="Schema version to convert to.",
113-
)
114-
parser.add_argument(
115-
"--validate",
116-
"-v",
117-
action="store_true",
118-
help="Validate DFN files without converting them.",
119-
)
12045
args = parser.parse_args()
121-
122-
if args.validate:
123-
if not is_valid(args.indir):
124-
sys.exit(1)
125-
else:
126-
convert(args.indir, args.outdir, args.schema_version)
46+
convert(args.indir, args.outdir)

modflow_devtools/dfns/dfn2toml.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
"""Convert DFNs to TOML."""
2+
3+
import argparse
4+
import sys
5+
import textwrap
6+
from dataclasses import asdict
7+
from os import PathLike
8+
from pathlib import Path
9+
10+
import tomli_w as tomli
11+
from boltons.iterutils import remap
12+
13+
from modflow_devtools.dfns import Dfn, is_valid, load, load_flat, map, to_flat, to_tree
14+
from modflow_devtools.dfns.parse import parse_dfn
15+
from modflow_devtools.dfns.schema.block import block_sort_key
16+
from modflow_devtools.misc import drop_none_or_empty
17+
18+
# mypy: ignore-errors
19+
20+
21+
def convert(inpath: PathLike, outdir: PathLike, schema_version: str = "2") -> None:
22+
"""
23+
Convert DFN files in `inpath` to TOML files in `outdir`.
24+
By default, convert the definitions to schema version 2.
25+
"""
26+
inpath = Path(inpath).expanduser().absolute()
27+
outdir = Path(outdir).expanduser().absolute()
28+
outdir.mkdir(exist_ok=True, parents=True)
29+
30+
if inpath.is_file():
31+
if inpath.name == "common.dfn":
32+
raise ValueError("Cannot convert common.dfn as a standalone file")
33+
34+
common_path = inpath.parent / "common.dfn"
35+
if common_path.exists():
36+
with common_path.open() as f:
37+
common, _ = parse_dfn(f)
38+
else:
39+
common = {}
40+
41+
with inpath.open() as f:
42+
dfn = load(f, name=inpath.stem, common=common, format="dfn")
43+
44+
dfn = map(dfn, schema_version=schema_version)
45+
_convert(dfn, outdir / f"{inpath.stem}.toml")
46+
else:
47+
dfns = {
48+
name: map(dfn, schema_version=schema_version) for name, dfn in load_flat(inpath).items()
49+
}
50+
tree = to_tree(dfns)
51+
flat = to_flat(tree)
52+
for dfn_name, dfn in flat.items():
53+
_convert(dfn, outdir / f"{dfn_name}.toml")
54+
55+
56+
def _convert(dfn: Dfn, outpath: Path) -> None:
57+
with Path.open(outpath, "wb") as f:
58+
# TODO if we start using c/attrs, swap out
59+
# all this for a custom unstructuring hook
60+
dfn_dict = asdict(dfn)
61+
dfn_dict["schema_version"] = str(dfn_dict["schema_version"])
62+
if blocks := dfn_dict.pop("blocks", None):
63+
for block_name, block_fields in blocks.items():
64+
if block_name not in dfn_dict:
65+
dfn_dict[block_name] = {}
66+
for field_name, field_data in block_fields.items():
67+
dfn_dict[block_name][field_name] = field_data
68+
69+
tomli.dump(
70+
dict(
71+
sorted(
72+
remap(dfn_dict, visit=drop_none_or_empty).items(),
73+
key=block_sort_key,
74+
)
75+
),
76+
f,
77+
)
78+
79+
80+
if __name__ == "__main__":
81+
"""
82+
Convert DFN files in the original format and schema version 1
83+
to TOML files, by default also converting to schema version 2.
84+
"""
85+
86+
parser = argparse.ArgumentParser(
87+
description="Convert DFN files to TOML.",
88+
epilog=textwrap.dedent(
89+
"""\
90+
Convert DFN files in the original format and schema version 1
91+
to TOML files, by default also converting to schema version 2.
92+
"""
93+
),
94+
)
95+
parser.add_argument(
96+
"--indir",
97+
"-i",
98+
type=str,
99+
help="Directory containing DFN files, or a single DFN file.",
100+
)
101+
parser.add_argument(
102+
"--outdir",
103+
"-o",
104+
help="Output directory.",
105+
)
106+
parser.add_argument(
107+
"--schema-version",
108+
"-s",
109+
type=str,
110+
default="2",
111+
help="Schema version to convert to.",
112+
)
113+
parser.add_argument(
114+
"--validate",
115+
"-v",
116+
action="store_true",
117+
help="Validate DFN files without converting them.",
118+
)
119+
args = parser.parse_args()
120+
121+
if args.validate:
122+
if not is_valid(args.indir):
123+
sys.exit(1)
124+
else:
125+
convert(args.indir, args.outdir, args.schema_version)

0 commit comments

Comments
 (0)