Skip to content

Commit

Permalink
fix(fixtures): fix model filtering by package
Browse files Browse the repository at this point in the history
* get_packages() was called incorrectly in model-loading fixtures, fix it
* mention optional dependencies in README and make some minor corrections
  • Loading branch information
wpbonelli committed Jan 4, 2023
1 parent cb19930 commit a0482af
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 16 deletions.
34 changes: 26 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,46 +16,64 @@ Python tools for MODFLOW development and testing.
- [Requirements](#requirements)
- [Installation](#installation)
- [Use cases](#use-cases)
- [Quickstart](#quickstart)
- [Documentation](#documentation)
- [MODFLOW Resources](#modflow-resources)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

## Requirements

This package requires Python3.8+. Its only dependencies are `numpy` and `pytest`.
This project requires Python3.8+. Its only core dependencies are `numpy` and `pytest`.

## Installation

The package is available on PyPI and can be installed with pip:
`modflow-devtools` is available on PyPI and can be installed with pip:

```shell
pip install modflow-devtools
```

This package pairs well with a few pytest plugins:

- `pytest-cases`
- `pytest-dotenv`
- `pytest-xdist`

These and a few other optional 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).

## Use cases

This package contains shared tools for developing and testing MODFLOW 6 and FloPy, including standalone utilities as well as `pytest` fixtures, CLI options, and test cases:

- a `ZipFile` subclass preserving file attributes
- variably-scoped `pytest` temporary directory fixtures
- a `pytest` smoke test CLI option (to run a fast subset of cases)
- a minimal `pytest` framework for reusing test functions and data
- a `pytest_generate_tests` hook to load example/test model fixtures
- a `ZipFile` subclass preserving file permissions ([more information here](https://stackoverflow.com/questions/39296101/python-zipfile-removes-execute-permissions-from-binaries))
- a `pytest` CLI option for smoke testing (running a fast subset of cases)
- a minimal `pytest-cases` framework for reusing test functions and data
- a set of keepable `pytest` temporary directory fixtures for each scope
- a set of fixtures to parametrize tests with models from external repos
- `MODFLOW-USGS/modflow6-examples`
- `MODFLOW-USGS/modflow6-testmodels`
- `MODFLOW-USGS/modflow6-largetestmodels`
- a set of `pytest` markers to conditionally skip test cases based on
- operating system
- Python packages installed
- executables available on the path

## Quickstart

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

```python
pytest_plugins = [ "modflow_devtools.fixtures" ]
```

Note that `pytest` requires this to be a top-level `conftest.py` living in your project root. Nested `conftest.py` files may override or extend this package's behavior.
**Note**: `pytest` requires this to be a top-level `conftest.py` file. Nested `conftest.py` files may override or extend this package's fixtures.

## Documentation

Expand Down
2 changes: 1 addition & 1 deletion docs/md/zip.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# `MFZipFile`

Python's `ZipFile` doesn't preserve execute permissions. The `MFZipFile` subclass modifies `ZipFile.extract()` to do so, as per the recommendation [here](https://stackoverflow.com/questions/39296101/python-zipfile-removes-execute-permissions-from-binaries).
Python's `ZipFile` doesn't preserve file permissions at extraction time. The `MFZipFile` subclass modifies `ZipFile.extract()` to do so, as per the recommendation [here](https://stackoverflow.com/questions/39296101/python-zipfile-removes-execute-permissions-from-binaries).
5 changes: 3 additions & 2 deletions modflow_devtools/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
from typing import Dict, List, Optional

import pytest

from modflow_devtools.misc import (
get_model_paths,
get_namefile_paths,
get_packages,
)


# temporary directory fixtures


Expand Down Expand Up @@ -284,7 +285,7 @@ def get_examples():
for name, namefiles in examples.items():
ftypes = []
for namefile in namefiles:
ftype = get_packages(namefile, packages_selected)
ftype = get_packages(namefile)
if ftype not in ftypes:
ftypes += ftype
if len(ftypes) > 0:
Expand Down
2 changes: 1 addition & 1 deletion modflow_devtools/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def get_packages(namefile_path: PathLike) -> List[str]:
def has_package(namefile_path: PathLike, package: str) -> bool:
"""Determines whether the model with the given namefile contains the selected package"""
packages = get_packages(namefile_path)
return package.lower in packages
return package.lower() in packages


def get_namefile_paths(
Expand Down
17 changes: 13 additions & 4 deletions modflow_devtools/test/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
get_model_paths,
get_namefile_paths,
get_packages,
set_dir,
set_dir, has_package,
)


Expand All @@ -32,12 +32,21 @@ def test_set_dir(tmp_path):


@pytest.mark.skipif(not any(_example_paths), reason="examples not found")
def test_has_packages():
example_path = _example_paths[0]
packages = get_packages(example_path / "mfsim.nam")
def test_get_packages():
namefile_path = _example_paths[0]
packages = get_packages(namefile_path / "mfsim.nam")
assert set(packages) == {"tdis", "gwf", "ims"}


@pytest.mark.skipif(not any(_example_paths), reason="examples not found")
def test_has_package():
namefile_path = _example_paths[0] / "mfsim.nam"
assert has_package(namefile_path, "tdis")
assert has_package(namefile_path, "gwf")
assert has_package(namefile_path, "ims")
assert not has_package(namefile_path, "gwt")


def get_expected_model_dirs(path, pattern="mfsim.nam") -> List[Path]:
folders = []
for root, dirs, files in os.walk(path):
Expand Down

0 comments on commit a0482af

Please sign in to comment.