Skip to content

Commit d2a495c

Browse files
authored
Clean up utils (#131)
1 parent 78f1683 commit d2a495c

File tree

2 files changed

+30
-75
lines changed

2 files changed

+30
-75
lines changed

cf_xarray/accessor.py

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import inspect
33
import itertools
44
import warnings
5-
from collections import ChainMap, defaultdict
5+
from collections import ChainMap
66
from typing import (
77
Any,
88
Callable,
@@ -21,7 +21,7 @@
2121
from xarray import DataArray, Dataset
2222

2323
from .helpers import bounds_to_vertices
24-
from .utils import parse_cell_methods_attr
24+
from .utils import _is_datetime_like, invert_mappings, parse_cell_methods_attr
2525

2626
#: Classes wrapped by cf_xarray.
2727
_WRAPPED_CLASSES = (
@@ -140,37 +140,6 @@
140140
attrs["vertical"] = attrs["Z"]
141141

142142

143-
def _is_datetime_like(da: DataArray) -> bool:
144-
import numpy as np
145-
146-
if np.issubdtype(da.dtype, np.datetime64) or np.issubdtype(
147-
da.dtype, np.timedelta64
148-
):
149-
return True
150-
151-
try:
152-
import cftime
153-
154-
if isinstance(da.data[0], cftime.datetime):
155-
return True
156-
except ImportError:
157-
pass
158-
159-
return False
160-
161-
162-
def invert_mappings(*mappings):
163-
"""Takes a set of mappings and iterates through, inverting to make a
164-
new mapping of value: set(keys). Keys are deduplicated to avoid clashes between
165-
standard_name and coordinate names."""
166-
merged = defaultdict(set)
167-
for mapping in mappings:
168-
for k, v in mapping.items():
169-
for name in v:
170-
merged[name] |= set([k])
171-
return merged
172-
173-
174143
# Type for Mapper functions
175144
Mapper = Callable[[Union[DataArray, Dataset], str], List[str]]
176145

cf_xarray/utils.py

Lines changed: 28 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,26 @@
1-
from typing import Any, Dict, Hashable, Mapping, Optional, TypeVar, cast
1+
from collections import defaultdict
2+
from typing import Dict
23

3-
K = TypeVar("K")
4-
V = TypeVar("V")
5-
T = TypeVar("T")
4+
from xarray import DataArray
65

76

8-
def either_dict_or_kwargs(
9-
pos_kwargs: Optional[Mapping[Hashable, T]],
10-
kw_kwargs: Mapping[str, T],
11-
func_name: str,
12-
) -> Mapping[Hashable, T]:
13-
if pos_kwargs is not None:
14-
if not is_dict_like(pos_kwargs):
15-
raise ValueError(
16-
"the first argument to .%s must be a dictionary" % func_name
17-
)
18-
if kw_kwargs:
19-
raise ValueError(
20-
"cannot specify both keyword and positional "
21-
"arguments to .%s" % func_name
22-
)
23-
return pos_kwargs
24-
else:
25-
# Need an explicit cast to appease mypy due to invariance; see
26-
# https://github.com/python/mypy/issues/6228
27-
return cast(Mapping[Hashable, T], kw_kwargs)
7+
def _is_datetime_like(da: DataArray) -> bool:
8+
import numpy as np
289

10+
if np.issubdtype(da.dtype, np.datetime64) or np.issubdtype(
11+
da.dtype, np.timedelta64
12+
):
13+
return True
2914

30-
def is_dict_like(value: Any) -> bool:
31-
return hasattr(value, "keys") and hasattr(value, "__getitem__")
15+
try:
16+
import cftime
3217

18+
if isinstance(da.data[0], cftime.datetime):
19+
return True
20+
except ImportError:
21+
pass
3322

34-
# copied from xarray
35-
class UncachedAccessor:
36-
"""Acts like a property, but on both classes and class instances
37-
This class is necessary because some tools (e.g. pydoc and sphinx)
38-
inspect classes for which property returns itself and not the
39-
accessor.
40-
"""
41-
42-
def __init__(self, accessor):
43-
self._accessor = accessor
44-
45-
def __get__(self, obj, cls):
46-
if obj is None:
47-
return self._accessor
48-
49-
return self._accessor(obj)
23+
return False
5024

5125

5226
def parse_cell_methods_attr(attr: str) -> Dict[str, str]:
@@ -67,3 +41,15 @@ def parse_cell_methods_attr(attr: str) -> Dict[str, str]:
6741
raise ValueError(f"attrs['cell_measures'] = {attr!r} is malformed.")
6842

6943
return dict(zip(strings[slice(0, None, 2)], strings[slice(1, None, 2)]))
44+
45+
46+
def invert_mappings(*mappings):
47+
"""Takes a set of mappings and iterates through, inverting to make a
48+
new mapping of value: set(keys). Keys are deduplicated to avoid clashes between
49+
standard_name and coordinate names."""
50+
merged = defaultdict(set)
51+
for mapping in mappings:
52+
for k, v in mapping.items():
53+
for name in v:
54+
merged[name] |= set([k])
55+
return merged

0 commit comments

Comments
 (0)