From bb48aefb5c6dc12fff4d8a9028470a09a8129fec Mon Sep 17 00:00:00 2001 From: erexer <13180883+erexer@users.noreply.github.com> Date: Thu, 7 Nov 2024 12:11:51 -0800 Subject: [PATCH 1/5] autopush to pypi action, rename build to test action, add python versions badge --- .github/workflows/docs.yml | 40 +++++++ .github/workflows/publish-to-pypi.yml | 125 ++++++++++++++++++++++ .github/workflows/{build.yml => test.yml} | 4 +- README.md | 2 + 4 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/docs.yml create mode 100644 .github/workflows/publish-to-pypi.yml rename .github/workflows/{build.yml => test.yml} (93%) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..8e8756d --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,40 @@ +name: docs + +on: + push: + branches: [ main ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Install pandoc + run: | + sudo apt-get update -y && sudo apt-get install -y pandoc + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.9' + - name: Update pip and install python dependencies + run: | + python -m pip install --upgrade pip + pip install .[dev] + - name: Build html docs + working-directory: 'docs/' + run: | + make html + - name: Commit documentation changes + run: | + cd docs/build/html + git init + git add -A + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git commit -m 'deploy' -a || true + - name: Push changes to gh-pages + uses: ad-m/github-push-action@master + with: + branch: gh-pages + directory: docs/build/html + force: true + github_token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/publish-to-pypi.yml b/.github/workflows/publish-to-pypi.yml new file mode 100644 index 0000000..6499ed6 --- /dev/null +++ b/.github/workflows/publish-to-pypi.yml @@ -0,0 +1,125 @@ +# This GitHub Action will only push to PyPI if the branch is tagged and then merged to main. +# Tag the branch with: +# $ git push REMOTE-NAME TAG-NAME + +name: Publish Python to PyPI + +on: + push: + branches: + - main + +jobs: + build: + name: Build distribution + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.10.x" + - name: Install pypa/build + run: >- + python3 -m + pip install + build + --user + - name: Build a binary wheel and a source tarball + run: python3 -m build + - name: Store the distribution packages + uses: actions/upload-artifact@v4 + with: + name: python-package-distributions + path: dist/ + + publish-to-pypi: + name: >- + Publish Python distribution to PyPI + if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes + needs: + - build + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/p/mosartwmpy + permissions: + id-token: write # IMPORTANT: mandatory for trusted publishing + + steps: + - name: Download all the dists + uses: actions/download-artifact@v4 + with: + name: python-package-distributions + path: dist/ + - name: Publish distribution to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + + github-release: + name: >- + Sign the Python distribution with Sigstore + and upload them to GitHub Release + needs: + - publish-to-pypi + runs-on: ubuntu-latest + + permissions: + contents: write # IMPORTANT: mandatory for making GitHub Releases + id-token: write # IMPORTANT: mandatory for sigstore + + steps: + - name: Download all the dists + uses: actions/download-artifact@v4 + with: + name: python-package-distributions + path: dist/ + - name: Sign the dists with Sigstore + uses: sigstore/gh-action-sigstore-python@v2.1.1 + with: + inputs: >- + ./dist/*.tar.gz + ./dist/*.whl + - name: Create GitHub Release + env: + GITHUB_TOKEN: ${{ github.token }} + run: >- + gh release create + '${{ github.ref_name }}' + --repo '${{ github.repository }}' + --notes "" + - name: Upload artifact signatures to GitHub Release + env: + GITHUB_TOKEN: ${{ github.token }} + # Upload to GitHub Release using the `gh` CLI. + # `dist/` contains the built packages, and the + # sigstore-produced signatures and certificates. + run: >- + gh release upload + '${{ github.ref_name }}' dist/** + --repo '${{ github.repository }}' + + publish-to-testpypi: + name: Publish to TestPyPI + needs: + - build + runs-on: ubuntu-latest + + environment: + name: testpypi + url: https://test.pypi.org/p/mosartwmpy + + permissions: + id-token: write # IMPORTANT: mandatory for trusted publishing + + steps: + - name: Download all the dists + uses: actions/download-artifact@v4 + with: + name: python-package-distributions + path: dist/ + - name: Publish distribution to TestPyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + repository-url: https://test.pypi.org/legacy/ + verbose: true \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/test.yml similarity index 93% rename from .github/workflows/build.yml rename to .github/workflows/test.yml index ab74e77..51c0001 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/test.yml @@ -1,4 +1,4 @@ -name: build +name: test on: [push] @@ -19,7 +19,7 @@ jobs: steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@master diff --git a/README.md b/README.md index 7d31c55..00f0787 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ [![codecov](https://codecov.io/gh/IMMM-SFA/mosartwmpy/branch/main/graph/badge.svg?token=IPOY8984MB)](https://codecov.io/gh/IMMM-SFA/mosartwmpy) [![DOI](https://joss.theoj.org/papers/10.21105/joss.03221/status.svg)](https://doi.org/10.21105/joss.03221) [![DOI](https://zenodo.org/badge/312114600.svg)](https://zenodo.org/badge/latestdoi/312114600) +[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/mosartwmpy)](https://pypi.org/project/mosartwmpy/) + ## mosartwmpy From 189b4f873c1a8cd880d70baa8a41a932f8f77e6a Mon Sep 17 00:00:00 2001 From: erexer <13180883+erexer@users.noreply.github.com> Date: Thu, 7 Nov 2024 12:18:47 -0800 Subject: [PATCH 2/5] add pre-commit --- .pre-commit-config.yaml | 25 +++++++++++ setup.py | 93 +++++++++++++++++++++-------------------- 2 files changed, 73 insertions(+), 45 deletions(-) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..df51270 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,25 @@ +# pre-commit hooks require a user to have installed `pre-commit`: +# $ pip install pre-commit +# Then install the hooks within the repo: +# $ cd /PATH/TO/REPO +# $ pre-commit install + +repos: +- repo: https://github.com/charliermarsh/ruff-pre-commit + rev: v0.6.9 + hooks: + - id: ruff + args: [ --fix, --exit-non-zero-on-fix] + exclude: .rst +- repo: https://github.com/psf/black + rev: 24.10.0 + hooks: + - id: black + args: [--line-length=100] +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: check-ast + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace diff --git a/setup.py b/setup.py index bb01883..3e6e0a1 100644 --- a/setup.py +++ b/setup.py @@ -4,66 +4,69 @@ def readme(): """Return the contents of the project README file.""" - with open('README.md') as f: + with open("README.md") as f: return f.read() -version = re.search(r"__version__ = ['\"]([^'\"]*)['\"]", open('mosartwmpy/_version.py').read(), re.M).group(1) +version = re.search( + r"__version__ = ['\"]([^'\"]*)['\"]", open("mosartwmpy/_version.py").read(), re.M +).group(1) setup( - name='mosartwmpy', + name="mosartwmpy", version=version, packages=find_packages(), - url='https://github.com/IMMM-SFA/mosartwmpy', - license='BSD2-Simplified', - author='Travis Thurber', - author_email='travis.thurber@pnnl.gov', - description='Python implementation of MOSART-WM: A water routing and management model', + url="https://github.com/IMMM-SFA/mosartwmpy", + license="BSD2-Simplified", + author="Travis Thurber", + author_email="travis.thurber@pnnl.gov", + description="Python implementation of MOSART-WM: A water routing and management model", long_description=readme(), long_description_content_type="text/markdown", - python_requires='>=3.9,<4.0', + python_requires=">=3.9,<4.0", include_package_data=True, entry_points={ - 'console_scripts': [ - 'create_grand_parameters = mosartwmpy.utilities.create_grand_parameters:create_grand_parameters', - 'bil_to_parquet = mosartwmpy.utilities.bil_to_parquet:bil_to_parquet', + "console_scripts": [ + "create_grand_parameters = mosartwmpy.utilities.create_grand_parameters:create_grand_parameters", + "bil_to_parquet = mosartwmpy.utilities.bil_to_parquet:bil_to_parquet", ] }, install_requires=[ - 'bmipy>=2.0', - 'click>=8.0.1', - 'contextily>=1.2.0', - 'dask[complete]>=2021.10.0', - 'geopandas>=0.10.2', - 'h5netcdf>=0.11.0', - 'hvplot>=0.7.3', - 'matplotlib>=3.4.3', - 'nc-time-axis>=1.4.0', - 'netCDF4>=1.5.7', - 'numba>=0.53.1', - 'numpy>=1.20.3,<2.0', - 'pandas>=1.3.4', - 'pathvalidate>=2.5.0', - 'psutil>=5.8.0', - 'pyarrow>=6.0.0', - 'pyomo>=6.2', - 'python-benedict>=0.24.3', - 'regex>=2021.10.23', - 'requests>=2.26.0', - 'rioxarray>=0.8.0', - 'tqdm>=4.62.3', - 'xarray>=0.19.0' + "bmipy>=2.0", + "click>=8.0.1", + "contextily>=1.2.0", + "dask[complete]>=2021.10.0", + "geopandas>=0.10.2", + "h5netcdf>=0.11.0", + "hvplot>=0.7.3", + "matplotlib>=3.4.3", + "nc-time-axis>=1.4.0", + "netCDF4>=1.5.7", + "numba>=0.53.1", + "numpy>=1.20.3,<2.0", + "pandas>=1.3.4", + "pathvalidate>=2.5.0", + "psutil>=5.8.0", + "pyarrow>=6.0.0", + "pyomo>=6.2", + "python-benedict>=0.24.3", + "regex>=2021.10.23", + "requests>=2.26.0", + "rioxarray>=0.8.0", + "tqdm>=4.62.3", + "xarray>=0.19.0", ], extras_require={ - 'dev': [ - 'build>=0.7.0', - 'nbsphinx>=0.8.7', - 'recommonmark>=0.7.1', - 'setuptools>=58.3.0', - 'sphinx==4.2.0', - 'sphinx-panels>=0.6.0', - 'sphinx-rtd-theme>=1.0.0', - 'twine>=3.4.2' + "dev": [ + "build>=0.7.0", + "nbsphinx>=0.8.7", + "recommonmark>=0.7.1", + "setuptools>=58.3.0", + "sphinx==4.2.0", + "sphinx-panels>=0.6.0", + "sphinx-rtd-theme>=1.0.0", + "twine>=3.4.2", + "pre-commit", ] - } + }, ) From ead836e33b762a9a2f579c0285f3e0d483a5272c Mon Sep 17 00:00:00 2001 From: erexer <13180883+erexer@users.noreply.github.com> Date: Tue, 12 Nov 2024 10:53:33 -0800 Subject: [PATCH 3/5] change docs to 3.9<=python<3.13 --- README.md | 4 ++-- setup.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 00f0787..19a66ed 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ For a quick start, check out the [Jupyter notebook tutorial](https://github.com/ ## getting started -Ensure you have Python >= 3.8 available (consider using a [virtual environment](https://github.com/pyenv/pyenv), see the docs [here](https://mosartwmpy.readthedocs.io/en/latest/virtualenv.html) for a brief tutorial), then install `mosartwmpy` with: +Ensure you have Python v3.9 - v3.12 (consider using a [virtual environment](https://github.com/pyenv/pyenv), see the docs [here](https://mosartwmpy.readthedocs.io/en/latest/virtualenv.html) for a brief tutorial), then install `mosartwmpy` with: ```shell pip install mosartwmpy ``` @@ -137,7 +137,7 @@ Seattle: > ``` By default, the output files will still store empty NaN-like values for grid cells outside the subdomain, but -for even faster simulations and smaller output files set the `grid -> unmask_output` option to `false`. Disabling +for even faster simulations and smaller output files set the `grid -> unmask_output` option to `false`. Disabling this option causes the output files to only store values for grid cells within the subdomain. These smaller files will likely take extra processing to effectively interoperate with other models. diff --git a/setup.py b/setup.py index 3e6e0a1..43c069b 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ def readme(): description="Python implementation of MOSART-WM: A water routing and management model", long_description=readme(), long_description_content_type="text/markdown", - python_requires=">=3.9,<4.0", + python_requires=">=3.9,<3.13", include_package_data=True, entry_points={ "console_scripts": [ From a081d043d6af977c8b490a8d77bd64a71b2a3922 Mon Sep 17 00:00:00 2001 From: erexer <13180883+erexer@users.noreply.github.com> Date: Tue, 12 Nov 2024 11:09:26 -0800 Subject: [PATCH 4/5] run tests on all supported python versions --- .github/workflows/test.yml | 69 ++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 51c0001..d61f394 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,39 +1,50 @@ name: test -on: [push] +on: + push: + schedule: + - cron: '0 8 * * 1' # Runs every monday at 12am Pacific time env: HDF5_USE_FILE_LOCKING: 'FALSE' jobs: build: - runs-on: ${{ matrix.os }} - - strategy: - matrix: - os: [ubuntu-latest] - - env: - OS: ${{ matrix.os }} - PYTHON: '3.9' - - steps: - - - uses: actions/checkout@v4 - - - name: Set up Python - uses: actions/setup-python@master - with: - python-version: 3.9 - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install . - - - name: Test and generate coverage report - run: | + strategy: + matrix: + python-version: [ '3.9', '3.10', '3.11', '3.12' ] + os: [ ubuntu-latest ] + fail-fast: false + + name: Python ${{ matrix.python-version }} on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v2 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@master + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install . + + - name: Test and generate coverage report + run: | pip install pytest pip install pytest-cov - pytest --cov=./ - + pytest --cov=./ --cov-report=xml + + - uses: codecov/codecov-action@v4 + with: + files: ./coverage.xml # optional + name: codecov-umbrella # optional + token: ${{ secrets.CODECOV_TOKEN }} # required + + - name: Notify on failure + if: failure() # This step will only run if any previous step fails + run: | + echo "Build or tests failed. Please check the logs." From c2fbd0ccb0c1611514a824e4b26fb8884d6b78f8 Mon Sep 17 00:00:00 2001 From: erexer <13180883+erexer@users.noreply.github.com> Date: Tue, 12 Nov 2024 11:16:56 -0800 Subject: [PATCH 5/5] docs instructions for development/contributing --- CONTRIBUTING.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 19fca8a..799ed2f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,11 +13,13 @@ __I found a bug!__ __I fixed a bug!__ * First of all, thanks! +* Make sure that you're running the changed files and/or new files through pre-commit by running `$ pip install pre-commit` and `$ pre-commit install` in the mosartwmpy repo. Pre-commit will now automatically check your file formatting when you `$ git commit`. * Open a [new Pull Request] with the fix. Ensure the description clearly outlines the bug and the solution. Include the Issue number if applicable. __I created a new feature!__ * You're the best! * Consider opening a [new Issue] to describe use cases for the new feature. This will offer a platform for discussion and critique. +* Make sure that you're running the changed files and/or new files through pre-commit by running `$ pip install pre-commit` and `$ pre-commit install` in the mosartwmpy repo. Pre-commit will now automatically check your file formatting when you `$ git commit`. * Then, open a [new Pull Request] with clear documentation of the methodology. Be sure to include new unit tests if appropriate. -The [IM3] team truly appreciates and encourages community involvement. We're all in this together! \ No newline at end of file +The [IM3] team truly appreciates and encourages community involvement. We're all in this together!