Skip to content

Commit

Permalink
Merge pull request MODFLOW-USGS#154 from MODFLOW-USGS/v1.5.0
Browse files Browse the repository at this point in the history
Release 1.5.0
  • Loading branch information
wpbonelli authored May 15, 2024
2 parents 5182e3b + 9302fd8 commit 78eee25
Show file tree
Hide file tree
Showing 33 changed files with 549 additions and 380 deletions.
52 changes: 31 additions & 21 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,10 @@ jobs:
cache-dependency-path: pyproject.toml

- name: Install Python packages
run: |
pip install .
pip install ".[lint]"
- name: Run isort
run: isort --verbose --check --diff modflow_devtools

- name: Run black
run: black --check --diff modflow_devtools

- name: Run flake8
run: flake8 --count --show-source --exit-zero modflow_devtools
run: pip install ".[lint]"

- name: Run pylint
run: pylint --jobs=0 --errors-only --exit-zero modflow_devtools
- name: Run ruff
run: ruff check .

build:
name: Build
Expand Down Expand Up @@ -120,6 +109,11 @@ jobs:

- name: Install executables
uses: modflowpy/install-modflow-action@v1

- name: Install nightly build
uses: modflowpy/install-modflow-action@v1
with:
repo: modflow6-nightly-build

- name: Setup GNU Fortran ${{ env.GCC_V }}
uses: awvwgk/setup-fortran@main
Expand All @@ -134,26 +128,29 @@ jobs:

- name: Install Python packages
working-directory: modflow-devtools
run: |
pip install .
pip install ".[test]"
run: pip install ".[test]"

- name: Cache modflow6 examples
if: matrix.python != 3.8
id: cache-examples
uses: actions/cache@v3
with:
path: modflow6-examples/examples
key: modflow6-examples-${{ hashFiles('modflow6-examples/data/**') }}

- name: Install extra Python packages
if: steps.cache-examples.outputs.cache-hit != 'true'
if: matrix.python != 3.8
working-directory: modflow6-examples/etc
run: |
pip install -r requirements.pip.txt
pip install -r requirements.usgs.txt
- name: Update FloPy packages
if: matrix.python != 3.8
run: python -m flopy.mf6.utils.generate_classes --ref develop --no-backup

- name: Build modflow6 example models
if: steps.cache-examples.outputs.cache-hit != 'true'
if: matrix.python != 3.8 && steps.cache-examples.outputs.cache-hit != 'true'
working-directory: modflow6-examples/autotest
run: pytest -v -n auto test_scripts.py --init

Expand All @@ -173,4 +170,17 @@ jobs:
env:
REPOS_PATH: ${{ github.workspace }}
GITHUB_TOKEN: ${{ github.token }}
run: pytest -v -n auto --durations 0 test_download.py
run: pytest -v -n auto --durations 0 test_download.py

rtd:
name: Docs
needs: test
runs-on: ubuntu-22.04
if: github.repository_owner == 'MODFLOW-USGS' && github.event_name == 'push'
steps:
- name: Trigger RTD
uses: dfm/rtds-action@v1
with:
webhook_url: ${{ secrets.RTDS_WEBHOOK_URL }}
webhook_token: ${{ secrets.RTDS_WEBHOOK_TOKEN }}
commit_ref: ${{ github.ref }}
1 change: 0 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ jobs:
ref="${{ github.ref_name }}"
version="${ref#"v"}"
python scripts/update_version.py -v "$version"
python scripts/lint.py
python -c "import modflow_devtools; print('Version: ', modflow_devtools.__version__)"
echo "version=$version" >> $GITHUB_OUTPUT
Expand Down
23 changes: 15 additions & 8 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
### Version 1.4.0
### Version 1.5.0

#### New features

