Skip to content

Commit 8f8584b

Browse files
authored
Copy over xarray's set_options context manager (#243)
1 parent 2f46ee3 commit 8f8584b

File tree

5 files changed

+81
-16
lines changed

5 files changed

+81
-16
lines changed

cf_xarray/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from .accessor import CFAccessor # noqa
22
from .helpers import bounds_to_vertices, vertices_to_bounds # noqa
3+
from .options import set_options # noqa
34
from .utils import _get_version
45

56
__version__ = _get_version()

cf_xarray/accessor.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
from .criteria import cf_role_criteria, coordinate_criteria, regex
2929
from .helpers import bounds_to_vertices
30+
from .options import OPTIONS
3031
from .utils import (
3132
_get_version,
3233
_is_datetime_like,
@@ -65,13 +66,6 @@
6566
ATTRS["time"] = ATTRS["T"]
6667
ATTRS["vertical"] = ATTRS["Z"]
6768

68-
OPTIONS: MutableMapping[str, Any] = {"custom_criteria": []}
69-
70-
71-
def set_options(custom_criteria):
72-
OPTIONS["custom_criteria"] = always_iterable(custom_criteria, allowed=(tuple, list))
73-
74-
7569
# Type for Mapper functions
7670
Mapper = Callable[[Union[DataArray, Dataset], str], List[str]]
7771

cf_xarray/options.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
"""
2+
Started from xarray options.py
3+
"""
4+
5+
import copy
6+
from typing import Any, MutableMapping
7+
8+
from .utils import always_iterable
9+
10+
OPTIONS: MutableMapping[str, Any] = {
11+
"custom_criteria": [],
12+
}
13+
14+
15+
class set_options:
16+
"""Set options for cf-xarray in a controlled context.
17+
Currently supported options:
18+
- ``custom_critera``: Translate from axis, coord, or custom name to
19+
variable name optionally using ``custom_criteria``. Default: [].
20+
21+
You can use ``set_options`` either as a context manager:
22+
>>> my_custom_criteria = { 'ssh': {'name': 'elev$'} }
23+
>>> ds = xr.Dataset({"elev": np.arange(1000)})
24+
>>> with cf_xarray.set_options(custom_criteria=my_custom_criteria):
25+
... assert (ds['elev'] == ds.cf['ssh']).all()
26+
27+
Or to set global options:
28+
>>> cf_xarray.set_options(custom_criteria=my_custom_criteria)
29+
>>> assert (ds['elev'] == ds.cf['ssh']).all()
30+
"""
31+
32+
def __init__(self, **kwargs):
33+
self.old = {}
34+
for k, v in kwargs.items():
35+
if k not in OPTIONS:
36+
raise ValueError(
37+
f"argument name {k!r} is not in the set of valid options {set(OPTIONS)!r}"
38+
)
39+
self.old[k] = OPTIONS[k]
40+
self._apply_update(kwargs)
41+
42+
def _apply_update(self, options_dict):
43+
options_dict = copy.deepcopy(options_dict)
44+
for k, v in options_dict.items():
45+
if k == "custom_criteria":
46+
options_dict["custom_criteria"] = always_iterable(
47+
options_dict["custom_criteria"], allowed=(tuple, list)
48+
)
49+
OPTIONS.update(options_dict)
50+
51+
def __enter__(self):
52+
return
53+
54+
def __exit__(self, type, value, traceback):
55+
self._apply_update(self.old)

cf_xarray/tests/test_accessor.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,10 +1252,11 @@ def test_custom_criteria():
12521252
},
12531253
}
12541254
my_custom_criteria2 = {"temp": {"name": "temperature"}}
1255-
cf_xarray.accessor.set_options(my_custom_criteria)
12561255
my_custom_criteria_list = [my_custom_criteria, my_custom_criteria2]
12571256
my_custom_criteria_tuple = (my_custom_criteria, my_custom_criteria2)
12581257

1258+
cf_xarray.set_options(custom_criteria=my_custom_criteria)
1259+
12591260
# Match by name regex match
12601261
ds = xr.Dataset()
12611262
ds["salinity"] = ("dim", np.arange(10))
@@ -1301,16 +1302,16 @@ def test_custom_criteria():
13011302
)
13021303

13031304
# test criteria list of dicts
1304-
cf_xarray.accessor.set_options(my_custom_criteria_list)
1305-
ds = xr.Dataset()
1306-
ds["temperature"] = ("dim", np.arange(10))
1307-
assert_identical(ds.cf["temp"], ds["temperature"])
1305+
with cf_xarray.set_options(custom_criteria=my_custom_criteria_list):
1306+
ds = xr.Dataset()
1307+
ds["temperature"] = ("dim", np.arange(10))
1308+
assert_identical(ds.cf["temp"], ds["temperature"])
13081309

13091310
# test criteria tuple of dicts
1310-
cf_xarray.accessor.set_options(my_custom_criteria_tuple)
1311-
ds = xr.Dataset()
1312-
ds["temperature"] = ("dim", np.arange(10))
1313-
assert_identical(ds.cf["temp"], ds["temperature"])
1311+
with cf_xarray.set_options(custom_criteria=my_custom_criteria_tuple):
1312+
ds = xr.Dataset()
1313+
ds["temperature"] = ("dim", np.arange(10))
1314+
assert_identical(ds.cf["temp"], ds["temperature"])
13141315

13151316

13161317
def test_cf_standard_name_table_version():

cf_xarray/tests/test_options.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"""
2+
Tests OPTIONS logic brought in from xarray.
3+
"""
4+
5+
import pytest
6+
7+
import cf_xarray as cfxr
8+
9+
10+
def test_options():
11+
12+
# test for inputting a nonexistent option
13+
with pytest.raises(ValueError):
14+
cfxr.set_options(DISPLAY_WIDTH=80)

0 commit comments

Comments
 (0)