1
- import collections .abc
2
1
from collections import OrderedDict
3
2
from contextlib import contextmanager
4
- from typing import Any , Hashable , Mapping , Iterator , Union , TYPE_CHECKING
3
+ from typing import (
4
+ TYPE_CHECKING ,
5
+ Any ,
6
+ Hashable ,
7
+ Mapping ,
8
+ Iterator ,
9
+ Union ,
10
+ Set ,
11
+ Tuple ,
12
+ Sequence ,
13
+ cast ,
14
+ )
5
15
6
16
import pandas as pd
7
17
8
18
from . import formatting , indexing
19
+ from .indexes import Indexes
9
20
from .merge import (
10
21
expand_and_merge_variables ,
11
22
merge_coords ,
23
34
_THIS_ARRAY = ReprObject ("<this-array>" )
24
35
25
36
26
- class AbstractCoordinates (collections .abc .Mapping ):
27
- def __getitem__ (self , key ):
28
- raise NotImplementedError
37
+ class AbstractCoordinates (Mapping [Hashable , "DataArray" ]):
38
+ _data = None # type: Union["DataArray", "Dataset"]
29
39
30
- def __setitem__ (self , key , value ):
40
+ def __getitem__ (self , key : Hashable ) -> "DataArray" :
41
+ raise NotImplementedError ()
42
+
43
+ def __setitem__ (self , key : Hashable , value : Any ) -> None :
31
44
self .update ({key : value })
32
45
33
46
@property
34
- def indexes (self ):
47
+ def _names (self ) -> Set [Hashable ]:
48
+ raise NotImplementedError ()
49
+
50
+ @property
51
+ def dims (self ) -> Union [Mapping [Hashable , int ], Tuple [Hashable , ...]]:
52
+ raise NotImplementedError ()
53
+
54
+ @property
55
+ def indexes (self ) -> Indexes :
35
56
return self ._data .indexes
36
57
37
58
@property
38
59
def variables (self ):
39
- raise NotImplementedError
60
+ raise NotImplementedError ()
40
61
41
62
def _update_coords (self , coords ):
42
- raise NotImplementedError
63
+ raise NotImplementedError ()
43
64
44
- def __iter__ (self ):
65
+ def __iter__ (self ) -> Iterator [ "Hashable" ] :
45
66
# needs to be in the same order as the dataset variables
46
67
for k in self .variables :
47
68
if k in self ._names :
48
69
yield k
49
70
50
- def __len__ (self ):
71
+ def __len__ (self ) -> int :
51
72
return len (self ._names )
52
73
53
- def __contains__ (self , key ) :
74
+ def __contains__ (self , key : Hashable ) -> bool :
54
75
return key in self ._names
55
76
56
- def __repr__ (self ):
77
+ def __repr__ (self ) -> str :
57
78
return formatting .coords_repr (self )
58
79
59
- @property
60
- def dims (self ):
61
- return self ._data .dims
80
+ def to_dataset (self ) -> "Dataset" :
81
+ raise NotImplementedError ()
62
82
63
- def to_index (self , ordered_dims = None ):
83
+ def to_index (self , ordered_dims : Sequence [ Hashable ] = None ) -> pd . Index :
64
84
"""Convert all index coordinates into a :py:class:`pandas.Index`.
65
85
66
86
Parameters
67
87
----------
68
- ordered_dims : sequence, optional
88
+ ordered_dims : sequence of hashable , optional
69
89
Possibly reordered version of this object's dimensions indicating
70
90
the order in which dimensions should appear on the result.
71
91
@@ -77,7 +97,7 @@ def to_index(self, ordered_dims=None):
77
97
than more dimension.
78
98
"""
79
99
if ordered_dims is None :
80
- ordered_dims = self .dims
100
+ ordered_dims = list ( self .dims )
81
101
elif set (ordered_dims ) != set (self .dims ):
82
102
raise ValueError (
83
103
"ordered_dims must match dims, but does not: "
@@ -94,7 +114,7 @@ def to_index(self, ordered_dims=None):
94
114
names = list (ordered_dims )
95
115
return pd .MultiIndex .from_product (indexes , names = names )
96
116
97
- def update (self , other ) :
117
+ def update (self , other : Mapping [ Hashable , Any ]) -> None :
98
118
other_vars = getattr (other , "variables" , other )
99
119
coords = merge_coords (
100
120
[self .variables , other_vars ], priority_arg = 1 , indexes = self .indexes
@@ -127,7 +147,7 @@ def _merge_inplace(self, other):
127
147
yield
128
148
self ._update_coords (variables )
129
149
130
- def merge (self , other ) :
150
+ def merge (self , other : "AbstractCoordinates" ) -> "Dataset" :
131
151
"""Merge two sets of coordinates to create a new Dataset
132
152
133
153
The method implements the logic used for joining coordinates in the
@@ -167,32 +187,38 @@ class DatasetCoordinates(AbstractCoordinates):
167
187
objects.
168
188
"""
169
189
170
- def __init__ (self , dataset ):
190
+ _data = None # type: Dataset
191
+
192
+ def __init__ (self , dataset : "Dataset" ):
171
193
self ._data = dataset
172
194
173
195
@property
174
- def _names (self ):
196
+ def _names (self ) -> Set [ Hashable ] :
175
197
return self ._data ._coord_names
176
198
177
199
@property
178
- def variables (self ):
200
+ def dims (self ) -> Mapping [Hashable , int ]:
201
+ return self ._data .dims
202
+
203
+ @property
204
+ def variables (self ) -> Mapping [Hashable , Variable ]:
179
205
return Frozen (
180
206
OrderedDict (
181
207
(k , v ) for k , v in self ._data .variables .items () if k in self ._names
182
208
)
183
209
)
184
210
185
- def __getitem__ (self , key ) :
211
+ def __getitem__ (self , key : Hashable ) -> "DataArray" :
186
212
if key in self ._data .data_vars :
187
213
raise KeyError (key )
188
- return self ._data [key ]
214
+ return cast ( "DataArray" , self ._data [key ])
189
215
190
- def to_dataset (self ):
216
+ def to_dataset (self ) -> "Dataset" :
191
217
"""Convert these coordinates into a new Dataset
192
218
"""
193
219
return self ._data ._copy_listed (self ._names )
194
220
195
- def _update_coords (self , coords ) :
221
+ def _update_coords (self , coords : Mapping [ Hashable , Any ]) -> None :
196
222
from .dataset import calculate_dimensions
197
223
198
224
variables = self ._data ._variables .copy ()
@@ -210,7 +236,7 @@ def _update_coords(self, coords):
210
236
self ._data ._dims = dims
211
237
self ._data ._indexes = None
212
238
213
- def __delitem__ (self , key ) :
239
+ def __delitem__ (self , key : Hashable ) -> None :
214
240
if key in self :
215
241
del self ._data [key ]
216
242
else :
@@ -232,17 +258,23 @@ class DataArrayCoordinates(AbstractCoordinates):
232
258
dimensions and the values given by corresponding DataArray objects.
233
259
"""
234
260
235
- def __init__ (self , dataarray ):
261
+ _data = None # type: DataArray
262
+
263
+ def __init__ (self , dataarray : "DataArray" ):
236
264
self ._data = dataarray
237
265
238
266
@property
239
- def _names (self ):
267
+ def dims (self ) -> Tuple [Hashable , ...]:
268
+ return self ._data .dims
269
+
270
+ @property
271
+ def _names (self ) -> Set [Hashable ]:
240
272
return set (self ._data ._coords )
241
273
242
- def __getitem__ (self , key ) :
274
+ def __getitem__ (self , key : Hashable ) -> "DataArray" :
243
275
return self ._data ._getitem_coord (key )
244
276
245
- def _update_coords (self , coords ):
277
+ def _update_coords (self , coords ) -> None :
246
278
from .dataset import calculate_dimensions
247
279
248
280
coords_plus_data = coords .copy ()
@@ -259,19 +291,15 @@ def _update_coords(self, coords):
259
291
def variables (self ):
260
292
return Frozen (self ._data ._coords )
261
293
262
- def _to_dataset (self , shallow_copy = True ) :
294
+ def to_dataset (self ) -> "Dataset" :
263
295
from .dataset import Dataset
264
296
265
297
coords = OrderedDict (
266
- (k , v .copy (deep = False ) if shallow_copy else v )
267
- for k , v in self ._data ._coords .items ()
298
+ (k , v .copy (deep = False )) for k , v in self ._data ._coords .items ()
268
299
)
269
300
return Dataset ._from_vars_and_coord_names (coords , set (coords ))
270
301
271
- def to_dataset (self ):
272
- return self ._to_dataset ()
273
-
274
- def __delitem__ (self , key ):
302
+ def __delitem__ (self , key : Hashable ) -> None :
275
303
del self ._data ._coords [key ]
276
304
277
305
def _ipython_key_completions_ (self ):
@@ -300,9 +328,10 @@ def __len__(self) -> int:
300
328
return len (self ._data ._level_coords )
301
329
302
330
303
- def assert_coordinate_consistent (obj , coords ):
304
- """ Maeke sure the dimension coordinate of obj is
305
- consistent with coords.
331
+ def assert_coordinate_consistent (
332
+ obj : Union ["DataArray" , "Dataset" ], coords : Mapping [Hashable , Variable ]
333
+ ) -> None :
334
+ """Make sure the dimension coordinate of obj is consistent with coords.
306
335
307
336
obj: DataArray or Dataset
308
337
coords: Dict-like of variables
@@ -320,17 +349,20 @@ def assert_coordinate_consistent(obj, coords):
320
349
321
350
322
351
def remap_label_indexers (
323
- obj , indexers = None , method = None , tolerance = None , ** indexers_kwargs
324
- ):
325
- """
326
- Remap **indexers from obj.coords.
327
- If indexer is an instance of DataArray and it has coordinate, then this
328
- coordinate will be attached to pos_indexers.
352
+ obj : Union ["DataArray" , "Dataset" ],
353
+ indexers : Mapping [Hashable , Any ] = None ,
354
+ method : str = None ,
355
+ tolerance = None ,
356
+ ** indexers_kwargs : Any
357
+ ) -> Tuple [dict , dict ]: # TODO more precise return type after annotations in indexing
358
+ """Remap indexers from obj.coords.
359
+ If indexer is an instance of DataArray and it has coordinate, then this coordinate
360
+ will be attached to pos_indexers.
329
361
330
362
Returns
331
363
-------
332
364
pos_indexers: Same type of indexers.
333
- np.ndarray or Variable or DataArra
365
+ np.ndarray or Variable or DataArray
334
366
new_indexes: mapping of new dimensional-coordinate.
335
367
"""
336
368
from .dataarray import DataArray
0 commit comments