Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Streamline fixtures, use pytest-xdist, drop Python3.8 #345

Merged
merged 26 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
8aac17e
use pytest-xdist to distribute tests, pin some missing dependencies
Zeitsperre Aug 26, 2024
a7b1394
streamline testing logic, remove unsafe loads and optimize many pytes…
Zeitsperre Aug 26, 2024
2b13b70
typo fixes
Zeitsperre Aug 26, 2024
adc08f0
thread fixes
Zeitsperre Aug 26, 2024
d1dc45d
wip - completely rewrite test setup
Zeitsperre Aug 26, 2024
8149f1c
wip - finish replacing file locations
Zeitsperre Aug 26, 2024
a4488a2
stability improvements, fix folder tree path
Zeitsperre Aug 27, 2024
cb9262b
more adjustments
Zeitsperre Aug 27, 2024
2351433
address a few warnings
Zeitsperre Aug 27, 2024
25a30f5
Python3.8 adjustments
Zeitsperre Aug 27, 2024
be58cff
wip - complete rewrite
Zeitsperre Aug 27, 2024
79bc907
wip - prepare mini-esgf for pooch
Zeitsperre Aug 27, 2024
5dc834e
add data registries, adapt to new system
Zeitsperre Aug 27, 2024
0e09cf0
drop Python3.8
Zeitsperre Sep 4, 2024
70bee09
update conventions
Zeitsperre Sep 4, 2024
5e496d5
split esgf data into files and globs, update test fixtures, update no…
Zeitsperre Sep 4, 2024
1196bdc
update dependencies and conventions
Zeitsperre Sep 4, 2024
b9ea150
fix coverage, try loading mfdatasets
Zeitsperre Sep 5, 2024
37cf12e
fix random seeding
Zeitsperre Sep 5, 2024
b44be81
update changelog and synchronize pins
Zeitsperre Sep 5, 2024
52d4cee
use deptry, dependency updates and synchronizations, update changelog
Zeitsperre Sep 5, 2024
f343046
use test data caching
Zeitsperre Sep 5, 2024
b6d94b4
add a cache cleaning workflow
Zeitsperre Sep 5, 2024
2bb0f07
fix coverage reporting
Zeitsperre Sep 5, 2024
60d3288
update release date
Zeitsperre Oct 3, 2024
6906e97
pin micromamba, fix dependency name
Zeitsperre Oct 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}

env:
ESGF_TEST_DATA_VERSION: restructuring

permissions:
contents: read

Expand Down Expand Up @@ -44,8 +47,6 @@ jobs:
strategy:
matrix:
include:
- python-version: "3.8"
tox-env: py38
- python-version: "3.9"
tox-env: py39
- python-version: "3.10"
Expand Down Expand Up @@ -117,7 +118,7 @@ jobs:
python -m pip check || true
- name: Test with conda
run: |
python -m pytest --cov tests
python -m pytest --numprocesses=logical --cov tests

finish:
needs:
Expand Down
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ repos:
rev: v3.17.0
hooks:
- id: pyupgrade
args: [ '--py38-plus' ]
args: [ '--py39-plus' ]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
Expand Down Expand Up @@ -72,5 +72,5 @@ ci:
autoupdate_branch: ''
autoupdate_commit_msg: '[pre-commit.ci] pre-commit autoupdate'
autoupdate_schedule: quarterly
skip: []
skip: [ ]
submodules: false
2 changes: 1 addition & 1 deletion CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ Before you submit a pull request, please follow these guidelines:
Remember to add the feature or bug fixes explanation to the appropriate section in the HISTORY.rst.

#.
The pull request should work for Python 3.8+ as well as raise test coverage.
The pull request should work for Python 3.9+ as well as raise test coverage.
Pull requests are also checked for documentation build status and for `PEP8`_ compliance.

The build statuses and build errors for pull requests can be found at:
Expand Down
3 changes: 2 additions & 1 deletion clisops/core/average.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"""Average module."""

import warnings
from collections.abc import Sequence
from pathlib import Path
from typing import Sequence, Tuple, Union
from typing import Union

