From 3a8896e7e0af852192d26dcaee5fae6fbd70f1f0 Mon Sep 17 00:00:00 2001 From: Stephan Hoyer Date: Fri, 1 Jan 2016 15:09:10 -0800 Subject: [PATCH] Check that dimensions are all valid when using reindex This fixes the underlying issue that allowed GH693. --- xray/core/alignment.py | 7 ++++++- xray/core/dataarray.py | 4 +++- xray/core/dataset.py | 8 +++++++- xray/core/merge.py | 7 +++++-- xray/test/test_dataset.py | 4 ++++ 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/xray/core/alignment.py b/xray/core/alignment.py index bc4010c2d87..d5b0692aca1 100644 --- a/xray/core/alignment.py +++ b/xray/core/alignment.py @@ -84,7 +84,12 @@ def align(*objects, **kwargs): % list(kwargs)) joined_indexes = _join_indexes(join, objects) - return tuple(obj.reindex(copy=copy, **joined_indexes) for obj in objects) + result = [] + for obj in objects: + valid_indexers = dict((k, v) for k, v in joined_indexes.items() + if k in obj.dims) + result.append(obj.reindex(copy=copy, **valid_indexers)) + return tuple(result) def partial_align(*objects, **kwargs): diff --git a/xray/core/dataarray.py b/xray/core/dataarray.py index 3db54faf8b6..87a297d7780 100644 --- a/xray/core/dataarray.py +++ b/xray/core/dataarray.py @@ -658,8 +658,10 @@ def reindex_like(self, other, method=None, tolerance=None, copy=True): DataArray.reindex align """ + indexers = dict((k, v) for k, v in other.indexes.items() + if k in self.dims) return self.reindex(method=method, tolerance=tolerance, copy=copy, - **other.indexes) + **indexers) def reindex(self, method=None, tolerance=None, copy=True, **indexers): """Conform this object onto a new set of indexes, filling in diff --git a/xray/core/dataset.py b/xray/core/dataset.py index 964b298c1be..62de1c43273 100644 --- a/xray/core/dataset.py +++ b/xray/core/dataset.py @@ -1152,8 +1152,10 @@ def reindex_like(self, other, method=None, tolerance=None, copy=True): Dataset.reindex align """ + indexers = dict((k, v) for k, v in other.indexes.items() + if k in self.dims) return self.reindex(method=method, copy=copy, tolerance=tolerance, - **other.indexes) + **indexers) def reindex(self, indexers=None, method=None, tolerance=None, copy=True, **kw_indexers): """Conform this object onto a new set of indexes, filling in @@ -1203,6 +1205,10 @@ def reindex(self, indexers=None, method=None, tolerance=None, copy=True, **kw_in # shortcut return self.copy(deep=True) if copy else self + bad_dims = [d for d in indexers if d not in self.dims] + if bad_dims: + raise ValueError('invalid reindex dimensions: %s' % bad_dims) + variables = alignment.reindex_variables( self.variables, self.indexes, indexers, method, tolerance, copy=copy) return self._replace_vars_and_dims(variables) diff --git a/xray/core/merge.py b/xray/core/merge.py index 5f6c7ede787..0b7d61592a6 100644 --- a/xray/core/merge.py +++ b/xray/core/merge.py @@ -151,8 +151,11 @@ def _reindex_variables_against(variables, indexes, copy=False): """Reindex all DataArrays in the provided dict, leaving other values alone. """ alignable = [k for k, v in variables.items() if hasattr(v, 'indexes')] - aligned = [variables[a].reindex(copy=copy, **indexes) - for a in alignable] + aligned = [] + for a in alignable: + valid_indexes = dict((k, v) for k, v in indexes.items() + if k in variables[a].dims) + aligned.append(variables[a].reindex(copy=copy, **valid_indexes)) new_variables = OrderedDict(variables) new_variables.update(zip(alignable, aligned)) return new_variables diff --git a/xray/test/test_dataset.py b/xray/test/test_dataset.py index 7213d3293d9..18c2279c392 100644 --- a/xray/test/test_dataset.py +++ b/xray/test/test_dataset.py @@ -868,6 +868,10 @@ def test_reindex(self): with self.assertRaisesRegexp(ValueError, 'dictionary'): data.reindex('foo') + # invalid dimension + with self.assertRaisesRegexp(ValueError, 'invalid reindex dim'): + data.reindex(invalid=0) + # out of order expected = data.sel(dim1=data['dim1'][:10:-1]) actual = data.reindex(dim1=data['dim1'][:10:-1])