diff --git a/.coveralls.yml b/.coveralls.yml deleted file mode 100644 index 4ecf44e5..00000000 --- a/.coveralls.yml +++ /dev/null @@ -1,2 +0,0 @@ -service_name: github -# repo_token: YOURTOKENHERE diff --git a/.cruft.json b/.cruft.json index 53f71f66..b6e76501 100644 --- a/.cruft.json +++ b/.cruft.json @@ -1,6 +1,6 @@ { "template": "https://github.com/Ouranosinc/cookiecutter-pypackage", - "commit": "64eceda7d95aeb8937fa9961989d3d617a525c04", + "commit": "617b216e87e1ddf008fcca890dfd5dd1ee601f51", "checkout": null, "context": { "cookiecutter": { @@ -17,6 +17,7 @@ "use_conda": "y", "add_pyup_badge": "n", "make_docs": "y", + "add_translations": "y", "command_line_interface": "No command-line interface", "create_author_file": "y", "open_source_license": "Apache Software License 2.0", diff --git a/.github/workflows/actions-versions-updater.yml b/.github/deactivated/actions-versions-updater.yml similarity index 100% rename from .github/workflows/actions-versions-updater.yml rename to .github/deactivated/actions-versions-updater.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..a9f28754 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,15 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: daily + time: '12:00' + open-pull-requests-limit: 10 + + - package-ecosystem: pip + directory: / + schedule: + interval: daily + time: '12:00' + open-pull-requests-limit: 10 diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 00000000..ef5459f4 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,20 @@ +# label rules used by .github/workflows/label.yml + +# label 'ci' all automation-related steps and files +# Since this repository is in itself an automation process to deploy a server instance, +# we refer here to CI as the 'meta' configuration files for managing the code and integrations with the repository, +# not configurations related to the deployment process itself. + +# Uncomment the following lines to enable the labeler (requires labels with the same name to exist in the repository) + +# label 'ci' all automation-related steps and files +'CI': + - changed-files: + - any-glob-to-any-file: + - '.editorconfig' + - '.flake8' + - '.pre-commit-config.yaml' + - '.yamllint.yml' + - '.github/workflows/*' + - 'tox.ini' + - 'Makefile' diff --git a/.github/workflows/bump-version.yml b/.github/workflows/bump-version.yml index 7f0e7a60..cd57ba33 100644 --- a/.github/workflows/bump-version.yml +++ b/.github/workflows/bump-version.yml @@ -1,3 +1,8 @@ +# This workflow requires a personal access token named `BUMP_VERSION_TOKEN` with the following privileges: +# - Contents: Read and Write +# - Metadata: Read-Only +# - Pull Requests: Read and Write + name: "Bump Patch Version" on: @@ -38,6 +43,15 @@ jobs: actions: read contents: write steps: + - name: Harden Runner + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + with: + disable-sudo: true + egress-policy: block + allowed-endpoints: > + files.pythonhosted.org:443 + github.com:443 + pypi.org:443 - uses: actions/checkout@v4.1.1 with: persist-credentials: false @@ -48,14 +62,23 @@ jobs: run: | git config --local user.email "bumpversion[bot]@hydrologie.com" git config --local user.name "bumpversion[bot]" + - name: Install bump-my-version + run: | + python -m pip install "bump-my-version>=0.17.1" - name: Current Version - run: echo "current_version=$(grep -E '__version__' xhydro/__init__.py | cut -d ' ' -f3)" - - name: Bump Patch Version run: | - pip install bump-my-version - echo "Bumping version" - bump-my-version bump --tag patch - echo "new_version=$(grep -E '__version__' xhydro/__init__.py | cut -d ' ' -f3)" + bump-my-version show current_version + CURRENT_VERSION="$(grep -E '__version__' xhydro/__init__.py | cut -d ' ' -f3)" + echo "CURRENT_VERSION=${CURRENT_VERSION}" >> $GITHUB_ENV + - name: Conditional Bump Version + run: | + if [[ ${{ env.CURRENT_VERSION }} =~ -dev(\.\d+)? ]]; then + echo "Development version (ends in 'dev(\.\d+)?'), bumping 'build' version" + bump-my-version show new_version --increment build + else + echo "Version is stable, bumping 'patch' version" + bump-my-version show new_version --increment patch + fi - name: Push Changes uses: ad-m/github-push-action@v0.8.0 with: diff --git a/.github/workflows/cache-cleaner.yml b/.github/workflows/cache-cleaner.yml new file mode 100644 index 00000000..4812b67b --- /dev/null +++ b/.github/workflows/cache-cleaner.yml @@ -0,0 +1,47 @@ +# Example taken from https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#managing-caches +name: Cleanup Caches on Pull Request Merge +on: + pull_request: + types: + - closed + +permissions: # added using https://github.com/step-security/secure-repo + contents: read + +jobs: + cleanup: + name: Cleanup + runs-on: ubuntu-latest + steps: + - name: Harden Runner + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + with: + disable-sudo: true + egress-policy: block + allowed-endpoints: > + api.github.com:443 + github.com:443 + objects.githubusercontent.com:443 + + - uses: actions/checkout@v4.1.1 + + - name: Cleanup + run: | + gh extension install actions/gh-actions-cache + + REPO=${{ github.repository }} + BRANCH="refs/pull/${{ github.event.pull_request.number }}/merge" + + echo "Fetching list of cache key" + cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH -L 100 | cut -f 1 ) + + ## Setting this to not fail the workflow while deleting cache keys. + set +e + echo "Deleting caches..." + for cacheKey in $cacheKeysForPR + do + gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm + done + echo "Done" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 00000000..c977388d --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,31 @@ +# Dependency Review Action +# +# This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging. +# +# Source repository: https://github.com/actions/dependency-review-action +# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement +name: 'Dependency Review' +on: + pull_request: + +permissions: + contents: read + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: Harden Runner + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + with: + disable-sudo: true + egress-policy: block + allowed-endpoints: > + api.github.com:443 + github.com:443 + + - name: 'Checkout Repository' + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: 'Dependency Review' + uses: actions/dependency-review-action@4901385134134e04cec5fbe5ddfe3b2c5bd5d976 diff --git a/.github/workflows/first_pull_request.yml b/.github/workflows/first-pull-request.yml similarity index 84% rename from .github/workflows/first_pull_request.yml rename to .github/workflows/first-pull-request.yml index 22a18751..24ba6cd8 100644 --- a/.github/workflows/first_pull_request.yml +++ b/.github/workflows/first-pull-request.yml @@ -16,6 +16,14 @@ jobs: contents: read pull-requests: write steps: + - name: Harden Runner + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + with: + disable-sudo: true + egress-policy: block + allowed-endpoints: > + api.github.com:443 + - uses: actions/github-script@v7.0.1 with: script: | @@ -45,7 +53,7 @@ jobs: repo: context.repo.repo, body: `**Welcome**, new contributor! - It appears that this is your first Pull Request. To give credit where it's due, we ask that you add your information to the \`AUTHORS.rst\` and \`.zenodo.json\`.: + It appears that this is your first Pull Request. To give credit where it's due, we ask that you add your information to the \`AUTHORS.rst\` and \`.zenodo.json\`: - [ ] The relevant author information has been added to \`AUTHORS.rst\` and \`.zenodo.json\`. Please make sure you've read our [contributing guide](CONTRIBUTING.rst). We look forward to reviewing your Pull Request shortly ✨` diff --git a/.github/workflows/label.yml b/.github/workflows/label.yml new file mode 100644 index 00000000..00036d9c --- /dev/null +++ b/.github/workflows/label.yml @@ -0,0 +1,37 @@ +# This workflow will triage pull requests and apply a label based on the +# paths that are modified in the pull request. +# +# To use this workflow, you will need to set up a .github/labeler.yml +# file with configuration. For more information, see: +# https://github.com/actions/labeler/blob/master/README.md + +name: Labeler +on: + pull_request_target: + # Note: potential security risk from this action using pull_request_target. + # Do not add actions in here which need a checkout of the repo, and do not use any caching in here. + # See: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target + +permissions: + contents: read + +jobs: + label: + name: Label + runs-on: ubuntu-latest + permissions: + checks: write + contents: read + pull-requests: write + steps: + - name: Harden Runner + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + with: + disable-sudo: true + egress-policy: block + allowed-endpoints: > + api.github.com:443 + + - uses: actions/labeler@v5.0.0 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2e44db24..11ff502c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -5,16 +5,21 @@ on: branches: - main paths-ignore: + - .cruft.json - CHANGES.rst - README.rst - - setup.cfg - pyproject.toml + - tests/test_xhydro.py - xhydro/__init__.py pull_request: +concurrency: + # For a given workflow, if we push to the same branch, cancel all previous builds on that branch except on master. + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} + permissions: contents: read - pull-requests: read jobs: lint: @@ -25,11 +30,7 @@ jobs: python-version: - "3.x" steps: - - name: Cancel previous runs - uses: styfle/cancel-workflow-action@0.12.1 - with: - access_token: ${{ secrets.GITHUB_TOKEN }} - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4 - name: Set up Python${{ matrix.python-version }} uses: actions/setup-python@v5.0.0 with: @@ -48,11 +49,19 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.9", "3.10", "3.11"] + include: + - python-version: "3.9" + - python-version: "3.10" + - python-version: "3.11" +# - python-version: "3.12" defaults: run: shell: bash -l {0} steps: + - name: Harden Runner + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + with: + egress-policy: audit - uses: actions/checkout@v4.1.1 - name: Setup Conda (Micromamba) with Python${{ matrix.python-version }} uses: mamba-org/setup-micromamba@v1.8.0 diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 9e42f6ef..cd04c194 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -17,6 +17,10 @@ jobs: # IMPORTANT: this permission is mandatory for trusted publishing id-token: write steps: + - name: Harden Runner + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + with: + egress-policy: audit - uses: actions/checkout@v4.1.1 - name: Set up Python3 uses: actions/setup-python@v5.0.0 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 00000000..25d4e2f5 --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,82 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by separate terms of service, privacy +# policy, and support documentation. + +name: Scorecard supply-chain security +on: + # For Branch-Protection check. Only the default branch is supported. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection + branch_protection_rule: + # To guarantee Maintained check is occasionally updated. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained + schedule: + - cron: '41 8 * * 4' + push: + branches: + - main + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + # Needed to publish results and get a badge (see publish_results below). + id-token: write + steps: + - name: Harden Runner + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + with: + disable-sudo: true + egress-policy: block + allowed-endpoints: > + api.github.com:443 + api.osv.dev:443 + api.securityscorecards.dev:443 + fulcio.sigstore.dev:443 + github.com:443 + oss-fuzz-build-logs.storage.googleapis.com:443 + rekor.sigstore.dev:443 + tuf-repo-cdn.sigstore.dev:443 + www.bestpractices.dev:443 + + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + with: + persist-credentials: false + + - name: Run analysis + uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 + with: + results_file: results.sarif + results_format: sarif + # This job step requires a personal access token named `OPENSSF_SCORECARD_TOKEN` with the following privileges: + # - Administration: Read-Only + # - Metadata: Read-Only + # - Webhooks: Read-Only + # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. + repo_token: ${{ secrets.OPENSSF_SCORECARD_TOKEN }} + + # Public repositories: + # - Publish results to OpenSSF REST API for easy access by consumers + # - Allows the repository to include the Scorecard badge. + # - See https://github.com/ossf/scorecard-action#publishing-results. + publish_results: true + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF + # format to the repository Actions tab. + - name: Upload artifact + uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard. + - name: Upload to code-scanning + uses: github/codeql-action/upload-sarif@e5f05b81d5b6ff8cfa111c80c22c5fd02a384118 # 3.23.0 + with: + sarif_file: results.sarif diff --git a/.github/workflows/tag-testpypi.yml b/.github/workflows/tag-testpypi.yml index 520aed96..efc4b93c 100644 --- a/.github/workflows/tag-testpypi.yml +++ b/.github/workflows/tag-testpypi.yml @@ -16,6 +16,10 @@ jobs: permissions: contents: write steps: + - name: Harden Runner + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + with: + egress-policy: audit - name: Checkout code uses: actions/checkout@v4.1.1 - name: Create Release @@ -24,8 +28,8 @@ jobs: # This token is provided by Actions, you do not need to create your own token GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - tag_name: ${{ github.ref }} - name: Release ${{ github.ref }} + tag_name: ${{ github.ref_name }} + name: Release ${{ github.ref_name }} draft: true prerelease: false @@ -37,6 +41,10 @@ jobs: # IMPORTANT: this permission is mandatory for trusted publishing id-token: write steps: + - name: Harden Runner + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + with: + egress-policy: audit - uses: actions/checkout@v4.1.1 - name: Set up Python3 uses: actions/setup-python@v5.0.0 diff --git a/.github/workflows/workflow-warning.yml b/.github/workflows/workflow-warning.yml new file mode 100644 index 00000000..433881bb --- /dev/null +++ b/.github/workflows/workflow-warning.yml @@ -0,0 +1,69 @@ +name: Workflow Changes Warnings + +on: + # Note: potential security risk from this action using pull_request_target. + # Do not add actions in here which need a checkout of the repo, and do not use any caching in here. + # See: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target + pull_request_target: + types: + - opened + - reopened + - synchronize + paths: + - .github/workflows/*.yml + +permissions: + contents: read + +jobs: + comment-concerning-workflow-changes: + name: Comment Concerning Workflow Changes + runs-on: ubuntu-latest + if: | + (github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) + permissions: + contents: read + pull-requests: write + steps: + - name: Harden Runner + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + with: + disable-sudo: true + egress-policy: block + allowed-endpoints: > + api.github.com:443 + - name: Find comment + uses: peter-evans/find-comment@a54c31d7fa095754bfef525c0c8e5e5674c4b4b1 # v2.4.0 + id: fc + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: 'github-actions[bot]' + body-includes: | + This Pull Request modifies GitHub workflows and is coming from a fork. + - name: Create comment + if: | + (steps.fc.outputs.comment-id == '') && + (!contains(github.event.pull_request.labels.*.name, 'approved')) && + (github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) + uses: peter-evans/create-or-update-comment@23ff15729ef2fc348714a3bb66d2f655ca9066f2 # v3.1.0 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body: | + > **Warning** + > This Pull Request modifies GitHub Workflows and is coming from a fork. + **It is very important for the reviewer to ensure that the workflow changes are appropriate.** + edit-mode: replace + - name: Update comment + if: | + contains(github.event.pull_request.labels.*.name, 'approved') + uses: peter-evans/create-or-update-comment@23ff15729ef2fc348714a3bb66d2f655ca9066f2 # v3.1.0 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body: | + > **Note** + > Changes have been approved by a maintainer. + reactions: | + hooray + edit-mode: append diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d175412e..db7757ac 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -29,7 +29,7 @@ repos: hooks: - id: rst-inline-touching-normal - repo: https://github.com/psf/black-pre-commit-mirror - rev: 23.12.1 + rev: 24.1.1 hooks: - id: black - repo: https://github.com/PyCQA/isort @@ -38,11 +38,11 @@ repos: - id: isort exclude: ^docs/ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.1.9 + rev: v0.1.14 hooks: - id: ruff - repo: https://github.com/pycqa/flake8 - rev: 6.1.0 + rev: 7.0.0 hooks: - id: flake8 additional_dependencies: [ 'flake8-alphabetize', 'flake8-rst-docstrings' ] @@ -56,7 +56,7 @@ repos: rev: v0.3.9 hooks: - id: blackdoc - additional_dependencies: [ 'black==23.12.1' ] + additional_dependencies: [ 'black==24.1.1' ] - repo: https://github.com/adrienverge/yamllint.git rev: v1.33.0 hooks: diff --git a/CHANGES.rst b/CHANGES.rst index 00aedb6d..dba4824b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -10,8 +10,9 @@ Contributors to this version: Trevor James Smith (:user:`Zeitsperre`), Thomas-Ch New features and enhancements ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Added French language support to the documentation. (:issue:`53`, :pull:`55`). -* Added a new set of functions to support creating and updating `pooch` registries, caching testing datasets from `hydrologie/xhydro-testdata`, and ensuring that testing datasets can be loaded into temporary directories. +* Added a new set of functions to support creating and updating `pooch` registries, caching testing datasets from `hydrologie/xhydro-testdata`, and ensuring that testing datasets can be loaded into temporary directories. (:pull:`62`). * `xhydro` is now configured to use `pooch` to download and cache testing datasets from `hydrologie/xhydro-testdata`. (:pull:`62`). +* `xhydro` is now `Semantic Versioning v2.0.0 `_ compliant. (:pull:`70`). Breaking changes ^^^^^^^^^^^^^^^^ @@ -24,6 +25,12 @@ Internal changes * `load_registry`: Loads installed (or custom) registry and returns dictionary * `populate_testing_data`: Fetches the registry and optionally caches files at a different location (helpful for `pytest-xdist`). * Added a `pre-commit` hook (`numpydoc`) to ensure that `numpy` docstrings are formatted correctly. (:pull:`62`). +* The cookiecutter has been updated to the latest commit (:pull:`70`): + * Added some workflows (Change file labelling, Cache cleaning, Dependency scans, `OpenSSF Scorecard `_). + * The README has been updated to organize badges in a table, including a badge for the OpenSSF Scorecard. + * Updated pre-commit hook versions to the latest available. + * Formatting tools are now pinned to their pre-commit equivalents. + * `actions-version-updater.yml` has been replaced by `dependabot `_. v0.3.0 (2023-12-01) ------------------- diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index dbfff75f..6707fb0d 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -106,11 +106,11 @@ Ready to contribute? Here's how to set up ``xhydro`` for local development. # Or, to run multiple build tests $ tox - .. note:: + .. note:: - Running `pytest` or `tox` will automatically fetch and cache the testing data for the package to your local cache (using the `platformdirs` library). On Linux, this is located at ``XDG_CACHE_HOME`` (usually ``~/.cache``). On Windows, this is located at ``%LOCALAPPDATA%`` (usually ``C:\Users\username\AppData\Local``). On MacOS, this is located at ``~/Library/Caches``. + Running `pytest` or `tox` will automatically fetch and cache the testing data for the package to your local cache (using the `platformdirs` library). On Linux, this is located at ``XDG_CACHE_HOME`` (usually ``~/.cache``). On Windows, this is located at ``%LOCALAPPDATA%`` (usually ``C:\Users\username\AppData\Local``). On MacOS, this is located at ``~/Library/Caches``. - If for some reason you wish to cache this data elsewhere, you can set the ``XHYDRO_DATA_DIR`` environment variable to a different location before running the tests. For example, to cache the data in the current working directory, run:: + If for some reason you wish to cache this data elsewhere, you can set the ``XHYDRO_DATA_DIR`` environment variable to a different location before running the tests. For example, to cache the data in the current working directory, run:: $ export XHYDRO_DATA_DIR=$(pwd)/.cache @@ -187,20 +187,16 @@ A reminder for the **maintainers** on how to deploy. This section is only releva #. Create a new branch from `main` (e.g. `release-0.2.0`). #. Update the `CHANGES.rst` file to change the `Unreleased` section to the current date. -#. Bump the version in your branch to the next version (e.g. `v0.1.0 -> v0.2.0`): +#. Bump the version in your branch to the next version (e.g. `v0.1.0 -> v0.2.0`):: - .. code-block:: shell - - $ bump-my-version bump minor # In most cases, we will be releasing a minor version - $ git push + $ bump-my-version bump minor # In most cases, we will be releasing a minor version + $ git push #. Create a pull request from your branch to `main`. -#. Once the pull request is merged, create a new release on GitHub. On the main branch, run: - - .. code-block:: shell +#. Once the pull request is merged, create a new release on GitHub. On the main branch, run:: - $ git tag v0.2.0 - $ git push --tags + $ git tag v0.2.0 + $ git push --tags This will trigger a GitHub workflow to build the package and upload it to TestPyPI. At the same time, the GitHub workflow will create a draft release on GitHub. Assuming that the workflow passes, the final release can then be published on GitHub by finalizing the draft release. diff --git a/README.rst b/README.rst index 9788d1d4..45f9caef 100644 --- a/README.rst +++ b/README.rst @@ -2,7 +2,17 @@ xHydro ====== -|pypi| |build| |docs| |license| ++----------------------------+-----------------------------------------------------+ +| Versions | |pypi| |versions| | ++----------------------------+-----------------------------------------------------+ +| Documentation and Support | |docs| | ++----------------------------+-----------------------------------------------------+ +| Open Source | |license| |ossf| | ++----------------------------+-----------------------------------------------------+ +| Coding Standards | |black| |ruff| |pre-commit| | ++----------------------------+-----------------------------------------------------+ +| Development Status | |status| |build| |coveralls| | ++----------------------------+-----------------------------------------------------+ Hydrological analysis library built with xarray @@ -22,18 +32,22 @@ This package was created with Cookiecutter_ and the `Ouranosinc/cookiecutter-pyp .. _Cookiecutter: https://github.com/cookiecutter/cookiecutter .. _`Ouranosinc/cookiecutter-pypackage`: https://github.com/Ouranosinc/cookiecutter-pypackage -.. |pypi| image:: https://img.shields.io/pypi/v/xhydro.svg - :target: https://pypi.python.org/pypi/xhydro - :alt: PyPI +.. |black| image:: https://img.shields.io/badge/code%20style-black-000000.svg + :target: https://github.com/psf/black + :alt: Python Black .. |build| image:: https://github.com/hydrologie/xhydro/actions/workflows/main.yml/badge.svg :target: https://github.com/hydrologie/xhydro/actions :alt: Build Status +.. |coveralls| image:: https://coveralls.io/repos/github/hydrologie/xhydro/badge.svg + :target: https://coveralls.io/github/hydrologie/xhydro + :alt: Coveralls + .. .. |docs| image:: https://img.shields.io/badge/Docs-GitHub.io-blue :target: https://hydrologie.github.io/xhydro/ - :alt: Documentation + :alt: Documentation Status .. |docs| image:: https://readthedocs.org/projects/xhydro/badge/?version=latest :target: https://xhydro.readthedocs.io/en/latest/?version=latest @@ -42,3 +56,27 @@ This package was created with Cookiecutter_ and the `Ouranosinc/cookiecutter-pyp .. |license| image:: https://img.shields.io/pypi/l/xhydro :target: https://github.com/hydrologie/xhydro/blob/main/LICENSE :alt: License + +.. |ossf| image:: https://api.securityscorecards.dev/projects/github.com/hydrologie/xhydro/badge + :target: https://securityscorecards.dev/viewer/?uri=github.com/hydrologie/xhydro + :alt: OpenSSF Scorecard + +.. |pre-commit| image:: https://results.pre-commit.ci/badge/github/hydrologie/xhydro/main.svg + :target: https://results.pre-commit.ci/latest/github/hydrologie/xhydro/main + :alt: pre-commit.ci Status + +.. |pypi| image:: https://img.shields.io/pypi/v/xhydro.svg + :target: https://pypi.python.org/pypi/xhydro + :alt: PyPI + +.. |ruff| image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json + :target: https://github.com/astral-sh/ruff + :alt: Ruff + +.. |status| image:: https://www.repostatus.org/badges/latest/active.svg + :target: https://www.repostatus.org/#active + :alt: Project Status: Active – The project has reached a stable, usable state and is being actively developed. + +.. |versions| image:: https://img.shields.io/pypi/pyversions/xhydro.svg + :target: https://pypi.python.org/pypi/xhydro + :alt: Supported Python Versions diff --git a/docs/conf.py b/docs/conf.py index 730ccea3..89579d51 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -112,9 +112,9 @@ # Usually you set "language" from the command line for these cases. language = "en" -# Set the locales +# Sphinx-intl configuration locale_dirs = ["locales"] -gettext_compact = False +gettext_compact = False # optional # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. diff --git a/docs/index.rst b/docs/index.rst index 1cae8912..20624f18 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -16,6 +16,12 @@ Welcome to xHydro's documentation! authors changes +.. toctree:: + :maxdepth: 1 + :caption: All Modules + + apidoc/modules + .. Indices and tables .. ================== .. * :ref:`genindex` diff --git a/docs/usage.rst b/docs/usage.rst index 8596b61b..ee24501e 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -2,6 +2,8 @@ Usage ===== -To use xHydro in a project:: +To use xHydro in a project: + +.. code-block:: python import xhydro diff --git a/environment-dev.yml b/environment-dev.yml index 4049c6e1..c816b371 100644 --- a/environment-dev.yml +++ b/environment-dev.yml @@ -10,25 +10,29 @@ dependencies: - pydantic >=2.0,<2.5.3 # FIXME: Remove pin once our dependencies (xclim, xscen) support pydantic 2.5.3 - statsmodels - xarray - - xclim >=0.45.0 + - xclim >=0.47.0 # FIXME: Remove pin once our dependencies (xclim, xscen) support pandas 2.2.0 - xscen >=0.7.1 - pip - pip: - xdatasets # Dev - - bump-my-version >=0.12.0 - - coveralls + - black ==24.1.1 + - blackdoc ==0.3.9 + - bump-my-version >=0.17.1 + - coveralls >=3.3.1 + - flake8 >=7.0.0 - furo - ipykernel - ipython + - isort ==5.13.2 - jupyter_client - nbsphinx - nbval - pandoc - pooch - - pre-commit - - pytest - - pytest-cov + - pre-commit >=3.3.2 + - pytest >=7.3.1 + - pytest-cov >=4.0.0 - sphinx - sphinx-autoapi - sphinx-codeautolink diff --git a/environment.yml b/environment.yml index 5f6dcca3..65b46eec 100644 --- a/environment.yml +++ b/environment.yml @@ -10,7 +10,7 @@ dependencies: - pydantic >=2.0,<2.5.3 - statsmodels - xarray - - xclim >=0.45.0 + - xclim >=0.47.0 - xscen >=0.7.1 - pip - pip: diff --git a/pyproject.toml b/pyproject.toml index 49c07bd7..ab26a3e8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,6 +29,7 @@ classifiers = [ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + # "Programming Language :: Python :: 3.12", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Scientific/Engineering :: GIS", "Topic :: Scientific/Engineering :: Hydrology" @@ -41,7 +42,7 @@ dependencies = [ "pydantic>=2.0,<2.5.3", "statsmodels", "xarray", - "xclim>=0.45.0", + "xclim>=0.47.0", "xdatasets>=0.3.1", "xscen>=0.7.1" ] @@ -50,20 +51,20 @@ dependencies = [ dev = [ # Dev tools and testing "pip>=23.1.2", - "bump-my-version>=0.12.0", + "bump-my-version>=0.17.1", "watchdog>=3.0.0", - "flake8>=6.1.0", + "flake8>=7.0.0", "flake8-alphabetize>=0.0.21", "flake8-rst-docstrings>=0.3.0", - "flit", + "flit>=3.9.0", "tox>=4.5.1", "coverage>=6.2.2,<7.0.0", "coveralls>=3.3.1", "pytest>=7.3.1", "pytest-cov>=4.0.0", - "black>=23.10.1", - "blackdoc>=0.3.9", - "isort>=5.12.0", + "black==24.1.1", + "blackdoc==0.3.9", + "isort==5.13.2", "pre-commit>=3.3.2" ] docs = [ @@ -96,17 +97,22 @@ target-version = [ "py38", "py39", "py310", - "py311" + "py311", + "py312" ] [tool.bumpversion] current_version = "0.3.3" commit = true +commit_args = "--no-verify" tag = false tag_name = "v{new_version}" allow_dirty = false -serialize = ["{major}.{minor}.{patch}"] -parse = "(?P\\d+)\\.(?P\\d+)\\.(?P\\d+)" +parse = "(?P\\d+)\\.(?P\\d+)\\.(?P\\d+)(\\-(?P[a-z]+)(\\.(?P\\d+)))?" +serialize = [ + "{major}.{minor}.{patch}-{release}.{build}", + "{major}.{minor}.{patch}" +] [[tool.bumpversion.files]] filename = "xhydro/__init__.py" @@ -123,6 +129,16 @@ filename = ".cruft.json" search = "\"version\": \"{current_version}\"" replace = "\"version\": \"{new_version}\"" +[tool.bumpversion.parts.build] +independent = false + +[tool.bumpversion.parts.release] +optional_value = "release" +values = [ + "dev", + "release" +] + [tool.coverage.run] relative_files = true include = ["xhydro/*"] @@ -165,6 +181,7 @@ exclude = [ "docs/_*", "docs/apidoc/modules.rst", "docs/apidoc/xhydro*.rst", + "docs/locales", "xhydro/testing/data/*" ] diff --git a/tests/test_local.py b/tests/test_local.py index fd10190e..c178644e 100644 --- a/tests/test_local.py +++ b/tests/test_local.py @@ -70,9 +70,11 @@ def test_min_years(self, miny): params = xhfa.local.fit(ds, distributions=["gamma"], min_years=miny) np.testing.assert_array_almost_equal( params.streamflow, - [[9.95357815e00, -3.07846650e01, 1.56498193e01]] - if miny == 10 - else [[np.nan, np.nan, np.nan]], + ( + [[9.95357815e00, -3.07846650e01, 1.56498193e01]] + if miny == 10 + else [[np.nan, np.nan, np.nan]] + ), ) diff --git a/tox.ini b/tox.ini index 638d60e1..0d8e6bde 100644 --- a/tox.ini +++ b/tox.ini @@ -2,7 +2,7 @@ # min_version = 4.0 # removed until tox-conda is updated for use with tox>=4.0 envlist = lint - py{39,310,311} + py{39,310,311,312} docs coveralls requires = @@ -14,11 +14,11 @@ opts = [testenv:lint] skip_install = True deps = - black - blackdoc - isort - flake8 - ruff + black ==24.1.1 + blackdoc ==0.3.9 + isort ==5.13.2 + flake8 + ruff commands = make lint allowlist_externals = diff --git a/xhydro/__init__.py b/xhydro/__init__.py index 1e92ef37..49207474 100644 --- a/xhydro/__init__.py +++ b/xhydro/__init__.py @@ -1,4 +1,5 @@ """Hydrological analysis library built with xarray.""" + from . import cc, indicators, utils # Import top-level functions diff --git a/xhydro/cc.py b/xhydro/cc.py index 0723b93a..ffaedd06 100644 --- a/xhydro/cc.py +++ b/xhydro/cc.py @@ -1,4 +1,5 @@ """Module to compute climate change statistics using xscen functions.""" + import xarray # Special imports from xscen diff --git a/xhydro/frequency_analysis/local.py b/xhydro/frequency_analysis/local.py index 55bce387..c4e9ff9e 100644 --- a/xhydro/frequency_analysis/local.py +++ b/xhydro/frequency_analysis/local.py @@ -144,16 +144,16 @@ def parametric_quantiles( if mode == "max" else "Probability of non-exceedance" ) - da_q.attrs[ - "description" - ] = "Parametric distribution quantiles for the given return period." + da_q.attrs["description"] = ( + "Parametric distribution quantiles for the given return period." + ) da_q.attrs["mode"] = mode quantiles = quantiles.assign_coords(p_quantile=da_q) quantiles.attrs["scipy_dist"] = distributions - quantiles.attrs[ - "description" - ] = f"Return period ({mode}) estimated with statistic distributions" + quantiles.attrs["description"] = ( + f"Return period ({mode}) estimated with statistic distributions" + ) quantiles.attrs["long_name"] = "Return period" quantiles.attrs["mode"] = mode out.append(quantiles) @@ -247,9 +247,9 @@ def _get_criteria_1d(da, params, dist): + f", [{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] " f"criteria: computed AIC, BIC and AICC. - statsmodels version: {statsmodels.__version__}" ) - crit.attrs[ - "description" - ] = "Information criteria for the distribution parameters." + crit.attrs["description"] = ( + "Information criteria for the distribution parameters." + ) crit.attrs["long_name"] = "Information criteria" # Remove a few attributes that are not relevant anymore diff --git a/xhydro/indicators.py b/xhydro/indicators.py index 455a657b..8ef851ba 100644 --- a/xhydro/indicators.py +++ b/xhydro/indicators.py @@ -1,4 +1,5 @@ """Module to compute indicators using xclim's build_indicator_module_from_yaml.""" + import warnings from typing import Optional diff --git a/xhydro/utils.py b/xhydro/utils.py index 1d87af94..b1392915 100644 --- a/xhydro/utils.py +++ b/xhydro/utils.py @@ -1,4 +1,5 @@ """Utility functions for xhydro.""" + from xscen.diagnostics import health_checks __all__ = ["health_checks"]