Skip to content

Commit ad0b128

Browse files
committed
compatibility plan
1 parent 39adf97 commit ad0b128

1 file changed

Lines changed: 97 additions & 68 deletions

File tree

docs/md/dev/dfns.md

Lines changed: 97 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -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
10761105
from modflow_devtools.dfn import DfnSpec, get_dfn, get_registry, sync_dfns
10771106

1078-
# New functionality
1107+
# Sync and access DFNs
10791108
sync_dfns(ref="6.6.0")
10801109
dfn = get_dfn("gwf-chd", ref="6.6.0")
10811110
registry = 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.)
12211251
3. **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
12261256
from 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
12321262
from 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

Comments
 (0)