@@ -1062,79 +1062,109 @@ def _detect_schema_version(self) -> Version:
10621062
10631063# ## API compatibility
10641064
1065- **Backwards compatible API design **:
1065+ **Breaking changes in current implementation **:
10661066
1067- ```python
1068- # Existing dfn branch API (continue to work)
1069- from modflow_devtools.dfn import load, fetch_dfns
1067+ The `dfn` branch introduces fundamental breaking changes that make it incompatible with a 1.x release:
10701068
1071- # Works exactly as before
1072- dfn = load("/path/to/dfn/file.dfn")
1073- fetch_dfns("MODFLOW-ORG", "modflow6", "6.6.0", "/tmp/dfns")
1069+ 1. **Core types changed from TypedDict to dataclass**:
1070+ ```python
1071+ # Old (develop) - dict-like access
1072+ dfn["name"]
1073+ field.get("type")
1074+
1075+ # New (dfn branch) - attribute access
1076+ dfn.name
1077+ field.type
1078+ ```
1079+
1080+ 2. **`Dfn` structure changed**:
1081+ - Removed: `sln`, `fkeys`
1082+ - Added: `schema_version`, `parent`, `blocks`
1083+ - Renamed: `fkeys` → `children`
1084+
1085+ 3. **Removed exports**:
1086+ - `get_dfns()` - now `fetch_dfns()` in submodule, not re-exported from main module
1087+ - `FormatVersion`, `Sln`, `FieldType`, `Reader` type aliases
1088+
1089+ 4. **`Field` structure changed** - different attributes and semantics between v1/v2
1090+
1091+ **Why aliasing is not feasible**:
1092+
1093+ The TypedDict → dataclass change is fundamental and cannot be cleanly aliased:
1094+ - Code using `dfn["name"]` syntax would break immediately
1095+ - Making a dataclass behave like a dict requires implementing `__getitem__`, `get()`, `keys()`, `values()`, `items()`, etc.
1096+ - Even with these methods, isinstance checks and type hints would behave differently
1097+ - The complexity and maintenance burden outweigh the benefits
10741098
1075- # New DFNs API (additive, doesn't break existing)
1099+ **Recommendation**: Release as **devtools 2.0**, not 1.x.
1100+
1101+ **New API (devtools 2.x)**:
1102+
1103+ ```python
1104+ # DFNs API
10761105from modflow_devtools.dfn import DfnSpec, get_dfn, get_registry, sync_dfns
10771106
1078- # New functionality
1107+ # Sync and access DFNs
10791108sync_dfns(ref="6.6.0")
10801109dfn = get_dfn("gwf-chd", ref="6.6.0")
10811110registry = get_registry(ref="6.6.0")
1082- spec = registry.spec # Registry wraps a DfnSpec
1083- ```
1111+ spec = registry.spec
10841112
1085- **No breaking changes to existing classes**:
1086- - `Dfn`, `Block`, `Field` dataclasses remain compatible
1087- - `FieldV1`, `FieldV2` continue to work
1088- - `MapV1To2` schema mapping continues to work
1089- - Add `MapV1To11` and `MapV11To2` as needed
1090- - `load()` function continues to work (loads individual DFN files)
1091- - New `DfnSpec` class is additive (doesn't break existing code)
1113+ # Attribute access (dataclass style)
1114+ print(dfn.name) # "gwf-chd"
1115+ print(dfn.blocks["options"])
10921116
1093- **Deprecation strategy**:
1094- - Mark old APIs as deprecated with clear migration path
1095- - Deprecation warnings point to new equivalent functionality
1096- - Keep deprecated APIs working for at least one major version
1097- - Document migration in release notes and migration guide
1117+ # fetch_dfns() still available for manual downloads
1118+ from modflow_devtools.dfn.fetch import fetch_dfns
1119+ fetch_dfns("MODFLOW-ORG", "modflow6", "6.6.0", "/tmp/dfns")
1120+ ```
10981121
10991122# ## Migration timeline
11001123
1101- **devtools 1.x** (current):
1102- - ✅ Merge dfn branch with v1.1 schema (stable, no breaking changes)
1103- - ✅ Implement DFNs API with v1/v1.1 support
1104- - ✅ FloPy 3 continues using v1.1 schema from mainline
1105- - ✅ All existing APIs remain unchanged and supported
1106- - ⚠️ Deprecate `fetch_dfns()` in favor of DFNs API (but keep working)
1107-
1108- **devtools 2.0** (future):
1109- - ✅ Add v2 schema support (v1, v1.1, and v2 all work)
1110- - ✅ Merge dfn-v2 branch to mainline
1111- - ✅ FloPy 4 begins using v2 schema
1112- - ✅ FloPy 3 continues using v1.1 schema (no changes needed)
1113- - ⚠️ Deprecate v1 schema support (but keep working for one more major version)
1124+ **devtools 1.x** (current stable):
1125+ - Existing `modflow_devtools/dfn.py` with TypedDict-based API
1126+ - `get_dfns()` function for manual downloads
1127+ - No registry infrastructure
1128+ - **No changes** - maintain stability for existing users
1129+
1130+ **devtools 2.0** (this work):
1131+ - ❌ Breaking: `Dfn`, `Field` change from TypedDict to dataclass
1132+ - ❌ Breaking: `get_dfns()` renamed to `fetch_dfns()` (in submodule)
1133+ - ❌ Breaking: Several type aliases removed or moved
1134+ - ✅ New: Full DFNs API with registry infrastructure
1135+ - ✅ New: `DfnSpec` class with hierarchical and flat access
1136+ - ✅ New: `RemoteDfnRegistry`, `LocalDfnRegistry` classes
1137+ - ✅ New: CLI commands (sync, info, list, clean)
1138+ - ✅ New: Schema versioning and mapping (v1 ↔ v2)
1139+ - ✅ New: Pydantic-based configuration and validation
1140+
1141+ **devtools 2.x** (future minor releases):
1142+ - Add v2 DFN schema support when MODFLOW 6 adopts it
1143+ - Schema mapping between all versions (v1, v1.1, v2)
1144+ - Additional CLI commands and features
1145+ - Performance improvements
11141146
11151147**devtools 3.0** (distant future):
1116- - ✅ v1.1 and v2 schema both fully supported
1117- - ❌ Remove v1 schema support (deprecated in 2.0)
1118- - ⚠️ Final deprecation warnings for any legacy APIs
1148+ - Consider removing v1 schema support (with deprecation warnings in 2.x)
1149+ - Potential further API refinements
11191150
11201151**Key principles**:
1121- 1. **Additive changes only** on mainline during 1.x
1122- 2. **Multi-version support** - DFNs API works with v1, v1.1, and v2 simultaneously
1123- 3. **No forced upgrades** - FloPy 3 never has to migrate off v1.1
1124- 4. **Explicit migration** - Users opt-in to v2 via schema mapping
1125- 5. **Long deprecation** - At least one major version warning before removal
1152+ 1. **Clean break at 2.0** - no half-measures with aliasing
1153+ 2. **Multi-version schema support** - DFNs API works with v1, v1.1, and v2 simultaneously
1154+ 3. **Clear migration path** - document all breaking changes in release notes
1155+ 4. **Semantic versioning** - breaking changes require major version bump
11261156
11271157**Testing strategy**:
11281158- Test suite covers all schema versions (v1, v1.1, v2)
11291159- Test schema mapping in all directions (v1↔v1.1↔v2)
1130- - Test FloPy 3 integration continuously (don't break existing consumers)
11311160- Test mixed-version scenarios (different refs with different schemas)
1161+ - Integration tests with real MODFLOW 6 repository
11321162
11331163**Documentation**:
1134- - Clear migration guides for each transition
1164+ - Clear migration guide from 1.x to 2.x
1165+ - Document all breaking changes with before/after examples
11351166- Document which MODFLOW 6 versions use which schema versions
11361167- Examples showing multi-version usage
1137- - Deprecation timeline clearly communicated
11381168
11391169# # Implementation Dependencies
11401170
@@ -1220,34 +1250,33 @@ Merge sequence:
12201250 - Adds substantial new functionality (schema classes, parsers, etc.)
122112513. **Finally**: Implement DFNs API features on `develop` (registries, sync, CLI, `DfnSpec`)
12221252
1223- API compatibility during merge:
1253+ API changes during merge:
12241254```python
12251255# Old dfn.py API (on develop now) - uses TypedDicts
12261256from modflow_devtools.dfn import get_dfns, Field, Dfn
1257+ dfn["name"] # dict-like access
12271258
1228- # New dfn/ package API (after dfn branch merge) - upgrades to dataclasses
1229- from modflow_devtools.dfn import get_dfns # Aliased to fetch_dfns, still works
1230- from modflow_devtools.dfn import fetch_dfns # New preferred name
1231- from modflow_devtools.dfn import load, Dfn, Block, Field # Upgraded to dataclasses
1259+ # New dfn/ package API (after dfn branch merge) - dataclasses
1260+ from modflow_devtools.dfn import Dfn, Block, Field # Now dataclasses
1261+ from modflow_devtools.dfn.fetch import fetch_dfns # Renamed, moved to submodule
12321262from modflow_devtools.dfn import DfnSpec, get_registry, sync_dfns # New additions
1233-
1234- # The import path stays the same, functionality expands
1235- # get_dfns() kept as alias for backwards compatibility
1263+ dfn.name # attribute access
12361264```
12371265
1238- Breaking changes (justified):
1239- - `Field`, `Dfn`, etc. change from `TypedDict` to `dataclass` - more powerful, better typing
1240- - This is acceptable since only internal dogfooding currently (FloPy uses schema, not these classes directly)
1241-
1242- **Needed for DFNs API**:
1243- - ❌ Bootstrap file and registry schema
1244- - ❌ Registry discovery and synchronization
1245- - ❌ Pooch integration for file caching
1246- - ❌ Registry classes (`DfnRegistry`, `RemoteDfnRegistry`, `LocalDfnRegistry`)
1247- - ❌ CLI commands (sync, info, list, clean)
1248- - ❌ Module-level convenience API
1249- - ❌ Registry generation tool (`make_registry.py`)
1250- - ❌ Integration with MODFLOW 6 CI
1266+ **Breaking changes** (see [API compatibility](#api-compatibility) section for full details):
1267+ - `Field`, `Dfn`, etc. change from `TypedDict` to `dataclass` - **requires 2.0 release**
1268+ - `get_dfns()` renamed to `fetch_dfns()` and moved to submodule
1269+ - Several type aliases removed or moved to schema submodules
1270+
1271+ **Implementation status** (DFNs API):
1272+ - ✅ Bootstrap file and registry schema
1273+ - ✅ Registry discovery and synchronization
1274+ - ✅ Pooch integration for file caching
1275+ - ✅ Registry classes (`DfnRegistry`, `RemoteDfnRegistry`, `LocalDfnRegistry`)
1276+ - ✅ CLI commands (sync, info, list, clean)
1277+ - ✅ Module-level convenience API
1278+ - ✅ Registry generation tool (`make_registry.py`)
1279+ - ⚠️ Integration with MODFLOW 6 CI (requires registry branch merge in MF6 repo)
12511280
12521281# ## Core components
12531282
0 commit comments