From 2a69e7f2bb4c6a8fd67f9fe401bff29d237282f0 Mon Sep 17 00:00:00 2001 From: Martin Vonk Date: Thu, 23 May 2024 14:13:41 +0200 Subject: [PATCH 01/15] Create .pre-commit-config.yaml --- .pre-commit-config.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..d7d2bf68 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,12 @@ +repos: + - repo: https://github.com/astral-sh/ruff-pre-commit + # Ruff version. + rev: v0.4.4 + hooks: + # Run the linter. + - id: ruff + types_or: [python, pyi, jupyter] + args: ["--select-extend", "I", "--fix"] + # Run the formatter. + - id: ruff-format + types_or: [python, pyi, jupyter] From d69913b84f3316eb5eb86c9b8b82cfdd06356dec Mon Sep 17 00:00:00 2001 From: Martin Vonk Date: Thu, 23 May 2024 14:14:28 +0200 Subject: [PATCH 02/15] update code style docs to ruff --- doc/developers/code_style.rst | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/doc/developers/code_style.rst b/doc/developers/code_style.rst index e21da466..88f37612 100644 --- a/doc/developers/code_style.rst +++ b/doc/developers/code_style.rst @@ -2,25 +2,24 @@ Pastas Code Style ================= This page provides information on the code style to use when writing code for Pastas. -Black formatting +Formatting and Linting ---------------- To ensure high quality code that is easy to read and maintain we follow the -`Black `_ code formatting standard. -Please checkout the `Black Documentation `_ -on how to format Python code this way. +`Ruff `_ code standard. Please checkout the `Ruff +Documentation `_ on how to format Python code +this way. Type Hints ---------- -Pastas uses TypeHinting, which is used to check user-provided input options. Please provide -TypeHints when creating new methods and classes. +Pastas uses Type Hinting, which is used to check user-provided input options. +Please provide Type Hints when creating new methods and classes. Docstrings ---------- -Documentation is -created using `Sphinxdoc `_. Docstrings within -the method or class need to be written in `NumPy docformat `_ to enable -automatic documentation on this website. +Documentation is created using `Sphinxdoc `_. +Docstrings within the method or class need to be written in `NumPy docformat +`_ +to enable automatic documentation on this website. Optimization ------------ From 2cef9aa7a44142f55f472db32be8fabfe291e5e8 Mon Sep 17 00:00:00 2001 From: Martin Vonk Date: Thu, 23 May 2024 14:15:07 +0200 Subject: [PATCH 03/15] update contributiong docs with pre-commit and ruff --- doc/developers/contributing.rst | 92 ++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 41 deletions(-) diff --git a/doc/developers/contributing.rst b/doc/developers/contributing.rst index 15c6dfc8..01235837 100644 --- a/doc/developers/contributing.rst +++ b/doc/developers/contributing.rst @@ -14,11 +14,11 @@ to commit code changes to GitHub open source projects. Let's start! 0. Pick an Issue ---------------- -Before you start, it is a good idea to check if there are any issues that you can help -with. You can find a list of issues that are open on the `GitHub Issues page -`_` with the tag -"good-first-issue". These issues are a good place to start if you are new to Pastas -and want to contribute to the project. +Before you start, it is a good idea to check if there are any issues that you +can help with. You can find a list of issues that are open on the `GitHub +Issues page `_` with +the tag "good-first-issue". These issues are a good place to start if you are +new to Pastas and want to contribute to the project. 1. Create a GitHub Issue ------------------------ @@ -27,63 +27,73 @@ propose to make and why these are necessary. This is an easy way to inform the Pastas community in an early stage of any issues that needs to be solved and allows others to help you work out a solution. -2. Fork Pastas --------------- -To start making changes to the original code, you need to make a local copy -of the Pastas, called "Forking" in git-language. You can read how to fork a -GitHub repository `here `_. +2. Fork and install Pastas +-------------------------- +To start making changes to the original code, you need to make a local copy of +the Pastas, called "Forking" in git-language. You can read how to fork a GitHub +repository `here +`_. +To use all the development tools; install Pastas in development mode by running +`pip install -e .[dev]` in the root of the repository. This will install all +development dependencies such as `tox`, `ruff`, `pre=commit` and `pytest`. .. note:: - Make sure to make changes in the make changes in your local Development - branch (Dev) or start an entirely new branch that branches of the - Dev-branch. + Make sure to make changes in the make changes in a new branch that branches + of the Dev-branch. This way you can easily create a Pull Request later on. 3. Write Code ------------- After you forked Pastas, you can start making changes to the code or add new features to it. To ensure high quality code that is easy to read and maintain -we follow the `Black `_ code -formatting standard. Check out the Pastas Code Style section to learn +we follow the `Ruff `_ code +formatting and linting standard. Check out the Pastas Code Style section to learn more about the formatting of code and docstrings. +.. note:: + To make sure your code is up to standards, you can run the following: + - ruff check --select-extend I --fix + - ruff format + Or use the git pre-commit hook by installing it with `pip install + pre-commit` and running `pre-commit install` in the active python + environment. + 4. Test Code ------------- -The ensure a proper functioning of the Pastas, it is important to supply -tests in the test-suite (`see here `_). The ensure a proper functioning of -the Pastas, the software is automatically tested using Github Actions when changes -are made. Pastas uses `pytest `_ to run tests. +the Pastas, the software is automatically tested using Github Actions when +changes are made. Pastas uses `pytest `_ to +run tests. 5. Document Code ---------------- -When submitting a new function, method or class, docstrings are required -before the new code will be pulled into the dev branch. Documentation is -created using `Sphinxdoc `_. Docstrings within -the method or class need to be written in `NumPy docformat `_ to enable -automatic documentation on this website. In the case of a new module, the module -needs to be added to `index.rst` in the api-folder. +When submitting a new function, method or class, docstrings are required before +the new code will be pulled into the dev branch. Documentation is created using +`Sphinxdoc `_. Docstrings within the method or class +need to be written in `NumPy docformat `_ to enable automatic +documentation on this website. In the case of a new module, the module needs to +be added to `index.rst` in the api-folder. A Jupyter Notebook explaining the use of your new code can be added the to -examples folder. This Notebook will also be automatically converted and -placed on the Examples page on this website. +examples folder. This Notebook will also be automatically converted and placed +on the Examples page on this website. 6. Create a pull request ------------------------ Once you have written, tested, and documented your code you can start a pull -request on the development branch (dev) of Pastas. Pull requests can only -be submitted to the dev-branch and need to be reviewed by one of the core +request on the development branch (dev) of Pastas. Pull requests can only be +submitted to the dev-branch and need to be reviewed by one of the core developers. When you start your Pull Request, you will automatically see a -checklist to go through to check if your PR is up to standards. Pastas will -run automatic code tests to ensure that the code works, is documented and -has a good code style. +checklist to go through to check if your PR is up to standards. Pastas will run +automatic code tests to ensure that the code works, is documented and has a +good code style. 7. Share and enjoy your work! ----------------------------- -After you have create a Pull Request the Core Development Team will -review your code and discuss potential improvements on GitHub before merging -your code into the development branch. After a successful Pull Request your -code will be included in the next release of Pastas when the master-branch is -updated. Congratulations, you are now officially a contributor to the Pastas -project! +After you have create a Pull Request the Core Development Team will review your +code and discuss potential improvements on GitHub before merging your code into +the development branch. After a successful Pull Request your code will be +included in the next release of Pastas when the master-branch is updated. +Congratulations, you are now officially a contributor to the Pastas project! From 8426d38e718a6280bcb85e8a8a27443869893aac Mon Sep 17 00:00:00 2001 From: Martin Vonk Date: Thu, 23 May 2024 14:15:49 +0200 Subject: [PATCH 04/15] update pool request template with ruff --- .github/pull_request_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 66361c7c..268c34af 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -4,7 +4,7 @@ Add a short description describing the pull request (PR) here. # Checklist before PR can be merged: - [ ] closes issue #xxxx - [ ] is documented -- [ ] Format code with [Black formatting](https://black.readthedocs.io) +- [ ] Format code with [ruff formatting](https://docs.astral.sh/ruff/) - [ ] type hints for functions and methods - [ ] tests added / passed - [ ] Example Notebook (for new features) From bb59b0027e5f4211fc85cd339d9d5ddc521a1aba Mon Sep 17 00:00:00 2001 From: Martin Vonk Date: Thu, 23 May 2024 14:16:44 +0200 Subject: [PATCH 05/15] update ci with formatting and linting with ruff --- .github/workflows/ci.yml | 8 ----- .github/workflows/test_format_lint.yml | 49 ++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/test_format_lint.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 07204527..bb99516b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,14 +35,6 @@ jobs: python: "3.12" toxenv: py312 experimental: false - - name: Formatting with black + isort - python: "3.9" - toxenv: format - experimental: false - - name: Linting with flake8 - python: "3.9" - toxenv: lint - experimental: false - name: Test suite for all unit tests including Notebooks python: "3.9" toxenv: all diff --git a/.github/workflows/test_format_lint.yml b/.github/workflows/test_format_lint.yml new file mode 100644 index 00000000..15746318 --- /dev/null +++ b/.github/workflows/test_format_lint.yml @@ -0,0 +1,49 @@ +name: CI RUFF + +on: + push: + pull_request: + branches: + - master + - dev + +jobs: + test: + name: ${{ matrix.name }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - name: Formatting and linting with ruff + python: "3.9" + toxenv: ruff + env: + # Color Output + # Rich (pip) + FORCE_COLOR: 1 + # Tox + PY_COLORS: 1 + # Pytest + PYTEST_ADDOPTS: "--color=yes" + steps: + - uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python }} + check-latest: true + cache: "pip" + cache-dependency-path: pyproject.toml + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install tox + + - name: Setup tox environment + run: tox -e ${{ matrix.toxenv }} --notest + + - name: Test + run: tox -e ${{ matrix.toxenv }} --skip-pkg-install From e7dd5083f933f6b884033eab8b88a0dcbe441285 Mon Sep 17 00:00:00 2001 From: Martin Vonk Date: Thu, 23 May 2024 14:49:51 +0200 Subject: [PATCH 06/15] typo in ruff check --- .pre-commit-config.yaml | 2 +- doc/developers/contributing.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d7d2bf68..b26ed7c2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: # Run the linter. - id: ruff types_or: [python, pyi, jupyter] - args: ["--select-extend", "I", "--fix"] + args: ["--extend-select", "I", "--fix"] # Run the formatter. - id: ruff-format types_or: [python, pyi, jupyter] diff --git a/doc/developers/contributing.rst b/doc/developers/contributing.rst index 01235837..5e5ca1ec 100644 --- a/doc/developers/contributing.rst +++ b/doc/developers/contributing.rst @@ -51,7 +51,7 @@ more about the formatting of code and docstrings. .. note:: To make sure your code is up to standards, you can run the following: - - ruff check --select-extend I --fix + - ruff check --extend-select I --fix - ruff format Or use the git pre-commit hook by installing it with `pip install pre-commit` and running `pre-commit install` in the active python From 74c5e2585929f978094951a29e20d9c67718fc03 Mon Sep 17 00:00:00 2001 From: Martin Vonk Date: Thu, 23 May 2024 14:56:16 +0200 Subject: [PATCH 07/15] fix everything ruff does not like --- doc/conf.py | 8 +++----- pastas/dataset.py | 2 +- pastas/extensions/__init__.py | 8 +++++--- pastas/extensions/accessor.py | 2 +- pastas/io/base.py | 1 - pastas/io/pas.py | 6 ++++-- pastas/model.py | 7 +++---- pastas/plotting/bokeh.py | 5 +---- pastas/recharge.py | 2 +- pastas/solver.py | 6 ++---- pastas/stats/core.py | 6 ++---- pastas/stats/dutch.py | 3 +-- pastas/stats/signatures.py | 23 ++++++++++++++++------- pastas/stressmodels.py | 3 +-- pastas/timeseries_utils.py | 7 ++++--- tests/test_001.py | 2 ++ 16 files changed, 47 insertions(+), 44 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index 4b93eaf1..caa16bdf 100755 --- a/doc/conf.py +++ b/doc/conf.py @@ -9,15 +9,13 @@ from datetime import date import requests - -year = date.today().strftime("%Y") - from matplotlib import use -use("agg") - from pastas import __version__ +year = date.today().strftime("%Y") +use("agg") + # 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/pastas/dataset.py b/pastas/dataset.py index 2f1d579c..ce875a29 100644 --- a/pastas/dataset.py +++ b/pastas/dataset.py @@ -127,5 +127,5 @@ def list_datasets() -> List[str]: print("Available datasets in the pastas-data repository on GitHub:") for folder in data: print(f" - {folder}") - print(f"Use ps.load_dataset('folder_name') to load a dataset from the repository.") + print("Use ps.load_dataset('folder_name') to load a dataset from the repository.") return data diff --git a/pastas/extensions/__init__.py b/pastas/extensions/__init__.py index 2a98b8f6..b9415000 100644 --- a/pastas/extensions/__init__.py +++ b/pastas/extensions/__init__.py @@ -1,19 +1,21 @@ import logging -from pastas.extensions.accessor import register_model_accessor +from pastas.extensions.accessor import ( + register_model_accessor as register_model_accessor, +) logger = logging.getLogger(__name__) def register_plotly(): """Register Plotly extension for pastas.Model class for interactive plotting.""" - from pastas.plotting.plotly import Plotly + from pastas.plotting.plotly import Plotly as Plotly logger.info("Registered plotly extension in Model class, e.g. `ml.plotly.plot()`.") def register_bokeh(): """Register Bokeh extension for pastas.Model class for interactive plotting.""" - from pastas.plotting.bokeh import Bokeh + from pastas.plotting.bokeh import Bokeh as Bokeh logger.info("Registered bokeh extension in Model class, e.g. `ml.bokeh.plot()`.") diff --git a/pastas/extensions/accessor.py b/pastas/extensions/accessor.py index 93b29049..6f5b2d4e 100644 --- a/pastas/extensions/accessor.py +++ b/pastas/extensions/accessor.py @@ -57,7 +57,7 @@ def _register_accessor(name: str, cls): .. code-block:: python - def __init__(self, pastas_object): # noqa: E999 + def __init__(self, pastas_object): ... Examples diff --git a/pastas/io/base.py b/pastas/io/base.py index 42eb9efd..32203379 100644 --- a/pastas/io/base.py +++ b/pastas/io/base.py @@ -5,7 +5,6 @@ from os import path from packaging import version -from pandas import to_numeric import pastas as ps diff --git a/pastas/io/pas.py b/pastas/io/pas.py index 0ff8d637..7509adfd 100644 --- a/pastas/io/pas.py +++ b/pastas/io/pas.py @@ -47,7 +47,8 @@ def pastas_hook(obj: dict): elif key == "series": try: obj[key] = read_json(stringIO(value), typ="series", orient="split") - except: + except Exception as e: + logger.error(e) obj[key] = value if isinstance(obj[key], Series): obj[key].index = obj[key].index.tz_localize(None) @@ -64,7 +65,8 @@ def pastas_hook(obj: dict): else: try: obj[key] = json.loads(value, object_hook=pastas_hook) - except: + except Exception as e: + logger.error(e) obj[key] = value return obj diff --git a/pastas/model.py b/pastas/model.py index bdb15e14..9c1c33b1 100644 --- a/pastas/model.py +++ b/pastas/model.py @@ -25,7 +25,6 @@ from pastas.decorators import get_stressmodel from pastas.io.base import _load_model, dump from pastas.modelstats import Statistics -from pastas.noisemodels import ArNoiseModel from pastas.plotting.modelplots import Plotting, _table_formatter_stderr from pastas.rfunc import HantushWellModel from pastas.solver import LeastSquares @@ -38,10 +37,9 @@ get_sample, ) from pastas.transform import ThresholdTransform -from pastas.typing import ArrayLike +from pastas.typing import ArrayLike, Solver, StressModel, TimestampType from pastas.typing import Model as ModelType from pastas.typing import NoiseModel as NoiseModelType -from pastas.typing import Solver, StressModel, TimestampType from pastas.utils import validate_name from pastas.version import __version__ @@ -1820,7 +1818,8 @@ def _get_file_info(self) -> dict: try: file_info["owner"] = getlogin() - except: + except Exception as e: + logger.error(e) file_info["owner"] = "Unknown" return file_info diff --git a/pastas/plotting/bokeh.py b/pastas/plotting/bokeh.py index ebc77c4b..12c012fc 100644 --- a/pastas/plotting/bokeh.py +++ b/pastas/plotting/bokeh.py @@ -257,10 +257,7 @@ def results(self, tmin=None, tmax=None, height=500, width=800, show_plot=True): x_range=p.x_range, ) - if rfunc_plot is not None: - xrange = rfunc_plot.x_range - else: - xrange = False + # xrange = False if rfunc_plot is None else rfunc_plot.x_range rfunc_plot = figure( x_axis_label=None, diff --git a/pastas/recharge.py b/pastas/recharge.py index 0886861f..6bb1e779 100644 --- a/pastas/recharge.py +++ b/pastas/recharge.py @@ -669,7 +669,7 @@ def get_recharge( fc: float = 1.0, sr: float = 0.5, de: float = 250.0, - l: float = -2.0, + l: float = -2.0, # noqa: E741 m: float = 0.5, ks: float = 50.0, dt: float = 1.0, diff --git a/pastas/solver.py b/pastas/solver.py index 731da110..f5b4b10e 100644 --- a/pastas/solver.py +++ b/pastas/solver.py @@ -353,14 +353,12 @@ def get_parameter_sample( suggestion = "You could try increasing 'max_iter'." if samples.shape[0] == 0: raise Exception( - "No parameter samples were found within %s runs. ".format(max_iter) + "No parameter samples were found within %s runs. " % max_iter + suggestion ) else: logger.warning( - f"Parameter sample size is smaller than n: %s/%s. ".format( - max_iter, n - ) + "Parameter sample size is smaller than n: %s/%s. " % (max_iter, n) + suggestion ) return samples[:n, :] diff --git a/pastas/stats/core.py b/pastas/stats/core.py index d0d10364..83f597f2 100644 --- a/pastas/stats/core.py +++ b/pastas/stats/core.py @@ -230,10 +230,9 @@ def _compute_ccf_rectangle( """Internal numba-optimized method to compute the ccf.""" c = empty_like(lags) b = empty_like(lags) - l = len(lags) n = len(t_x) - for k in range(l): + for k in range(len(lags)): cl = 0.0 b_sum = 0.0 for i in range(n): @@ -263,13 +262,12 @@ def _compute_ccf_gaussian( """Internal numba-optimized method to compute the ccf.""" c = empty_like(lags) b = empty_like(lags) - l = len(lags) n = len(t_x) den1 = -2 * bin_width**2 # denominator 1 den2 = sqrt(2 * pi * bin_width) # denominator 2 - for k in range(l): + for k in range(len(lags)): cl = 0.0 b_sum = 0.0 diff --git a/pastas/stats/dutch.py b/pastas/stats/dutch.py index d2098c7c..e8baa824 100644 --- a/pastas/stats/dutch.py +++ b/pastas/stats/dutch.py @@ -9,9 +9,8 @@ from numpy import nan from packaging.version import parse as parse_version -from pandas import Series, Timedelta +from pandas import Series, Timedelta, concat, date_range from pandas import __version__ as pd_version -from pandas import concat, date_range from pastas.timeseries_utils import get_sample from pastas.typing import Function, TimestampType diff --git a/pastas/stats/signatures.py b/pastas/stats/signatures.py index df1a76ee..f3c15fe5 100644 --- a/pastas/stats/signatures.py +++ b/pastas/stats/signatures.py @@ -24,9 +24,8 @@ where, ) from packaging.version import parse as parse_version -from pandas import DataFrame, DatetimeIndex, Series, Timedelta +from pandas import DataFrame, DatetimeIndex, Series, Timedelta, concat, cut, to_datetime from pandas import __version__ as pd_version -from pandas import concat, cut, to_datetime from scipy.optimize import curve_fit from scipy.stats import linregress @@ -1279,7 +1278,9 @@ def recession_constant( return nan # Fit an exponential model to the binned data and return the decay constant - f = lambda t, *p: -p[0] * (1 - exp(-t / p[1])) + def f(t, p): + return -p[0] * (1 - exp(-t / p[1])) + popt, _ = curve_fit( f, binned.index, binned.values, p0=[1, 100], bounds=(0, [100, 1e3]) ) @@ -1349,8 +1350,10 @@ def recovery_constant( if binned.empty: return nan - # Fit an exponential model to the binned data and return the recovery constant - f = lambda t, *p: p[0] * (1 - exp(-t / p[1])) + # Fit an exponential model to the binned data and return the decay constant + def f(t, p): + return -p[0] * (1 - exp(-t / p[1])) + popt, _ = curve_fit( f, binned.index, binned.values, p0=[1, 100], bounds=(0, [100, 1e3]) ) @@ -1368,7 +1371,10 @@ def recovery_constant( def duration_curve_slope( - series: Series, l: float = 0.1, u: float = 0.9, normalize: bool = False + series: Series, + l: float = 0.1, # noqa: E741 + u: float = 0.9, + normalize: bool = False, ) -> float: """Slope of the head duration curve between percentile l and u after :cite:t:`oudin_are_2010`. @@ -1415,7 +1421,10 @@ def duration_curve_slope( def duration_curve_ratio( - series: Series, l: float = 0.1, u: float = 0.9, normalize: bool = True + series: Series, + l: float = 0.1, # noqa: E741 + u: float = 0.9, + normalize: bool = True, ) -> float: """Ratio of the head duration curve between the percentile l and u after :cite:t:`richards_measures_1990`. diff --git a/pastas/stressmodels.py b/pastas/stressmodels.py index a2d9fe77..17fa73df 100644 --- a/pastas/stressmodels.py +++ b/pastas/stressmodels.py @@ -22,9 +22,8 @@ import numpy as np from packaging.version import parse as parse_version -from pandas import DataFrame, Series, Timedelta, Timestamp +from pandas import DataFrame, Series, Timedelta, Timestamp, concat, date_range from pandas import __version__ as pd_version -from pandas import concat, date_range from scipy.signal import fftconvolve from pastas.typing import ( diff --git a/pastas/timeseries_utils.py b/pastas/timeseries_utils.py index 5df68daf..3a9c9703 100644 --- a/pastas/timeseries_utils.py +++ b/pastas/timeseries_utils.py @@ -54,9 +54,9 @@ def _frequency_is_supported(freq: str) -> str: offset = to_offset(freq) try: Timedelta(offset) - except: + except Exception as e: msg = "Frequency %s not supported." - logger.error(msg, freq) + logger.error(msg, freq, e) raise ValueError(msg % freq) if offset.n == 1: freq = offset.name @@ -90,7 +90,8 @@ def _get_stress_dt(freq: str) -> float: offset = to_offset(freq) try: dt = Timedelta(offset) / Timedelta(1, "D") - except: + except Exception as e: + logging.error(e) num = offset.n freq = offset._prefix if freq in ["A", "Y", "AS", "YS", "YE", "BA", "BY", "BAS", "BYS"]: diff --git a/tests/test_001.py b/tests/test_001.py index 2dd9c93b..3bfa9011 100644 --- a/tests/test_001.py +++ b/tests/test_001.py @@ -1,2 +1,4 @@ def test_import() -> None: import pastas as ps + + assert ps is not None From 914d409278e56e3dc4a4ca6b483fd122df1f9913 Mon Sep 17 00:00:00 2001 From: Martin Vonk Date: Thu, 23 May 2024 15:17:47 +0200 Subject: [PATCH 08/15] update ruff in pyproject.toml tox --- .../workflows/test_benchmark_notebooks.yml | 2 +- .github/workflows/test_format_lint.yml | 2 +- doc/developers/contributing.rst | 14 +++++--- pyproject.toml | 32 +++++++++---------- 4 files changed, 27 insertions(+), 23 deletions(-) diff --git a/.github/workflows/test_benchmark_notebooks.yml b/.github/workflows/test_benchmark_notebooks.yml index 6655e2e6..7f70ddda 100644 --- a/.github/workflows/test_benchmark_notebooks.yml +++ b/.github/workflows/test_benchmark_notebooks.yml @@ -14,7 +14,7 @@ jobs: matrix: include: - name: Test suite for benchmark Notebooks - python: "3.9" + python: "3.10" toxenv: notebooks env: # Color Output diff --git a/.github/workflows/test_format_lint.yml b/.github/workflows/test_format_lint.yml index 15746318..25af7c88 100644 --- a/.github/workflows/test_format_lint.yml +++ b/.github/workflows/test_format_lint.yml @@ -16,7 +16,7 @@ jobs: matrix: include: - name: Formatting and linting with ruff - python: "3.9" + python: "3.10" toxenv: ruff env: # Color Output diff --git a/doc/developers/contributing.rst b/doc/developers/contributing.rst index 5e5ca1ec..3d4c60e8 100644 --- a/doc/developers/contributing.rst +++ b/doc/developers/contributing.rst @@ -51,11 +51,15 @@ more about the formatting of code and docstrings. .. note:: To make sure your code is up to standards, you can run the following: - - ruff check --extend-select I --fix - - ruff format - Or use the git pre-commit hook by installing it with `pip install - pre-commit` and running `pre-commit install` in the active python - environment. + - `ruff check --extend-select I --fix` + - `ruff format` + or use tox: + - `tox -e ruff_fix` + +.. note:: + If you want to make sure your code is formatted and linted on every commit: + consider using the git pre-commit hook by installing it with `pip install + pre-commit` and running `pre-commit install` in the root of the repository. 4. Test Code ----------- diff --git a/pyproject.toml b/pyproject.toml index 21db4ba2..3889ba43 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,8 +49,9 @@ documentation = "https://pastas.readthedocs.io" solvers = ["lmfit >= 1.0.0", "emcee >= 3.0"] latexify = ["latexify-py"] full = ["pastas[latexify,solvers]"] -formatting = ["isort", "black[jupyter]"] -linting = ["flake8"] +ruffing = ["ruff"] +formatting = ["pastas[ruffing]"] +linting = ["pastas[ruffing]"] pytesting = ["pytest>=7", "pytest-cov", "pytest-sugar"] ci = [ "pastas[pytesting,solvers]", @@ -74,7 +75,7 @@ rtd = [ "sphinx-design", "myst_nb", ] -dev = ["tox", "pastas[formatting,linting,ci,rtd]"] +dev = ["tox", "pre-commit", "pastas[ruffing,ci,rtd]"] numbascipy = ["numba-scipy >= 0.3.1"] [tool.setuptools.dynamic] @@ -94,7 +95,7 @@ markers = ["notebooks: run notebooks", "bnotebooks: run benchmark notebooks"] legacy_tox_ini = """ [tox] requires = tox>=4 - env_list = format, lint, notebooks, py{39,310,311,312} + env_list = ruff, notebooks, py{39,310,311,312} [testenv] description = run unit tests @@ -115,20 +116,19 @@ legacy_tox_ini = """ commands = pytest tests -m "bnotebooks" - [testenv:format] - description = run formatters - basepython = python3.9 - extras = formatting + [testenv:ruff] + description = run ruff checks + basepython = python3.10 + extras = ruffing commands = - black pastas --check --diff - isort pastas --check --diff --profile=black + ruff check --preview + ruff format --check --preview - [testenv:lint] - description = run linters - basepython = python3.9 - extras = linting + [testenv:ruff_fix] + description = run ruff locally and fix issues + extras = ruffing commands = - flake8 pastas --count --show-source --exit-zero --max-line-length=88 --ignore=E203,W503,W504 - flake8 pastas --count --exit-zero --max-line-length=88 --statistics --ignore=E203,W503,W504 + ruff check --extend-select I --fix + ruff format """ From d32f43745c6ab604ea0d90ea938b89f2dd65b2ad Mon Sep 17 00:00:00 2001 From: Martin Vonk Date: Thu, 23 May 2024 15:18:30 +0200 Subject: [PATCH 09/15] ruff formatting --- pastas/objective_functions.py | 4 ++-- pastas/plotting/modelcompare.py | 3 +-- pastas/plotting/plotly.py | 5 ++--- pastas/plotting/plotutil.py | 3 +-- pastas/stats/tests.py | 4 +--- 5 files changed, 7 insertions(+), 12 deletions(-) diff --git a/pastas/objective_functions.py b/pastas/objective_functions.py index 5bdcb9fa..d33e64f1 100644 --- a/pastas/objective_functions.py +++ b/pastas/objective_functions.py @@ -1,5 +1,5 @@ -"""This module contains the objective functions that can be used with the pastas -`EmceeSolve` solver. +"""This module contains the objective functions that can be used with the pastas +`EmceeSolve` solver. """ diff --git a/pastas/plotting/modelcompare.py b/pastas/plotting/modelcompare.py index 17ae7168..bc5e8dba 100644 --- a/pastas/plotting/modelcompare.py +++ b/pastas/plotting/modelcompare.py @@ -1,5 +1,4 @@ -"""This module contains tools for visually comparing multiple models. -""" +"""This module contains tools for visually comparing multiple models.""" from itertools import combinations from logging import getLogger diff --git a/pastas/plotting/plotly.py b/pastas/plotting/plotly.py index 376cb092..a77a3495 100644 --- a/pastas/plotting/plotly.py +++ b/pastas/plotting/plotly.py @@ -1,5 +1,4 @@ -"""This module contains interactive plots for Pastas models. -""" +"""This module contains interactive plots for Pastas models.""" import numpy as np import pandas as pd @@ -598,7 +597,7 @@ def diagnostics(self): ) # normality - counts, bins = np.histogram(series.values, bins=50) + _, bins = np.histogram(series.values, bins=50) bins = 0.5 * (bins[:-1] + bins[1:]) fig.add_trace( go.Histogram( diff --git a/pastas/plotting/plotutil.py b/pastas/plotting/plotutil.py index be03e7ba..e42e29e3 100644 --- a/pastas/plotting/plotutil.py +++ b/pastas/plotting/plotutil.py @@ -1,5 +1,4 @@ -"""This module contains utility functions for plotting. -""" +"""This module contains utility functions for plotting.""" from typing import List, Union diff --git a/pastas/stats/tests.py b/pastas/stats/tests.py index 06ed82ad..3168acd3 100644 --- a/pastas/stats/tests.py +++ b/pastas/stats/tests.py @@ -1,6 +1,4 @@ -"""The following methods may be used for the diagnostic checking of the residual time series of a calibrated (Pastas) model. - -""" +"""The following methods may be used for the diagnostic checking of the residual time series of a calibrated (Pastas) model.""" from logging import getLogger From 609cc322137888b82f3d2158b6a70ac41591c073 Mon Sep 17 00:00:00 2001 From: Martin Vonk Date: Thu, 23 May 2024 15:25:00 +0200 Subject: [PATCH 10/15] remove --preview --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 3889ba43..8848013f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -122,7 +122,7 @@ legacy_tox_ini = """ extras = ruffing commands = ruff check --preview - ruff format --check --preview + ruff format --check [testenv:ruff_fix] description = run ruff locally and fix issues From 822a1160cb5487988c2128022aec225447a30e60 Mon Sep 17 00:00:00 2001 From: Martin Vonk Date: Thu, 23 May 2024 15:27:00 +0200 Subject: [PATCH 11/15] check imports sorting/formatting --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 8848013f..b5cfd109 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -121,7 +121,7 @@ legacy_tox_ini = """ basepython = python3.10 extras = ruffing commands = - ruff check --preview + ruff check --extend-select I --preview ruff format --check [testenv:ruff_fix] From 21e724c8cb92235e6ad60ed680adb89051edc93e Mon Sep 17 00:00:00 2001 From: Martin Vonk Date: Thu, 23 May 2024 15:38:41 +0200 Subject: [PATCH 12/15] rename unit tests ci --- .github/workflows/{ci.yml => test_unit_pytest.yml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename .github/workflows/{ci.yml => test_unit_pytest.yml} (99%) diff --git a/.github/workflows/ci.yml b/.github/workflows/test_unit_pytest.yml similarity index 99% rename from .github/workflows/ci.yml rename to .github/workflows/test_unit_pytest.yml index bb99516b..d0d9846b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/test_unit_pytest.yml @@ -1,4 +1,4 @@ -name: CI +name: CI PYTEST on: push: From 170f2b8bba432df421547b22ba32ff5f36598ff2 Mon Sep 17 00:00:00 2001 From: Martin Vonk Date: Thu, 23 May 2024 16:34:03 +0200 Subject: [PATCH 13/15] fix signatures helper function --- pastas/stats/signatures.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pastas/stats/signatures.py b/pastas/stats/signatures.py index f3c15fe5..f5de7739 100644 --- a/pastas/stats/signatures.py +++ b/pastas/stats/signatures.py @@ -1278,7 +1278,7 @@ def recession_constant( return nan # Fit an exponential model to the binned data and return the decay constant - def f(t, p): + def f(t, *p): return -p[0] * (1 - exp(-t / p[1])) popt, _ = curve_fit( @@ -1351,7 +1351,7 @@ def recovery_constant( return nan # Fit an exponential model to the binned data and return the decay constant - def f(t, p): + def f(t, *p): return -p[0] * (1 - exp(-t / p[1])) popt, _ = curve_fit( From 0ba2ce3fc87893c9b0095f51afc99e6322ff99c8 Mon Sep 17 00:00:00 2001 From: Martin Vonk Date: Fri, 24 May 2024 14:25:46 +0200 Subject: [PATCH 14/15] add logger debug to bare excepts --- pastas/io/pas.py | 4 ++-- pastas/model.py | 2 +- pastas/timeseries_utils.py | 5 +++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pastas/io/pas.py b/pastas/io/pas.py index 7509adfd..965071b1 100644 --- a/pastas/io/pas.py +++ b/pastas/io/pas.py @@ -48,7 +48,7 @@ def pastas_hook(obj: dict): try: obj[key] = read_json(stringIO(value), typ="series", orient="split") except Exception as e: - logger.error(e) + logger.debug(e) obj[key] = value if isinstance(obj[key], Series): obj[key].index = obj[key].index.tz_localize(None) @@ -66,7 +66,7 @@ def pastas_hook(obj: dict): try: obj[key] = json.loads(value, object_hook=pastas_hook) except Exception as e: - logger.error(e) + logger.debug(e) obj[key] = value return obj diff --git a/pastas/model.py b/pastas/model.py index 9c1c33b1..87f87ea3 100644 --- a/pastas/model.py +++ b/pastas/model.py @@ -1819,7 +1819,7 @@ def _get_file_info(self) -> dict: try: file_info["owner"] = getlogin() except Exception as e: - logger.error(e) + logger.debug(e) file_info["owner"] = "Unknown" return file_info diff --git a/pastas/timeseries_utils.py b/pastas/timeseries_utils.py index 3a9c9703..113b03cd 100644 --- a/pastas/timeseries_utils.py +++ b/pastas/timeseries_utils.py @@ -56,7 +56,8 @@ def _frequency_is_supported(freq: str) -> str: Timedelta(offset) except Exception as e: msg = "Frequency %s not supported." - logger.error(msg, freq, e) + logger.error(msg, freq) + logger.debug(e) raise ValueError(msg % freq) if offset.n == 1: freq = offset.name @@ -91,7 +92,7 @@ def _get_stress_dt(freq: str) -> float: try: dt = Timedelta(offset) / Timedelta(1, "D") except Exception as e: - logging.error(e) + logging.debug(e) num = offset.n freq = offset._prefix if freq in ["A", "Y", "AS", "YS", "YE", "BA", "BY", "BAS", "BYS"]: From ec4e3be85d3ec2d1d6bfebfea1dc2c850ea5f3e3 Mon Sep 17 00:00:00 2001 From: Martin Vonk Date: Fri, 31 May 2024 09:54:49 +0200 Subject: [PATCH 15/15] fix pastas/dataset.py:139:13: F541 [*] f-string without any placeholders --- pastas/dataset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pastas/dataset.py b/pastas/dataset.py index ec8b68b8..9ba9e216 100644 --- a/pastas/dataset.py +++ b/pastas/dataset.py @@ -136,6 +136,6 @@ def list_datasets(silent: bool = True) -> List[str]: for folder in data: print(f" - {folder}") print( - f"Use ps.load_dataset('folder_name') to load a dataset from the repository." + "Use ps.load_dataset('folder_name') to load a dataset from the repository." ) return data