-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make Indexer classes not inherit from tuple. #1705
Conversation
I'm not entirely sure this is a good idea. The advantage is that it ensures that all our indexing code is entirely explicit: everything that reaches a backend *must* be an ExplicitIndexer. The downside is that it removes a bit of internal flexibility: we can't just use tuples in place of basic indexers anymore. On the whole, I think this is probably worth it but I would appreciate feedback.
This looks pretty clean and less error-prone. For more cleanliness, I'm wondering if we could more clearly distinguish between raw array-wrappers (such as Regarding the more array-type support in the future (as suggested in comment), |
There's been discussion about abstract classes on the NumPy mailing list.
It would be nice to use something standard if possible:
https://mail.python.org/pipermail/numpy-discussion/2017-November/thread.html#77312
…On Thu, Nov 9, 2017 at 6:19 AM Keisuke Fujii ***@***.***> wrote:
This looks pretty clean and less error-prone.
For more cleanliness, I'm wondering if we could more clearly distinguish
between raw array-wrappers (such as NumpyIndexingAdapter) and wrappers of
array-wrapper (such as MemoryCachedArray).
But as a whole, I like this idea.
Regarding the more array-type support in the future (as suggested in
comment
<#1617 (comment)>),
is there something to prepare in this PR?
I guess there are some typical indexing types, such as Fortran-type and
Numpy-type.
Can we have some abstract classes (maybe too early)?
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#1705 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ABKS1tRYI6F0WTmR9ozdBdvy0g6Yi-Ipks5s0wnagaJpZM4QXhhG>
.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few comments.
xarray/core/variable.py
Outdated
@@ -766,6 +769,7 @@ def chunk(self, chunks=None, name=None, lock=False): | |||
if utils.is_dict_like(chunks): | |||
chunks = tuple(chunks.get(n, s) | |||
for n, s in enumerate(self.shape)) | |||
data = indexing.WrapImplicitIndexing(data, indexing.OuterIndexer) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this line necessary here? (and only OuterIndexer?)
I think it would be better if we could have a simple comment above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a comment to explain, with a link to the upstream dask issue (dask/dask#2883).
xarray/core/indexing.py
Outdated
return key.tuple | ||
|
||
|
||
class WrapImplicitIndexing(utils.NDArrayMixin): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This name sounds like a function which behaves opposite to unwrap_explicit_indexer
. Can we change this something like ImplicitIndexedArrayWrapper
?
(But as the below comment, I did not yet understand how this wrapper will be used.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed to ImplicitToExplicitIndexingAdapter
, which is more consistent with the "Adapter" names of the other array wrapper classes. It's long but descriptive.
xarray/core/indexing.py
Outdated
|
||
|
||
class VectorizedIndexer(IndexerTuple): | ||
""" Tuple for vectorized indexing """ | ||
class ExplicitNDArrayMixin(utils.NDArrayMixin, ExplicitlyIndexed): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like a more explicit name such as ExplicitlyIndexedNDArrayMixin
. Is it too long?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's definitely better. Renamed.
xarray/core/indexing.py
Outdated
new_key = [] | ||
for k in key: | ||
if isinstance(k, integer_types): | ||
k = int(k) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks a good idea over checking an integer type in array wrappers 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your review @fujiisoup !
xarray/core/indexing.py
Outdated
|
||
|
||
class VectorizedIndexer(IndexerTuple): | ||
""" Tuple for vectorized indexing """ | ||
class ExplicitNDArrayMixin(utils.NDArrayMixin, ExplicitlyIndexed): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's definitely better. Renamed.
xarray/core/indexing.py
Outdated
return key.tuple | ||
|
||
|
||
class WrapImplicitIndexing(utils.NDArrayMixin): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed to ImplicitToExplicitIndexingAdapter
, which is more consistent with the "Adapter" names of the other array wrapper classes. It's long but descriptive.
xarray/core/variable.py
Outdated
@@ -766,6 +769,7 @@ def chunk(self, chunks=None, name=None, lock=False): | |||
if utils.is_dict_like(chunks): | |||
chunks = tuple(chunks.get(n, s) | |||
for n, s in enumerate(self.shape)) | |||
data = indexing.WrapImplicitIndexing(data, indexing.OuterIndexer) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a comment to explain, with a link to the upstream dask issue (dask/dask#2883).
I plan to merge this shortly and issue another release candidate unless any one has objections. It does occur to me that this could break custom backends, since they will not longer be getting tuples as indexers. @rabernat any ideas for how to minimize that pain? |
xarray/core/variable.py
Outdated
@@ -1261,7 +1270,7 @@ def equals(self, other, equiv=duck_array_ops.array_equiv): | |||
return (self.dims == other.dims and | |||
(self._data is other._data or | |||
equiv(self.data, other.data))) | |||
except (TypeError, AttributeError): | |||
except (TypeError, AttributeError) as e: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it doesn't look like e
is ever used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, this was introduced in debugging
Actually, looking over @rabernat's custom backend code in xmitgcm, I think that should be OK. This would only be a problem if you pass custom duck arrays into |
OK, merging. Hopefully we'll catch any issues in the next release candidate! |
I'm not entirely sure this is a good idea. The advantage is that it ensures that
all our indexing code is entirely explicit: everything that reaches a backend
must be an ExplicitIndexer. The downside is that it removes a bit of
internal flexibility: we can't just use tuples in place of basic indexers
anymore. On the whole, I think this is probably worth it but I would appreciate
feedback.
@fujiisoup can you take a look?
git diff upstream/master **/*py | flake8 --diff