Skip to content

Commit

Permalink
update pyproject.toml to SciTools standard
Browse files Browse the repository at this point in the history
  • Loading branch information
stephenworsley committed Nov 14, 2024
1 parent b777eca commit 4b2ac6c
Show file tree
Hide file tree
Showing 44 changed files with 350 additions and 406 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ repos:
rev: 'v1.10.0'
hooks:
- id: mypy
exclude: 'noxfile\.py|docs/conf\.py'
exclude: 'noxfile\.py|docs/src/conf\.py|^benchmarks'

- repo: https://github.com/abravalheri/validate-pyproject
# More exhaustive than Ruff RUF200.
Expand Down
3 changes: 1 addition & 2 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 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
17 changes: 8 additions & 9 deletions docs/src/conf.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""
Configuration file for the Sphinx documentation builder.
"""Configuration file for the Sphinx documentation builder.
Created originally using sphinx-quickstart on 2022-02-21.
"""
Expand Down Expand Up @@ -80,18 +79,18 @@ def _dotv(version):


# Automate the discovery of the python versions tested with CI.
python_support = sorted(
[fname.stem for fname in Path(".").glob("../../requirements/py*.yml")]
python_support_list = sorted(
[fname.stem for fname in Path().glob("../../requirements/py*.yml")]
)


if not python_support:
if not python_support_list:
python_support = "unknown Python versions"
elif len(python_support) == 1:
python_support = f"Python {_dotv(python_support[0])}"
elif len(python_support_list) == 1:
python_support = f"Python {_dotv(python_support_list[0])}"
else:
rest = ", ".join([_dotv(v) for v in python_support[:-1]])
last = _dotv(python_support[-1])
rest = ", ".join([_dotv(v) for v in python_support_list[:-1]])
last = _dotv(python_support_list[-1])
python_support = f"Python {rest} and {last}"

rst_epilog = f"""
Expand Down
1 change: 0 additions & 1 deletion esmf_regrid/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,4 @@
from .constants import Constants, check_method, check_norm
from .schemes import *


__version__ = "0.12.dev0"
24 changes: 8 additions & 16 deletions esmf_regrid/_esmf_sdo.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@


class SDO(ABC):
"""
Abstract base class for handling spatial discretisation objects.
"""Abstract base class for handling spatial discretisation objects.
This contains shared things for representing the three spatial discretisation
objects supported by ESMPy, Grids, Meshes, and LocStreams.
Expand Down Expand Up @@ -74,8 +73,7 @@ def mask(self):
return self._mask

def _array_to_matrix(self, array):
"""
Reshape data to a form that is compatible with weight matrices.
"""Reshape data to a form that is compatible with weight matrices.
The data should be presented in the form of a matrix (i.e. 2D) in order
to be compatible with the weight matrix.
Expand All @@ -87,17 +85,15 @@ def _array_to_matrix(self, array):
return array.T.reshape((self.size, -1))

def _matrix_to_array(self, array, extra_dims):
"""
Reshape data to restore original dimensions.
"""Reshape data to restore original dimensions.
This is the inverse operation of `_array_to_matrix`.
"""
return array.reshape((extra_dims + self._shape)[::-1]).T


class GridInfo(SDO):
"""
Class for handling structured grids.
"""Class for handling structured grids.
This class holds information about lat-lon type grids. That is, grids
defined by lists of latitude and longitude values for points/bounds
Expand Down Expand Up @@ -125,8 +121,7 @@ def __init__(
mask=None,
center=False,
):
"""
Create a :class:`GridInfo` object describing the grid.
"""Create a :class:`GridInfo` object describing the grid.
Parameters
----------
Expand Down Expand Up @@ -327,8 +322,7 @@ def add_get_item(grid, **kwargs):


class RefinedGridInfo(GridInfo):
"""
Class for handling structured grids represented in :mod:`esmpy` in higher resolution.
"""Class for handling structured grids represented in :mod:`esmpy` in higher resolution.
A specialised version of :class:`GridInfo`. Designed to provide higher
accuracy conservative regridding for rectilinear grids, especially those with
Expand All @@ -349,8 +343,7 @@ def __init__(
crs=None,
mask=None,
):
"""
Create a :class:`RefinedGridInfo` object describing the grid.
"""Create a :class:`RefinedGridInfo` object describing the grid.
Parameters
----------
Expand Down Expand Up @@ -436,8 +429,7 @@ def _refined_mask(self):
return new_mask

def _collapse_weights(self, is_tgt):
"""
Return a matrix to collapse the weight matrix.
"""Return a matrix to collapse the weight matrix.
The refined grid may contain more cells than the represented grid. When this is
the case, the generated weight matrix will refer to too many points and will have
Expand Down
4 changes: 2 additions & 2 deletions esmf_regrid/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class NormType(Enum):

def check_method(method):
"""Check that method is a member of the `Constants.Method` enum or raise an error."""
if method in method_dict.keys():
if method in method_dict:
result = method_dict[method]
elif method in method_dict.values():
result = method
Expand All @@ -49,7 +49,7 @@ def check_method(method):

def check_norm(norm):
"""Check that normtype is a member of the `Constants.NormType` enum or raise an error."""
if norm in norm_dict.keys():
if norm in norm_dict:
result = norm_dict[norm]
elif norm in norm_dict.values():
result = norm
Expand Down
Loading

0 comments on commit 4b2ac6c

Please sign in to comment.