diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 4f6797d7..8a412b0f 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -5,12 +5,43 @@ name: Python package on: push: - branches: ['main'] + branches: ['**'] pull_request: branches: ['main'] +permissions: + contents: read + jobs: + lint: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 + with: + ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} + - name: Debug checkout ref + run: | + echo "event_name=${{ github.event_name }}" + echo "github_ref=${{ github.ref }}" + echo "github_sha=${{ github.sha }}" + echo "pr_head_sha=${{ github.event.pull_request.head.sha }}" + git rev-parse HEAD + - name: Set up Python 3.14 + uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 + with: + python-version: '3.14' + cache: pip + cache-dependency-path: pyproject.toml + - name: Install Ruff + run: python -m pip install --upgrade pip ruff + - name: Ruff check + run: ruff check . + - name: Ruff format check + run: ruff format --check . + build: + needs: lint runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -20,20 +51,18 @@ jobs: steps: - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 + with: + ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 with: python-version: ${{ matrix.python-version }} + cache: pip + cache-dependency-path: pyproject.toml - name: Install dependencies run: | python -m pip install --upgrade pip pip install .[test,nldi] - - name: Lint with flake8 - run: | - # stop the build if there are Python syntax errors or undefined names - flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Test with pytest and report coverage run: | coverage run -m pytest tests/ diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index f0f6d337..9ec679e6 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -17,24 +17,23 @@ permissions: jobs: deploy: - runs-on: ubuntu-latest steps: - - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 - - name: Set up Python - uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 - with: - python-version: '3.x' - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install build - pip install setuptools setuptools-scm wheel twine check-manifest - - name: Build package - run: python -m build - - name: Publish package - uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 - with: - user: __token__ - password: ${{ secrets.PYPI_API_TOKEN }} + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 + - name: Set up Python 3.13 + uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 + with: + python-version: '3.13' + cache: pip + cache-dependency-path: pyproject.toml + - name: Install build tooling + run: | + python -m pip install --upgrade pip build + - name: Build package + run: python -m build + - name: Publish package + uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 + with: + user: __token__ + password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/.github/workflows/sphinx-docs.yml b/.github/workflows/sphinx-docs.yml index e949c485..7a5aee99 100644 --- a/.github/workflows/sphinx-docs.yml +++ b/.github/workflows/sphinx-docs.yml @@ -4,6 +4,7 @@ name: Sphinx Docs Build on: push: + branches: ['main'] pull_request: jobs: @@ -14,21 +15,20 @@ jobs: uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 with: persist-credentials: false - - name: Install dataretrieval, dependencies, and Sphinx then build docs - shell: bash -l {0} + - name: Set up Python 3.13 + uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 + with: + python-version: '3.13' + cache: pip + cache-dependency-path: pyproject.toml + - name: Install documentation dependencies run: | python -m pip install --upgrade pip pip install .[doc,nldi] ipython kernel install --name "python3" --user - sudo apt update -y && sudo apt install -y latexmk texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended dvipng pandoc + sudo apt-get update -y + sudo apt-get install -y latexmk texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended dvipng pandoc (cd docs && make html) - - name: Debug - run: | - echo $REF - echo $EVENT_NAME - echo ${{ github.event_name == 'push' }} - echo ${{ github.ref == 'refs/heads/main' }} - echo ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} - name: Deploy to GitHub Pages uses: JamesIves/github-pages-deploy-action@881db5376404c5c8d621010bcbec0310b58d5e29 if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 36b65c4b..8e97a187 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,26 +22,11 @@ repos: args: - '--py38-plus' - - repo: https://github.com/psf/black - rev: 23.3.0 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.15.6 hooks: - - id: black - - id: black-jupyter - - - repo: https://github.com/keewis/blackdoc - rev: v0.3.8 - hooks: - - id: blackdoc - - - repo: https://github.com/PyCQA/flake8 - rev: 6.0.0 - hooks: - - id: flake8 - - - repo: https://github.com/PyCQA/isort - rev: 5.12.0 - hooks: - - id: isort + - id: ruff-check + - id: ruff-format - repo: https://github.com/pre-commit/mirrors-prettier rev: v3.0.0-alpha.6 diff --git a/dataretrieval/__init__.py b/dataretrieval/__init__.py index 54fe7a94..ffc81bb2 100644 --- a/dataretrieval/__init__.py +++ b/dataretrieval/__init__.py @@ -5,11 +5,11 @@ except PackageNotFoundError: __version__ = "version-unknown" -from dataretrieval.nadp import * # noqa: F403 -from dataretrieval.nwis import * # noqa: F403 -from dataretrieval.samples import * # noqa: F403 -from dataretrieval.streamstats import * # noqa: F403 -from dataretrieval.utils import * # noqa: F403 -from dataretrieval.waterdata import * # noqa: F403 -from dataretrieval.waterwatch import * # noqa: F403 -from dataretrieval.wqp import * # noqa: F403 +from dataretrieval.nadp import * +from dataretrieval.nwis import * +from dataretrieval.samples import * +from dataretrieval.streamstats import * +from dataretrieval.utils import * +from dataretrieval.waterdata import * +from dataretrieval.waterwatch import * +from dataretrieval.wqp import * diff --git a/dataretrieval/codes/__init__.py b/dataretrieval/codes/__init__.py old mode 100755 new mode 100644 index eca1cc1e..a1b0e400 --- a/dataretrieval/codes/__init__.py +++ b/dataretrieval/codes/__init__.py @@ -1,2 +1,2 @@ -from .states import * # noqa: F403 -from .timezones import * # noqa: F403 +from .states import * +from .timezones import * diff --git a/dataretrieval/nldi.py b/dataretrieval/nldi.py index 89df8a65..27478538 100644 --- a/dataretrieval/nldi.py +++ b/dataretrieval/nldi.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from json import JSONDecodeError from typing import Literal, Optional, Union @@ -246,12 +248,12 @@ def get_features( " be provided with lat or long" ) + if not lat and (comid or data_source) and navigation_mode is None: + raise ValueError( + "navigation_mode is required if comid or data_source is provided" + ) + if not lat: - if comid or data_source: - if navigation_mode is None: - raise ValueError( - "navigation_mode is required if comid or data_source is provided" - ) # validate the feature source and comid _validate_feature_source_comid(feature_source, feature_id, comid) # validate the data source diff --git a/dataretrieval/nwis.py b/dataretrieval/nwis.py index 099e9ec8..88b59978 100644 --- a/dataretrieval/nwis.py +++ b/dataretrieval/nwis.py @@ -4,6 +4,8 @@ """ +from __future__ import annotations + import re import warnings from io import StringIO @@ -79,10 +81,9 @@ def format_response( if service == "peaks": df = preformat_peaks_response(df) - if gpd is not None: - if "dec_lat_va" in list(df): - geoms = gpd.points_from_xy(df.dec_long_va.values, df.dec_lat_va.values) - df = gpd.GeoDataFrame(df, geometry=geoms, crs=_CRS) + if gpd is not None and "dec_lat_va" in list(df): + geoms = gpd.points_from_xy(df.dec_long_va.values, df.dec_lat_va.values) + df = gpd.GeoDataFrame(df, geometry=geoms, crs=_CRS) # check for multiple sites: if "datetime" not in df.columns: diff --git a/docs/source/meta/installing.rst b/docs/source/meta/installing.rst index 34caf181..89c2ceac 100644 --- a/docs/source/meta/installing.rst +++ b/docs/source/meta/installing.rst @@ -4,13 +4,11 @@ Installation Guide Whether you are a user or developer we recommend installing ``dataretrieval`` in a virtual environment. This can be done using something like ``virtualenv`` or ``conda``. Package dependencies are listed in the `requirements.txt`_ file, -a full list of dependencies necessary for development are listed in the -`requirements-dev.txt`_ file. +a full list of dependencies necessary for development are available from the +``dev`` extra in ``pyproject.toml``. .. _requirements.txt: https://github.com/DOI-USGS/dataretrieval-python/blob/main/requirements.txt -.. _requirements-dev.txt: https://github.com/DOI-USGS/dataretrieval-python/blob/main/requirements-dev.txt - User Installation ----------------- @@ -59,8 +57,7 @@ the package for development: .. code-block:: bash - $ pip install -r requirements-dev.txt - $ pip install -e . + $ pip install -e ".[dev]" To check your installation you can run the tests with the following commands: diff --git a/pyproject.toml b/pyproject.toml index 3f26ff48..c87f6abc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,7 +36,6 @@ test = [ "pytest-cov[all]", "coverage", "requests-mock", - "flake8", ] doc = [ "docutils<0.22", @@ -52,6 +51,23 @@ doc = [ nldi = [ 'geopandas>=0.10' ] +dev = [ + "pytest > 5.0.0", + "pytest-cov[all]", + "coverage", + "requests-mock", + "ruff", + "docutils<0.22", + "sphinx", + "sphinx-rtd-theme", + "nbsphinx", + "nbsphinx_link", + "ipython", + "ipykernel", + "matplotlib", + "folium>=0.12", + "geopandas>=0.10", +] [project.urls] homepage = "https://github.com/DOI-USGS/dataretrieval-python" @@ -61,12 +77,6 @@ repository = "https://github.com/DOI-USGS/dataretrieval-python.git" [tool.setuptools_scm] write_to = "dataretrieval/_version.py" -[tool.isort] -profile = "black" - -[tool.black] -skip-string-normalization = true - [tool.ruff.format] quote-style = "double" docstring-code-format = true @@ -83,4 +93,6 @@ extend-select = [ [tool.ruff.lint.per-file-ignores] "demos/*.ipynb" = ["E501", "W291"] +"dataretrieval/__init__.py" = ["F403"] +"dataretrieval/codes/__init__.py" = ["F403"] diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100755 index d6a6f519..00000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,17 +0,0 @@ -numpy<2 -pandas==2.* -geopandas==0.14.* -scipy -python-dateutil -requests -requests-mock -coverage -pytest -flake8 -sphinx -sphinx-rtd-theme -ipython -ipykernel -nbsphinx -nbsphinx_link -matplotlib diff --git a/tests/wqp_test.py b/tests/wqp_test.py old mode 100755 new mode 100644