1
1
"""Testing functions exposed to the user API"""
2
2
from collections import OrderedDict
3
+ from typing import Hashable , Union
3
4
4
5
import numpy as np
5
6
import pandas as pd
6
7
7
- from xarray .core import duck_array_ops , formatting
8
+ from xarray .core import duck_array_ops
9
+ from xarray .core import formatting
10
+ from xarray .core .dataarray import DataArray
11
+ from xarray .core .dataset import Dataset
12
+ from xarray .core .variable import IndexVariable , Variable
8
13
from xarray .core .indexes import default_indexes
9
14
10
15
@@ -48,12 +53,11 @@ def assert_equal(a, b):
48
53
assert_identical, assert_allclose, Dataset.equals, DataArray.equals,
49
54
numpy.testing.assert_array_equal
50
55
"""
51
- import xarray as xr
52
56
__tracebackhide__ = True # noqa: F841
53
57
assert type (a ) == type (b ) # noqa
54
- if isinstance (a , (xr . Variable , xr . DataArray )):
58
+ if isinstance (a , (Variable , DataArray )):
55
59
assert a .equals (b ), formatting .diff_array_repr (a , b , 'equals' )
56
- elif isinstance (a , xr . Dataset ):
60
+ elif isinstance (a , Dataset ):
57
61
assert a .equals (b ), formatting .diff_dataset_repr (a , b , 'equals' )
58
62
else :
59
63
raise TypeError ('{} not supported by assertion comparison'
@@ -77,15 +81,14 @@ def assert_identical(a, b):
77
81
--------
78
82
assert_equal, assert_allclose, Dataset.equals, DataArray.equals
79
83
"""
80
- import xarray as xr
81
84
__tracebackhide__ = True # noqa: F841
82
85
assert type (a ) == type (b ) # noqa
83
- if isinstance (a , xr . Variable ):
86
+ if isinstance (a , Variable ):
84
87
assert a .identical (b ), formatting .diff_array_repr (a , b , 'identical' )
85
- elif isinstance (a , xr . DataArray ):
88
+ elif isinstance (a , DataArray ):
86
89
assert a .name == b .name
87
90
assert a .identical (b ), formatting .diff_array_repr (a , b , 'identical' )
88
- elif isinstance (a , (xr . Dataset , xr . Variable )):
91
+ elif isinstance (a , (Dataset , Variable )):
89
92
assert a .identical (b ), formatting .diff_dataset_repr (a , b , 'identical' )
90
93
else :
91
94
raise TypeError ('{} not supported by assertion comparison'
@@ -117,15 +120,14 @@ def assert_allclose(a, b, rtol=1e-05, atol=1e-08, decode_bytes=True):
117
120
--------
118
121
assert_identical, assert_equal, numpy.testing.assert_allclose
119
122
"""
120
- import xarray as xr
121
123
__tracebackhide__ = True # noqa: F841
122
124
assert type (a ) == type (b ) # noqa
123
125
kwargs = dict (rtol = rtol , atol = atol , decode_bytes = decode_bytes )
124
- if isinstance (a , xr . Variable ):
126
+ if isinstance (a , Variable ):
125
127
assert a .dims == b .dims
126
128
allclose = _data_allclose_or_equiv (a .values , b .values , ** kwargs )
127
129
assert allclose , '{}\n {}' .format (a .values , b .values )
128
- elif isinstance (a , xr . DataArray ):
130
+ elif isinstance (a , DataArray ):
129
131
assert_allclose (a .variable , b .variable , ** kwargs )
130
132
assert set (a .coords ) == set (b .coords )
131
133
for v in a .coords .variables :
@@ -135,7 +137,7 @@ def assert_allclose(a, b, rtol=1e-05, atol=1e-08, decode_bytes=True):
135
137
b .coords [v ].values , ** kwargs )
136
138
assert allclose , '{}\n {}' .format (a .coords [v ].values ,
137
139
b .coords [v ].values )
138
- elif isinstance (a , xr . Dataset ):
140
+ elif isinstance (a , Dataset ):
139
141
assert set (a .data_vars ) == set (b .data_vars )
140
142
assert set (a .coords ) == set (b .coords )
141
143
for k in list (a .variables ) + list (a .coords ):
@@ -147,14 +149,12 @@ def assert_allclose(a, b, rtol=1e-05, atol=1e-08, decode_bytes=True):
147
149
148
150
149
151
def _assert_indexes_invariants_checks (indexes , possible_coord_variables , dims ):
150
- import xarray as xr
151
-
152
152
assert isinstance (indexes , OrderedDict ), indexes
153
153
assert all (isinstance (v , pd .Index ) for v in indexes .values ()), \
154
154
{k : type (v ) for k , v in indexes .items ()}
155
155
156
156
index_vars = {k for k , v in possible_coord_variables .items ()
157
- if isinstance (v , xr . IndexVariable )}
157
+ if isinstance (v , IndexVariable )}
158
158
assert indexes .keys () <= index_vars , (set (indexes ), index_vars )
159
159
160
160
# Note: when we support non-default indexes, these checks should be opt-in
@@ -166,17 +166,97 @@ def _assert_indexes_invariants_checks(indexes, possible_coord_variables, dims):
166
166
(indexes , defaults )
167
167
168
168
169
- def _assert_indexes_invariants (a ):
170
- """Separate helper function for checking indexes invariants only."""
171
- import xarray as xr
172
-
173
- if isinstance (a , xr .DataArray ):
174
- if a ._indexes is not None :
175
- _assert_indexes_invariants_checks (a ._indexes , a ._coords , a .dims )
176
- elif isinstance (a , xr .Dataset ):
177
- if a ._indexes is not None :
178
- _assert_indexes_invariants_checks (
179
- a ._indexes , a ._variables , a ._dims )
180
- elif isinstance (a , xr .Variable ):
181
- # no indexes
182
- pass
169
+ def _assert_variable_invariants (var : Variable , name : Hashable = None ):
170
+ if name is None :
171
+ name_or_empty = () # type: tuple
172
+ else :
173
+ name_or_empty = (name ,)
174
+ assert isinstance (var ._dims , tuple ), name_or_empty + (var ._dims ,)
175
+ assert len (var ._dims ) == len (var ._data .shape ), \
176
+ name_or_empty + (var ._dims , var ._data .shape )
177
+ assert isinstance (var ._encoding , (type (None ), dict )), \
178
+ name_or_empty + (var ._encoding ,)
179
+ assert isinstance (var ._attrs , (type (None ), OrderedDict )), \
180
+ name_or_empty + (var ._attrs ,)
181
+
182
+
183
+ def _assert_dataarray_invariants (da : DataArray ):
184
+ assert isinstance (da ._variable , Variable ), da ._variable
185
+ _assert_variable_invariants (da ._variable )
186
+
187
+ assert isinstance (da ._coords , OrderedDict ), da ._coords
188
+ assert all (
189
+ isinstance (v , Variable ) for v in da ._coords .values ()), da ._coords
190
+ assert all (set (v .dims ) <= set (da .dims ) for v in da ._coords .values ()), \
191
+ (da .dims , {k : v .dims for k , v in da ._coords .items ()})
192
+ assert all (isinstance (v , IndexVariable )
193
+ for (k , v ) in da ._coords .items ()
194
+ if v .dims == (k ,)), \
195
+ {k : type (v ) for k , v in da ._coords .items ()}
196
+ for k , v in da ._coords .items ():
197
+ _assert_variable_invariants (v , k )
198
+
199
+ if da ._indexes is not None :
200
+ _assert_indexes_invariants_checks (da ._indexes , da ._coords , da .dims )
201
+
202
+ assert da ._initialized is True
203
+
204
+
205
+ def _assert_dataset_invariants (ds : Dataset ):
206
+ assert isinstance (ds ._variables , OrderedDict ), type (ds ._variables )
207
+ assert all (
208
+ isinstance (v , Variable ) for v in ds ._variables .values ()), \
209
+ ds ._variables
210
+ for k , v in ds ._variables .items ():
211
+ _assert_variable_invariants (v , k )
212
+
213
+ assert isinstance (ds ._coord_names , set ), ds ._coord_names
214
+ assert ds ._coord_names <= ds ._variables .keys (), \
215
+ (ds ._coord_names , set (ds ._variables ))
216
+
217
+ assert type (ds ._dims ) is dict , ds ._dims
218
+ assert all (isinstance (v , int ) for v in ds ._dims .values ()), ds ._dims
219
+ var_dims = set () # type: set
220
+ for v in ds ._variables .values ():
221
+ var_dims .update (v .dims )
222
+ assert ds ._dims .keys () == var_dims , (set (ds ._dims ), var_dims )
223
+ assert all (ds ._dims [k ] == v .sizes [k ]
224
+ for v in ds ._variables .values ()
225
+ for k in v .sizes ), \
226
+ (ds ._dims , {k : v .sizes for k , v in ds ._variables .items ()})
227
+ assert all (isinstance (v , IndexVariable )
228
+ for (k , v ) in ds ._variables .items ()
229
+ if v .dims == (k ,)), \
230
+ {k : type (v ) for k , v in ds ._variables .items () if v .dims == (k ,)}
231
+ assert all (v .dims == (k ,)
232
+ for (k , v ) in ds ._variables .items ()
233
+ if k in ds ._dims ), \
234
+ {k : v .dims for k , v in ds ._variables .items () if k in ds ._dims }
235
+
236
+ if ds ._indexes is not None :
237
+ _assert_indexes_invariants_checks (ds ._indexes , ds ._variables , ds ._dims )
238
+
239
+ assert isinstance (ds ._encoding , (type (None ), dict ))
240
+ assert isinstance (ds ._attrs , (type (None ), OrderedDict ))
241
+ assert ds ._initialized is True
242
+
243
+
244
+ def _assert_internal_invariants (
245
+ xarray_obj : Union [DataArray , Dataset , Variable ],
246
+ ):
247
+ """Validate that an xarray object satisfies its own internal invariants.
248
+
249
+ This exists for the benefit of xarray's own test suite, but may be useful
250
+ in external projects if they (ill-advisedly) create objects using xarray's
251
+ private APIs.
252
+ """
253
+ if isinstance (xarray_obj , Variable ):
254
+ _assert_variable_invariants (xarray_obj )
255
+ elif isinstance (xarray_obj , DataArray ):
256
+ _assert_dataarray_invariants (xarray_obj )
257
+ elif isinstance (xarray_obj , Dataset ):
258
+ _assert_dataset_invariants (xarray_obj )
259
+ else :
260
+ raise TypeError (
261
+ '{} is not a supported type for xarray invariant checks'
262
+ .format (type (xarray_obj )))
0 commit comments