diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml deleted file mode 100644 index a666667..0000000 --- a/.github/workflows/docs.yml +++ /dev/null @@ -1,53 +0,0 @@ -name: Documentation - -on: - push: - paths: - - "docs/**" - - "AUTHORS.rst" - - "CHANGES.rst" - - "CONTRIBUTING.rst" - - "LICENSE.rst" - - "README.rst" - pull_request: - paths: - - "docs/**" - - "AUTHORS.rst" - - "CHANGES.rst" - - "CONTRIBUTING.rst" - - "LICENSE.rst" - - "README.rst" - -jobs: - build: - # We want to run on external PRs, but not on our own internal PRs as they'll be run - # by the push to the branch. Without this if check, checks are duplicated since - # internal PRs match both the push and pull_request events. - if: - github.event_name == 'push' || github.event.pull_request.head.repo.full_name != - github.repository - - runs-on: ubuntu-latest - - defaults: - run: - shell: bash -l {0} - - steps: - - uses: actions/checkout@v3 - - uses: conda-incubator/setup-miniconda@v2 - with: - auto-update-conda: true - python-version: "3.11" - channels: conda-forge - channel-priority: true - - - name: Show conda installation info - run: conda info - - - name: Install dependencies - run: | - pip install nox - - - name: Build documentation - run: nox -s docs diff --git a/.github/workflows/flake8.yml b/.github/workflows/flake8.yml deleted file mode 100644 index 6ecca74..0000000 --- a/.github/workflows/flake8.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Lint - -on: [push, pull_request] - -jobs: - - lint: - name: Check for lint - # We want to run on external PRs, but not on our own internal PRs as they'll be run - # by the push to the branch. Without this if check, checks are duplicated since - # internal PRs match both the push and pull_request events. - if: - github.event_name == 'push' || github.event.pull_request.head.repo.full_name != - github.repository - - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Set up Python 3.8 - uses: actions/setup-python@v4 - with: - python-version: 3.11 - - - name: Lint - run: | - pip install nox - nox -s lint diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3718c09..9c1020c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -3,15 +3,84 @@ name: Test on: [push, pull_request] jobs: - build-and-test: - name: Run the tests - # We want to run on external PRs, but not on our own internal PRs as they'll be run - # by the push to the branch. Without this if check, checks are duplicated since - # internal PRs match both the push and pull_request events. - if: - github.event_name == 'push' || github.event.pull_request.head.repo.full_name != - github.repository + check-tag: + # Run on external PRs, but not on internal PRs, to avoid duplicate runs + if: | + github.event_name == 'push' || + github.event.pull_request.head.repo.full_name != github.repository + runs-on: ubuntu-latest + outputs: + publish_url: ${{ steps.check-publish.outputs.publish_url }} + + steps: + - name: Check if this is a release/prerelease + id: check-publish + run: | + tag_name="${GITHUB_REF#refs/tags/}" + if [[ "$tag_name" =~ ^v[0-9]+\.[0-9]+\.[0-9]+[ab][0-9]+$ ]]; then + publish_url="https://test.pypi.org/legacy/" + elif [[ "$tag_name" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + publish_url="https://upload.pypi.org/legacy/" + else + publish_url="none" + fi + echo "publish_url=$publish_url" >> "$GITHUB_OUTPUT" + echo "tag_name=$tag_name" + echo "publish_url=$publish_url" + + build-sdist: + name: Build source distribution + needs: check-tag + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Build sdist + run: pipx run build --sdist + + - uses: actions/upload-artifact@v4 + with: + name: build-sdist + path: ${{ github.workspace }}/dist/*.tar.gz + + test-with-pip: + name: Test with pip + needs: build-sdist + runs-on: ${{ matrix.os }} + + defaults: + run: + shell: bash -l {0} + + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + python-version: ["3.10", "3.11", "3.12"] + fail-fast: false + + steps: + - uses: actions/checkout@v4 + + - name: Use Python ${{ matrix.python-version}} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - uses: actions/download-artifact@v4 + with: + pattern: "build-*" + merge-multiple: true + path: ${{ github.workspace }}/dist + + - name: Test package + run: | + pip install nox + nox --verbose --force-python=${{ matrix.python-version }} -s test-with-pip -- dist/*.tar.gz + + test-with-conda: + name: Test with conda + needs: build-sdist runs-on: ${{ matrix.os }} defaults: @@ -21,31 +90,78 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python-version: ["3.9", "3.10", "3.11"] - installer: ["pip", "conda"] - exclude: - - python-version: "3.11" - installer: "pip" - - os: windows-latest - installer: "pip" + python-version: ["3.10", "3.11", "3.12"] fail-fast: false steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: conda-incubator/setup-miniconda@v2 + - uses: conda-incubator/setup-miniconda@v3 with: auto-update-conda: true python-version: ${{ matrix.python-version }} channels: conda-forge channel-priority: true + - uses: actions/download-artifact@v4 + with: + pattern: "build-*" + merge-multiple: true + path: ${{ github.workspace }}/dist + - name: Show conda installation info run: | + conda list conda info - conda install mamba - name: Test package run: | pip install nox - nox --verbose --force-python=${{ matrix.python-version }} -s test-with-${{ matrix.installer }} + nox --verbose --force-python=${{ matrix.python-version }} -s test-with-conda -- dist/*.tar.gz + + build-docs: + name: Build the docs + needs: check-tag + runs-on: ubuntu-latest + + defaults: + run: + shell: bash -l {0} + + steps: + - uses: actions/checkout@v4 + - name: Use Python + uses: actions/setup-python@v5 + with: + python-version: 3.12 + + - name: Build documentation + run: | + pip install nox + nox -s docs + + publish: + needs: + - check-tag + - test-with-pip + - test-with-conda + - build-docs + name: "Publish to PyPI/TestPyPI" + runs-on: ubuntu-latest + + permissions: + id-token: write + + steps: + - uses: actions/download-artifact@v4 + with: + pattern: "build-*" + merge-multiple: true + path: ${{ github.workspace }}/dist + - uses: pypa/gh-action-pypi-publish@release/v1 + if: ${{ startsWith(needs.check-tag.outputs.publish_url, 'http') }} + with: + repository-url: ${{ needs.check-tag.outputs.publish_url }} + skip-existing: true + print-hash: true + verify-metadata: false diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0f7dfe1..441f465 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -66,6 +66,7 @@ repos: - id: forbid-new-submodules - id: mixed-line-ending - id: trailing-whitespace + - id: name-tests-test - repo: https://github.com/regebro/pyroma rev: "4.2" diff --git a/docs/requirements.txt b/docs/requirements.txt index d6463df..85bc44b 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -5,3 +5,4 @@ sphinx==7.0.1 sphinx-copybutton==0.5.1 sphinx-inline-tabs==2022.1.2b11 sphinxcontrib-towncrier==0.3.2a0 +towncrier==23.11.0 diff --git a/noxfile.py b/noxfile.py index 879fca4..8221486 100644 --- a/noxfile.py +++ b/noxfile.py @@ -1,5 +1,7 @@ +import os import pathlib import shutil +import sys from itertools import chain import nox @@ -7,11 +9,22 @@ ROOT = pathlib.Path(__file__).parent -@nox.session(name="test-with-pip", python=["3.9", "3.10", "3.11"]) +@nox.session(name="test-with-pip", python=["3.10", "3.11", "3.12"]) def test_with_pip(session: nox.Session) -> None: """Run the tests.""" + first_arg = session.posargs[0] if session.posargs else None + session.install("-r", "requirements-testing.in") - session.install(".") + if sys.platform.startswith("win"): + session.install("ecmwflibs") + + if first_arg: + if os.path.isfile(first_arg): + session.install(first_arg) + else: + session.error("path must be a source distribution") + else: + session.install(".") session.run("pytest", "--cov=src/bmi_wavewatch3", "-vvv") session.run("coverage", "report", "--ignore-errors", "--show-missing") @@ -19,13 +32,22 @@ def test_with_pip(session: nox.Session) -> None: @nox.session( - name="test-with-conda", venv_backend="mamba", python=["3.9", "3.10", "3.11"] + name="test-with-conda", venv_backend="conda", python=["3.10", "3.11", "3.12"] ) def test_with_conda(session: nox.Session) -> None: """Run the tests.""" + first_arg = session.posargs[0] if session.posargs else None + session.conda_install("--file=requirements-testing.in") session.conda_install("--file=requirements-conda.in") - session.install(".", "--no-deps") + + if first_arg: + if os.path.isfile(first_arg): + session.install(first_arg, "--no-deps") + else: + session.error("path must be a source distribution") + else: + session.install(".", "--no-deps") session.run("pytest", "--cov=src/bmi_wavewatch3", "-vvv") session.run("coverage", "report", "--ignore-errors", "--show-missing") diff --git a/pyproject.toml b/pyproject.toml index 342fd64..80ea8b2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,6 @@ dependencies = [ "tomli", "tqdm", "xarray", - "ecmwflibs", ] dynamic = ["readme", "version"] @@ -64,9 +63,14 @@ ww3 = "bmi_wavewatch3.cli:ww3" channels = ["conda-forge", "defaults"] platforms = ["osx-arm64", "linux-64", "osx-64", "win-64"] +# [tool.setuptools] +# py-modules = [] + +[tool.setuptools.packages.find] +where = ["src"] [tool.setuptools.dynamic] -readme = {file = ["README.md", "AUTHORS.md", "CHANGES.md"], content_type="text/markdown"} +readme = {file = ["README.md", "AUTHORS.md", "CHANGES.md"], content-type="text/markdown"} version = {attr = "bmi_wavewatch3._version.__version__"} [tool.pytest.ini_options] diff --git a/requirements-conda.in b/requirements-conda.in index 69e109e..3fcf966 100644 --- a/requirements-conda.in +++ b/requirements-conda.in @@ -2,7 +2,6 @@ bmipy cfgrib click dask -findlibs matplotlib rich-click tomli diff --git a/requirements.in b/requirements.in index 91b9673..3fcf966 100644 --- a/requirements.in +++ b/requirements.in @@ -2,7 +2,6 @@ bmipy cfgrib click dask -ecmwflibs matplotlib rich-click tomli diff --git a/tests/test_cli.py b/tests/cli_test.py similarity index 100% rename from tests/test_cli.py rename to tests/cli_test.py diff --git a/tests/test_url.py b/tests/url_test.py similarity index 97% rename from tests/test_url.py rename to tests/url_test.py index 7892093..cc0d864 100644 --- a/tests/test_url.py +++ b/tests/url_test.py @@ -45,6 +45,9 @@ def test_url(source, grid, quantity): assert f"{grid}.{quantity}.{date.year}{date.month:02}.grb" in url.filename +# NOTE: these tests seem to be flaky because of disruption caused by +# Hurricane Helene +@pytest.mark.xfail @pytest.mark.parametrize( "source,grid,quantity", [ diff --git a/tests/test_wavewatch3.py b/tests/wavewatch3_test.py similarity index 100% rename from tests/test_wavewatch3.py rename to tests/wavewatch3_test.py