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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ jobs:
working-directory: modflow-devtools/autotest
env:
REPOS_PATH: ${{ github.workspace }}
MODFLOW_DEVTOOLS_NO_AUTO_SYNC: 1
MODFLOW_DEVTOOLS_AUTO_SYNC: 0
TEST_DFN_PATH: ${{ github.workspace }}/modflow6/doc/mf6io/mf6ivar/dfn
# use --dist loadfile to so tests requiring pytest-virtualenv run on the same worker
run: uv run pytest -v -n auto --dist loadfile --durations 0 --ignore test_download.py --ignore test_models.py --ignore test_dfns_registry.py
Expand Down
36 changes: 10 additions & 26 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,19 @@
### Version 1.9.0
### Version 1.9.1

#### New features
#### Bug fixes

* [feat(misc)](https://github.com/MODFLOW-ORG/modflow-devtools/commit/910a1f1d201c262e218da27865b7e9487271e4d2): Add verbose option to set_dir (#258). Committed by wpbonelli on 2025-11-06.
* [feat(models)](https://github.com/MODFLOW-ORG/modflow-devtools/commit/c8a136872198e1d9f36be74e958d003cdc75f6eb): Improve models API (#268). Committed by wpbonelli on 2026-01-15.
* [feat(programs)](https://github.com/MODFLOW-ORG/modflow-devtools/commit/5e85417270cea1b4e5081d531c8c98b072acc371): Add programs API (#270). Committed by wpbonelli on 2026-01-16.
* [feat(version)](https://github.com/MODFLOW-ORG/modflow-devtools/commit/f9e26de1efdda95d509c0cc0cb1cf886a3f6c278): Add project version management tool (#284). Committed by wpbonelli on 2026-02-13.
* [feat(dfns)](https://github.com/MODFLOW-ORG/modflow-devtools/commit/aa99c56f5bc5fc2e846262d5bb5c6d80dc9d69b9): Improve DFNs API (#271). Committed by wpbonelli on 2026-02-23.
* [feat(models)](https://github.com/MODFLOW-ORG/modflow-devtools/commit/c430e8b26157e954a5543344b083125dc5b2ed18): Add copy command (#295). Committed by wpbonelli on 2026-02-25.
* [fix(dfn)](https://github.com/MODFLOW-ORG/modflow-devtools/commit/2dd65bf57307aa42a6043aca3e6da8f8253dc4f9): Restore old dfn2toml logic (#299). Committed by wpbonelli on 2026-03-04.
* [fix](https://github.com/MODFLOW-ORG/modflow-devtools/commit/1e94d1bae8d33acf27becce3560bec092922dc35): Fix version comparison, improve autosync behavior (#300). Committed by wpbonelli on 2026-03-04.

#### Bug fixes
### Version 1.9.0

#### New features

* [fix(models)](https://github.com/MODFLOW-ORG/modflow-devtools/commit/d736dfd881cbc39d2fe82180d98d1d2a0130f146): Backwards-compatibility adjustments (#272). Committed by wpbonelli on 2026-01-20.
* [fix(models)](https://github.com/MODFLOW-ORG/modflow-devtools/commit/a1497797fc9b1a7cf4ed7cd72e43f0b290fd49d4): Miscellaneous fixes (#273). Committed by wpbonelli on 2026-01-21.
* [fix(models)](https://github.com/MODFLOW-ORG/modflow-devtools/commit/5dce2af85369063d037c58a3bfc12a2e32c74770): Check env var before auto-sync, fix tests (#275). Committed by wpbonelli on 2026-01-23.
* [fix(models)](https://github.com/MODFLOW-ORG/modflow-devtools/commit/f6cc9bbbcc8577a4384e18159597c128181e3ecf): Exclude output files from registries (#274). Committed by wpbonelli on 2026-01-23.
* [fix(models)](https://github.com/MODFLOW-ORG/modflow-devtools/commit/5aa924836fe700bb7ccf4c56faeea52b72368bb5): Auto-sync only on api commands (#277). Committed by wpbonelli on 2026-02-10.
* [fix(programs)](https://github.com/MODFLOW-ORG/modflow-devtools/commit/2674176f6151814fa158269478015b1b175ba884): Exe path at program or dist level, add tests, update docs (#281). Committed by wpbonelli on 2026-02-11.
* [fix(programs)](https://github.com/MODFLOW-ORG/modflow-devtools/commit/a9584012258e5ca52be86a7d631da2f0bf10b75c): Multiple fixes/improvements (#282). Committed by wpbonelli on 2026-02-12.
* [fix](https://github.com/MODFLOW-ORG/modflow-devtools/commit/18af51ae53bf1c8fb877620b0fa26e7be28ea210): More fixes/improvements (#283). Committed by wpbonelli on 2026-02-12.
* [fix](https://github.com/MODFLOW-ORG/modflow-devtools/commit/448993522772773ea650206e94185ad8ec72bb83): Multiple fixes (#285). Committed by wpbonelli on 2026-02-20.
* [fix(models)](https://github.com/MODFLOW-ORG/modflow-devtools/commit/02ab50dac6540191914506329dcc9ef52820f7ff): Fix model registry generation from release assets (#290). Committed by wpbonelli on 2026-02-23.
* [fix(dfn)](https://github.com/MODFLOW-ORG/modflow-devtools/commit/ebaffb9e2d364210789cd003a5654f4d6741436d): Restore dfn module and tests (#291). Committed by wpbonelli on 2026-02-23.
* [fix(tests)](https://github.com/MODFLOW-ORG/modflow-devtools/commit/d83dfa9470c619693c36da2aacd526916141aec1): Fix test branch (#292). Committed by wpbonelli on 2026-02-24.
* [fix(models)](https://github.com/MODFLOW-ORG/modflow-devtools/commit/9dfa972efffe310f5de79fa31cdc0235716edc2c): Don't exclude .obs files when copying input files (#293). Committed by wpbonelli on 2026-02-25.
This release improves the architecture of the models API, decoupling model repositories from devtools and adding a CLI. The improvements should all be backwards-compatible.

#### Refactoring
This release also contains an experimental programs API that can be used to inspect available versions of MODFLOW 6 and related programs, and help with installs, as well as an experimental redesign of the MF6 DFN specification file utilities.

* [refactor(programs)](https://github.com/MODFLOW-ORG/modflow-devtools/commit/bb76dc1c36f235b3e8bd5b10231661081dda7fe9): Multiple programs api improvements (#276). Committed by wpbonelli on 2026-02-09.
* [refactor(registries)](https://github.com/MODFLOW-ORG/modflow-devtools/commit/75c6909a6202da02b30a1b7b5743e75498aa26a7): Leaner model/program registry file contents (#279). Committed by wpbonelli on 2026-02-10.
* [refactor(dependencies)](https://github.com/MODFLOW-ORG/modflow-devtools/commit/fa8c8d9753da38a9a400c0f7d736944d08a3a059): Introduce ecosystem group (#289). Committed by wpbonelli on 2026-02-22.
The aim here is to unify this project's ecosystem management utilities with consistent design and UX once we reach version 2. No breaking changes (and new stuff will stay experimental) for the remainder of 1.x.

### Version 1.8.0

Expand Down
4 changes: 2 additions & 2 deletions autotest/test_dfns.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
import pytest
from packaging.version import Version

from modflow_devtools.dfn2toml import convert, is_valid
from modflow_devtools.dfns import Dfn, _load_common, load, load_flat
from modflow_devtools.dfns.dfn2toml import convert, is_valid
from modflow_devtools.dfns.fetch import fetch_dfns
from modflow_devtools.dfns.schema.v1 import FieldV1
from modflow_devtools.dfns.schema.v2 import FieldV2
from modflow_devtools.markers import requires_pkg

PROJ_ROOT = Path(__file__).parents[1]
DFN_DIR = PROJ_ROOT / "autotest" / "temp" / "dfn"
DFN_DIR = PROJ_ROOT / "autotest" / "temp" / "dfns"
TOML_DIR = DFN_DIR / "toml"
SPEC_DIRS = {1: DFN_DIR, 2: TOML_DIR}
MF6_OWNER = "MODFLOW-ORG"
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

project = "modflow-devtools"
author = "MODFLOW Team"
release = "1.9.0"
release = "1.9.1"

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
Expand Down
4 changes: 2 additions & 2 deletions docs/md/dev/dfns.md
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ status = get_sync_status()
- **At install time**: Best-effort sync to default refs during package installation (fail silently on network errors)
- **On first use**: If registry cache is empty for requested ref, attempt to sync before raising errors
- **Lazy loading**: Don't sync until DFN access is actually requested
- **Configurable**: Users can disable auto-sync via environment variable: `MODFLOW_DEVTOOLS_NO_AUTO_SYNC=1`
- **Configurable (Experimental)**: Auto-sync is opt-in via environment variable: `MODFLOW_DEVTOOLS_AUTO_SYNC=1` (set to "1", "true", or "yes")

### Source repository integration

Expand Down Expand Up @@ -1295,7 +1295,7 @@ dfn.name # attribute access
5. Implement `sync_dfns()` function
6. Add registry metadata caching with hash verification
7. Implement version-controlled registry discovery
8. Add auto-sync on first use (with opt-out via `MODFLOW_DEVTOOLS_NO_AUTO_SYNC`)
8. Add auto-sync on first use (opt-in via `MODFLOW_DEVTOOLS_AUTO_SYNC` while experimental)
9. **Implement `DfnSpec` dataclass** with `Mapping` protocol for single canonical hierarchical representation with flat dict access

**CLI and module API** (depends on Registry infrastructure):
Expand Down
2 changes: 1 addition & 1 deletion docs/md/dev/programs.md
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ status = get_sync_status()

- **At install time**: Best-effort sync during package installation (fail silently on network errors)
- **On first use**: If registry cache is empty, attempt to sync before raising errors
- **Configurable**: Users can disable auto-sync via environment variable: `MODFLOW_DEVTOOLS_NO_AUTO_SYNC=1`
- **Configurable (Experimental)**: Auto-sync is opt-in via environment variable: `MODFLOW_DEVTOOLS_AUTO_SYNC=1` (set to "1", "true", or "yes")

#### Force semantics

Expand Down
14 changes: 7 additions & 7 deletions docs/md/models.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ python -m modflow_devtools.models cp mf6/example/ex-gwf-twri01 /path/to/workspac
```

The copy command:
- Automatically attempts to sync registries before copying (unless `MODFLOW_DEVTOOLS_NO_AUTO_SYNC=1`)
- Automatically attempts to sync registries before copying (if `MODFLOW_DEVTOOLS_AUTO_SYNC=1`)
- Creates the workspace directory if it doesn't exist
- Copies all input files for the specified model
- Preserves subdirectory structure within the workspace
Expand Down Expand Up @@ -316,16 +316,16 @@ mf models clear --force

## Automatic Synchronization

By default, `modflow-devtools` attempts to sync registries:
- On first import (best-effort, fails silently on network errors)
- When accessing models (unless `MODFLOW_DEVTOOLS_NO_AUTO_SYNC=1`)

To disable auto-sync:
Auto-sync is **opt-in** (experimental). To enable:

```bash
export MODFLOW_DEVTOOLS_NO_AUTO_SYNC=1
export MODFLOW_DEVTOOLS_AUTO_SYNC=1 # or "true" or "yes"
```

When enabled, `modflow-devtools` attempts to sync registries:
- On first access (best-effort, fails silently on network errors)
- When accessing models via the API or CLI

Then manually sync when needed:

```bash
Expand Down
14 changes: 7 additions & 7 deletions docs/md/programs.md
Original file line number Diff line number Diff line change
Expand Up @@ -347,17 +347,17 @@ mf programs install mf6 --force

## Automatic Synchronization

By default, `modflow-devtools` attempts to sync registries:
- On first import (best-effort, fails silently on network errors)
- Before installation (unless `MODFLOW_DEVTOOLS_NO_AUTO_SYNC=1`)
- Before listing available programs

To disable auto-sync:
Auto-sync is **opt-in** (experimental). To enable:

```bash
export MODFLOW_DEVTOOLS_NO_AUTO_SYNC=1
export MODFLOW_DEVTOOLS_AUTO_SYNC=1 # or "true" or "yes"
```

When enabled, `modflow-devtools` attempts to sync registries:
- On first access (best-effort, fails silently on network errors)
- Before installation
- Before listing available programs

Then manually sync when needed:

```bash
Expand Down
4 changes: 2 additions & 2 deletions modflow_devtools/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
__author__ = "Joseph D. Hughes"
__date__ = "Feb 25, 2026"
__version__ = "1.9.0"
__date__ = "Mar 05, 2026"
__version__ = "1.9.1"
__maintainer__ = "Joseph D. Hughes"
__email__ = "jdhughes@usgs.gov"
__status__ = "Production"
Expand Down
70 changes: 69 additions & 1 deletion modflow_devtools/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
Root CLI for modflow-devtools.

Usage:
mf sync
mf dfns sync
mf dfns info
mf dfns list
mf dfns clean
mf models sync
mf models info
mf models list
Expand All @@ -17,6 +22,56 @@

import argparse
import sys
import warnings


def _sync_all():
"""Sync all registries (dfns, models, programs)."""
print("Syncing all registries...")
print()

# Sync DFNs
print("=== DFNs ===")
try:
from modflow_devtools.dfns.registry import sync_dfns

registries = sync_dfns()
for registry in registries:
meta = registry.registry_meta
print(f" {registry.ref}: {len(meta.files)} files")
print(f"Synced {len(registries)} DFN registry(ies)")
except Exception as e:
print(f"Error syncing DFNs: {e}")
print()

# Sync Models
print("=== Models ===")
try:
from modflow_devtools.models import ModelSourceConfig

config = ModelSourceConfig.load()
config.sync()
print("Models synced successfully")
except Exception as e:
print(f"Error syncing models: {e}")
print()

# Sync Programs
print("=== Programs ===")
try:
# Suppress experimental warning
with warnings.catch_warnings():
warnings.filterwarnings("ignore", message=".*modflow_devtools.programs.*experimental.*")
from modflow_devtools.programs import ProgramSourceConfig

config = ProgramSourceConfig.load()
config.sync()
print("Programs synced successfully")
except Exception as e:
print(f"Error syncing programs: {e}")
print()

print("All registries synced!")


def main():
Expand All @@ -27,6 +82,12 @@ def main():
)
subparsers = parser.add_subparsers(dest="subcommand", help="Available commands")

# Sync subcommand (syncs all APIs)
subparsers.add_parser("sync", help="Sync all registries (dfns, models, programs)")

# DFNs subcommand
subparsers.add_parser("dfns", help="Manage MODFLOW 6 definition files")

# Models subcommand
subparsers.add_parser("models", help="Manage MODFLOW model registries")

Expand All @@ -41,7 +102,14 @@ def main():
sys.exit(1)

# Dispatch to the appropriate module CLI with remaining args
if args.subcommand == "models":
if args.subcommand == "sync":
_sync_all()
elif args.subcommand == "dfns":
from modflow_devtools.dfns.__main__ import main as dfns_main

sys.argv = ["mf dfns", *remaining]
sys.exit(dfns_main())
elif args.subcommand == "models":
from modflow_devtools.models.__main__ import main as models_main

# Replace sys.argv to make it look like we called the submodule directly
Expand Down
Loading