Release 2.0.0 - #353
Merged
Merged
Conversation
Post release 1.5.0 reset
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* update windows-2019 to windows-2022 * update gridgen download to use github repo * update mt3d-usgs download to use github repo
update flopy version to 3.9.5
* exclude gridgen build on windows with intel-classic * fix test_gridgen skip on windows
using -ex produced make-program: error: ambiguous option: -ex could match -e, -exf
* fix conditional in scheduled test job in ci.yml * simplify conditional syntax throughout ci.yml * add pytest --exclude option, forward to test
* update triangle source https path * modified how scheduled steps are run
* fix: order the source files the same way every time The order the source files are compiled in is written to a makefile, and it was not the same from one run to the next or from one operating system to another, so a makefile pymake writes could not be reproduced. Two things decided the order. The graph pymake sorted itself took nodes from a set, which has no order, and the source files were found with a walk of the source directory, which is read in the order the file system returns. networkx sorts the graph now, which pymake already depends on, and the walk and the graph are sorted, so the order does not depend on the file system or on the order the files were found in. The --networkx argument is removed, since there is one way to sort the graph. * docs: say what the graph class is for * test: check the graph orders the source files the same way every time _dag.py ended with a block that built a small graph and printed it when the file was run, which is where the module level names the functions shadow came from. The graph is checked by a test instead, which is what the block was doing by hand. The test builds a graph that can be ordered more than one way, gives it to the graph in a different order eight times and checks the result is the same each time, which the graph pymake sorted itself does not do. * refactor: find what a c file includes in its own function _order_c_source_files read a source file, searched its lines for what it includes and worked out what the file defines, which the analysis reported as too complex to follow. The lines are searched by _c_include_names, which returns the names a file includes and the one that matches the file. The list of source files a makefile is written from is unchanged.
* docs: say what builds a program in build_apps build_apps said make-program compiles the source files, which is what the build engine that was removed did, and was the last page that did not say meson builds a program. * docs: list the programs that can actually be built GSFLOW was listed as a program make-program can build and is not one of the targets, so asking for it fails. MODFLOW-USG Transport, the MODFLOW 6 shared library and the three ZONEBUDGET programs can be built and were not listed. The README also said make-program compiles the program from the source files, which is what the build engine that was removed did.
…base (#333) os.path is replaced by pathlib in _dag.py, which no longer imports os, and in usgsprograms.py. The files where a path is worked out differently are left for now. os.path returns an empty string for the directory of a bare file name where pathlib returns a dot, which pymake_build_apps.py and pymake_base.py test for, and os.path.commonpath, which _file_utils.py uses, has no pathlib equivalent.
os.path is replaced by pathlib for the paths download.py builds, and a file is removed and its mode set with Path. What is left uses os because pathlib does not do the same thing. os.walk yields the files in every directory below one, which zip_all needs, os.getcwd and os.fspath are what ZipFile is given, os.listdir lists a directory without building a path for each entry, and os.environ is not a path.
os.path is replaced by pathlib where a path is built or a file is removed in pymake.py, which is 15 of the 28 calls. The rest are left because os.path does something pathlib does not. os.path.normpath takes the parent directories out of a path and pathlib does not, and it is what tidies the extrafiles paths that are written to a build file. os.path.splitext keeps the directory in the name it returns where Path.stem does not. os.path.dirname returns an empty string for the directory of a bare file name where Path.parent returns a dot, which is compared with appdir to decide where a target is written. os.path.abspath does not resolve a symbolic link where Path.resolve does, and it decides whether a target has been built already.
Bumps [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) from 21 to 23. - [Release notes](https://github.com/dawidd6/action-download-artifact/releases) - [Commits](dawidd6/action-download-artifact@v21...v23) --- updated-dependencies: - dependency-name: dawidd6/action-download-artifact dependency-version: '23' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
os.path is replaced by pathlib where a path is built and where a file is removed or renamed, which is 67 of the 75 calls. The file edits the source files a target is released with rather than working out paths, so it does not use os.path.relpath, os.path.normpath, os.path.splitext or os.path.dirname, which is what the other files are left with. os.listdir lists a directory without building a path for each entry, and os.path.abspath takes the parent directories out of a path without following a symbolic link, which Path.resolve does.
The Setup Graphviz on Linux step installed graphviz system wide, but the only test that needs it runs under pixi, where the environment bin directory comes first on PATH and pydotplus resolves the environment copy instead. The action's graphviz was never invoked, and the step hung for over two hours on three separate runs. graphviz is now a direct dependency rather than one pulled in only as a transitive dependency of pydotplus.
The minimum python is 3.11, which has tomllib in the standard library, so the tomli backport can never be imported and the dependency is dropped. MODFLOW 6 raised its own minimum python to 3.11 in MODFLOW-ORG/modflow6#2925, so the consumer the backport was kept for no longer needs it.
* refactor: use pathlib for the paths in the meson build files Replace the os.path calls that have a direct pathlib equivalent in _meson_build.py. The six os.path.relpath calls are kept, because they produce the parent directory segments that Path.relative_to only walks up to with walk_up, which is not available until python 3.12. The header search that collects the include directories now uses rglob and sorts the result, so the include directories are written to the generated meson.build file in the same order on every run rather than the order the file system happens to return them in. * test: pin the order of the generated include directories Move the header search into _get_include_dirs so it can be tested on its own, and add tests that the include directories are the directories that hold a header file and that they are sorted. The os.walk search this replaced returned the directories in the order the file system provided, which is not the sorted order on any of the trial runs, so the tests fail against it. * test: use a helper rather than a fixture for the source tree A fixture and the test argument that takes it have the same name, which redefines the fixture from the outer scope. The source tree is built by a helper that takes the tmp_path fixture instead. * style: specify the encoding the meson build files are written with The generated meson build files were written with the encoding the system happens to default to, which is not utf-8 on every platform.
Replace the os.path calls that have a direct pathlib equivalent in pymake_base.py, and collect the source directories a makefile needs with _source_dirs rather than a pair of os.walk comprehensions. The target is still assembled with os.path.join, because Path drops the "." directory that the callers taking os.path.dirname of the target rely on, and the fifteen os.path.relpath calls are kept, because they produce the parent directory segments that Path.relative_to only walks up to with walk_up, which is not available until python 3.12.
Replace the os.path calls that have a direct pathlib equivalent in pymake.py, _compiler_language_files.py, _compiler_switches.py, _file_utils.py, dependency_graphs.py, download.py and pymake_build_apps.py, and drop the hasattr(os, "fspath") guard, which is for python 3.5 and earlier. The os.path.dirname calls that are compared with a directory are kept, because Path.parent is "." where dirname is "" and the comparison relies on the difference, along with os.path.normpath, os.path.commonpath and the os.path.relpath calls, which have no pathlib equivalent before python 3.12.
The makefile and makedefaults files were written through a file object that was closed by hand and opened with the encoding the system happens to default to, which is not utf-8 on every platform. They are written from a with block with an explicit encoding instead, so the file is closed when writing raises.
* fix: take a replaced .fpp extra file from the free format file An extra source file listed with a .fpp extension that had been replaced by a .f90 file was never found. The fallback tested the .fpp file it had already established was not there, rather than the .f90 file, so the condition could not be true and the build stopped with a FileNotFoundError. * test: run the extrafiles tests from the temporary directory An inplace build takes the path of an extra file relative to the current directory, and os.path.relpath raises on windows when the two are on different drives, which is the case on a runner where the temporary directory is on C: and the checkout is on D:.
Replace the remaining os.listdir calls with Path.iterdir, and sort them so the files are renamed and moved in the same order on every run rather than the order the file system returns them in. Remove the commented out source folder removal, which no longer applies to any target.
The fortran flags, c flags and linker flags a user asked for were dropped from a generated makefile. The fortran and linker flag builders were called with an empty list, and the c flag builder was called with the fortran flags, so a fortran flag was written to CFLAGS and a c flag was written nowhere. The syslibs _create_makefile takes were never passed to _write_makedefaults at all. Each builder is now given the flags that belong to it, and syslibs is passed down.
Convert the os.path.abspath and os.path.dirname calls whose pathlib equivalent behaves the same, and take the vs2dt main source from the parent directory rather than from a ".." segment abspath had to normalize away. The four that are left are commented with what they rely on: dirname giving the empty string for a target with no directory, which Path.parent gives as ".", and abspath removing the ".." segments so that two spellings of a target count as one in the build targets list.
mf6, zbud6 and libmf6 build the 6.8.0 release and the development targets report 6.9.0.dev0. MODFLOW 6 6.8.0 adds Timing/ParallelAts.f90 to the source files that are only built with MPI, which is now removed with the other files that have external library dependencies. numpy, coverage, matplotlib, modflow-devtools and codespell also carry the versions flopy pins, and python 3.14 is added to the classifiers. The Release Notes project url pointed at the flopy changelog, and the pixi project table is renamed to workspace.
pydotplus is a fork of pydot that has not been released since 2014, and was imported when pymake was imported. pydot provides the same interface, is maintained, and is what the networkx dot interface is written against. pydot is now an optional dependency, installed with 'pip install mfpymake[plot]'. Plotting a dependency graph also needs the graphviz binaries, which pip cannot install, so an install no longer carries a dependency it may not be able to use. make_plots and to_pydot report what to install when pydot is missing.
The classifiers report python 3.11 through 3.14, but the tests only ran on 3.11. The python version moves into a feature so an environment can choose it, the tests also run in a python 3.14 environment on Linux, and the standard installation job runs on every supported version. python 3.13 stopped repeating the metavar for an option with a short and a long form, so the documented command line help depended on the python that wrote it. The newer form is now written on every python.
continuous integration runs on macos-latest, which is arm64, so the osx-64 environments were locked but never used. Removing the platform takes 3602 lines out of the lock file. The pypi and conda-forge packages are unaffected, since both are os independent.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #353 +/- ##
=============================================
- Coverage 84.448% 80.818% -3.631%
=============================================
Files 20 20
Lines 3511 3274 -237
=============================================
- Hits 2965 2646 -319
- Misses 546 628 +82
🚀 New features to boost your workflow:
|
wpbonelli
approved these changes
Sep 9, 2026
jdhughes-dev
marked this pull request as ready for review
September 9, 2026 15:17
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release 2.0.0
The release can be approved by merging this pull request into
master. This will trigger a job to publish the release to PyPI.