diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..563dd9b
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,11 @@
+# See https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/keeping-your-actions-up-to-date-with-dependabot
+
+version: 2
+updates:
+
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "daily"
+ labels:
+ - "Bot"
diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml
new file mode 100644
index 0000000..d4abc4f
--- /dev/null
+++ b/.github/workflows/deploy-docs.yml
@@ -0,0 +1,51 @@
+
+name: Documentation
+
+on:
+ pull_request:
+ push:
+ branches: [master, main]
+ release:
+ types:
+ - published
+
+jobs:
+ build-docs:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: checkout
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+
+ - name: Setup Micromamba
+ uses: mamba-org/setup-micromamba@v1
+ with:
+ environment-name: TEST
+ init-shell: bash
+ create-args: >-
+ python=3 pip
+ --file requirements.txt
+ --file requirements-dev.txt
+ --channel conda-forge
+
+ - name: Install utide
+ shell: bash -l {0}
+ run: |
+ pip install -e . --no-deps --force-reinstall
+
+ - name: Build documentation
+ shell: bash -l {0}
+ run: |
+ set -e
+ pushd docs
+ make clean html linkcheck
+ popd
+
+ - name: Deploy
+ if: success() && github.event_name == 'release'
+ uses: peaceiris/actions-gh-pages@v3
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ publish_dir: docs/build/html
diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml
index 3220003..88275c2 100644
--- a/.github/workflows/pre-commit.yml
+++ b/.github/workflows/pre-commit.yml
@@ -8,17 +8,7 @@ on:
jobs:
pre-commit:
runs-on: ubuntu-latest
- env:
- FORCE_COLOR: "1"
steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-python@v2
- with:
- python-version: '3.x'
- - id: file_changes
- uses: trilom/file-changes-action@v1.2.3
- with:
- output: ' '
- - uses: pre-commit/action@v2.0.0
- with:
- extra_args: --files ${{ steps.file_changes.outputs.files}}
+ - uses: actions/checkout@v3
+ - uses: actions/setup-python@v4
+ - uses: pre-commit/action@v3.0.0
diff --git a/.github/workflows/publish.yml b/.github/workflows/pypi.yml
similarity index 54%
rename from .github/workflows/publish.yml
rename to .github/workflows/pypi.yml
index f77af7b..8cb448c 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/pypi.yml
@@ -1,47 +1,53 @@
name: Publish to PyPI
on:
+ pull_request:
+ push:
+ branches: [master, main]
release:
types:
- published
+defaults:
+ run:
+ shell: bash
+
jobs:
packages:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Set up Python
- uses: actions/setup-python@v1
+ uses: actions/setup-python@v4
with:
python-version: "3.x"
- name: Get tags
run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
- shell: bash
- name: Install build tools
run: |
- python -m pip install --upgrade pip wheel setuptools setuptools_scm build twine pytest numpy scipy
-
- shell: bash
+ python -m pip install --upgrade pip build
- - name: Build binary wheel
+ - name: Build sdist and binary wheel
run: python -m build --sdist --wheel . --outdir dist
- name: CheckFiles
run: |
ls dist
- shell: bash
+ python -m pip install --upgrade check-manifest
+ check-manifest --verbose
- name: Test wheels
run: |
- cd dist && python -m pip install UTide*.whl
+ cd dist && python -m pip install *.whl
+ python -m pip install --upgrade twine
python -m twine check *
- shell: bash
- name: Publish a Python distribution to PyPI
- uses: pypa/gh-action-pypi-publish@master
+ if: success() && github.event_name == 'release'
+ uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_PASSWORD }}
diff --git a/.github/workflows/tarball-tests.yml b/.github/workflows/tarball-tests.yml
deleted file mode 100644
index 33171ca..0000000
--- a/.github/workflows/tarball-tests.yml
+++ /dev/null
@@ -1,35 +0,0 @@
-name: Tarball tests
-
-on:
- pull_request:
- push:
- branches: [master]
-
-jobs:
- run:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
-
- - name: Setup Conda
- uses: s-weigand/setup-conda@v1
- with:
- activate-conda: false
- conda-channels: conda-forge
-
- - name: Create environment
- shell: bash -l {0}
- run: |
- conda create --name TEST --file requirements.txt --file requirements-dev.txt
- source activate TEST
- conda info --all
- conda list
-
- - name: Tarball
- shell: bash -l {0}
- run: |
- source activate TEST
- python setup.py --version
- pip wheel . -w dist --no-deps
- check-manifest --verbose
- twine check dist/*
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index a113612..a8fff7b 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -10,41 +10,40 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
- python-version: [ "3.7", "3.8", "3.9", "3.10"]
+ python-version: ["3.8", "3.9", "3.10", "3.11"]
os: [windows-latest, ubuntu-latest, macos-latest]
# Oldest one based on NEP-29 and latest one.
# See https://numpy.org/neps/nep-0029-deprecation_policy.html
- numpy-version: ["1.19", "1.22"]
+ numpy-version: ["1.21", "1.25"]
exclude:
- - python-version: "3.10"
- numpy-version: "1.19"
+ - python-version: "3.11"
+ numpy-version: "1.21"
+ - python-version: "3.8"
+ numpy-version: "1.25"
fail-fast: false
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- - name: Setup
- uses: mamba-org/provision-with-micromamba@main
+ - name: Setup Micromamba Python ${{ matrix.python-version }}
+ uses: mamba-org/setup-micromamba@v1
with:
- environment-file: false
+ environment-name: TEST
+ init-shell: bash
+ create-args: >-
+ python=${{ matrix.python-version }} pip
+ --file requirements.txt
+ --file requirements-dev.txt
+ --channel conda-forge
- - name: Python ${{ matrix.python-version }} numpy ${{ matrix.numpy-version }}
+ - name: Install utide
shell: bash -l {0}
- run: |
- micromamba create --name TEST python=${{ matrix.python-version }} --file requirements.txt --file requirements-dev.txt --channel conda-forge
- micromamba activate TEST
- micromamba install numpy=${{ matrix.numpy-version }}
- pip install -e . --no-deps --force-reinstall
-
- - name: Debug Info
- shell: bash -l {0}
- run: |
- micromamba activate TEST
- micromamba info --all
- micromamba list
+ run: >
+ python -m pip install -e . --no-deps --force-reinstall
+ && micromamba install numpy=${{ matrix.numpy-version }}
+ && pip install -e . --no-deps --force-reinstall
- - name: Tests
+ - name: Run tests
shell: bash -l {0}
run: |
- micromamba activate TEST
- pytest -n 2 -rxs --cov=utide tests
+ pytest -rxs --cov=utide tests
diff --git a/.gitignore b/.gitignore
index f4ce211..49f63e5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -73,3 +73,4 @@ doc/_build/
.project
.pydevproject
.vscode/
+utide/_version.py
diff --git a/.isort.cfg b/.isort.cfg
deleted file mode 100644
index 324a78a..0000000
--- a/.isort.cfg
+++ /dev/null
@@ -1,2 +0,0 @@
-[settings]
-known_third_party = matplotlib,numpy,oct2py,pandas,pkg_resources,pytest,scipy,setuptools
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index d775052..9549007 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,7 +1,7 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.2.0
+ rev: v4.4.0
hooks:
- id: check-ast
- id: end-of-file-fixer
@@ -14,34 +14,44 @@ repos:
- id: trailing-whitespace
- id: debug-statements
-- repo: https://gitlab.com/pycqa/flake8
- rev: 3.9.2
+- repo: https://github.com/psf/black
+ rev: 23.3.0
hooks:
- - id: flake8
- exclude: docs/source/conf.py
- args: [--max-line-length=105]
+ - id: black
+ language_version: python3
-- repo: https://github.com/pre-commit/mirrors-isort
- rev: v5.10.1
+- repo: https://github.com/asottile/add-trailing-comma
+ rev: v2.5.1
hooks:
- - id: isort
- additional_dependencies: [toml]
- args: [--project=utide, --multi-line=3, --lines-after-imports=2, --lines-between-types=1, --trailing-comma, --force-grid-wrap=0, --use-parentheses, --line-width=88]
+ - id: add-trailing-comma
-- repo: https://github.com/psf/black
- rev: 22.3.0
+- repo: https://github.com/keewis/blackdoc
+ rev: v0.3.8
hooks:
- - id: black
- language_version: python3
+ - id: blackdoc
-- repo: https://github.com/asottile/pyupgrade
- rev: v2.32.0
+- repo: https://github.com/codespell-project/codespell
+ rev: v2.2.5
hooks:
- - id: pyupgrade
+ - id: codespell
+ exclude: >
+ (?x)^(
+ .*\.yaml
+ )$
args:
- - --py36-plus
+ - --ignore-words-list=fo,htmp
- repo: https://github.com/asottile/add-trailing-comma
- rev: v2.2.3
+ rev: v2.5.1
hooks:
- id: add-trailing-comma
+
+- repo: https://github.com/charliermarsh/ruff-pre-commit
+ rev: v0.0.272
+ hooks:
+ - id: ruff
+
+- repo: https://github.com/tox-dev/pyproject-fmt
+ rev: 0.12.0
+ hooks:
+ - id: pyproject-fmt
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index d90af42..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,45 +0,0 @@
-language: minimal
-
-sudo: false
-
-env:
- global:
- - secure: "ZN/NaiMNwlLUbxD4P+ha8SDfv1hfaJl9Dm838Z27cGPrOOFYC66sC1zLYnlWn1qeutyKZcML+EJ8m+aARe7ONQ97Noshm0i2ldtTAthpIoCOmIWja+9TvWQ5L3if3FUt9OsiHunkOZUM0IUILYryEgCrisUtO2WzcPs2XMO+c8M="
-
-matrix:
- fast_finish: true
- include:
- - name: "docs"
- env: PY=3
-
-before_install:
- # Install miniconda and create TEST env.
- - |
- wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh
- bash miniconda.sh -b -p $HOME/miniconda
- export PATH="$HOME/miniconda/bin:$PATH"
- conda config --set always_yes yes --set changeps1 no --set show_channel_urls true
- conda update conda --quiet
- conda config --add channels conda-forge --force
- conda config --set channel_priority strict
- conda config --set safety_checks disabled
- conda create --name TEST python=$PY --file requirements.txt --file requirements-dev.txt
- source activate TEST
-
-install:
- - pip install -e . --no-deps --force-reinstall
-
-script:
- - |
- if [[ $TRAVIS_JOB_NAME == 'docs' ]]; then
- set -e
- pushd docs
- make clean html linkcheck
- popd
- if [[ -z "$TRAVIS_TAG" ]]; then
- python -m doctr deploy --build-tags --key-path github_deploy_key_wesleybowman_utide.enc --built-docs docs/_build/html dev
- else
- python -m doctr deploy --build-tags --key-path github_deploy_key_wesleybowman_utide.enc --built-docs docs/_build/html "version-$TRAVIS_TAG"
- python -m doctr deploy --build-tags --key-path github_deploy_key_wesleybowman_utide.enc --built-docs docs/_build/html .
- fi
- fi
diff --git a/MANIFEST.in b/MANIFEST.in
index daf8330..aa9c15c 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,5 +1,5 @@
include *.txt
-include README.rst
+include README.md
include pyproject.toml
graft utide
@@ -11,6 +11,6 @@ prune *.egg-info
global-exclude *.mat
-exclude *.yml
-exclude *.enc
+exclude *.yaml
exclude .gitignore
+exclude utide/_version.py
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5c82983
--- /dev/null
+++ b/README.md
@@ -0,0 +1,64 @@
+# UTide
+
+[![gha](https://github.com/wesleybowman/UTide/actions/workflows/tests.yml/badge.svg)](https://github.com/wesleybowman/UTide/actions)
+[![license](https://anaconda.org/conda-forge/utide/badges/license.svg)](https://choosealicense.com/licenses/mit/)
+[![downloads](https://anaconda.org/conda-forge/utide/badges/downloads.svg)](https://anaconda.org/conda-forge/utide)
+[![anaconda_cloud](https://anaconda.org/conda-forge/utide/badges/version.svg)](https://anaconda.org/conda-forge/utide)
+
+Python re-implementation of the Matlab package UTide.
+
+Still in heavy development\--everything is subject to change!
+
+Note: the user interface differs from the Matlab version, so consult the
+Python function docstrings to see how to specify parameters. Some
+functionality from the Matlab version is not yet available. For more
+information see:
+
+ Codiga, D.L., 2011. Unified Tidal Analysis and Prediction Using the
+ UTide Matlab Functions. Technical Report 2011-01. Graduate School
+ of Oceanography, University of Rhode Island, Narragansett, RI.
+ 59pp.
+ ftp://www.po.gso.uri.edu/pub/downloads/codiga/pubs/2011Codiga-UTide-Report.pdf
+
+ UTide v1p0 9/2011 d.codiga@gso.uri.edu
+ http://www.po.gso.uri.edu/~codiga/utide/utide.htm
+
+# Installation
+
+``` shell
+pip install utide
+```
+
+If you are using conda,
+
+``` shell
+conda install utide --channel conda-forge
+```
+
+The public functions can be imported using
+
+``` python
+from utide import solve, reconstruct
+```
+
+A sample call would be
+
+``` python
+from utide import solve
+
+coef = solve(
+ time,
+ time_series_u,
+ time_series_v,
+ lat=30,
+ nodal=False,
+ trend=False,
+ method="ols",
+ conf_int="linear",
+ Rayleigh_min=0.95,
+)
+```
+
+For more examples see the
+[notebooks](https://nbviewer.jupyter.org/github/wesleybowman/UTide/tree/master/notebooks/)
+folder.
diff --git a/README.rst b/README.rst
deleted file mode 100644
index bf5af3a..0000000
--- a/README.rst
+++ /dev/null
@@ -1,77 +0,0 @@
-UTide
-=====
-|gha| |license| |conda| |downloads| |anaconda_cloud|
-
-.. |gha| image:: https://github.com/wesleybowman/UTide/actions/workflows/tests.yml/badge.svg
- :target: https://github.com/wesleybowman/UTide/actions
-
-.. |license| image:: https://anaconda.org/conda-forge/utide/badges/license.svg
- :target: https://choosealicense.com/licenses/mit/
-
-.. |conda| image:: https://anaconda.org/conda-forge/utide/badges/installer/conda.svg
- :target: https://anaconda.org/conda-forge/utide
-
-.. |downloads| image:: https://anaconda.org/conda-forge/utide/badges/downloads.svg
- :target: https://anaconda.org/conda-forge/utide
-
-.. |anaconda_cloud| image:: https://anaconda.org/conda-forge/utide/badges/version.svg
- :target: https://anaconda.org/conda-forge/utide
-
-Python re-implementation of the Matlab package UTide.
-
-Still in heavy development--everything is subject to change!
-
-Note: the user interface differs from the Matlab version, so
-consult the Python function docstrings to see how to specify
-parameters. Some functionality from the Matlab version is
-not yet available. For more information see:
-
-::
-
- Codiga, D.L., 2011. Unified Tidal Analysis and Prediction Using the
- UTide Matlab Functions. Technical Report 2011-01. Graduate School
- of Oceanography, University of Rhode Island, Narragansett, RI.
- 59pp. ftp://www.po.gso.uri.edu/pub/downloads/codiga/pubs/
- 2011Codiga-UTide-Report.pdf
-
- UTide v1p0 9/2011 d.codiga@gso.uri.edu
- http://www.po.gso.uri.edu/~codiga/utide/utide.htm
-
-Installation
-============
-
-.. code:: shell
-
- pip install utide
-
-If you are using conda,
-
-.. code:: shell
-
- conda install utide -c conda-forge
-
-
-The public functions can be imported using
-
-.. code:: python
-
- from utide import solve, reconstruct
-
-A sample call would be
-
-.. code:: python
-
- from utide import solve
-
- coef = solve(time, time_series_u, time_series_v,
- lat=30,
- nodal=False,
- trend=False,
- method='ols',
- conf_int='linear',
- Rayleigh_min=0.95,)
-
-
-For more examples see the
-`notebooks `__
-folder.
diff --git a/docs/conf.py b/docs/conf.py
index b51c9ad..408a018 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -15,7 +15,6 @@
import utide
-
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
diff --git a/github_deploy_key_wesleybowman_utide.enc b/github_deploy_key_wesleybowman_utide.enc
deleted file mode 100644
index 297d776..0000000
--- a/github_deploy_key_wesleybowman_utide.enc
+++ /dev/null
@@ -1 +0,0 @@
-gAAAAABctHINHbJo74bSpj4MSjKOYz5AwU0qWjTJmoQ2Yw73TSVvFql3h7ERrxxmo3Sbw96YlBR00KXDSPeKnCen0QX8vdBE-fR_tEqgCElBklDTD4L1AYW6CM8Nl7ZyING8DQ0HMsSjSyGLzsmUQU96w5rWe04F6oALY3OJDc7V6I5ll1x_HC0bVq2kTQfwju9_dUiU2zdIJSnRLjwsXgmmzMFqkf-ZLj7-ol_6wi6VQ_eEssEee4SvvQZ0lVfq7iG8-_hxHL6eD3roecy69P8VlN1hwDSy58dWh_U-Ye587wv_UasXAfPeKN6ImOJHJfxcSaGKXwbYiIw75lQbpNDsR5Jm9g5OrX60skQcoitBVT7_9QgCjNtMYkCBPEK8v4_R_xoX0MnXMnjdu1saAV7s3ZkYfVNdMA_8MCWxtW1_g3kTKpQGekInLSArIwr9WEN4GwO9dcLHr0J0Y21aib3yAS6MJrfLowQBg9YlNm0Jt7SfY5np7Kha_Wn_I_vGgMdc8dh0e5K8lkWPbuCi9ts_bM2YdTwvozN2obrKMYM5UjcyidcOeUq3ZDHSYvquXfttxq7neShfkuUDXcJzy5I8AQQdl-NB4wX6bT9RHQLpc6RUveJd1gYcGy65ZO_E7QMr7Lj5En7t6lNu1Zr_1vA9buoNi_nA0g8ytAtyUcZRpJwIZQXELxqYGf6pnO3kWx_c7X7n65CUta_KiQb_716KF54c5ZWVp4cILCw06PIosyTSOmag5XDDK8q4SWKa8F4eqx3tyrVsHVZp27G4iK3FqXNm2_dZd1OQfdO9jhyKaPGZDfSpAwQn6iWhz46zMIpqQpyGq0xJqKwAIJkTwvrNk5JbiyvuZqcjVO4mb8iEjDz-fKcdXAsfSOJ_oQJf04GpFPFKLOuv3HOz7iBzknmo1f5tsuY3BOlUgDymAA6UypibwaksYvt3LKIVPPFAeEva1uleRF85pFGATZdV1jZYpJ51dP8pcn9WG1ZLaydlSm_yDoBKB5IJg80NuKrAY9AXAw6Le-rel0JVzx6957y78iQAbwe-CMQQfIoe0tu1wm9wt9FBWoAsC4QPSc9ov3ASIS8eSvngmQEp-x4hMPRXQCNp01bTHYVYdJcc-yLvbpDqfjKLl270fubLuBi4zUfA8v67KdmUv3h2XKGz1XfWia617UCJKFE4TatEXgEjHG2gZvCSFChweji5FWV-T1Cra4IkV_aYnVMbjRHtWGwxWiPTefk0xQZPpry7Ogb9oeyPdTGtO3cCkaILruN81wFJl-txCxhnVXIoetwGcpJJBdX0vLvSZispwj7j1a11eaM2RYjMBCaj8D3RXntD3jLOxDncp488Fs1tOYPPNXSzGhox5XJ7VSfsTr5UiSjsJ5mT8Kf4VAkCVj9OD3iyDjmVZxV82FhRVOI6-IGGMMIKC7nKKjI6eaEimm_HAabs2B7Ty4mlZK2beksimLvHVX5YdGrkQbmrNPN-8im1nVY5wzWYXCdMV2bJSEgZjlQ9xblOHKSkkLQUIzH7WHhxyHveqCzMdp139ESYz2AaqZjMSfAapNdAP-NY596dzrWa8qXaCBWLb0TU5KOq2urpaFofQOkbf1unmYThzhk9_k0_YVDIkLTHj7WLSGt7V0saADDLhxSWUhkHey8EMRTheld_jrB6CCIPkw4H3ind9r5Ap3LYNNiIyGB6U-mfoUcvz-rt3Z1xezmx8gqO21CSUgS4E074-b-EULXJ74E-B8YAZShjXukZOytJOz2l8iP-GMvSR7VoJWAFohgJdxkl3PzdN370SPmSPwF0tKzf6LmkkvuqfkohJpuff6JPxdkXa_EGWQMtYeSI9rwGy25SC4j3Bnu6d5JCLlzVmk8ztKVBQbtB54ljZ-X5YUNZYyeFQhUjhwa8Zeiw8C0qoIpoENjNLCpdmdp7nr5UMZOXzeFbJCqN1KcaIPyzerfHANM7aH65ftSAhBGegtDYW7EUA2beAGjtlOrq1FSZqbbYxgR5VTEnnnciovT7JBuc2tkaDI4o2TANbcOFhQkQthIlNsKF6YAuY2g4bSKF_CcICWohDYWXOrAd-TnFknN71YbQuyO-due1OjT04ZQptZGHlKyKKx4EvEG4AGsWPyT-2OlAZQ_7pNyIVfTo1QXTuFFcHAlmo0Y24z5iQuDAZmajrwLcv1vqHSJ3xE2-GFwGao0NnvoMC7Y0dEzUWVGhzjkPn5aU2x8T-9V-OUfIWIDZSaL6T39Tdh-yPfF3uND-qibt78f0jVtYfSmwR16QN0ItYLc1e1vbXh7blXk_kSA1a-ZJdzbuf32OiuGunvo2InJDr02K5_7a3sY-wgLTa2Z-zBTKJWLNoogHo09L5jxVZ34tHt_fCe0d54mnWtNi3pQ32_nnHW5otU6MhWoNZ53vqkwZNm9GN4hIOGrWrTm1LOn2dEXlOz96GIKj5NaxP2qQqQeMV1PTiqwmAuyKrjlfcaoWDbe9wVa1JCvUJtJUNYbDyCgvals_PvYsJ_jQP-IDpS5JX1GJwvoQ19k_UFsNsRNZ1ZOckgOuBDQgu3KaftZ9ZdV0Xq2eTNfUFsLFQJ0vxN9JIB6LG5fBZ9ozQaCSLXRPWoXciV8ZVjFAww6HpsPKHWK-sPVt-L8cjDX0dWKl7hVrETbKg21TgZkSzAWi9Btfbrx453EnFPAET5xLUQaylTXqSEbb0mQVeiI1gprYuk_RAxdzb0RXQZmNYbvRqTk4Hn5EmosDdXA0ZQuuDKxIkSm5jdOTWk2Rem8syAgQBvZ1rYN43WQOGr4O0Gl5Ohlo-t59BcKUyuRwsZ36Ny5CzQykSMfDRcGOnMz7W9jzELDGWv8ZaWX-WvlBd0XyCodDtGpSgnnt6_g9AONSIbDpwSSmwa4jAlOGwqlAReJ3jAHb8RnB55vWuwul9maQ7toKKkeqwkUYsUtjQ1D1UGkEBVkPLc2bAnCfVEVC1p3UOXsh0VXViLPUt3IwJR9JMCSJPYgEDXxCLjFSw_yealup_dkrbjWD1U6oc8HAKWLuJTiuj6gFtacoM2GtcEOqs1UDlRJfd5-neXM_hBx3zF5N-3rffZ0fKX-3LaMT7bh0ddbSUR12oaWnULalmzIjABS1cHazpSmXZvxtzXcYQ0cTULajpMyXgy8QV2sGZ4BTAQCjz8xmylPt7Pspd6Q78dx6kDtSb15YGZRyv_d6W0DmwXWLhsA3KEguAFEv78BkAGhUANB-ZR6CPznWBVBPhB_hjvflb3HHI3hc4LTFAfQZBHIC_GFeFA1K8XTSDDP4_sWmTy5wtOMN9ZfgsgFgH4r4SdVlkV5mtdFEcajAI5DEbyh243vmxXdio9s9EV14YUVC2gxSpGuG2pd1R34r2j4x_SOOSL7zSdvuZWQC6E9A3w-w9VXrq1eRP9Nk6XQneGIn5IYc3JP1pIyKd6sSkRDv0MIrNRqBglKQ-tN1NV6qatz-X_pDLYmcA-ovUMNsosd7VCPPO6LDfVTMiSISjf5IDqTfe8VrnqyjsMWvwPF2zwig3ThDck9I48UrNI8aRzXyLgy2voaSk98QCCipiN-3FgkjAa7L3eYzXFkBTt1wW8SRIYiPJT7NI-WSYO5eANBQJASxf4YD7BX7LxUvv2PMKYQ8YaOV537WsqKSEgCpZV11o26mXJsxSeQ-LJ5keo58Z0dFpFSLJSmNd-disk4gZPjJvc7eKfz6dHPapChJ7AfaBo3qPzxDvQxBYv4n_AOBKOb1X8SjEI7bypWpcLHnaxBCMklGmqJB0DalnZ9KdEgee2e9pWvQq7ubcqyQy4ZsFUIr6VEiXQ26z95HXRf740Qjfir4uDLaXF28N_XVyaIDOu-YOVldDG5Azc_n-6aFuV2OCcGh26tm_ZEwQ41f8O1T25gtQ71XOL4AtJksYWn8C6CLLWXvYWYnyGyK0dyvmFGbgSMOqx7nxHTJyiLthOebWgnTZCZubWAnM27iz0dNGC9zoJfrVw9bTIZUCPyF5f7dqnhwVaAYwkpSxYNqtI9XYN9hjkd5nAd_BT7o8iC6Q33ccM4gTjHSOHVVOG-ADvONJ3DBkG0VGNgTZ0J7VWISxhIS5-mD4PD5VI7Nyptu6ru9PWOCPa3X2fy7E1_JBNvcWMGMm3OD5KjlwBO629tktB2q4YU3DC5yAnBnlNzcpUgahQh8Vm8ptUEp1Du6aRxFYZjF_ZvWBhxWy4eXDMxg3BUj6V5h9V4TATVqMzdmlNp4t65eDHgxRUTWQe67R-cW9IcKtd_X47HrNlqfxCwixn9xC4XronjGhzURj1EUU6BNI5bu1Fow1TsZjD_mPNbSGvgWYZeAH8VbAbGz6baTA79x46DGDR0PXElvw1LcOxyTOA72TTeLvVlkRLY82LbJL9Tl8X_HAIbZHB1x9dDl-MhV3VwNSsgE4o3r14H-3gvSvOfCBBmXCqvkAGJQUlQTYg==
\ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
index 7150f71..44e0fff 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,3 +1,76 @@
[build-system]
-requires = ["setuptools>=41.2", "setuptools_scm", "wheel"]
build-backend = "setuptools.build_meta"
+requires = [
+ "setuptools>=42",
+ "setuptools_scm",
+ "wheel",
+]
+
+[project]
+name = "utide"
+description = "Python distribution of the MatLab package UTide"
+license = {text = "MIT"}
+authors = [
+ {name = "Wesley Bowman", email = "wesley.bowman23@gmail.com"},
+]
+requires-python = ">=3.8"
+classifiers = [
+ "Programming Language :: Python :: 3 :: Only",
+ "Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
+]
+dynamic = [
+ "dependencies",
+ "version",
+]
+[project.urls]
+documentation = "https://wesleybowman.github.io/UTide"
+homepage = "https://github.com/wesleybowman/UTide"
+repository = "https://github.com/wesleybowman/UTide"
+
+[tool.setuptools]
+license-files = ["LICENSE.txt"]
+packages = ["utide"]
+include-package-data = true
+
+[tool.setuptools.dynamic]
+readme = {file = "README.md", content-type = "text/markdown"}
+dependencies = {file = ["requirements.txt"]}
+
+[tool.setuptools_scm]
+write_to = "utide/_version.py"
+write_to_template = "__version__ = '{version}'"
+tag_regex = "^(?Pv)?(?P[^\\+]+)(?P.*)?$"
+
+[tool.ruff]
+select = [
+ "A", # flake8-builtins
+ "B", # flake8-bugbear
+ "C4", # flake8-comprehensions
+ "E", # pycodecstyle
+ "F", # flakes
+ "I", # import sorting
+ "UP", # upgrade
+]
+target-version = "py38"
+line-length = 110
+
+[tool.ruff.per-file-ignores]
+"docs/conf.py" = [
+ "E401",
+ "E402",
+]
+
+[tool.check-manifest]
+ignore = [
+ "*.yml",
+ "utide/data/*.mat",
+ "docs",
+ "docs/*",
+ "notebooks",
+ "notebooks/*",
+ "tests",
+ "tests/*",
+]
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 4fc52f8..0000000
--- a/setup.cfg
+++ /dev/null
@@ -1,56 +0,0 @@
-[metadata]
-name = UTide
-description = Python distribution of the MatLab package UTide
-author = Wesley Bowman
-author_email = wesley.bowman23@gmail.com
-url = https://github.com/wesleybowman/UTide
-long_description_content_type = text/x-rst
-long_description = file: README.rst
-license = MIT
-license_file = LICENSE.txt
-keywords = oceanography tides
-platforms = any
-classifiers =
- Development Status :: 5 - Production/Stable
- Environment :: Console
- Intended Audience :: Science/Research
- Intended Audience :: Developers
- Intended Audience :: Education
- License :: OSI Approved :: MIT License
- Operating System :: OS Independent
- Programming Language :: Python
- Topic :: Scientific/Engineering
- Topic :: Education
-
-[options]
-install_requires =
- scipy
- numpy
-python_requires = >=3.6
-packages = find:
-zip_safe = False
-include_package_data = True
-
-[options.package_data]
-* =
- data/*.npz
-
-[sdist]
-formats = gztar
-
-[check-manifest]
-ignore =
- *.yml
- utide/data/*.mat
- docs
- docs/*
- *.enc
- notebooks
- notebooks/*
- tests
- tests/*
-
-[flake8]
-max-line-length = 105
-select = C,E,F,W,B,B950
-ignore = E203, E501, W503
diff --git a/setup.py b/setup.py
deleted file mode 100644
index 0eb5031..0000000
--- a/setup.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from setuptools import setup
-
-
-setup(use_scm_version=True)
diff --git a/tests/test_HNL.py b/tests/test_HNL.py
index 992787d..39fcd95 100644
--- a/tests/test_HNL.py
+++ b/tests/test_HNL.py
@@ -2,14 +2,11 @@
import numpy as np
import pytest
-
from numpy.testing import assert_array_almost_equal, assert_array_equal
import utide
-
from utide.utilities import Bunch, convert_unicode_arrays, loadbunch
-
thisdir = os.path.dirname(__file__)
datapath = os.path.join(thisdir, "data")
HNL_path = os.path.join(datapath, "HNL2010.asc")
diff --git a/tests/test_harmonics.py b/tests/test_harmonics.py
index 43729af..ec24a4a 100644
--- a/tests/test_harmonics.py
+++ b/tests/test_harmonics.py
@@ -14,7 +14,6 @@
from utide.harmonics import FUV
from utide.utilities import loadbunch
-
fname = os.path.join(_base_dir, "FUV0.npz")
diff --git a/tests/test_order_constit.py b/tests/test_order_constit.py
index b836581..05b7720 100644
--- a/tests/test_order_constit.py
+++ b/tests/test_order_constit.py
@@ -4,7 +4,6 @@
from utide import reconstruct, solve
from utide._ut_constants import constit_index_dict, ut_constants
-
ts = 735604
duration = 35
@@ -42,7 +41,6 @@
@pytest.mark.parametrize("conf_int", ["none", "linear", "MC"])
def test_order(conf_int):
-
orders = [None, "PE", "frequency", opts0["constit"]]
if conf_int != "none":
orders.append("SNR")
diff --git a/tests/test_solve.py b/tests/test_solve.py
index d7a1c3d..7719390 100644
--- a/tests/test_solve.py
+++ b/tests/test_solve.py
@@ -13,7 +13,6 @@
from utide._ut_constants import ut_constants
from utide.utilities import Bunch
-
ts = 735604
duration = 35
@@ -196,7 +195,7 @@ def test_MC():
):
print(f"{name:>5} {AA:10.4g} {AA_ci:10.4g} {gg:10.4g} {gg_ci:10.4g}")
- for (name, Lsmaj, Lsmaj_ci, Lsmin, Lsmin_ci, theta, theta_ci, gg, gg_ci) in zip(
+ for name, Lsmaj, Lsmaj_ci, Lsmin, Lsmin_ci, theta, theta_ci, gg, gg_ci in zip(
speed_coef.name,
speed_coef.Lsmaj,
speed_coef.Lsmaj_ci,
diff --git a/tests/test_uv.py b/tests/test_uv.py
index d0d5ad9..b85f704 100644
--- a/tests/test_uv.py
+++ b/tests/test_uv.py
@@ -4,7 +4,6 @@
"""
import numpy as np
import pytest
-
from pandas import date_range
from utide import reconstruct, solve
diff --git a/utide/__init__.py b/utide/__init__.py
index 045b842..2e0c9e1 100644
--- a/utide/__init__.py
+++ b/utide/__init__.py
@@ -9,7 +9,6 @@
ut_constants,
)
-
try:
__version__ = pkg_resources.get_distribution("utide").version
except Exception:
diff --git a/utide/_reconstruct.py b/utide/_reconstruct.py
index 0b3e279..67974c5 100644
--- a/utide/_reconstruct.py
+++ b/utide/_reconstruct.py
@@ -91,7 +91,6 @@ def reconstruct(
def _reconstruct(t, goodmask, coef, verbose, constit, min_SNR, min_PE):
-
twodim = coef["aux"]["opt"]["twodim"]
# Determine constituents to include.
diff --git a/utide/_solve.py b/utide/_solve.py
index d48f7ff..db0f71f 100644
--- a/utide/_solve.py
+++ b/utide/_solve.py
@@ -12,7 +12,6 @@
from .robustfit import robustfit
from .utilities import Bunch
-
default_opts = {
"constit": "auto",
"order_constit": None,
@@ -225,7 +224,6 @@ def solve(t, u, v=None, lat=None, **opts):
def _solv1(tin, uin, vin, lat, **opts):
-
# The following returns a possibly modified copy of tin (ndarray).
# t, u, v are fully edited ndarrays (unless v is None).
packed = _slvinit(tin, uin, vin, lat, **opts)
@@ -262,7 +260,6 @@ def _solv1(tin, uin, vin, lat, **opts):
B = np.hstack((E, E.conj()))
if opt.infer is not None:
-
Etilp = np.empty((nt, coef.nR), dtype=complex)
Etilm = np.empty((nt, coef.nR), dtype=complex)
@@ -465,7 +462,6 @@ def _reorder(coef, opt):
def _slvinit(tin, uin, vin, lat, **opts):
-
if lat is None:
raise ValueError("Latitude must be supplied")
diff --git a/utide/_time_conversion.py b/utide/_time_conversion.py
index 0cb3cd0..0550674 100644
--- a/utide/_time_conversion.py
+++ b/utide/_time_conversion.py
@@ -4,11 +4,10 @@
import numpy as np
-
# to be added to get 1 on 1st January of year 1 from unix epoch '1970-01-01'
_DAY_TO_GREGORIAN_EPOCH = 719163
-# milisecond in a day
+# millisecond in a day
_MS_PER_DAY = 1000 * 86400
@@ -25,17 +24,17 @@ def _date2num(date, epoch="1970-01-01 00:00:00.000"):
try:
date = date.astype("datetime64[ms]")
- except ValueError:
+ except ValueError as err:
raise ValueError(
f"Cannot convert date argument ({date}) to scalar or array of numpy datetime64 dtype.",
- )
+ ) from err
try:
epoch = np.datetime64(epoch, "ms")
- except ValueError:
+ except ValueError as err:
raise ValueError(
f"Cannot convert epoch argument ({epoch}) to numpy datetime64 dtype.",
- )
+ ) from err
# datenum calculation
datenum = (date - epoch).astype(float) / _MS_PER_DAY
@@ -49,7 +48,7 @@ def _python_gregorian_datenum(date):
Python gregorian time is 1 on 1st day of 1st year. Essentially, it means,
the epoch for python gregorian time is 0000-12-31. With _date2num() defined
above, this amounts to 719163 days from the unix-epoch 1970-01-01 00:00:00.
- To avoid repetative calculation, this is defined as _DAY_TO_GREGORIAN_EPOCH.
+ To avoid repetitive calculation, this is defined as _DAY_TO_GREGORIAN_EPOCH.
"""
return _date2num(date) + _DAY_TO_GREGORIAN_EPOCH
@@ -76,8 +75,10 @@ def _normalize_time(t, epoch=None):
else:
try:
ofs = _python_gregorian_datenum(epoch)
- except ValueError:
- raise ValueError("Cannot parse epoch as string or date or datetime")
+ except ValueError as err:
+ raise ValueError(
+ "Cannot parse epoch as string or date or datetime",
+ ) from err
else:
return t + ofs
else:
diff --git a/utide/_ut_constants.py b/utide/_ut_constants.py
index 07f1f5f..a963cfe 100644
--- a/utide/_ut_constants.py
+++ b/utide/_ut_constants.py
@@ -4,7 +4,6 @@
from .utilities import Bunch, convert_unicode_arrays, loadbunch
-
_base_dir = os.path.join(os.path.dirname(__file__), "data")
_ut_constants_fname = os.path.join(_base_dir, "ut_constants.npz")
diff --git a/utide/astronomy.py b/utide/astronomy.py
index 8a2a1ea..68eaa24 100644
--- a/utide/astronomy.py
+++ b/utide/astronomy.py
@@ -1,6 +1,5 @@
import numpy as np
-
# (comments based on t_tide)
# Coefficients of the formulas in the Explan. Suppl.
_sc = np.array([270.434164, 13.1763965268, -0.0000850, 0.000000039])
diff --git a/utide/confidence.py b/utide/confidence.py
index 8d8520e..0ddd815 100644
--- a/utide/confidence.py
+++ b/utide/confidence.py
@@ -138,7 +138,8 @@ def nearestSPD(A):
# Normally no more than one adjustment will be needed.
if k > 100:
warnings.warn(
- "adjustment in nearestSPD did not converge; " "returning diagonal",
+ "adjustment in nearestSPD did not converge; returning diagonal",
+ stacklevel=2,
)
return np.diag(np.diag(A))
return Ahat
diff --git a/utide/constituent_selection.py b/utide/constituent_selection.py
index 603b479..9f022bc 100644
--- a/utide/constituent_selection.py
+++ b/utide/constituent_selection.py
@@ -68,7 +68,7 @@ def ut_cnstitsel(tref, minres, incnstit, infer):
_r = infer.reference_names
allrefs = list(OrderedDict(zip(_r, [1] * len(_r))).keys())
nR = len(allrefs)
- for k, name in enumerate(allrefs):
+ for _k, name in enumerate(allrefs):
refstruct = Bunch(name=name)
refstruct.lind = constit_index_dict[name]
refstruct.frq = freqs[refstruct.lind]
diff --git a/utide/data/make_FUV_data.py b/utide/data/make_FUV_data.py
index 7ef1689..40dbfab 100644
--- a/utide/data/make_FUV_data.py
+++ b/utide/data/make_FUV_data.py
@@ -8,11 +8,9 @@
"""
import numpy as np
-
from oct2py import Oct2PyError, octave
from scipy.io.matlab import savemat
-
octave.convert_to_float = False
@@ -61,7 +59,16 @@
except Oct2PyError:
print("failed")
- save_args = dict(t=t, t0=t0, lat=lat, lind=lind, flags=flags, Fo=Fo, Uo=Uo, Vo=Vo)
+ save_args = {
+ "t": t,
+ "t0": t0,
+ "lat": lat,
+ "lind": lind,
+ "flags": flags,
+ "Fo": Fo,
+ "Uo": Uo,
+ "Vo": Vo,
+ }
np.savez("FUV%d.npz" % ilind, **save_args)
diff --git a/utide/data/mat2npz.py b/utide/data/mat2npz.py
index 8272354..d4b76f7 100644
--- a/utide/data/mat2npz.py
+++ b/utide/data/mat2npz.py
@@ -4,7 +4,6 @@
from utide.utilities import loadbunch
-
datadir = os.path.join(os.path.dirname(__file__))
fname = "ut_constants"
diff --git a/utide/harmonics.py b/utide/harmonics.py
index 5425b96..0a671a9 100644
--- a/utide/harmonics.py
+++ b/utide/harmonics.py
@@ -8,7 +8,6 @@
from ._ut_constants import ut_constants
from .astronomy import ut_astron
-
sat = ut_constants.sat
const = ut_constants.const
shallow = ut_constants.shallow
diff --git a/utide/periodogram.py b/utide/periodogram.py
index fdc3f8b..099e101 100644
--- a/utide/periodogram.py
+++ b/utide/periodogram.py
@@ -13,12 +13,10 @@
"""
import numpy as np
-
from scipy import signal
from utide.utilities import Bunch
-
# __all__ = ['freq_bands', 'band_psd']
# Frequency bands in cycles per hour for
@@ -115,7 +113,7 @@ def _lomb_freqs(t, fbands=None, ofac=1, max_per_band=500):
nfreq = len(freq)
freqs = []
- for k, (f0, f1) in enumerate(fbands):
+ for _k, (f0, f1) in enumerate(fbands):
i0, i1 = np.searchsorted(freq, [f0, f1])
i1 = min(nfreq, i1 + 1)
inband = slice(i0, i1)
@@ -354,7 +352,6 @@ def band_psd(t, e, cfrq, equi=True, frqosamp=1):
# If e is complex, handle imaginary part.
if e.dtype.kind == "c":
-
if equi: # If even sampling, Welch.
Pvv1s = _psd(e.imag, hn, fs)
Puv1s = _psd(e, hn, fs) # complex cross-periodogram
diff --git a/utide/robustfit.py b/utide/robustfit.py
index 4507285..8f19a20 100644
--- a/utide/robustfit.py
+++ b/utide/robustfit.py
@@ -61,17 +61,17 @@ def welsch(r):
return w
-wfuncdict = dict(
- andrews=andrews,
- bisquare=bisquare,
- cauchy=cauchy,
- fair=fair,
- huber=huber,
- logistic=logistic,
- ols=ols,
- talwar=talwar,
- welsch=welsch,
-)
+wfuncdict = {
+ "andrews": andrews,
+ "bisquare": bisquare,
+ "cauchy": cauchy,
+ "fair": fair,
+ "huber": huber,
+ "logistic": logistic,
+ "ols": ols,
+ "talwar": talwar,
+ "welsch": welsch,
+}
tune_defaults = {
"andrews": 1.339,
@@ -208,7 +208,7 @@ def robustfit(
rsumsq = rsumsq[0]
if i == 0:
rms_resid = np.sqrt(rsumsq / n)
- out.update(dict(ols_b=b, ols_rms_resid=rms_resid))
+ out.update({"ols_b": b, "ols_rms_resid": rms_resid})
# Weighted mean of squared weighted residuals:
rmeansq = rsumsq / w.sum()
@@ -247,14 +247,14 @@ def robustfit(
rms_resid = np.sqrt(np.mean(np.abs(resid) ** 2))
out.update(
- dict(
- iterations=iterations,
- b=b,
- s=sing,
- w=w,
- rank=rank,
- rms_resid=rms_resid,
- ),
+ {
+ "iterations": iterations,
+ "b": b,
+ "s": sing,
+ "w": w,
+ "rank": rank,
+ "rms_resid": rms_resid,
+ },
)
return out
@@ -263,7 +263,6 @@ def robustfit(
# Some simple test cases; this probably will be removed.
if __name__ == "__main__":
-
np.random.seed(1)
n = 10000
x = np.arange(n)
diff --git a/utide/utilities.py b/utide/utilities.py
index 42864db..cb502cc 100644
--- a/utide/utilities.py
+++ b/utide/utilities.py
@@ -1,10 +1,8 @@
import warnings
import numpy as np
-
from scipy.io import loadmat
-
# This module began as an excerpt from the one in python-gsw.
# Based on Robert Kern's Bunch; taken from
@@ -59,8 +57,8 @@ def __init__(self, *args, **kwargs):
def __getattr__(self, name):
try:
return self[name]
- except KeyError:
- raise AttributeError("'Bunch' object has no attribute '%s'" % name)
+ except KeyError as err:
+ raise AttributeError(f"'Bunch' object has no attribute '{name}'") from err
def __setattr__(self, name, value):
self[name] = value
@@ -109,7 +107,7 @@ def from_pyfile(self, filename):
# Python 3 the scoping for list comprehensions would
# lead to a NameError. Wrapping the code in a function
# fixes this.
- d = dict()
+ d = {}
lines = ["def _temp_func():\n"]
with open(filename) as f:
lines.extend([" " + line for line in f])
@@ -137,7 +135,7 @@ def update_values(self, *args, **kw):
already in the Bunch instance will raise a KeyError.
"""
strict = kw.pop("strict", False)
- newkw = dict()
+ newkw = {}
for d in args:
newkw.update(d)
newkw.update(kw)
@@ -151,7 +149,7 @@ def update_None(self, *args, **kw):
will be updated only if it is None.
"""
strict = kw.pop("strict", False)
- newkw = dict()
+ newkw = {}
for d in args:
newkw.update(d)
newkw.update(kw)
@@ -174,6 +172,7 @@ def t_mpl(self):
warnings.warn(
"t_mpl is being depreciated. Please directly input a time array and use variable t_in for plots.",
category=FutureWarning,
+ stacklevel=2,
)
return self["t_mpl"]