diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 770e7a2..f964f5b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,17 +1,20 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2023 Benjamin Thomas Schwertfeger +# GitHub: https://github.com/btschwertfeger +# + repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.4.9 + rev: v0.7.0 hooks: - id: ruff - args: [--fix] + args: + - --fix + - --preview + - --exit-non-zero-on-fix - id: ruff-format - - repo: https://github.com/pycqa/flake8 - rev: 7.1.0 - hooks: - - id: flake8 - args: ["--select=E9,F63,F7,F82", "--show-source", "--statistics"] # - repo: https://github.com/pre-commit/mirrors-mypy # FIXME - # rev: v1.8.0 + # rev: v1.13.0 # hooks: # - id: mypy # name: mypy @@ -23,14 +26,14 @@ repos: rev: v2.3.0 hooks: - id: codespell - additional_dependencies: - - tomli + additional_dependencies: [tomli] - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.6.0 hooks: # all available hooks can be found here: https://github.com/pre-commit/pre-commit-hooks/blob/main/.pre-commit-hooks.yaml - id: check-yaml - id: check-ast + - id: check-json - id: check-toml - id: check-docstring-first - id: check-case-conflict @@ -53,26 +56,32 @@ repos: rev: v1.10.0 hooks: - id: python-use-type-annotations + - id: python-check-blanket-noqa + - id: python-check-blanket-type-ignore + - id: python-check-mock-methods + - id: rst-backticks + - id: python-no-eval + - id: python-no-log-warn - id: rst-backticks - # - id: rst-inline-touching-normal + - id: rst-inline-touching-normal - id: rst-directive-colons - id: text-unicode-replacement-char - # - repo: https://github.com/psf/black - # rev: 24.2.0 - # hooks: - # - id: black - # - repo: https://github.com/adamchainz/blacken-docs - # rev: 1.16.0 - # hooks: - # - id: blacken-docs - # additional_dependencies: [black==23.12.0] - repo: https://github.com/PyCQA/isort # TODO: remove as soon as ruff is stable rev: 5.13.2 hooks: - id: isort - args: ["--profile=black"] # solves conflicts between black and isort - - repo: https://github.com/pre-commit/mirrors-prettier - rev: v3.0.2 + args: [--profile=black] + - repo: https://github.com/PyCQA/bandit + rev: 1.7.10 + hooks: + - id: bandit + exclude: "^tests/.*|examples/.*" + - repo: https://github.com/yunojuno/pre-commit-xenon + rev: v0.1 hooks: - - id: prettier + - id: xenon + args: + - --max-average=B + - --max-modules=B + - --max-absolute=C exclude: '\.nc$|^tests/fixture/|\.ipynb$' diff --git a/README.md b/README.md index 391200d..979bbe0 100644 --- a/README.md +++ b/README.md @@ -293,11 +293,13 @@ Notes: - First check if there is an existing issue or PR that addresses your problem/solution. If not - create one first - before creating a PR. -- Typo fixes, project configuration, CI, documentation or style/formatting PRs will be - rejected. Please create an issue for that. +- Typo fixes, project configuration, CI, documentation or style/formatting PRs + will be rejected. Please create an issue for that. - PRs must provide a reasonable, easy to understand and maintain solution for an existing problem. You may want to propose a solution when creating the issue to discuss the approach before creating a PR. +- There is currently no need for the implementation of further bias correction + methods. diff --git a/cmethods/__init__.py b/cmethods/__init__.py index 8f8e60d..eec4f34 100644 --- a/cmethods/__init__.py +++ b/cmethods/__init__.py @@ -53,7 +53,7 @@ def print_version( """Prints the version of the package""" if not value or ctx.resilient_parsing: return - from importlib.metadata import version + from importlib.metadata import version # noqa: PLC0415 echo(version("python-cmethods")) ctx.exit() diff --git a/cmethods/core.py b/cmethods/core.py index a08c4a9..8364f33 100644 --- a/cmethods/core.py +++ b/cmethods/core.py @@ -144,7 +144,7 @@ def adjust( # to unrealistic monthly transitions. If such behavior is wanted, # mock this function or apply ``CMethods.__apply_ufunc` directly # on your data sets. - if kwargs.get("group", None) is None: + if kwargs.get("group") is None: return apply_ufunc(method, obs, simh, simp, **kwargs).to_dataset() if method not in SCALING_METHODS: diff --git a/cmethods/distribution.py b/cmethods/distribution.py index e76c174..2f2772c 100644 --- a/cmethods/distribution.py +++ b/cmethods/distribution.py @@ -42,7 +42,7 @@ def quantile_mapping( """ check_adjust_called( function_name="quantile_mapping", - adjust_called=kwargs.get("adjust_called", None), + adjust_called=kwargs.get("adjust_called"), ) check_np_types(obs=obs, simh=simh, simp=simp) @@ -73,7 +73,7 @@ def quantile_mapping( xbins, cdf_simh, left=kwargs.get("val_min", 0.0), - right=kwargs.get("val_max", None), + right=kwargs.get("val_max"), ) return get_inverse_of_cdf(cdf_obs, epsilon, xbins) # Eq. 2 @@ -157,7 +157,7 @@ def detrended_quantile_mapping( xbins, cdf_simh, left=kwargs.get("val_min", 0.0), - right=kwargs.get("val_max", None), + right=kwargs.get("val_max"), ) X = np.interp(epsilon, cdf_obs, xbins) * ensure_dividable( m_simp_mean, @@ -205,7 +205,7 @@ def quantile_delta_mapping( """ check_adjust_called( function_name="quantile_delta_mapping", - adjust_called=kwargs.get("adjust_called", None), + adjust_called=kwargs.get("adjust_called"), ) check_np_types(obs=obs, simh=simh, simp=simp) diff --git a/cmethods/scaling.py b/cmethods/scaling.py index d80e78e..e01c7b3 100644 --- a/cmethods/scaling.py +++ b/cmethods/scaling.py @@ -43,7 +43,7 @@ def linear_scaling( """ check_adjust_called( function_name="linear_scaling", - adjust_called=kwargs.get("adjust_called", None), + adjust_called=kwargs.get("adjust_called"), ) check_np_types(obs=obs, simh=simh, simp=simp) @@ -85,7 +85,7 @@ def variance_scaling( """ check_adjust_called( function_name="variance_scaling", - adjust_called=kwargs.get("adjust_called", None), + adjust_called=kwargs.get("adjust_called"), ) check_np_types(obs=obs, simh=simp, simp=simp) @@ -130,7 +130,7 @@ def delta_method( """ check_adjust_called( function_name="delta_method", - adjust_called=kwargs.get("adjust_called", None), + adjust_called=kwargs.get("adjust_called"), ) check_np_types(obs=obs, simh=simh, simp=simp) diff --git a/cmethods/utils.py b/cmethods/utils.py index fdca6c8..8e861e6 100644 --- a/cmethods/utils.py +++ b/cmethods/utils.py @@ -32,7 +32,7 @@ def __init__(self: UnknownMethodError, method: str, available_methods: list): def check_adjust_called( function_name: str, - adjust_called: Optional[bool] = None, + adjust_called: Optional[bool] = None, # noqa: FBT001 ) -> None: """ Displays a user warning in case a correction function was not called via diff --git a/doc/conf.py b/doc/conf.py index 58bbc0f..0ca2c85 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -11,7 +11,9 @@ """This module is the configuration for the Sphinx documentation building process""" import sys +from os.path import join from pathlib import Path +from shutil import copyfile project = "python-cmethods" copyright = "2023, Benjamin Thomas Schwertfeger" # pylint: disable=redefined-builtin @@ -29,9 +31,6 @@ def setup(app) -> None: # noqa: ARG001 - from os.path import join - from shutil import copyfile - copyfile(join("..", "examples", "examples.ipynb"), "examples.ipynb") diff --git a/doc/methods.rst b/doc/methods.rst index 06e19d0..2501f90 100644 --- a/doc/methods.rst +++ b/doc/methods.rst @@ -92,7 +92,7 @@ where: >>> variable = "tas" # temperatures >>> result = adjust( ... method="linear_scaling", - ... obs=obs[variable], + ... obs=obsh[variable], ... simh=simh[variable], ... simp=simp[variable], ... kind="+", @@ -173,7 +173,7 @@ enables the adjustment of the standard deviation in the following step. >>> variable = "tas" # temperatures >>> result = adjust( ... method="variance_scaling", - ... obs=obs[variable], + ... obs=obsh[variable], ... simh=simh[variable], ... simp=simp[variable], ... kind="+", @@ -257,7 +257,7 @@ where: >>> variable = "tas" # temperatures >>> result = adjust( ... method="delta_method", - ... obs=obs[variable], + ... obs=obsh[variable], ... simh=simh[variable], ... simp=simp[variable], ... kind="+", @@ -340,7 +340,7 @@ In the following the equations of Alex J. Cannon (2015) are shown and explained: >>> variable = "tas" # temperatures >>> qm_adjusted = adjust( ... method="quantile_mapping", - ... obs=obs[variable], + ... obs=obsh[variable], ... simh=simh[variable], ... simp=simp[variable], ... n_quantiles=250, @@ -417,7 +417,7 @@ where: >>> simp = xr.open_dataset("path/to/the_dataset_to_adjust-scenario_period.nc") >>> variable = "tas" # temperatures >>> qm_adjusted = detrended_quantile_mapping( - ... obs=obs[variable], + ... obs=obsh[variable], ... simh=simh[variable], ... simp=simp[variable], ... n_quantiles=250 @@ -520,7 +520,7 @@ following the additive and multiplicative variant are shown. >>> variable = "tas" # temperatures >>> qdm_adjusted = adjust( ... method="quantile_delta_mapping", - ... obs=obs[variable], + ... obs=obsh[variable], ... simh=simh[variable], ... simp=simp[variable], ... n_quantiles=250, diff --git a/pyproject.toml b/pyproject.toml index 97c3dce..9e04e85 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -250,8 +250,11 @@ cache-dir = ".cache/ruff" lint.task-tags = ["todo", "TODO"] [tool.ruff.lint.per-file-ignores] +"cmethods/types.py" = [ + "A005", # Shadowing builtin +] "doc/*.py" = [ - "CPY001", # Missing copyright notice at top of file + # "CPY001", # Missing copyright notice at top of file "PTH118", # `os.path.join()` should be replaced by `Path` with `/` operator, "PTH123", # `open()` should be replaced by `Path.open()` "PTH100", # `os.path.abspath()` should be replaced by `Path.resolve()` diff --git a/tests/conftest.py b/tests/conftest.py index 0289705..639dada 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -22,7 +22,7 @@ FIXTURE_DIR: str = os.path.join(os.path.dirname(__file__), "fixture") -@pytest.fixture() +@pytest.fixture def cli_runner() -> CliRunner: """Provide a cli-runner for testing the CLI""" return CliRunner() @@ -43,7 +43,7 @@ def dask_cluster() -> Any: client.close() -@pytest.fixture() +@pytest.fixture def datasets() -> dict: obsh_add, obsp_add, simh_add, simp_add = get_datasets(kind="+") obsh_mult, obsp_mult, simh_mult, simp_mult = get_datasets(kind="*") @@ -65,7 +65,7 @@ def datasets() -> dict: @lru_cache(maxsize=None) -@pytest.fixture() +@pytest.fixture def datasets_from_zarr() -> dict: return { "+": {