import cf_xarray # noqa
import geopandas as gpd
Expand Down
5 changes: 2 additions & 3 deletions clisops/core/regrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,7 @@ def weights_cache_init(
weights_dir = config["clisops:grid_weights"]["local_weights_dir"]

# Create directory tree if required
if not os.path.isdir(weights_dir):
os.makedirs(weights_dir)
os.makedirs(weights_dir, exist_ok=True)


# Initialize weights cache as defined in the clisops configuration (roocs.ini)
Expand Down Expand Up @@ -638,7 +637,7 @@ def detect_type(self) -> str:
)
and all(
[
self.ds.dims[dim] > 2
self.ds.sizes[dim] > 2
for dim in [
self.ds[self.lon_bnds].dims[-1],
self.ds[self.lat_bnds].dims[-1],
Expand Down
19 changes: 10 additions & 9 deletions clisops/core/subset.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

import numbers
import re
from collections.abc import Sequence
from functools import wraps
from pathlib import Path
from typing import Callable, Dict, List, Optional, Sequence, Tuple, Union
from typing import Callable, Optional, Union

import cf_xarray # noqa
import geopandas as gpd
Expand Down Expand Up @@ -1186,8 +1187,8 @@ def subset_shape(
@check_lons
def subset_bbox(
da: Union[xarray.DataArray, xarray.Dataset],
lon_bnds: Union[np.array, Tuple[Optional[float], Optional[float]]] = None,
lat_bnds: Union[np.array, Tuple[Optional[float], Optional[float]]] = None,
lon_bnds: Union[np.array, tuple[Optional[float], Optional[float]]] = None,
lat_bnds: Union[np.array, tuple[Optional[float], Optional[float]]] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
first_level: Optional[Union[float, int]] = None,
Expand Down Expand Up @@ -1371,8 +1372,8 @@ def subset_bbox(


def assign_bounds(
bounds: Tuple[Optional[float], Optional[float]], coord: xarray.DataArray
) -> Tuple[Optional[float], Optional[float]]:
bounds: tuple[Optional[float], Optional[float]], coord: xarray.DataArray
) -> tuple[Optional[float], Optional[float]]:
"""Replace unset boundaries by the minimum and maximum coordinates.

Parameters
Expand All @@ -1396,7 +1397,7 @@ def assign_bounds(
return bn, bx


def in_bounds(bounds: Tuple[float, float], coord: xarray.DataArray) -> xarray.DataArray:
def in_bounds(bounds: tuple[float, float], coord: xarray.DataArray) -> xarray.DataArray:
"""Check which coordinates are within the boundaries.

Parameters
Expand All @@ -1417,9 +1418,9 @@ def in_bounds(bounds: Tuple[float, float], coord: xarray.DataArray) -> xarray.Da

def _check_desc_coords(
coord: xarray.Dataset,
bounds: Union[Tuple[float, float], List[np.ndarray]],
bounds: Union[tuple[float, float], list[np.ndarray]],
dim: str,
) -> Tuple[float, float]:
) -> tuple[float, float]:
"""If Dataset coordinates are descending, and bounds are ascending, reverse bounds."""
if np.all(coord.diff(dim=dim) < 0) and len(coord) > 1 and bounds[1] > bounds[0]:
bounds = np.flip(bounds)
Expand Down Expand Up @@ -1716,7 +1717,7 @@ def subset_time_by_values(
def subset_time_by_components(
da: Union[xarray.DataArray, xarray.Dataset],
*,
time_components: Union[Dict, None] = None,
time_components: Union[dict, None] = None,
) -> xarray.DataArray:
"""Subsets by one or more time components (year, month, day etc).

Expand Down
9 changes: 5 additions & 4 deletions clisops/ops/average.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from collections.abc import Sequence
from pathlib import Path
from typing import List, Optional, Sequence, Tuple, Union
from typing import Optional, Union

import geopandas as gpd
import xarray as xr
Expand Down Expand Up @@ -50,7 +51,7 @@ def average_over_dims(
output_type: str = "netcdf",
split_method: str = "time:auto",
file_namer: str = "standard",
) -> List[Union[xr.Dataset, str]]:
) -> list[Union[xr.Dataset, str]]:
"""Calculate an average over given dimensions.

Parameters
Expand Down Expand Up @@ -125,7 +126,7 @@ def average_shape(
output_type: str = "netcdf",
split_method: str = "time:auto",
file_namer: str = "standard",
) -> List[Union[xr.Dataset, str]]:
) -> list[Union[xr.Dataset, str]]:
"""Calculate a spatial average over a given shape.

Parameters
Expand Down Expand Up @@ -201,7 +202,7 @@ def average_time(
output_type: str = "netcdf",
split_method: str = "time:auto",
file_namer: str = "standard",
) -> List[Union[xr.Dataset, str]]:
) -> list[Union[xr.Dataset, str]]:
"""

Parameters
Expand Down
6 changes: 3 additions & 3 deletions clisops/ops/base_operation.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from collections import ChainMap
from pathlib import Path
from typing import List, Optional, Union
from typing import Optional, Union

import xarray as xr
from loguru import logger
from roocs_utils.xarray_utils.xarray_utils import get_main_variable, open_xr_dataset
from roocs_utils.xarray_utils.xarray_utils import open_xr_dataset

from clisops.utils.common import expand_wildcards
from clisops.utils.file_namers import get_file_namer
Expand Down Expand Up @@ -199,7 +199,7 @@ def _remove_redundant_coordinates_attr(ds):
ds[var].attrs.pop("coordinates", None)
return ds

def process(self) -> List[Union[xr.Dataset, Path]]:
def process(self) -> list[Union[xr.Dataset, Path]]:
"""Main processing method used by all subclasses.

Returns
Expand Down
4 changes: 2 additions & 2 deletions clisops/ops/regrid.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from datetime import datetime as dt
from pathlib import Path
from typing import List, Optional, Union
from typing import Optional, Union

import xarray as xr
from loguru import logger
Expand Down Expand Up @@ -179,7 +179,7 @@ def regrid(
split_method: Optional[str] = "time:auto",
file_namer: Optional[str] = "standard",
keep_attrs: Optional[Union[bool, str]] = True,
) -> List[Union[xr.Dataset, str]]:
) -> list[Union[xr.Dataset, str]]:
"""Regrid specified input file or xarray object.

Parameters
Expand Down
12 changes: 6 additions & 6 deletions clisops/ops/subset.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from pathlib import Path
from typing import Dict, List, Optional, Tuple, Union
from typing import List, Optional, Union

import xarray as xr
from loguru import logger
Expand Down Expand Up @@ -162,11 +162,11 @@ def _calculate(self):
def subset(
ds: Union[xr.Dataset, str, Path],
*,
time: Optional[Union[str, Tuple[str, str], TimeParameter, Series, Interval]] = None,
time: Optional[Union[str, tuple[str, str], TimeParameter, Series, Interval]] = None,
area: Optional[
Union[
str,
Tuple[
tuple[
Union[int, float, str],
Union[int, float, str],
Union[int, float, str],
Expand All @@ -178,19 +178,19 @@ def subset(
level: Optional[
Union[
str,
Tuple[Union[int, float, str], Union[int, float, str]],
tuple[Union[int, float, str], Union[int, float, str]],
LevelParameter,
Interval,
]
] = None,
time_components: Optional[
Union[str, Dict, TimeComponents, TimeComponentsParameter]
Union[str, dict, TimeComponents, TimeComponentsParameter]
] = None,
output_dir: Optional[Union[str, Path]] = None,
output_type="netcdf",
split_method="time:auto",
file_namer="standard",
) -> List[Union[xr.Dataset, str]]:
) -> list[Union[xr.Dataset, str]]:
"""Subset operation.

Parameters
Expand Down
2 changes: 1 addition & 1 deletion clisops/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
from .common import *
from .tutorial import *
from .testing import *
4 changes: 2 additions & 2 deletions clisops/utils/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import warnings
from pathlib import Path
from types import FunctionType, ModuleType
from typing import List, Optional, Union
from typing import Optional, Union

from loguru import logger
from packaging.version import Version
Expand Down Expand Up @@ -74,7 +74,7 @@ def _logging_examples() -> None:
logger.critical("5")


def enable_logging() -> List[int]:
def enable_logging() -> list[int]:
logger.enable("clisops")

config = dict(
Expand Down
12 changes: 6 additions & 6 deletions clisops/utils/dataset_utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import warnings
from typing import Optional, Tuple
from typing import Optional

import cf_xarray as cfxr # noqa
import cftime
Expand Down Expand Up @@ -498,14 +498,14 @@ def reformat_SCRIP_to_CF(ds, keep_attrs=False):
(
ds.grid_dims.values[1],
ds.grid_dims.values[0],
ds.dims["grid_corners"],
ds.sizes["grid_corners"],
)
).astype(np.float32)
lon_b = ds.grid_corner_lon.values.reshape(
(
ds.grid_dims.values[1],
ds.grid_dims.values[0],
ds.dims["grid_corners"],
ds.sizes["grid_corners"],
)
).astype(np.float32)
lat_bnds = np.zeros((ds.grid_dims.values[1], 2), dtype=np.float32)
Expand Down Expand Up @@ -668,7 +668,7 @@ def detect_format(ds):
raise Exception("The grid format is not supported.")


def detect_shape(ds, lat, lon, grid_type) -> Tuple[int, int, int]:
def detect_shape(ds, lat, lon, grid_type) -> tuple[int, int, int]:
"""Detect the shape of the grid.

Returns a tuple of (nlat, nlon, ncells). For an unstructured grid nlat and nlon are not defined
Expand Down Expand Up @@ -996,7 +996,7 @@ def detect_gridtype(ds, lon, lat, lon_bnds=None, lat_bnds=None):
and all([ds[bnds].ndim == 2 for bnds in [lon_bnds, lat_bnds]])
and all(
[
ds.dims[dim] > 2
ds.sizes[dim] > 2
for dim in [
ds[lon_bnds].dims[-1],
ds[lat_bnds].dims[-1],
Expand All @@ -1008,7 +1008,7 @@ def detect_gridtype(ds, lon, lat, lon_bnds=None, lat_bnds=None):
# rectilinear: bounds [nlat/nlon, 2]
elif (
all([ds[bnds].ndim == 2 for bnds in [lon_bnds, lat_bnds]])
and ds.dims[ds.cf.get_bounds_dim_name(lon)] == 2
and ds.sizes[ds.cf.get_bounds_dim_name(lon)] == 2
):
return "regular_lat_lon"
else:
Expand Down
Loading