From a6f24a73ee39e1c52cbe8ebff709e7fe09e7718c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 12 Aug 2023 16:58:41 +0000 Subject: [PATCH 1/5] ci(release): update to development version 1.2.0.dev0 --- docs/conf.py | 2 +- modflow_devtools/__init__.py | 2 +- version.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index dbe67219..57170400 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -8,7 +8,7 @@ project = "modflow-devtools" author = "MODFLOW Team" -release = "1.1.0" +release = "1.2.0.dev0" # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration diff --git a/modflow_devtools/__init__.py b/modflow_devtools/__init__.py index abd32129..22660b1d 100644 --- a/modflow_devtools/__init__.py +++ b/modflow_devtools/__init__.py @@ -1,6 +1,6 @@ __author__ = "Joseph D. Hughes" __date__ = "Aug 12, 2023" -__version__ = "1.1.0" +__version__ = "1.2.0.dev0" __maintainer__ = "Joseph D. Hughes" __email__ = "jdhughes@usgs.gov" __status__ = "Production" diff --git a/version.txt b/version.txt index 1cc5f657..815ce04b 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.1.0 \ No newline at end of file +1.2.0.dev0 \ No newline at end of file From 72db457fabc658c5366b534ad79b2d501e75f580 Mon Sep 17 00:00:00 2001 From: w-bonelli Date: Thu, 24 Aug 2023 08:08:41 -0400 Subject: [PATCH 2/5] docs: update deprecated config in .readthedocs.yml (#110) --- .readthedocs.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index 99b914b9..c1325d5d 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -1,10 +1,13 @@ version: 2 +build: + os: "ubuntu-22.04" + tools: + python: "3.8" sphinx: configuration: docs/conf.py formats: - pdf python: - version: "3.8" install: - method: pip path: . From b8ee2e3e412bd57ee9fb3e4f185ed946f7f27100 Mon Sep 17 00:00:00 2001 From: w-bonelli Date: Sat, 2 Sep 2023 07:53:59 -0400 Subject: [PATCH 3/5] docs(readme): update badges (#111) * anaconda license, version, last updated * pypi license, format * github contributors --- README.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 75711ead..1ae2c7d2 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,24 @@ # MODFLOW developer tools +[![CI](https://github.com/MODFLOW-USGS/modflow-devtools/actions/workflows/ci.yml/badge.svg)](https://github.com/MODFLOW-USGS/modflow-devtools/actions/workflows/ci.yml) +[![Documentation Status](https://readthedocs.org/projects/modflow-devtools/badge/?version=latest)](https://modflow-devtools.readthedocs.io/en/latest/?badge=latest) +[![GitHub contributors](https://img.shields.io/github/contributors/MODFLOW-USGS/modflow-devtools)](https://img.shields.io/github/contributors/MODFLOW-USGS/modflow-devtools) [![GitHub tag](https://img.shields.io/github/tag/MODFLOW-USGS/modflow-devtools.svg)](https://github.com/MODFLOW-USGS/modflow-devtools/tags/latest) + +[![PyPI License](https://img.shields.io/pypi/l/modflow-devtools)](https://pypi.python.org/pypi/modflow-devtools) +[![PyPI Status](https://img.shields.io/pypi/status/modflow-devtools.png)](https://pypi.python.org/pypi/modflow-devtools) +[![PyPI Format](https://img.shields.io/pypi/format/modflow-devtools)](https://pypi.python.org/pypi/modflow-devtools) [![PyPI Version](https://img.shields.io/pypi/v/modflow-devtools.png)](https://pypi.python.org/pypi/modflow-devtools) [![PyPI Versions](https://img.shields.io/pypi/pyversions/modflow-devtools.png)](https://pypi.python.org/pypi/modflow-devtools) -[![PyPI Status](https://img.shields.io/pypi/status/modflow-devtools.png)](https://pypi.python.org/pypi/modflow-devtools) -[![CI](https://github.com/MODFLOW-USGS/modflow-devtools/actions/workflows/ci.yml/badge.svg)](https://github.com/MODFLOW-USGS/modflow-devtools/actions/workflows/ci.yml) -[![Documentation Status](https://readthedocs.org/projects/modflow-devtools/badge/?version=latest)](https://modflow-devtools.readthedocs.io/en/latest/?badge=latest) -Python development tools for MODFLOW 6. +[![Anaconda License](https://anaconda.org/conda-forge/modflow-devtools/badges/license.svg)](https://anaconda.org/conda-forge/modflow-devtools/badges/license.svg) +[![Anaconda Version](https://anaconda.org/conda-forge/modflow-devtools/badges/version.svg)](https://anaconda.org/conda-forge/modflow-devtools) +[![Anaconda Updated](https://anaconda.org/conda-forge/modflow-devtools/badges/latest_release_date.svg)](https://anaconda.org/conda-forge/modflow-devtools) +Python development tools for MODFLOW 6. - [Use cases](#use-cases) - [Requirements](#requirements) From a41caa75f8519780c7ee60daf61d8225b4380dd5 Mon Sep 17 00:00:00 2001 From: wpbonelli Date: Mon, 11 Sep 2023 20:58:08 -0400 Subject: [PATCH 4/5] feat(fixtures): add use_pandas pytest fixture and --pandas CLI arg (#112) --- modflow_devtools/fixtures.py | 40 ++++++++++---- modflow_devtools/test/test_fixtures.py | 73 ++++++++++++++++++++------ 2 files changed, 89 insertions(+), 24 deletions(-) diff --git a/modflow_devtools/fixtures.py b/modflow_devtools/fixtures.py index 66da7778..1fa695c8 100644 --- a/modflow_devtools/fixtures.py +++ b/modflow_devtools/fixtures.py @@ -1,3 +1,4 @@ +import random from collections import OrderedDict from itertools import groupby from os import PathLike, environ @@ -10,7 +11,8 @@ pytest = import_optional_dependency("pytest") -# temporary directory fixtures + +# fixtures @pytest.fixture(scope="function") @@ -23,7 +25,7 @@ def function_tmpdir(tmpdir_factory, request) -> Path: temp = Path(tmpdir_factory.mktemp(node)) yield Path(temp) - keep = request.config.getoption("--keep") + keep = request.config.option.KEEP if keep: path = Path(keep) / temp.name if path.is_dir(): @@ -46,7 +48,7 @@ def class_tmpdir(tmpdir_factory, request) -> Path: temp = Path(tmpdir_factory.mktemp(request.cls.__name__)) yield temp - keep = request.config.getoption("--keep") + keep = request.config.option.KEEP if keep: path = Path(keep) / temp.name if path.is_dir(): @@ -59,7 +61,7 @@ def module_tmpdir(tmpdir_factory, request) -> Path: temp = Path(tmpdir_factory.mktemp(request.module.__name__)) yield temp - keep = request.config.getoption("--keep") + keep = request.config.option.KEEP if keep: path = Path(keep) / temp.name if path.is_dir(): @@ -72,7 +74,7 @@ def session_tmpdir(tmpdir_factory, request) -> Path: temp = Path(tmpdir_factory.mktemp(request.session.name)) yield temp - keep = request.config.getoption("--keep") + keep = request.config.option.KEEP if keep: path = Path(keep) / temp.name if path.is_dir(): @@ -80,16 +82,26 @@ def session_tmpdir(tmpdir_factory, request) -> Path: copytree(temp, path) -# environment-dependent fixtures - - @pytest.fixture def repos_path() -> Optional[Path]: """Path to directory containing test model and example repositories""" return environ.get("REPOS_PATH", None) -# pytest configuration hooks +@pytest.fixture +def use_pandas(request): + pandas = request.config.option.PANDAS + if pandas == "yes": + return True + elif pandas == "no": + return False + elif pandas == "random": + return random.randint(0, 1) == 0 + else: + raise ValueError(f"Unsupported value for --pandas: {pandas}") + + +# configuration hooks def pytest_addoption(parser): @@ -98,6 +110,7 @@ def pytest_addoption(parser): "--keep", action="store", default=None, + dest="KEEP", help="Move the contents of temporary test directories to correspondingly named subdirectories at the given " "location after tests complete. This option can be used to exclude test results from automatic cleanup, " "e.g. for manual inspection. The provided path is created if it does not already exist. An error is " @@ -144,6 +157,15 @@ def pytest_addoption(parser): help="Select a subset of packages to run.", ) + parser.addoption( + "-P", + "--pandas", + action="store", + default="yes", + dest="PANDAS", + help="Package input data can be provided as either pandas dataframes or numpy recarrays. By default, pandas dataframes are used. To test with numpy recarrays, use 'no'. To randomize selection (per test), use 'random'.", + ) + def pytest_configure(config): config.addinivalue_line( diff --git a/modflow_devtools/test/test_fixtures.py b/modflow_devtools/test/test_fixtures.py index f553823d..c5364e68 100644 --- a/modflow_devtools/test/test_fixtures.py +++ b/modflow_devtools/test/test_fixtures.py @@ -47,18 +47,18 @@ def test_function_scoped_tmpdir_slash_in_name(function_tmpdir, name): class TestClassScopedTmpdir: - filename = "hello.txt" + fname = "hello.txt" @pytest.fixture(autouse=True) def setup(self, class_tmpdir): - with open(class_tmpdir / self.filename, "w") as file: + with open(class_tmpdir / self.fname, "w") as file: file.write("hello, class-scoped tmpdir") def test_class_scoped_tmpdir(self, class_tmpdir): assert isinstance(class_tmpdir, Path) assert class_tmpdir.is_dir() assert self.__class__.__name__ in class_tmpdir.stem - assert Path(class_tmpdir / self.filename).is_file() + assert Path(class_tmpdir / self.fname).is_file() def test_module_scoped_tmpdir(module_tmpdir): @@ -74,38 +74,38 @@ def test_session_scoped_tmpdir(session_tmpdir): # test CLI arguments --keep (-K) and --keep-failed for temp dir fixtures -FILE_NAME = "hello.txt" +test_keep_fname = "hello.txt" @pytest.mark.meta("test_keep") def test_keep_function_scoped_tmpdir_inner(function_tmpdir): - with open(function_tmpdir / FILE_NAME, "w") as f: + with open(function_tmpdir / test_keep_fname, "w") as f: f.write("hello, function-scoped tmpdir") @pytest.mark.meta("test_keep") class TestKeepClassScopedTmpdirInner: def test_keep_class_scoped_tmpdir_inner(self, class_tmpdir): - with open(class_tmpdir / FILE_NAME, "w") as f: + with open(class_tmpdir / test_keep_fname, "w") as f: f.write("hello, class-scoped tmpdir") @pytest.mark.meta("test_keep") def test_keep_module_scoped_tmpdir_inner(module_tmpdir): - with open(module_tmpdir / FILE_NAME, "w") as f: + with open(module_tmpdir / test_keep_fname, "w") as f: f.write("hello, module-scoped tmpdir") @pytest.mark.meta("test_keep") def test_keep_session_scoped_tmpdir_inner(session_tmpdir): - with open(session_tmpdir / FILE_NAME, "w") as f: + with open(session_tmpdir / test_keep_fname, "w") as f: f.write("hello, session-scoped tmpdir") @pytest.mark.parametrize("arg", ["--keep", "-K"]) def test_keep_function_scoped_tmpdir(function_tmpdir, arg): inner_fn = test_keep_function_scoped_tmpdir_inner.__name__ - file_path = Path(function_tmpdir / f"{inner_fn}0" / FILE_NAME) + file_path = Path(function_tmpdir / f"{inner_fn}0" / test_keep_fname) args = [ __file__, "-v", @@ -144,7 +144,9 @@ def test_keep_class_scoped_tmpdir(tmp_path, arg): ] assert pytest.main(args) == ExitCode.OK assert Path( - tmp_path / f"{TestKeepClassScopedTmpdirInner.__name__}0" / FILE_NAME + tmp_path + / f"{TestKeepClassScopedTmpdirInner.__name__}0" + / test_keep_fname ).is_file() @@ -171,7 +173,7 @@ def test_keep_module_scoped_tmpdir(tmp_path, arg): print(keep_path) pprint(list(keep_path.glob("*"))) - assert FILE_NAME in [f.name for f in keep_path.glob("*")] + assert test_keep_fname in [f.name for f in keep_path.glob("*")] @pytest.mark.parametrize("arg", ["--keep", "-K"]) @@ -188,12 +190,14 @@ def test_keep_session_scoped_tmpdir(tmp_path, arg, request): tmp_path, ] assert pytest.main(args) == ExitCode.OK - assert Path(tmp_path / f"{request.session.name}0" / FILE_NAME).is_file() + assert Path( + tmp_path / f"{request.session.name}0" / test_keep_fname + ).is_file() @pytest.mark.meta("test_keep_failed") def test_keep_failed_function_scoped_tmpdir_inner(function_tmpdir): - with open(function_tmpdir / FILE_NAME, "w") as f: + with open(function_tmpdir / test_keep_fname, "w") as f: f.write("hello, function-scoped tmpdir") assert False, "oh no" @@ -207,7 +211,9 @@ 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" / FILE_NAME).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 @@ -234,7 +240,7 @@ def pytest_terminal_summary(self, terminalreporter): def test_meta(): args = [ - f"{__file__}", + __file__, "-v", "-s", "-k", @@ -273,3 +279,40 @@ def test_large_test_model(large_test_model): assert isinstance(large_test_model, Path) assert large_test_model.is_file() 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 From 9810437aea087dee2ca2563aebc077d82787051f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 12 Sep 2023 01:00:54 +0000 Subject: [PATCH 5/5] ci(release): set version to 1.2.0, update changelog --- HISTORY.md | 6 ++++++ docs/conf.py | 2 +- modflow_devtools/__init__.py | 4 ++-- version.txt | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 96524f3e..0f7d8d99 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,3 +1,9 @@ +### Version 1.2.0 + +#### New features + +* [feat(fixtures)](https://github.com/MODFLOW-USGS/modflow-devtools/commit/a41caa75f8519780c7ee60daf61d8225b4380dd5): Add use_pandas pytest fixture and --pandas CLI arg (#112). Committed by wpbonelli on 2023-09-12. + ### Version 1.1.0 #### Refactoring diff --git a/docs/conf.py b/docs/conf.py index 57170400..ba8c65b6 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -8,7 +8,7 @@ project = "modflow-devtools" author = "MODFLOW Team" -release = "1.2.0.dev0" +release = "1.2.0" # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration diff --git a/modflow_devtools/__init__.py b/modflow_devtools/__init__.py index 22660b1d..a37151c7 100644 --- a/modflow_devtools/__init__.py +++ b/modflow_devtools/__init__.py @@ -1,6 +1,6 @@ __author__ = "Joseph D. Hughes" -__date__ = "Aug 12, 2023" -__version__ = "1.2.0.dev0" +__date__ = "Sep 12, 2023" +__version__ = "1.2.0" __maintainer__ = "Joseph D. Hughes" __email__ = "jdhughes@usgs.gov" __status__ = "Production" diff --git a/version.txt b/version.txt index 815ce04b..867e5243 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.2.0.dev0 \ No newline at end of file +1.2.0 \ No newline at end of file