Skip to content

Commit 74fa014

Browse files
committed
Update pre-commit and ci configuration
1 parent ceea222 commit 74fa014

File tree

17 files changed

+155
-259
lines changed

17 files changed

+155
-259
lines changed

.github/workflows/ci.yml

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,29 @@ on:
44
# Trigger the workflow on push to master or develop, except tag creation
55
push:
66
branches:
7-
- 'main'
8-
- 'develop'
7+
- "main"
8+
- "develop"
99
tags-ignore:
10-
- '**'
10+
- "**"
11+
paths-ignore:
12+
- "docs/**"
13+
- "README.md"
1114

1215
# Trigger the workflow on pull request
1316
pull_request:
17+
paths-ignore:
18+
- "docs/**"
19+
- "README.md"
1420

1521
# Trigger the workflow manually
1622
workflow_dispatch:
1723

1824
# Trigger after public PR approved for CI
1925
pull_request_target:
2026
types: [labeled]
27+
paths-ignore:
28+
- "docs/**"
29+
- "README.md"
2130

2231
jobs:
2332
# Run CI including downstream packages on self-hosted runners
@@ -28,10 +37,9 @@ jobs:
2837
with:
2938
earthkit-meteo: ecmwf/earthkit-meteo@${{ github.event.pull_request.head.sha || github.sha }}
3039
codecov_upload: true
31-
python_qa: true
40+
python_qa: false
3241
secrets: inherit
3342

34-
3543
# Build downstream packages on HPC
3644
downstream-ci-hpc:
3745
name: downstream-ci-hpc

.github/workflows/legacy-ci.yml

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,6 @@ defaults:
2424
shell: bash -l {0}
2525

2626
jobs:
27-
pre-commit:
28-
if: ${{ !github.event.pull_request.head.repo.fork && github.event.action != 'labeled' || github.event.label.name == 'approved-for-ci' }}
29-
runs-on: ubuntu-latest
30-
steps:
31-
- uses: actions/checkout@v3
32-
with:
33-
ref: ${{ github.event.pull_request.head.sha || github.ref }}
34-
- uses: actions/setup-python@v4
35-
with:
36-
python-version: 3.x
37-
- uses: pre-commit/action@v3.0.0
38-
3927
documentation:
4028
if: ${{ !github.event.pull_request.head.repo.fork && github.event.action != 'labeled' || github.event.label.name == 'approved-for-ci' }}
4129
runs-on: ubuntu-latest
@@ -48,7 +36,7 @@ jobs:
4836
with:
4937
ref: ${{ github.event.pull_request.head.sha || github.ref }}
5038
- name: Install Conda environment with Micromamba
51-
uses: mamba-org/provision-with-micromamba@v12
39+
uses: mamba-org/setup-micromamba@v1
5240
with:
5341
environment-file: tests/environment-unit-tests.yml
5442
environment-name: DEVELOP
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
name: Code Quality checks for PRs
2+
3+
on:
4+
push:
5+
pull_request:
6+
types: [opened, synchronize, reopened]
7+
8+
jobs:
9+
quality:
10+
uses: ecmwf-actions/reusable-workflows/.github/workflows/qa-precommit-run.yml@v2
11+
with:
12+
skip-hooks: "no-commit-to-branch"

