Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/optional.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,23 @@ jobs:
with:
cache-dependency-glob: "**/pyproject.toml"

- name: Install FloPy
run: uv sync --extra test
- name: Install FloPy without optional dependencies
run: uv sync --only-group test

- name: Install other dependencies
run: |
# Install optional dependencies according to matrix.optdeps.
# If matrix.optdeps is "some" remove 3 optional dependencies
# selected randomly using the current date as the seed.
if [[ ! "${{ matrix.optdeps }}" == *"no"* ]]; then
uv pip install ".[optional]"
uv sync --extra optional
fi
if [[ "${{ matrix.optdeps }}" == *"some"* ]]; then
deps=$(sed '/optional =/,/]/!d' pyproject.toml | sed -e '1d;$d' -e 's/\"//g' -e 's/,//g' | tr -d ' ' | cut -f 1 -d ';')
rmvd=$(echo $deps | tr ' ' '\n' | shuf --random-source <(yes date +%d.%m.%y) | head -n 3)
echo "Removing optional dependencies: $rmvd" >> removed_dependencies.txt
cat removed_dependencies.txt
uv pip uninstall --yes $rmvd
uv pip uninstall $rmvd
fi

- name: Upload removed dependencies log
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/rtd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ jobs:
working-directory: modflow6
run: |
pixi run -e rtd install
pixi run -e rtd pip install "../flopy[optional,test]"
pixi run -e rtd pip install "../flopy[optional]"

- name: Workaround OpenGL issue on Linux
if: runner.os == 'Linux'
Expand Down
36 changes: 27 additions & 9 deletions DEVELOPER.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,21 +62,39 @@ git config blame.ignoreRevsFile .git-blame-ignore-revs

