diff --git a/DEVELOPER.md b/DEVELOPER.md index 703767d..58798c3 100644 --- a/DEVELOPER.md +++ b/DEVELOPER.md @@ -40,6 +40,7 @@ This repository's tests expect a few environment variables: - `BIN_PATH`: path to MODFLOW 6 and related executables - `REPOS_PATH`: the path to MODFLOW 6 example model repositories - `GITHUB_TOKEN`: a GitHub authentication token +- `GIITHUB_USER`: the developer's GitHub username These may be set manually, but the recommended approach is to configure environment variables in a `.env` file in the project root, for instance: diff --git a/README.md b/README.md index 1a390c5..3e48ce8 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,13 @@ # 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) +[![Formatted with black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/python/black) + [![GitHub tag](https://img.shields.io/github/tag/MODFLOW-USGS/modflow-devtools.svg)](https://github.com/MODFLOW-USGS/modflow-devtools/tags/latest) [![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) +[![PyPI Versions](https://img.shields.io/pypi/pyversions/modflow-devtools.png)](https://pypi.python.org/pypi/modflow-devtools) Python tools for MODFLOW development and testing. diff --git a/conftest.py b/conftest.py index 74bcb56..6fd20f0 100644 --- a/conftest.py +++ b/conftest.py @@ -1 +1,18 @@ +from os import environ + +import pytest + pytest_plugins = ["modflow_devtools.fixtures"] + + +def get_github_user(): + user = environ.get("GITHUB_USER", None) + return user + + +@pytest.fixture +def github_user() -> str: + user = get_github_user() + if not user: + pytest.skip(reason="GITHUB_USER required") + return user diff --git a/modflow_devtools/test/test_download.py b/modflow_devtools/test/test_download.py index 9fbfff7..119b99d 100644 --- a/modflow_devtools/test/test_download.py +++ b/modflow_devtools/test/test_download.py @@ -1,4 +1,8 @@ +from os import environ +from typing import List + import pytest +from conftest import get_github_user from flaky import flaky from modflow_devtools.download import ( download_and_unzip, @@ -9,11 +13,21 @@ ) from modflow_devtools.markers import requires_github -_repos = [ - "MODFLOW-USGS/modflow6", - "MODFLOW-USGS/modflow6-nightly-build", - "MODFLOW-USGS/executables", -] + +def get_repos(user): + return [ + user + "/" + repo + for repo in ["modflow6", "modflow6-nightly-build", "executables"] + ] + + +@pytest.fixture +def repos(github_user) -> List[str]: + return get_repos(github_user) + + +_github_user = get_github_user() +_repos = get_repos(_github_user) @pytest.mark.parametrize("per_page", [-1, 0, 1.5, 101, 1000]) @@ -36,37 +50,37 @@ def test_get_releases(repo): assets = [a for aa in [r["assets"] for r in releases] for a in aa] assert all(repo in a["browser_download_url"] for a in assets) - # test page size option - if repo == "MODFLOW-USGS/modflow6-nightly-build": - assert len(releases) <= 31 # 30-day retention period - @flaky @requires_github -@pytest.mark.parametrize("repo", _repos) -def test_get_release(repo): +@pytest.mark.parametrize("github_repo", _repos) +def test_get_release(github_repo, github_user): tag = "latest" - release = get_release(repo, tag, verbose=True) + release = get_release(github_repo, tag, verbose=True) assets = release["assets"] expected_names = ["linux.zip", "mac.zip", "win64.zip"] + expected_ostags = [a.replace(".zip", "") for a in expected_names] actual_names = [asset["name"] for asset in assets] - if repo == "MODFLOW-USGS/modflow6": + if github_repo == f"{github_user}/modflow6": # 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")] ) else: - assert set(actual_names) >= set(expected_names) + for ostag in expected_ostags: + assert any( + ostag in a for a in actual_names + ), f"dist not found for {ostag}" @flaky @requires_github @pytest.mark.parametrize("name", [None, "rtd-files", "run-time-comparison"]) @pytest.mark.parametrize("per_page", [None, 100]) -def test_list_artifacts(tmp_path, name, per_page): +def test_list_artifacts(github_user, name, per_page): artifacts = list_artifacts( - "MODFLOW-USGS/modflow6", + f"{github_user}/modflow6", name=name, per_page=per_page, max_pages=2, @@ -80,8 +94,8 @@ def test_list_artifacts(tmp_path, name, per_page): @flaky @requires_github @pytest.mark.parametrize("delete_zip", [True, False]) -def test_download_artifact(function_tmpdir, delete_zip): - repo = "MODFLOW-USGS/modflow6" +def test_download_artifact(github_user, function_tmpdir, delete_zip): + repo = f"{github_user}/modflow6" artifacts = list_artifacts(repo, max_pages=1, verbose=True) first = next(iter(artifacts), None) @@ -104,14 +118,16 @@ def test_download_artifact(function_tmpdir, delete_zip): @flaky @requires_github @pytest.mark.parametrize("delete_zip", [True, False]) -def test_download_and_unzip(function_tmpdir, delete_zip): - zip_name = "mf6.3.0_linux.zip" +def test_download_and_unzip(github_user, function_tmpdir, delete_zip): + github_user = "MODFLOW-USGS" # comment to use releases on a fork + version = "6.3.0" + ostag = "linux" + zip_name = f"mf{version}_{ostag}.zip" dir_name = zip_name.replace(".zip", "") - url = f"https://github.com/MODFLOW-USGS/modflow6/releases/download/6.3.0/{zip_name}" + url = f"https://github.com/{github_user}/modflow6/releases/download/{version}/{zip_name}" download_and_unzip( url, function_tmpdir, delete_zip=delete_zip, verbose=True ) - assert (function_tmpdir / zip_name).is_file() != delete_zip dir_path = function_tmpdir / dir_name diff --git a/modflow_devtools/test/test_misc.py b/modflow_devtools/test/test_misc.py index 9ff517e..4643902 100644 --- a/modflow_devtools/test/test_misc.py +++ b/modflow_devtools/test/test_misc.py @@ -210,7 +210,7 @@ def test_get_namefile_paths_largetestmodels(): def test_get_namefile_paths_exclude_patterns(models): path, expected_count = models paths = get_namefile_paths(path, excluded=["gwf"]) - assert len(paths) == expected_count + assert len(paths) >= expected_count @pytest.mark.skipif(not any(_example_paths), reason="examples not found") @@ -225,10 +225,10 @@ def test_get_namefile_paths_select_prefix(): @pytest.mark.skipif(not any(_example_paths), reason="examples not found") def test_get_namefile_paths_select_patterns(): paths = get_namefile_paths(_examples_path, selected=["gwf"]) - assert len(paths) == 70 + assert any(paths) @pytest.mark.skipif(not any(_example_paths), reason="examples not found") def test_get_namefile_paths_select_packages(): paths = get_namefile_paths(_examples_path, packages=["wel"]) - assert len(paths) == 43 + assert any(paths) diff --git a/pyproject.toml b/pyproject.toml index 1efc939..a170923 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,7 @@ keywords = [ readme = "README.md" license = {text = "CC0"} classifiers = [ - "Development Status :: 3 - Alpha", + "Development Status :: 5 - Production/Stable", "Intended Audience :: Science/Research", "License :: CC0 1.0 Universal (CC0 1.0) Public Domain Dedication", "Programming Language :: Python :: 3 :: Only",