.pre-commit-config.yaml

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,48 @@
11
repos:
22
- repo: https://github.com/pre-commit/pre-commit-hooks
3-
rev: v4.4.0
3+
rev: v5.0.0
44
hooks:
5-
- id: trailing-whitespace
6-
- id: end-of-file-fixer
5+
- id: trailing-whitespace # Trailing whitespace checker
6+
- id: end-of-file-fixer # Ensure files end in a newline
77
- id: check-json
8-
- id: check-yaml
8+
- id: check-yaml # Check YAML files for syntax errors only
9+
args: [--unsafe, --allow-multiple-documents]
910
- id: check-toml
10-
# - id: check-added-large-files
11-
- id: debug-statements
11+
# - id: check-added-large-files
12+
- id: debug-statements # Check for debugger imports and py37+ breakpoint()
1213
- id: mixed-line-ending
14+
- id: no-commit-to-branch # Prevent committing to main / master
15+
- id: check-merge-conflict # Check for files that contain merge conflict
16+
exclude: /README\.rst$|^docs/.*\.rst$
1317
- repo: https://github.com/PyCQA/isort
14-
rev: 5.12.0
18+
rev: 5.13.2
1519
hooks:
1620
- id: isort
21+
args:
22+
- -l 110
23+
- --force-single-line-imports
24+
- --profile black
1725
- repo: https://github.com/psf/black
18-
rev: 23.9.1
26+
rev: 24.8.0
1927
hooks:
2028
- id: black
29+
args: [--line-length=110]
2130
- repo: https://github.com/keewis/blackdoc
2231
rev: v0.3.8
2332
hooks:
2433
- id: blackdoc
2534
additional_dependencies: [black==23.3.0]
26-
- repo: https://github.com/PyCQA/flake8
27-
rev: 6.1.0
28-
hooks:
29-
- id: flake8
35+
exclude: xr_engine_profile_rst\.py
36+
- repo: https://github.com/astral-sh/ruff-pre-commit
37+
rev: v0.6.9
38+
hooks:
39+
- id: ruff
40+
exclude: '(dev/.*|.*_)\.py$'
41+
args:
42+
- --line-length=110
43+
- --fix
44+
- --exit-non-zero-on-fix
45+
- --preview
3046
- repo: https://github.com/executablebooks/mdformat
3147
rev: 0.7.14
3248
hooks:
@@ -37,11 +53,11 @@ repos:
3753
hooks:
3854
- id: pretty-format-yaml
3955
args: [--autofix, --preserve-quotes]
40-
- id: pretty-format-toml
41-
args: [--autofix]
42-
- repo: https://github.com/PyCQA/pydocstyle.git
43-
rev: 6.1.1
44-
hooks:
45-
- id: pydocstyle
46-
additional_dependencies: [toml]
47-
exclude: tests|docs
56+
- repo: https://github.com/sphinx-contrib/sphinx-lint
57+
rev: v1.0.0
58+
hooks:
59+
- id: sphinx-lint
60+
- repo: https://github.com/tox-dev/pyproject-fmt
61+
rev: "2.2.4"
62+
hooks:
63+
- id: pyproject-fmt

pyproject.toml

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,56 @@
11
[build-system]
2-
requires = ["setuptools>=61", "setuptools-scm>=8.0"]
2+
requires = [ "setuptools>=61", "setuptools-scm>=8" ]
33