This project has historically aimed to support a wide range of [Python versions](https://devguide.python.org/versions/). In current and future development this window may narrow to follow [SPEC 0](https://scientific-python.org/specs/spec-0000/#support-window) instead.

Install Python >=3.10 via [standalone download](https://www.python.org/downloads/) or a distribution like [Anaconda](https://www.anaconda.com/products/individual) or [miniconda](https://docs.conda.io/en/latest/miniconda.html).
Install Python >=3.10 via [standalone download](https://www.python.org/downloads/), [uv](https://docs.astral.sh/uv/), or a conda-like distribution like [Anaconda](https://www.anaconda.com/products/individual), [miniconda](https://docs.conda.io/en/latest/miniconda.html) or [miniforge](https://github.com/conda-forge/miniforge) .

Then install FloPy and core dependencies from the project root:
Then install FloPy and core dependencies from the project root path:

```sh
pip install .
pip install -e .
```

The FloPy package has a number of [optional dependencies](.docs/optional_dependencies.md), as well as extra dependencies required for linting, testing, and building documentation. Extra dependencies are listed in the `test`, `lint`, `optional`, and `doc` groups under the `[project.optional-dependencies]` section in `pyproject.toml`. Core, linting, testing and optional dependencies are included in the Conda environment in `etc/environment.yml`. Only core dependencies are included in the PyPI package &mdash; to install extra dependency groups with pip, use `pip install ".[<group>]"`. For instance, to install all development dependencies:
The `-e` option installs FloPy as an "editable" package to implement and test changes iteratively, and is recommended for developers.

FloPy has a number of user-facing [optional dependencies](.docs/md/optional_dependencies.md) and developer-facing dependencies needed for linting and testing. These are handled differently, depending on the Python developer environment.

#### Pip-like

Pip and related tools (pipenv, uv) declare their optional dependencies under the `[project.optional-dependencies]` section in `pyproject.toml`, and can be installed with:

```sh
pip install ".[dev]"
pip install -e ".[optional]"
```

Alternatively, with Anaconda or Miniconda:
Developer-facing dependencies used for internal development, and are grouped by the following group labels: `test`, `lint` and `docs`. A `dev` group combines `test` and `lint` with the `optional` and `codegen` extras, and is recommended for developers. These dependencies are listed under the `[dependency-groups]` section in `pyproject.toml`

Dependency groups can be installed with `uv` or `pip` version 25.1 (2025-04-26), which support the `--group <group>` option:

```sh
pip install --group dev
```

Note that `uv sync` includes the `dev` group by default.

#### Conda-like

Conda environments can be created using a file `etc/environment.yml`, which includes optional dependencies, and dependencies for development. This development environment can be installed and activated with:

```sh
conda env create -f etc/environment.yml
Expand Down Expand Up @@ -180,10 +198,10 @@ To convert a Python example script to an `.ipynb` notebook, run:
jupytext --from py --to ipynb path/to/script.py
```

To work with `.ipynb` notebooks from a browser interface, you will need `jupyter` installed (`jupyter` is included with the `test` optional dependency group in `pyproject.toml`). Some of the notebooks use testing dependencies and [optional dependencies](.docs/optional_dependencies.md) as well. The conda environment provided in `etc/environment.yml` already includes all dependencies needed to run the examples. To install all development dependencies at once using `pip`:
To work with `.ipynb` notebooks from a browser interface, you will need `jupyter` installed (`jupyter` is included with the `test` dependency group in `pyproject.toml`). Some of the notebooks use testing dependencies and [optional dependencies](.docs/md/optional_dependencies.md) as well. The conda environment provided in `etc/environment.yml` already includes all dependencies needed to run the examples. To install all development dependencies at once using `pip`:

```sh
pip install ".[dev]"
pip install --group dev
```

To start a local Jupyter notebook server, run:
Expand Down Expand Up @@ -242,7 +260,7 @@ Each example should create and (attempt to) dispose of its own isolated temporar

## Tests

To run the tests you will need `pytest` and a few plugins, including [`pytest-xdist`](https://pytest-xdist.readthedocs.io/en/latest/), [`pytest-dotenv`](https://github.com/quiqua/pytest-dotenv), and [`pytest-benchmark`](https://pytest-benchmark.readthedocs.io/en/latest/index.html). Test dependencies are specified in the `test` extras group in `pyproject.toml` (with pip, use `pip install ".[test]"`). Test dependencies are included in the Conda environment `etc/environment`.
To run the tests you will need `pytest` and a few plugins, including [`pytest-xdist`](https://pytest-xdist.readthedocs.io/en/latest/), [`pytest-dotenv`](https://github.com/quiqua/pytest-dotenv), and [`pytest-benchmark`](https://pytest-benchmark.readthedocs.io/en/latest/index.html). See details installing test dependencies for [pip-like](#pip-like) or [Conda-like](#conda-like) environments.

**Note:** tests require the [`modflow-devtools`](https://github.com/MODFLOW-ORG/modflow-devtools) package, which is a grab bag of utilities and `pytest` fixtures shared by FloPy, MODFLOW 6, and other related projects. If you see testing errors that don't seem related to the contents of the tests, updating to the latest `modflow-devtools` is recommended as a first troubleshooting step.

Expand Down
8 changes: 4 additions & 4 deletions autotest/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,10 @@ def pytest_report_header(config):
except metadata.PackageNotFoundError:
items.append(f"{name} (not found)")
lines.append("required packages: " + ", ".join(items))
for optional in ["optional", "test"]:
for group in ["optional"]:
installed = []
not_found = []
for name in extra[optional]:
for name in extra[group]:
if name in processed:
continue
processed.add(name)
Expand All @@ -147,7 +147,7 @@ def pytest_report_header(config):
except metadata.PackageNotFoundError:
not_found.append(name)
if installed:
lines.append(f"{optional} packages: {', '.join(installed)}")
lines.append(f"{group} packages: {', '.join(installed)}")
if not_found:
lines.append(f"{optional} packages not found: {', '.join(not_found)}")
lines.append(f"{group} packages not found: {', '.join(not_found)}")
return "\n".join(lines)
2 changes: 1 addition & 1 deletion flopy/utils/utl_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@

from .parse_version import Version

# Update .docs/optional_dependencies.md when updating versions!
# Update .docs/md/optional_dependencies.md when updating versions!

VERSIONS = {
"shapefile": "2.0.0",
Expand Down
65 changes: 39 additions & 26 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,36 +33,13 @@ dependencies = [
dynamic = ["version", "readme"]

[project.optional-dependencies]
dev = ["flopy[codegen,lint,test,optional,doc]", "tach"]
codegen = [
"Jinja2>=3.0",
"boltons",
"modflow-devtools>=1.7.0,!=1.9.0,<2",
"tomli",
"tomli-w"
]
lint = ["cffconvert", "codespell[toml] >=2.2.2", "ruff"]
test = [
"flopy[lint]",
"boltons",
"coverage !=7.6.5",
"flaky",
"filelock",
"jupyter",
"jupyter_client >=8.4.0", # avoid datetime.utcnow() deprecation warning
"jupytext",
"modflow-devtools>=1.7.0,!=1.9.0,<2",
"pytest !=8.1.0",
"pytest-benchmark",
"pytest-cov",
"pytest-dotenv",
"pytest-xdist",
"pyzmq >=25.1.2",
"syrupy <5.0.0",
"tomli",
"tomli-w",
"virtualenv"
]
optional = [
"affine",
"descartes",
Expand All @@ -86,9 +63,38 @@ optional = [
"h5py",
"scikit-learn"
]
doc = [
"flopy[optional]",
"ipython[kernel]",

[dependency-groups]
lint = [
"cffconvert",
"codespell[toml] >=2.2.2",
"ruff",
]
test = [
"boltons",
"coverage !=7.6.5",
"filelock",
"flaky",
"jupyter",
"jupyter_client >=8.4.0", # avoid datetime.utcnow() deprecation warning
"jupytext",
"modflow-devtools>=1.7.0,!=1.9.0,<2",
"pytest !=8.1.0",
"pytest-benchmark",
"pytest-cov",
"pytest-dotenv",
"pytest-xdist",
"pyzmq >=25.1.2",
"syrupy <5.0.0",
"tomli",
"tomli-w",
"virtualenv",
{include-group = "lint"},
]
docs = [
"flopy[optional]", # self-reference from project.optional-dependencies
"ipython",
"ipykernel",
"jupytext",
"myst-parser",
"nbconvert <7.14.0",
Expand All @@ -98,6 +104,13 @@ doc = [
"sphinx ==7.1.2",
"sphinx-rtd-theme >=1",
]
dev = [
"flopy[codegen,optional]", # self-reference from project.optional-dependencies
"tach",
{include-group = "lint"},
{include-group = "test"},
# {include-group = "docs"},
]

[project.scripts]
get-modflow = "flopy.utils.get_modflow:cli_main"
Expand Down