* [feat(Executables)](https://github.com/MODFLOW-USGS/modflow-devtools/commit/3129417dae2de3aece80c8056a2ac50eede56b91): Support collection-style membership test (#131). Committed by wpbonelli on 2023-12-18.
* [feat](https://github.com/MODFLOW-USGS/modflow-devtools/commit/6728859a984a3080f8fd4f1135de36bc17454098): Add latex and plot style utilities (#132). Committed by wpbonelli on 2024-01-09.
* [feat(misc)](https://github.com/MODFLOW-USGS/modflow-devtools/commit/a9b801932866a26a996ed3a45f16048b15246472): Parse literals from environment variables (#135). Committed by wpbonelli on 2024-01-21.
* [feat(ostags)](https://github.com/MODFLOW-USGS/modflow-devtools/commit/0ad10751ea6ce752e59d83e8cd6275906d73fa70): Apple silicon (#139). Committed by wpbonelli on 2024-02-18.
* [feat(markers)](https://github.com/MODFLOW-USGS/modflow-devtools/commit/1f358de2bc721c1000c3d0823b9440776432e3b0): Add no_parallel marker, support differing pkg/module names (#148). Committed by wpbonelli on 2024-04-12.
* [feat(snapshots)](https://github.com/MODFLOW-USGS/modflow-devtools/commit/c9e445dd1544413f3729c7a78c2a77038db80050): Add snapshot fixtures, remove pandas fixture (#151). Committed by wpbonelli on 2024-05-13.

#### Bug fixes
#### Refactoring

* [refactor(latex)](https://github.com/MODFLOW-USGS/modflow-devtools/commit/827b5ec63ebe0b9ea833957637d6b60fdc2f3198): Support path-like, add docstrings (#142). Committed by wpbonelli on 2024-02-25.
* [refactor(snapshots)](https://github.com/MODFLOW-USGS/modflow-devtools/commit/d96089e512fbb79408e4fb58c89ee63da60dc727): Move to separate module (#152). Committed by wpbonelli on 2024-05-13.

* [fix](https://github.com/MODFLOW-USGS/modflow-devtools/commit/fd215000c6215b0891e78ee621e40abb2a20b28a): Drop plot styles (already in flopy) (#133). Committed by wpbonelli on 2024-01-09.
### Version 1.4.0

#### New features

* [feat(latex)](https://github.com/MODFLOW-USGS/modflow-devtools/commit/6728859a984a3080f8fd4f1135de36bc17454098): Add latex utilities (#132). Committed by wpbonelli on 2024-01-09.
* [feat(misc)](https://github.com/MODFLOW-USGS/modflow-devtools/commit/a9b801932866a26a996ed3a45f16048b15246472): Parse literals from environment variables (#135). Committed by wpbonelli on 2024-01-21.
* [feat(ostags)](https://github.com/MODFLOW-USGS/modflow-devtools/commit/0ad10751ea6ce752e59d83e8cd6275906d73fa70): add OS tags for Apple silicon (#139). Committed by wpbonelli on 2024-02-18.

#### Refactoring

* [refactor](https://github.com/MODFLOW-USGS/modflow-devtools/commit/9356e067ea813aeeeda2582cf7ec174c11d80159): Remove executables module/class (#136). Committed by wpbonelli on 2024-01-25.
* [refactor](https://github.com/MODFLOW-USGS/modflow-devtools/commit/9356e067ea813aeeeda2582cf7ec174c11d80159): Remove executables module/class (#136). Committed by wpbonelli on 2024-01-25. Should be in a major release per semver, but nothing is using it, so this should be safe.
* [refactor(fixtures)](https://github.com/MODFLOW-USGS/modflow-devtools/commit/613ad010ff6fc782f231b7fa21d1cc660732e7be): Support pytest>=8, drop pytest-cases dependency (#137). Committed by wpbonelli on 2024-01-31.

### Version 1.3.1
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ Python3.8+, dependency-free, but pairs well with `pytest` and select plugins, e.

- [`pytest-dotenv`](https://github.com/quiqua/pytest-dotenv)
- [`pytest-xdist`](https://github.com/pytest-dev/pytest-xdist)
- [`syrupy`](https://github.com/tophat/syrupy)

## Installation

Expand All @@ -65,15 +66,15 @@ Python3.8+, dependency-free, but pairs well with `pytest` and select plugins, e.
pip install modflow-devtools
```

Pytest, pytest plugins, and other optional dependencies can be installed with:
Pytest, pytest plugins, and other testing-related dependencies can be installed with:

```shell
pip install "modflow-devtools[test]"
```

To install from source and set up a development environment please see the [developer documentation](DEVELOPER.md).

To import `pytest` fixtures in a project consuming `modflow-devtools`, add the following to a `conftest.py` file:
To import `pytest` fixtures in a project consuming `modflow-devtools`, add the following to a test file or `conftest.py` file:

```python
pytest_plugins = [ "modflow_devtools.fixtures" ]
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[1.1 2.2 3.3]
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
1.100000000000000089e+00
2.200000000000000178e+00
3.299999999999999822e+00
4 changes: 1 addition & 3 deletions autotest/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@
_system = platform.system()
_exe_ext = ".exe" if _system == "Windows" else ""
_lib_ext = (
".so"
if _system == "Linux"
else (".dylib" if _system == "Darwin" else ".dll")
".so" if _system == "Linux" else (".dylib" if _system == "Darwin" else ".dll")
)


Expand Down
11 changes: 4 additions & 7 deletions autotest/test_download.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@
@pytest.mark.parametrize("retries", [-1, 0, 1.5])
def test_get_releases_bad_params(per_page, retries):
with pytest.raises(ValueError):
get_releases(
"executables", per_page=per_page, retries=retries, verbose=True
)
get_releases("executables", per_page=per_page, retries=retries, verbose=True)


@flaky
Expand Down Expand Up @@ -53,7 +51,8 @@ def test_get_release(repo):
actual_names = [asset["name"] for asset in assets]

if repo == "MODFLOW-USGS/modflow6":
# can remove if modflow6 releases follow asset name conventions followed in executables and nightly build repos
# can remove if modflow6 releases follow asset name
# conventions followed in executables and nightly build repos
assert set([a.rpartition("_")[2] for a in actual_names]) >= set(
[a for a in expected_names if not a.startswith("win")]
)
Expand Down Expand Up @@ -109,9 +108,7 @@ def test_download_and_unzip(function_tmpdir, delete_zip):
zip_name = "mf6.3.0_linux.zip"
dir_name = zip_name.replace(".zip", "")
url = f"https://github.com/MODFLOW-USGS/modflow6/releases/download/6.3.0/{zip_name}"
download_and_unzip(
url, function_tmpdir, delete_zip=delete_zip, verbose=True
)
download_and_unzip(url, function_tmpdir, delete_zip=delete_zip, verbose=True)

assert (function_tmpdir / zip_name).is_file() != delete_zip

Expand Down
56 changes: 8 additions & 48 deletions autotest/test_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
from _pytest.config import ExitCode

system = platform.system()
proj_root = Path(__file__).parent.parent.parent.parent
proj_root = Path(__file__).parents[1]
module_path = Path(inspect.getmodulename(__file__))


# test temporary directory fixtures
Expand Down Expand Up @@ -39,8 +40,7 @@ def test_function_scoped_tmpdir_slash_in_name(function_tmpdir, name):
replaced1 = name.replace("/", "_").replace("\\", "_").replace(":", "_")
replaced2 = name.replace("/", "_").replace("\\", "__").replace(":", "_")
assert (
f"{inspect.currentframe().f_code.co_name}[{replaced1}]"
in function_tmpdir.stem
f"{inspect.currentframe().f_code.co_name}[{replaced1}]" in function_tmpdir.stem
or f"{inspect.currentframe().f_code.co_name}[{replaced2}]"
in function_tmpdir.stem
)
Expand All @@ -64,7 +64,7 @@ def test_class_scoped_tmpdir(self, class_tmpdir):
def test_module_scoped_tmpdir(module_tmpdir):
assert isinstance(module_tmpdir, Path)
assert module_tmpdir.is_dir()
assert Path(inspect.getmodulename(__file__)).stem in module_tmpdir.name
assert module_path.stem in module_tmpdir.name


def test_session_scoped_tmpdir(session_tmpdir):
Expand Down Expand Up @@ -144,9 +144,7 @@ def test_keep_class_scoped_tmpdir(tmp_path, arg):
]
assert pytest.main(args) == ExitCode.OK
assert Path(
tmp_path
/ f"{TestKeepClassScopedTmpdirInner.__name__}0"
/ test_keep_fname
tmp_path / f"{TestKeepClassScopedTmpdirInner.__name__}0" / test_keep_fname
).is_file()


Expand All @@ -165,9 +163,7 @@ def test_keep_module_scoped_tmpdir(tmp_path, arg):
]
assert pytest.main(args) == ExitCode.OK
this_path = Path(__file__)
keep_path = (
tmp_path / f"{str(this_path.parent.name)}.{str(this_path.stem)}0"
)
keep_path = tmp_path / f"{str(this_path.parent.name)}.{str(this_path.stem)}0"
assert test_keep_fname in [f.name for f in keep_path.glob("*")]


Expand Down Expand Up @@ -206,9 +202,7 @@ def test_keep_failed_function_scoped_tmpdir(function_tmpdir, keep):
args += ["--keep-failed", function_tmpdir]
assert pytest.main(args) == ExitCode.TESTS_FAILED

kept_file = Path(
function_tmpdir / f"{inner_fn}0" / test_keep_fname
).is_file()
kept_file = Path(function_tmpdir / f"{inner_fn}0" / test_keep_fname).is_file()
assert kept_file if keep else not kept_file


Expand Down Expand Up @@ -276,41 +270,7 @@ def test_large_test_model(large_test_model):
assert large_test_model.name == "mfsim.nam"


# test pandas fixture

test_pandas_fname = "pandas.txt"


@pytest.mark.meta("test_pandas")
def test_pandas_inner(function_tmpdir, use_pandas):
with open(function_tmpdir / test_pandas_fname, "w") as f:
f.write(str(use_pandas))


@pytest.mark.parametrize("pandas", ["yes", "no", "random"])
@pytest.mark.parametrize("arg", ["--pandas", "-P"])
def test_pandas(pandas, arg, function_tmpdir):
inner_fn = test_pandas_inner.__name__
args = [
__file__,
"-v",
"-s",
"-k",
inner_fn,
arg,
pandas,
"--keep",
function_tmpdir,
"-M",
"test_pandas",
]
assert pytest.main(args) == ExitCode.OK
res = open(next(function_tmpdir.rglob(test_pandas_fname))).readlines()[0]
assert res
if pandas == "yes":
assert "True" in res
elif pandas == "no":
assert "False" in res
# test tabular data format fixture


test_tabular_fname = "tabular.txt"
Expand Down
40 changes: 37 additions & 3 deletions autotest/test_markers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,34 @@
from platform import python_version, system
from shutil import which

import pytest
from packaging.version import Version

from modflow_devtools.markers import *
from modflow_devtools.markers import (
excludes_platform,
no_parallel,
require_exe,
require_package,
require_platform,
require_program,
require_python,
requires_exe,
requires_pkg,
requires_platform,
requires_program,
requires_python,
)

exe = "pytest"
pkg = exe


@requires_exe(exe)
def test_require_exe():
assert which(exe)
require_exe(exe)
require_program(exe)
requires_program(exe)


exes = [exe, "python"]
Expand All @@ -24,14 +40,15 @@ def test_require_exe_multiple():
assert all(which(exe) for exe in exes)


@requires_pkg("pytest")
@requires_pkg(pkg)
def test_requires_pkg():
import numpy

assert numpy is not None
require_package(pkg)


@requires_pkg("pytest", "pluggy")
@requires_pkg(pkg, "pluggy")
def test_requires_pkg_multiple():
import pluggy
import pytest
Expand All @@ -42,6 +59,7 @@ def test_requires_pkg_multiple():
@requires_platform("Windows")
def test_requires_platform():
assert system() == "Windows"
require_platform("Windows")


@excludes_platform("Darwin", ci_only=True)
Expand All @@ -57,3 +75,19 @@ def test_requires_platform_ci_only():
def test_requires_python(version):
if Version(py_ver) >= Version(version):
assert requires_python(version)
assert require_python(version)


@no_parallel
@requires_pkg("pytest-xdist", name_map={"pytest-xdist": "xdist"})
def test_no_parallel(worker_id):
"""
Should only run with xdist disabled, in which case:
- xdist environment variables are not set
- worker_id is 'master' (assuming xdist is installed)
See https://pytest-xdist.readthedocs.io/en/stable/how-to.html#identifying-the-worker-process-during-a-test.
"""

assert environ.get("PYTEST_XDIST_WORKER") is None
assert worker_id == "master"
Loading

0 comments on commit 78eee25

Please sign in to comment.