44
[project]
5+
name = "earthkit-meteo"
6+
description = "Meteorological computations"
7+
readme = "README.md"
8+
license = { text = "Apache License Version 2.0" }
59
authors = [
6-
{name = "European Centre for Medium-Range Weather Forecasts (ECMWF)", email = "software.support@ecmwf.int"}
10+
{ name = "European Centre for Medium-Range Weather Forecasts (ECMWF)", email = "software.support@ecmwf.int" },
711
]
12+
requires-python = ">=3.8"
13+
814
classifiers = [
915
"Development Status :: 2 - Pre-Alpha",
1016
"Intended Audience :: Developers",
1117
"License :: OSI Approved :: Apache Software License",
12-
"Programming Language :: Python :: 3",
18+
"Operating System :: OS Independent",
19+
"Programming Language :: Python :: 3 :: Only",
1320
"Programming Language :: Python :: 3.8",
1421
"Programming Language :: Python :: 3.9",
1522
"Programming Language :: Python :: 3.10",
1623
"Programming Language :: Python :: 3.11",
24+
"Programming Language :: Python :: 3.12",
1725
"Programming Language :: Python :: Implementation :: CPython",
1826
"Programming Language :: Python :: Implementation :: PyPy",
19-
"Operating System :: OS Independent"
2027
]
28+
dynamic = [ "version" ]
2129
dependencies = [
22-
"numpy"
30+
"numpy",
2331
]
24-
description = "Meteorological computations"
25-
dynamic = ["version"]
26-
license = {text = "Apache License Version 2.0"}
27-
name = "earthkit-meteo"
28-
readme = "README.md"
29-
requires-python = ">= 3.8"
30-
31-
[project.optional-dependencies]
32-
test = [
32+
optional-dependencies.test = [
3333
"pytest",
34-
"pytest-cov"
34+
"pytest-cov",
3535
]
36+
urls.Documentation = "https://earthkit-meteo.readthedocs.io/"
37+
urls.Homepage = "https://github.com/ecmwf/earthkit-meteo/"
38+
urls.Issues = "https://github.com/ecmwf/earthkit-meteo.issues"
39+
urls.Repository = "https://github.com/ecmwf/earthkit-meteo/"
3640

37-
[project.urls]
38-
Documentation = "https://earthkit-meteo.readthedocs.io/"
39-
Homepage = "https://github.com/ecmwf/earthkit-meteo/"
40-
Issues = "https://github.com/ecmwf/earthkit-meteo.issues"
41-
Repository = "https://github.com/ecmwf/earthkit-meteo/"
41+
[tool.setuptools.packages.find]
42+
include = [ "earthkit.meteo" ]
43+
where = [ "src/" ]
4244

43-
[tool.coverage.run]
44-
branch = "true"
45+
[tool.setuptools_scm]
46+
version_file = "src/earthkit/meteo/_version.py"
4547

4648
[tool.isort]
4749
profile = "black"
4850

51+
[tool.coverage.run]
52+
branch = "true"
53+
4954
[tool.pydocstyle]
50-
add_ignore = ["D1", "D200", "D205", "D400", "D401"]
55+
add_ignore = [ "D1", "D200", "D205", "D400", "D401" ]
5156
convention = "numpy"
52-
53-
[tool.setuptools.packages.find]
54-
include = ["earthkit.meteo"]
55-
where = ["src/"]
56-
57-
[tool.setuptools_scm]
58-
version_file = "src/earthkit/meteo/_version.py"

src/earthkit/meteo/extreme/array/cpf.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,9 @@ def cpf(clim, ens, sort_clim=True, sort_ens=True):
6464
idx = (qv_f < qv_c) & (qv_c_2 < qv_c)
6565

6666
# intersection between two lines
67-
tau_i = (
68-
tau_c * (qv_c_2[idx] - qv_f[idx])
69-
+ tau_c_2 * (qv_f[idx] - qv_c[idx])
70-
) / (qv_c_2[idx] - qv_c[idx])
67+
tau_i = (tau_c * (qv_c_2[idx] - qv_f[idx]) + tau_c_2 * (qv_f[idx] - qv_c[idx])) / (
68+
qv_c_2[idx] - qv_c[idx]
69+
)
7170

7271
# populate matrix, no values below 0
7372
cpf[idx] = np.maximum(tau_i, 0)
@@ -85,10 +84,9 @@ def cpf(clim, ens, sort_clim=True, sort_ens=True):
8584

8685
idx = (qv_f > qv_c) & (qv_c_2 > qv_c) & (~mask)
8786

88-
tau_i = (
89-
tau_c * (qv_c_2[idx] - qv_f[idx])
90-
+ tau_c_2 * (qv_f[idx] - qv_c[idx])
91-
) / (qv_c_2[idx] - qv_c[idx])
87+
tau_i = (tau_c * (qv_c_2[idx] - qv_f[idx]) + tau_c_2 * (qv_f[idx] - qv_c[idx])) / (
88+
qv_c_2[idx] - qv_c[idx]
89+
)
9290

9391
# populate matrix, no values above 1
9492
cpf[idx] = np.minimum(tau_i, 1)

src/earthkit/meteo/extreme/array/efi.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,7 @@ def efi(clim, ens, eps=-0.1):
3131
EFI values
3232
"""
3333
# locate missing values
34-
missing_mask = np.logical_or(
35-
np.sum(np.isnan(clim), axis=0), np.sum(np.isnan(ens), axis=0)
36-
)
34+
missing_mask = np.logical_or(np.sum(np.isnan(clim), axis=0), np.sum(np.isnan(ens), axis=0))
3735

3836
# Compute fraction of the forecast below climatology
3937
nclim, npoints = clim.shape
@@ -65,9 +63,7 @@ def efi(clim, ens, eps=-0.1):
6563
mask = clim[icl + 1, :] > eps
6664
dEFI = np.where(
6765
mask,
68-
(2.0 * frac[icl, :] - 1.0) * acosdiff[icl]
69-
+ acoef[icl] * dFdp[icl, :]
70-
- proddiff[icl],
66+
(2.0 * frac[icl, :] - 1.0) * acosdiff[icl] + acoef[icl] * dFdp[icl, :] - proddiff[icl],
7167
0.0,
7268
)
7369
defimax = np.where(mask, -acosdiff[icl] - proddiff[icl], 0.0)
@@ -77,11 +73,7 @@ def efi(clim, ens, eps=-0.1):
7773
efi /= efimax
7874
else:
7975
for icl in range(nclim - 1):
80-
dEFI = (
81-
(2.0 * frac[icl, :] - 1.0) * acosdiff[icl]
82-
+ acoef[icl] * dFdp[icl, :]
83-
- proddiff[icl]
84-
)
76+
dEFI = (2.0 * frac[icl, :] - 1.0) * acosdiff[icl] + acoef[icl] * dFdp[icl, :] - proddiff[icl]
8577
efi += dEFI
8678
efi *= 2.0 / np.pi
8779
##################################

src/earthkit/meteo/extreme/array/sot.py

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@ def sot_func(qc_tail, qc, qf, eps=-1e-4, lower_bound=-10, upper_bound=10):
3939
err = np.seterr(divide="ignore", invalid="ignore")
4040

4141
min_den = np.fmax(eps, 0)
42-
sot = np.where(
43-
np.fabs(qc_tail - qc) > min_den, (qf - qc_tail) / (qc_tail - qc), np.nan
44-
)
42+
sot = np.where(np.fabs(qc_tail - qc) > min_den, (qf - qc_tail) / (qc_tail - qc), np.nan)
4543

4644
# revert to original error state
4745
np.seterr(**err)
@@ -78,20 +76,12 @@ def sot(clim, ens, perc, eps=-1e4):
7876
numpy array (npoints)
7977
SOT values
8078
"""
81-
if not (isinstance(perc, int) or isinstance(perc, np.int64)) or (
82-
perc < 2 or perc > 98
83-
):
84-
raise Exception(
85-
"Percentile value should be and Integer between 2 and 98, is {}".format(
86-
perc
87-
)
88-
)
79+
if not (isinstance(perc, int) or isinstance(perc, np.int64)) or (perc < 2 or perc > 98):
80+
raise Exception("Percentile value should be and Integer between 2 and 98, is {}".format(perc))
8981

9082
if clim.shape[0] != 101:
9183
raise Exception(
92-
"Climatology array should contain 101 percentiles, it has {} values".format(
93-
clim.shape
94-
)
84+
"Climatology array should contain 101 percentiles, it has {} values".format(clim.shape)
9585
)
9686

9787
qc = clim[perc]
@@ -136,20 +126,12 @@ def sot_unsorted(clim, ens, perc, eps=-1e4):
136126
numpy array (npoints)
137127
SOT values
138128
"""
139-
if not (isinstance(perc, int) or isinstance(perc, np.int64)) or (
140-
perc < 2 or perc > 98
141-
):
142-
raise Exception(
143-
"Percentile value should be and Integer between 2 and 98, is {}".format(
144-
perc
145-
)
146-
)
129+
if not (isinstance(perc, int) or isinstance(perc, np.int64)) or (perc < 2 or perc > 98):
130+
raise Exception("Percentile value should be and Integer between 2 and 98, is {}".format(perc))
147131

148132
if clim.shape[0] != 101:
149133
raise Exception(
150-
"Climatology array should contain 101 percentiles, it has {} values".format(
151-
clim.shape
152-
)
134+
"Climatology array should contain 101 percentiles, it has {} values".format(clim.shape)
153135
)
154136

155137
if eps > 0:

src/earthkit/meteo/score/array/crps.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,7 @@ def crps(x, y):
4848
alpha[-1] = np.fmax(-diffxy[-1], 0) # y-x(n)
4949
beta[-1] = 0
5050
# else
51-
alpha[1:-1] = np.fmin(
52-
diffxx, np.fmax(-diffxy[:-1], 0)
53-
) # x(i+1)-x(i) or y-x(i) or 0
51+
alpha[1:-1] = np.fmin(diffxx, np.fmax(-diffxy[:-1], 0)) # x(i+1)-x(i) or y-x(i) or 0
5452
beta[1:-1] = np.fmin(diffxx, np.fmax(diffxy[1:], 0)) # 0 or x(i+1)-y or x(i+1)-x(i)
5553

5654
# compute crps

0 commit comments

Comments
 (0)