Skip to content

Commit 6d81913

Browse files
Maintenance (#553)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 8c9cd90 commit 6d81913

15 files changed

+64
-57
lines changed

.pre-commit-config.yaml

+7-19
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,18 @@ ci:
33

44
repos:
55
- repo: https://github.com/asottile/pyupgrade
6-
rev: v3.17.0
6+
rev: v3.19.1
77
hooks:
88
- id: pyupgrade
99
args: ["--py310-plus"]
1010

1111
- repo: https://github.com/astral-sh/ruff-pre-commit
1212
# Ruff version.
13-
rev: 'v0.6.9'
13+
rev: 'v0.9.3'
1414
hooks:
1515
- id: ruff
16-
args: ["--show-fixes", "--fix"]
17-
18-
- repo: https://github.com/psf/black-pre-commit-mirror
19-
rev: 24.10.0
20-
hooks:
21-
- id: black
16+
args: ["--fix", "--show-fixes"]
17+
- id: ruff-format
2218

2319
- repo: https://github.com/rstcheck/rstcheck
2420
rev: v6.2.4
@@ -28,18 +24,16 @@ repos:
2824
args: ['--config', 'pyproject.toml']
2925

3026
- repo: https://github.com/executablebooks/mdformat
31-
rev: 0.7.17
27+
rev: 0.7.21
3228
hooks:
3329
- id: mdformat
3430
additional_dependencies:
3531
- mdformat-black
3632
- mdformat-myst
3733

3834
- repo: https://github.com/nbQA-dev/nbQA
39-
rev: 1.8.7
35+
rev: 1.9.1
4036
hooks:
41-
- id: nbqa-black
42-
- id: nbqa-ruff
4337
- id: nbqa
4438
entry: nbqa mdformat
4539
name: nbqa-mdformat
@@ -55,19 +49,13 @@ repos:
5549
- id: check-yaml
5650
- id: debug-statements
5751

58-
- repo: https://github.com/keewis/blackdoc
59-
rev: v0.3.9
60-
hooks:
61-
- id: blackdoc
62-
files: .+\.py$
63-
6452
- repo: https://github.com/citation-file-format/cff-converter-python
6553
rev: "44e8fc9"
6654
hooks:
6755
- id: validate-cff
6856

6957
- repo: https://github.com/abravalheri/validate-pyproject
70-
rev: v0.20.2
58+
rev: v0.23
7159
hooks:
7260
- id: validate-pyproject
7361

.readthedocs.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
version: 2
2-
2+
sphinx:
3+
configuration: doc/conf.py
34
build:
45
os: ubuntu-lts-latest
56
tools:

cf_xarray/accessor.py

+14-6
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ def _getattr(
680680
None,
681681
):
682682
raise AttributeError(
683-
f"{obj.__class__.__name__+'.cf'!r} object has no attribute {attr!r}"
683+
f"{obj.__class__.__name__ + '.cf'!r} object has no attribute {attr!r}"
684684
) from None
685685
raise AttributeError(
686686
f"{attr!r} is not a valid attribute on the underlying xarray object."
@@ -1374,7 +1374,11 @@ def curvefit(
13741374
coords_iter = coords
13751375
coords = [
13761376
apply_mapper(
1377-
[_single(_get_coords)], self._obj, v, error=False, default=[v] # type: ignore[arg-type]
1377+
[_single(_get_coords)], # type:ignore[arg-type]
1378+
self._obj,
1379+
v,
1380+
error=False,
1381+
default=[v],
13781382
)[0]
13791383
for v in coords_iter
13801384
]
@@ -1385,7 +1389,11 @@ def curvefit(
13851389
reduce_dims_iter = list(reduce_dims)
13861390
reduce_dims = [
13871391
apply_mapper(
1388-
[_single(_get_dims)], self._obj, v, error=False, default=[v] # type: ignore[arg-type]
1392+
[_single(_get_dims)], # type:ignore[arg-type]
1393+
self._obj,
1394+
v,
1395+
error=False,
1396+
default=[v],
13891397
)[0]
13901398
for v in reduce_dims_iter
13911399
]
@@ -2758,9 +2766,9 @@ def decode_vertical_coords(self, *, outnames=None, prefix=None):
27582766

27592767
for dim in allterms:
27602768
if prefix is None:
2761-
assert (
2762-
outnames is not None
2763-
), "if prefix is None, outnames must be provided"
2769+
assert outnames is not None, (
2770+
"if prefix is None, outnames must be provided"
2771+
)
27642772
# set outnames here
27652773
try:
27662774
zname = outnames[dim]

cf_xarray/datasets.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,14 @@
2121

2222
# POM dataset
2323
pomds = xr.Dataset()
24+
# fmt: off
2425
pomds["sigma"] = (
25-
# fmt: off
2626
"sigma",
2727
[-0.983333, -0.95 , -0.916667, -0.883333, -0.85 , -0.816667,
2828
-0.783333, -0.75 , -0.716667, -0.683333, -0.65 , -0.616667,
2929
-0.583333, -0.55 , -0.516667, -0.483333, -0.45 , -0.416667,
3030
-0.383333, -0.35 , -0.316667, -0.283333, -0.25 , -0.216667,
3131
-0.183333, -0.15 , -0.116667, -0.083333, -0.05 , -0.016667],
32-
# fmt: on
3332
{
3433
"units": "sigma_level",
3534
"long_name": "Sigma Stretched Vertical Coordinate at Nodes",
@@ -38,6 +37,7 @@
3837
"formula_terms": "sigma: sigma eta: zeta depth: depth",
3938
}
4039
)
40+
# fmt: on
4141
pomds["depth"] = 175.0
4242
pomds["zeta"] = ("ocean_time", [-0.155356, -0.127435])
4343

@@ -109,29 +109,29 @@
109109

110110

111111
romsds = xr.Dataset()
112+
# fmt: off
112113
romsds["s_rho"] = (
113-
# fmt: off
114114
"s_rho",
115115
[-0.983333, -0.95 , -0.916667, -0.883333, -0.85 , -0.816667,
116116
-0.783333, -0.75 , -0.716667, -0.683333, -0.65 , -0.616667,
117117
-0.583333, -0.55 , -0.516667, -0.483333, -0.45 , -0.416667,
118118
-0.383333, -0.35 , -0.316667, -0.283333, -0.25 , -0.216667,
119119
-0.183333, -0.15 , -0.116667, -0.083333, -0.05 , -0.016667],
120-
# fmt: on
121120
{
122121
"long_name": "S-coordinate at RHO-points",
123122
"valid_min": -1.0,
124123
"valid_max": 0.0,
125124
"standard_name": "ocean_s_coordinate_g2",
126125
"formula_terms": "s: s_rho C: Cs_r eta: zeta depth: h depth_c: hc",
127126
"field": "s_rho, scalar",
128-
}
127+
},
129128
)
129+
# fmt: on
130130
romsds.coords["hc"] = 20.0
131131
romsds.coords["h"] = 603.9
132132
romsds.coords["Vtransform"] = 2.0
133+
# fmt: off
133134
romsds.coords["Cs_r"] = (
134-
# fmt: off
135135
"s_rho",
136136
[-9.33010396e-01, -8.09234736e-01, -6.98779853e-01, -6.01008926e-01,
137137
-5.15058562e-01, -4.39938913e-01, -3.74609181e-01, -3.18031817e-01,
@@ -141,8 +141,8 @@
141141
-2.53860004e-02, -1.95414261e-02, -1.46880431e-02, -1.06952600e-02,
142142
-7.45515186e-03, -4.87981407e-03, -2.89916971e-03, -1.45919898e-03,
143143
-5.20560097e-04, -5.75774004e-05],
144-
# fmt: on
145144
)
145+
# fmt: on
146146
romsds["zeta"] = ("ocean_time", [-0.155356, -0.127435])
147147
romsds["temp"] = (
148148
("ocean_time", "s_rho"),

cf_xarray/geometry.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from collections import ChainMap
55
from collections.abc import Hashable, Sequence
66
from dataclasses import dataclass
7+
from typing import TYPE_CHECKING
78

89
import numpy as np
910
import pandas as pd
@@ -21,6 +22,9 @@
2122
]
2223

2324

25+
if TYPE_CHECKING:
26+
from shapely import MultiPoint, Point
27+
2428
# Useful convention language:
2529
# 1. Whether linked to normal CF space-time coordinates with a nodes attribute or not, inclusion of such coordinates is
2630
# recommended to maintain backward compatibility with software that has not implemented geometry capabilities.
@@ -547,7 +551,11 @@ def cf_to_shapely(ds: xr.Dataset, *, container: Hashable = GEOMETRY_CONTAINER_NA
547551
return geometries.rename("geometry")
548552

549553

550-
def points_to_cf(pts: xr.DataArray | Sequence, *, names: GeometryNames | None = None):
554+
def points_to_cf(
555+
pts: xr.DataArray | Sequence[Point | MultiPoint],
556+
*,
557+
names: GeometryNames | None = None,
558+
):
551559
"""Get a list of points (shapely.geometry.[Multi]Point) and return a CF-compliant geometry dataset.
552560
553561
Parameters
@@ -563,6 +571,7 @@ def points_to_cf(pts: xr.DataArray | Sequence, *, names: GeometryNames | None =
563571
"""
564572
from shapely.geometry import MultiPoint
565573

574+
pts_: Sequence[Point | MultiPoint]
566575
if isinstance(pts, xr.DataArray):
567576
# TODO: Fix this hardcoding
568577
if pts.ndim != 1:

cf_xarray/options.py

-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ class set_options: # numpydoc ignore=PR01,PR02
3838
>>> ds = xr.Dataset({"elev": np.arange(1000)})
3939
>>> with cf_xarray.set_options(custom_criteria=my_custom_criteria):
4040
... xr.testing.assert_identical(ds["elev"], ds.cf["ssh"])
41-
...
4241
4342
Or to set global options:
4443

cf_xarray/tests/__init__.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ def __call__(self, dsk, keys, **kwargs):
3232
self.total_computes += 1
3333
if self.total_computes > self.max_computes:
3434
raise RuntimeError(
35-
"Too many computes. Total: %d > max: %d."
36-
% (self.total_computes, self.max_computes)
35+
f"Too many computes. Total:{self.total_computes} > max: {self.max_computes}."
3736
)
3837
return dask.get(dsk, keys, **kwargs)
3938

cf_xarray/tests/test_accessor.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ def test_rename_like() -> None:
453453
@pytest.mark.parametrize(
454454
"attr, xrkwargs, cfkwargs",
455455
(
456-
("resample", {"time": "M"}, {"T": "M"}),
456+
("resample", {"time": "ME"}, {"T": "ME"}),
457457
("rolling", {"lat": 5}, {"Y": 5}),
458458
("groupby", {"group": "time"}, {"group": "T"}),
459459
("groupby", {"group": "time.month"}, {"group": "T.month"}),
@@ -1748,7 +1748,7 @@ def test_add_canonical_attributes(override, skip, verbose, capsys):
17481748

17491749
# Attributes have been added
17501750
for var in sum(ds.cf.standard_names.values(), []):
1751-
assert set(ds[var].attrs) < set(cf_ds[var].attrs)
1751+
assert set(ds[var].attrs) <= set(cf_ds[var].attrs)
17521752

17531753
# Time units did not change
17541754
assert ds["time"].attrs.get("units") is cf_ds["time"].attrs.get("units") is None
@@ -2047,7 +2047,8 @@ def test_ancillary_variables_extra_dim():
20472047
),
20482048
}
20492049
)
2050-
assert_identical(ds.cf["X"], ds["x"])
2050+
with pytest.warns(UserWarning):
2051+
assert_identical(ds.cf["X"], ds["x"])
20512052

20522053

20532054
def test_geometry_association(geometry_ds):

doc/bounds.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
`cf_xarray` supports parsing [coordinate bounds](http://cfconventions.org/Data/cf-conventions/cf-conventions-1.10/cf-conventions.html#cell-boundaries) as encoded in the CF `bounds` attribute. A useful feature for incomplete dataset is also the automatic bounds estimation possible through `cf.add_bounds`. This method will estimate the missing bounds by finding the middle points between elements of the given coordinate, but also by extrapolating to find the outer bounds of the grid. This linear estimation works well with rectilinear grids, but it is only a coarse approximation for curvilinear and simple irregular grids.
1616

17-
As an example, we present a "rotated pole" grid. It is defined on a rotated rectilinear grid which uses the `rlat` and `rlon` 1D coordinates, over North America at a resolution of 0.44°. The datasets comes with 2D `lat` and `lon` coordinates. `cf_xarray` will estimate the bounds by linear interpolation (extrapolation at the edges) of the existing `lon` and `lat`, which yields good results on parts of the grid where the rotation is small. However the errors is larger in other places, as seen when visualizing the distance in degrees between the estimated bounds and the true bounds.
17+
As an example, we present a "rotated pole" grid. It is defined on a rotated rectilinear grid which uses the `rlat` and `rlon` 1D coordinates, over North America at a resolution of 0.44°. The datasets comes with 2D `lat` and `lon` coordinates. `cf_xarray` will estimate the bounds by linear interpolation (extrapolation at the edges) of the existing `lon` and `lat`, which yields good results on parts of the grid where the rotation is small. However the errors is larger in other places, as seen when visualizing the distance in degrees between the estimated bounds and the true bounds.
1818

1919
![2d bounds error](2D_bounds_error.png)
2020

doc/coord_axes.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ This table lists these internal criteria
5555
:stub-columns: 1
5656
```
5757

58-
Any DataArray that has `standard_name: "latitude"` or `_CoordinateAxisType: "Lat"` or `"units": "degrees_north"` in its `attrs` will be identified as the `"latitude"` variable by cf-xarray. Similarly for other coordinate names.
58+
Any DataArray that has `standard_name: "latitude"` or `_CoordinateAxisType: "Lat"` or `"units": "degrees_north"` in its `attrs` will be identified as the `"latitude"` variable by cf-xarray. Similarly for other coordinate names.
5959

6060
## Axis Names
6161

@@ -68,7 +68,7 @@ Similar criteria exist for the concept of "axes".
6868
:stub-columns: 1
6969
```
7070

71-
## `.axes` and `.coordinates` properties
71+
## `.axes` and `.coordinates` properties
7272

7373
Alternatively use the special properties {py:attr}`DataArray.cf.axes` or {py:attr}`DataArray.cf.coordinates` to access the variable names. These properties return dictionaries that map "CF names" to a list of variable names. Note that a list is always returned even if only one variable name matches the name `"latitude"` (for example).
7474

doc/custom-criteria.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ with cfxr.set_options(custom_criteria=salt_criteria):
7373
salty
7474
```
7575

76-
Note that `salty` contains both `salt1` and `salt2`. Without setting these criteria, we would only get `salt1` by default
76+
Note that `salty` contains both `salt1` and `salt2`. Without setting these criteria, we would only get `salt1` by default
7777

7878
```{code-cell}
7979
ds.cf[["sea_water_salinity"]]

doc/selecting.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ CF conventions on
3030
1. [ancillary data](http://cfconventions.org/Data/cf-conventions/cf-conventions-1.8/cf-conventions.html#ancillary-data)
3131
```
3232

33-
A powerful feature of `cf_xarray` is the ability select DataArrays using special "CF names" like the "latitude", or "longitude" coordinate names, "X" or "Y" axes names, oreven using the `standard_name` attribute if present.
33+
A powerful feature of `cf_xarray` is the ability select DataArrays using special "CF names" like the "latitude", or "longitude" coordinate names, "X" or "Y" axes names, oreven using the `standard_name` attribute if present.
3434

3535
To demonstrate this, let's load a few datasets
3636

@@ -91,7 +91,7 @@ anc
9191

9292
## Selecting multiple variables
9393

94-
Sometimes a Dataset may contain multiple `X` or multiple `longitude` variables. In that case a simple `.cf["X"]` will raise an error. Instead follow Xarray convention and pass a list `.cf[["X"]]` to receive a Dataset with all available `"X"` variables
94+
Sometimes a Dataset may contain multiple `X` or multiple `longitude` variables. In that case a simple `.cf["X"]` will raise an error. Instead follow Xarray convention and pass a list `.cf[["X"]]` to receive a Dataset with all available `"X"` variables
9595

9696
```{code-cell}
9797
multiple.cf[["X"]]
@@ -103,7 +103,7 @@ pop.cf[["longitude"]]
103103

104104
## Mixing names
105105

106-
cf_xarray aims to be as friendly as possible, so it is possible to mix "CF names" and normal variable names. Here we select `UVEL` and `TEMP` by using the `standard_name` of `TEMP` (which is `sea_water_potential_temperature`)
106+
cf_xarray aims to be as friendly as possible, so it is possible to mix "CF names" and normal variable names. Here we select `UVEL` and `TEMP` by using the `standard_name` of `TEMP` (which is `sea_water_potential_temperature`)
107107

108108
```{code-cell}
109109
pop.cf[["sea_water_potential_temperature", "UVEL"]]

doc/sgrid_ugrid.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ variable `grid` list many more dimension names.
6565

6666
### Topology variable
6767

68-
`cf_xarray` supports identifying the `mesh_topology` variable using the `cf_role` attribute.
68+
`cf_xarray` supports identifying the `mesh_topology` variable using the `cf_role` attribute.
6969

7070
## More?
7171

doc/units.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ hide-toc: true
1414
1. [CF conventions on units](http://cfconventions.org/Data/cf-conventions/cf-conventions-1.8/cf-conventions.html#units)
1515
```
1616

17-
The xarray ecosystem supports unit-aware arrays using [pint](https://pint.readthedocs.io) and [pint-xarray](https://pint-xarray.readthedocs.io). Some changes are required to make these packages work well with [UDUNITS format recommended by the CF conventions](http://cfconventions.org/Data/cf-conventions/cf-conventions-1.8/cf-conventions.html#units).
17+
The xarray ecosystem supports unit-aware arrays using [pint](https://pint.readthedocs.io) and [pint-xarray](https://pint-xarray.readthedocs.io). Some changes are required to make these packages work well with [UDUNITS format recommended by the CF conventions](http://cfconventions.org/Data/cf-conventions/cf-conventions-1.8/cf-conventions.html#units).
1818

19-
`cf_xarray` makes those recommended changes when you `import cf_xarray.units`. These changes allow pint to parse and format UDUNIT units strings, and add several custom units like `degrees_north` for latitude, `psu` for ocean salinity, etc. Be aware that pint supports some units that UDUNITS does not recognize but `cf-xarray` will not try to detect them and raise an error. For example, a temperature subtraction returns "delta_degC" units in pint, which does not exist in UDUNITS.
19+
`cf_xarray` makes those recommended changes when you `import cf_xarray.units`. These changes allow pint to parse and format UDUNIT units strings, and add several custom units like `degrees_north` for latitude, `psu` for ocean salinity, etc. Be aware that pint supports some units that UDUNITS does not recognize but `cf-xarray` will not try to detect them and raise an error. For example, a temperature subtraction returns "delta_degC" units in pint, which does not exist in UDUNITS.
2020

2121
## Formatting units
2222

0 commit comments

Comments
 (0)