Skip to content

Release 2.0.0 - #353

Merged
jdhughes-dev merged 113 commits into
masterfrom
v2.0.0
Sep 9, 2026
Merged

Release 2.0.0#353
jdhughes-dev merged 113 commits into
masterfrom
v2.0.0

Conversation

@github-actions

@github-actions github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

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.

wpbonelli and others added 30 commits May 24, 2025 11:19
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
)

Update CI configuration by removing unused settings
jdhughes-dev and others added 23 commits August 17, 2026 18:53
* 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.
jdhughes-dev and others added 2 commits September 9, 2026 07:49
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

codecov Bot commented Sep 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.29776% with 104 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.818%. Comparing base (2f5cf6b) to head (f7bd161).
⚠️ Report is 116 commits behind head on master.

Files with missing lines Patch % Lines
pymake/pymake_base.py 91.512% 23 Missing ⚠️
pymake/utils/download.py 60.784% 20 Missing ⚠️
pymake/pymake.py 71.111% 13 Missing ⚠️
pymake/pymake_build_apps.py 53.333% 7 Missing ⚠️
pymake/utils/usgsprograms.py 75.862% 7 Missing ⚠️
pymake/utils/_meson_build.py 88.000% 6 Missing ⚠️
pymake/utils/_usgs_src_update.py 95.488% 6 Missing ⚠️
pymake/pymake_parser.py 61.538% 5 Missing ⚠️
pymake/plot/dependency_graphs.py 75.000% 4 Missing ⚠️
pymake/utils/_compiler_switches.py 92.156% 4 Missing ⚠️
... and 4 more
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     
Files with missing lines Coverage Δ
pymake/__init__.py 100.000% <ø> (ø)
pymake/__main__.py 0.000% <ø> (ø)
pymake/cmds/createjson.py 0.000% <ø> (-87.500%) ⬇️
pymake/config.py 100.000% <100.000%> (ø)
pymake/utils/_Popen_wrapper.py 55.263% <100.000%> (-42.298%) ⬇️
pymake/utils/_file_utils.py 72.413% <100.000%> (+8.128%) ⬆️
pymake/cmds/mfpymakecli.py 64.705% <75.000%> (-17.648%) ⬇️
pymake/cmds/build.py 53.061% <75.000%> (-40.556%) ⬇️
pymake/utils/_compiler_language_files.py 92.968% <82.352%> (-0.733%) ⬇️
pymake/utils/_dag.py 90.967% <93.617%> (+8.768%) ⬆️
... and 10 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jdhughes-dev
jdhughes-dev marked this pull request as ready for review September 9, 2026 15:17
@jdhughes-dev
jdhughes-dev merged commit 1ea1120 into master Sep 9, 2026
15 of 16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants