Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dfn): add dfn container, parser, toml conversion script #167

Merged
merged 3 commits into from
Dec 11, 2024
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
5 changes: 2 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ jobs:
- name: Install Python packages
run: |
pip install --upgrade pip
pip install build twine
pip --verbose install .
pip install ".[build]"

- name: Print package version
run: python -c "import modflow_devtools; print(modflow_devtools.__version__)"
Expand Down Expand Up @@ -134,7 +133,7 @@ jobs:

- name: Install Python packages
working-directory: modflow-devtools
run: pip install ".[test]"
run: pip install ".[dev]"

- name: Cache modflow6 examples
id: cache-examples
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -143,4 +143,6 @@ app
bin

**.DS_Store
data_backup
data_backup

autotest/temp/
33 changes: 33 additions & 0 deletions autotest/test_dfn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from pathlib import Path

from modflow_devtools.dfn import Dfn, get_dfns
from modflow_devtools.markers import requires_pkg

PROJ_ROOT = Path(__file__).parents[1]
DFN_PATH = PROJ_ROOT / "autotest" / "temp" / "dfn"
MF6_OWNER = "MODFLOW-USGS"
MF6_REPO = "modflow6"
MF6_REF = "develop"


def pytest_generate_tests(metafunc):
if "dfn_name" in metafunc.fixturenames:
if not any(DFN_PATH.glob("*.dfn")):
get_dfns(MF6_OWNER, MF6_REPO, MF6_REF, DFN_PATH, verbose=True)
dfn_names = [
dfn.stem
for dfn in DFN_PATH.glob("*.dfn")
if dfn.stem not in ["common", "flopy"]
]
metafunc.parametrize("dfn_name", dfn_names, ids=dfn_names)


@requires_pkg("boltons")
def test_dfn_load(dfn_name):
with (
(DFN_PATH / "common.dfn").open() as common_file,
(DFN_PATH / f"{dfn_name}.dfn").open() as dfn_file,
):
common, _ = Dfn._load_v1_flat(common_file)
dfn = Dfn.load(dfn_file, name=dfn_name, common=common)
assert any(dfn)
27 changes: 27 additions & 0 deletions docs/md/dfn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Working with definition files

MODFLOW 6 specifies input components and their variables with a custom file format. Input specification files are called definition (DFN) files and conventionally have suffix `.dfn`.

Work is underway to migrate MODFLOW 6 input specifications to a standard data interchange format. TOML has tentatively been selected.

The `modflow_devtools.dfn` module contains a parser for the legacy DFN format, a format-agnostic representation for input specifications, and a TOML conversion utility.

We envision MODFLOW 6 and FloPy will use these utilities for a relatively short period while the TOML migration is underway. This will involve adapting automated code- and documentation-generation systems in both MF6 and FloPy to consume TOML rather than DFN files. When this is complete, these utilities should no longer be necessary.

## TOML conversion

The `dfn` optional dependency group is necessary to use the TOML conversion utility.

To convert definition files to TOML, use:

```shell
python -m modflow_devtools.dfn.dfn2toml -i <path to dfns> -o <output dir path>
```

### Format

The TOML format is structurally different from the original DFN format: where legacy DFNs are flat lists of variables, with comments demarcating blocks, a TOML input definition is a tree of blocks, each of which contains child variables, each of which can be a scalar or a composite &mdash; composites contain their own child variables. The definition may also contain other top-level attributes besides blocks, so long as they do not conflict with block names.

Children are not explicitly marked as such &mdash; rather children are attached directly to the parent and can be identified by their type (i.e., as a dictionary rather than a scalar).

While structurally different, TOML definition files are visually similar to the DFN format, due to the fact that TOML represents hierarchy with headers, rather than indentation as in YAML.
Loading
Loading