Repository navigation
fix(mf6): find external files in model subdirectories with any path separator - #2879
Conversation
…eparator When loading a model with a model relative path, flopy checks whether an external file path already starts with the model directory before prepending it. The check split the path on `os.path.sep`, so on Windows a path like `level2/dat/botm.txt` was not recognized and the model directory was prepended again (`level2\level2/dat/botm.txt"``. Split with `PureWindowsPath(...).parts` instead, which accepts `/`` and `\`` on all platforms, and compare the leading parts as a whole. Close modflowpy#2878
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #2879 +/- ##
===========================================
+ Coverage 55.5% 72.7% +17.1%
===========================================
Files 644 659 +15
Lines 124135 132499 +8364
===========================================
+ Hits 68947 96373 +27426
+ Misses 55188 36126 -19062
🚀 New features to boost your workflow:
|
|
the CI failures are unrelated |
|
@wpbonelli Good points. I though about a separate function that takes care of such kind of path handling. Maybe there are other places that do similar things. I was not sure if the reuse potential is high enough yet. Maybe worth some refactoring that makes all path handling more consistent. As for case sensitiv, as far as I know, only Linux is truly case sensitive whereas Windows and macOS are only case preserving. I think using |
Close #2878
On Windows,
MFSimulation.load()fails for a model in a subdirectory when theOPEN/CLOSE paths of its external files use forward slashes, e.g. models written
by iMOD Python. Flopy prepends the model directory a second time and cannot find
the file (
level2\level2/dat/gwf.dis_botm.txt). MODFLOW 6 accepts these files, andflopy loads them on macOS and Linux.
Cause
The check added in #1298 (fix for #1289), which decides whether the model relative
path still has to be prepended, split paths on
os.path.sep. On Windows that is\,so a path with
/comes back as a single item and never matches the model directory.Changes
flopy/mf6/data/mfdatastorage.py(array data) andflopy/mf6/data/mfdataplist.py(list data, two places): split both paths withPureWindowsPath(...).parts, which accepts/and\on every OS, and prependthe model relative path only if the file path does not start with all of its
parts:
Comparing the leading parts as a whole also fixes two edge cases of the old loop
with multi-level model relative paths: an
IndexErrorwhen the file path hasfewer parts than the model relative path (e.g.
k.datwithmodels/gwf), andprepending only some components (e.g.
gwf/k.datwithmodels/gwfbecamemodels/gwf/k.dat).autotest/test_mf6.py: newtest_load_subdir_ext_files_with_any_sep,parametrized with
posixandwinseparators. It writes a model withmodel_rel_path="level2"and external array (DIS) and list (CHD) data, rewritesthe OPEN/CLOSE paths to
level2<sep>dat<sep><file>, reloads the simulation andchecks
botmand the CHD stress period data. Thewincase is skipped on macOSand Linux, where
\is not a path separator.Testing
On Windows 11, Python 3.14, MODFLOW 6.8.2:
test_load_subdir_ext_files_with_any_sep[posix]fails with thedoubled model directory;
[win]passes. With the fix, both pass.test_subdir,test_basic_gwf,test_load_sim_when_namefile_uses_rel_paths.pytest -n auto -S): the tests that fail with this change failidentically without it. They need executables missing in my environment
(e.g.
gridgen,mf2005).ruff check .andruff format --check .pass.Not tested on macOS or Linux; CI will cover these.