Skip to content

Commit

Permalink
Update pyproject.toml and .pre-commit-config.yaml for common SciTools…
Browse files Browse the repository at this point in the history
… standards (#435)

* update pyproject.toml and .pre-commit-config.yaml

* update .pre-commit-config.yaml

* add ignores

* update pyproject.toml to SciTools standard

* avoid iris deprecation

* avoid iris deprecation

* avoid warning errors

* fix for repo review

* annotate skipped codes

* repo-review fix

* annotate exclusions

* update comment, remove black from pyproject.toml

* remove flake8

* revised comment

* remove ruff.toml reference

* remove reference to non-existent directory

* fix pre-commit-config.yaml
  • Loading branch information
stephenworsley authored Nov 19, 2024
1 parent af9a69e commit 8096455
Show file tree
Hide file tree
Showing 45 changed files with 573 additions and 475 deletions.
38 changes: 0 additions & 38 deletions .flake8

This file was deleted.

104 changes: 86 additions & 18 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
# See https://pre-commit.ci/#configuration
# See https://github.com/scientific-python/cookie#sp-repo-review

ci:
autofix_prs: false
autoupdate_commit_msg: "chore: update pre-commit hooks"


# Alphabetised, for lack of a better order.
files: |
(?x)(
benchmarks\/.+\.py|
docs\/.+\.py|
esmf_regrid\/.+\.py|
noxfile\.py|
pyproject\.toml|
setup\.py
)
minimum_pre_commit_version: 1.21.0

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: 'v5.0.0'
Expand All @@ -14,22 +34,70 @@ repos:
- id: check-merge-conflict
# Check for debugger imports and py37+ `breakpoint()` calls in Python source.
- id: debug-statements
# Don't commit to master branch.
# Check TOML file syntax.
- id: check-toml
# Check YAML file syntax.
- id: check-yaml
# Makes sure files end in a newline and only a newline.
# Duplicates Ruff W292 but also works on non-Python files.
- id: end-of-file-fixer
# Replaces or checks mixed line ending.
- id: mixed-line-ending
# Don't commit to main branch.
- id: no-commit-to-branch
- repo: https://github.com/psf/black
rev: '24.10.0'
hooks:
- id: black
# Force black to run on whole repo, using settings from pyproject.toml
pass_filenames: false
args: [--config=./pyproject.toml, .]
- repo: https://github.com/PyCQA/flake8
rev: '7.1.1'
hooks:
# Run flake8.
- id: flake8
args: [--config=./.flake8]
additional_dependencies: [
'flake8-docstrings==1.7.0',
'flake8-import-order==0.18.2',
]
# Trims trailing whitespace.
# Duplicates Ruff W291 but also works on non-Python files.
- id: trailing-whitespace

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.4.4"
hooks:
- id: ruff
types: [file, python]
args: [--fix, --show-fixes]
- id: ruff-format
types: [file, python]

- repo: https://github.com/codespell-project/codespell
rev: "v2.2.6"
hooks:
- id: codespell
types_or: [asciidoc, python, markdown, rst]
additional_dependencies: [tomli]

- repo: https://github.com/adamchainz/blacken-docs
rev: 1.16.0
hooks:
- id: blacken-docs
types: [file, rst]

- repo: https://github.com/aio-libs/sort-all
rev: v1.2.0
hooks:
- id: sort-all
types: [file, python]

- repo: https://github.com/pre-commit/mirrors-mypy
rev: 'v1.10.0'
hooks:
- id: mypy
exclude: 'noxfile\.py|docs/src/conf\.py|^benchmarks'

- repo: https://github.com/abravalheri/validate-pyproject
# More exhaustive than Ruff RUF200.
rev: "v0.18"
hooks:
- id: validate-pyproject

- repo: https://github.com/scientific-python/cookie
rev: 2024.04.23
hooks:
- id: sp-repo-review
additional_dependencies: ["repo-review[cli]"]
args: ["--show=errskip"]

- repo: https://github.com/numpy/numpydoc
rev: v1.7.0
hooks:
- id: numpydoc-validation
types: [file, python]
6 changes: 2 additions & 4 deletions benchmarks/asv_delegated_conda.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@


class CondaDelegated(Conda):
"""
Manage a Conda environment using custom user scripts, run at each commit.
"""Manage a Conda environment using custom user scripts, run at each commit.
Ignores user input variations - ``matrix`` / ``pythons`` /
``conda_environment_file``, since environment is being managed outside ASV.
Expand All @@ -36,8 +35,7 @@ def __init__(
requirements: dict,
tagged_env_vars: dict,
) -> None:
"""
Create the instance.
"""Create the instance.
Parameters
----------
Expand Down
10 changes: 3 additions & 7 deletions benchmarks/benchmarks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@


def disable_repeat_between_setup(benchmark_object):
"""
Decorate benchmarks where object persistence would be inappropriate.
"""Decorate benchmarks where object persistence would be inappropriate.
E.g:
* Data is realised during testing.
Expand All @@ -30,8 +29,7 @@ def disable_repeat_between_setup(benchmark_object):


def skip_benchmark(benchmark_object):
"""
Decorate benchmarks to be skipped.
"""Decorate benchmarks to be skipped.
Simply doesn't return the object.
Expand All @@ -43,12 +41,10 @@ def skip_benchmark(benchmark_object):
(e.g. ``def time_something(self):`` ).
"""
pass


def on_demand_benchmark(benchmark_object):
"""
Decorate benchmark(s) that are disabled unless ON_DEMAND_BENCHARKS env var is set.
"""Decorate benchmark(s) that are disabled unless ON_DEMAND_BENCHARKS env var is set.
For benchmarks that, for whatever reason, should not be run by default.
E.g:
Expand Down
1 change: 1 addition & 0 deletions benchmarks/benchmarks/esmf_regridder/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
MeshToGridESMFRegridder,
)
from esmf_regrid.schemes import ESMFAreaWeightedRegridder

from ..generate_data import _curvilinear_cube, _grid_cube, _gridlike_mesh_cube


Expand Down
9 changes: 5 additions & 4 deletions benchmarks/benchmarks/esmf_regridder/scalability.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
MeshToGridESMFRegridder,
)
from esmf_regrid.schemes import ESMFAreaWeightedRegridder

from .. import on_demand_benchmark, skip_benchmark
from ..generate_data import _grid_cube, _gridlike_mesh_cube

Expand Down Expand Up @@ -64,7 +65,7 @@ def time_prepare(self, n):
class PrepareScalabilityMeshToGrid(PrepareScalabilityMixin):
"""Benchmarks for the prepare step of :class:`~esmf_regrid.esmf_regrid.schemes.MeshToGridESMFRegridder`."""

regridder = MeshToGridESMFRegridder
regridder = MeshToGridESMFRegridder # type: ignore[assignment]

def src_cube(self, n):
"""Cube to regrid from."""
Expand Down Expand Up @@ -114,7 +115,7 @@ def time_prepare(self, _, n):
class PrepareScalabilityGridToMesh(PrepareScalabilityMixin):
"""Benchmarks for the prepare step of :class:`~esmf_regrid.esmf_regrid.schemes.GridToMeshESMFRegridder`."""

regridder = GridToMeshESMFRegridder
regridder = GridToMeshESMFRegridder # type: ignore[assignment]

def tgt_cube(self, n):
"""Cube containing the regridding target grid."""
Expand Down Expand Up @@ -257,7 +258,7 @@ def time_lazy_perform(self, cache, height):
class PerformScalabilityMeshToGrid(PerformScalabilityMixin):
"""Benchmarks for the perform step of :class:`~esmf_regrid.esmf_regrid.schemes.MeshToGridESMFRegridder`."""

regridder = MeshToGridESMFRegridder
regridder = MeshToGridESMFRegridder # type: ignore[assignment]
chunk_size = [PerformScalabilityMixin.grid_size ^ 2, 10]
file_name = "chunked_cube_1d.nc"

Expand Down Expand Up @@ -298,7 +299,7 @@ def time_lazy_perform(self, cache, height):
class PerformScalabilityGridToMesh(PerformScalabilityMixin):
"""Benchmarks for the perform step of :class:`~esmf_regrid.esmf_regrid.schemes.GridToMeshESMFRegridder`."""

regridder = GridToMeshESMFRegridder
regridder = GridToMeshESMFRegridder # type: ignore[assignment]

def setup_cache(self):
"""ASV setup_cache method."""
Expand Down
19 changes: 7 additions & 12 deletions benchmarks/benchmarks/generate_data.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""
Scripts for generating supporting data for benchmarking.
"""Scripts for generating supporting data for benchmarking.
Data generated using iris-esmf-regrid should use
:func:`run_function_elsewhere`, which means that data is generated using a
Expand Down Expand Up @@ -43,7 +42,7 @@
default_data_dir = (Path(__file__).parent.parent / ".data").resolve()
# Optionally override the default data location with environment variable.
BENCHMARK_DATA = Path(environ.get("BENCHMARK_DATA", default_data_dir))
if BENCHMARK_DATA == default_data_dir:
if default_data_dir == BENCHMARK_DATA:
BENCHMARK_DATA.mkdir(exist_ok=True)
message = (
f"No BENCHMARK_DATA env var, defaulting to {BENCHMARK_DATA}. "
Expand All @@ -62,8 +61,7 @@


def run_function_elsewhere(func_to_run, *args, **kwargs):
"""
Run a given function using the :const:`DATA_GEN_PYTHON` executable.
"""Run a given function using the :const:`DATA_GEN_PYTHON` executable.
This structure allows the function to be written natively.
Expand All @@ -90,7 +88,7 @@ def run_function_elsewhere(func_to_run, *args, **kwargs):
func_string = dedent(getsource(func_to_run))
func_string = func_string.replace("@staticmethod\n", "")
func_call_term_strings = [repr(arg) for arg in args]
func_call_term_strings += [f"{name}={repr(val)}" for name, val in kwargs.items()]
func_call_term_strings += [f"{name}={val!r}" for name, val in kwargs.items()]
func_call_string = (
f"{func_to_run.__name__}(" + ",".join(func_call_term_strings) + ")"
)
Expand All @@ -115,8 +113,7 @@ def _grid_cube(
"""Call _grid_cube via :func:`run_function_elsewhere`."""

def external(*args, **kwargs):
"""
Prep and call _grid_cube, saving to a NetCDF file.
"""Prep and call _grid_cube, saving to a NetCDF file.
Saving to a file allows the original python executable to pick back up.
Expand Down Expand Up @@ -178,8 +175,7 @@ def _curvilinear_cube(
"""Call _curvilinear_cube via :func:`run_function_elsewhere`."""

def external(*args, **kwargs):
"""
Prep and call _curvilinear_cube, saving to a NetCDF file.
"""Prep and call _curvilinear_cube, saving to a NetCDF file.
Saving to a file allows the original python executable to pick back up.
Expand Down Expand Up @@ -227,8 +223,7 @@ def _gridlike_mesh_cube(n_lons, n_lats):
"""Call _gridlike_mesh via :func:`run_function_elsewhere`."""

def external(*args, **kwargs):
"""
Prep and call _gridlike_mesh, saving to a NetCDF file.
"""Prep and call _gridlike_mesh, saving to a NetCDF file.
Saving to a file allows the original python executable to pick back up.
Expand Down
23 changes: 12 additions & 11 deletions benchmarks/bm_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import shlex
import subprocess
from tempfile import NamedTemporaryFile
from typing import Literal

# The threshold beyond which shifts are 'notable'. See `asv compare`` docs
# for more.
Expand All @@ -29,7 +28,7 @@
def _echo(echo_string: str):
# Use subprocess for printing to reduce chance of printing out of sequence
# with the subsequent calls.
subprocess.run(["echo", f"BM_RUNNER DEBUG: {echo_string}"])
subprocess.run(["echo", f"BM_RUNNER DEBUG: {echo_string}"], check=False)


def _subprocess_runner(args, asv=False, **kwargs):
Expand Down Expand Up @@ -103,10 +102,10 @@ def _setup_common() -> None:

def _asv_compare(*commits: str) -> None:
"""Run through a list of commits comparing each one to the next."""
commits = [commit[:8] for commit in commits]
for i in range(len(commits) - 1):
before = commits[i]
after = commits[i + 1]
_commits = [commit[:8] for commit in commits]
for i in range(len(_commits) - 1):
before = _commits[i]
after = _commits[i + 1]
asv_command = shlex.split(
f"compare {before} {after} --factor={COMPARE_FACTOR} --split"
)
Expand All @@ -124,7 +123,7 @@ class _SubParserGenerator(ABC):
description: str = NotImplemented
epilog: str = NotImplemented

def __init__(self, subparsers: ArgumentParser.add_subparsers) -> None:
def __init__(self, subparsers: argparse._SubParsersAction) -> None:
self.subparser: ArgumentParser = subparsers.add_parser(
self.name,
description=self.description,
Expand Down Expand Up @@ -249,18 +248,20 @@ def func(args: argparse.Namespace) -> None:
)

# Only do a single round.
asv_command = shlex.split(re.sub(r"rounds=\d", "rounds=1", asv_command))
_asv_command = shlex.split(re.sub(r"rounds=\d", "rounds=1", asv_command))
try:
_subprocess_runner([*asv_command, *args.asv_args], asv=True)
_subprocess_runner([*_asv_command, *args.asv_args], asv=True)
except subprocess.CalledProcessError as err:
# C/SPerf benchmarks are much bigger than the CI ones:
# Don't fail the whole run if memory blows on 1 benchmark.
# ASV produces return code of 2 if the run includes crashes.
if err.returncode != 2:
raise

asv_command = shlex.split(f"publish {commit_range} --html-dir={publish_subdir}")
_subprocess_runner(asv_command, asv=True)
_asv_command = shlex.split(
f"publish {commit_range} --html-dir={publish_subdir}"
)
_subprocess_runner(_asv_command, asv=True)

# Print completion message.
location = BENCHMARKS_DIR / ".asv"
Expand Down
Loading

0 comments on commit 8096455

Please sign in to comment.