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 dbe6721..5717040 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 abd3212..22660b1 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 1cc5f65..815ce04 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 99b914b..c1325d5 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 75711ea..1ae2c7d 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 66da777..1fa695c 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 f553823..c5364e6 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 96524f3..0f7d8d9 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 5717040..ba8c65b 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 22660b1..a37151c 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 815ce04..867e524 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