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
BUG: fix a crash when retrieving rows from a multiple-index table #15826
base: main
Are you sure you want to change the base?
BUG: fix a crash when retrieving rows from a multiple-index table #15826
Conversation
Thank you for your contribution to Astropy! 🌌 This checklist is meant to remind the package maintainers who will review this pull request of some common things to look for.
|
👋 Thank you for your draft pull request! Do you know that you can use |
def _get_rows( | ||
self, | ||
item: int | Iterable[int] | slice | tuple[str, slice], | ||
) -> list[np.int64]: |
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.
obviously, these annotations are not part of the fix, rather a byproduct of my time spent looking for the bug :)
3147175
to
440fa77
Compare
astropy/table/tests/test_index.py
Outdated
if isinstance(main_col, Time): | ||
pytest.skip() |
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 don't know enough about whether this case should be supported too, and since it doesn't pass the test yet, I just skip it. I can look more into it if needed.
@@ -853,7 +864,7 @@ def _get_rows(self, item): | |||
# item should be a list or ndarray of values | |||
rows = [] | |||
for key in item: | |||
p = index.find((key,)) | |||
p = index.find(key if isinstance(key, tuple) else (key,)) |
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.
@taldcroft this part of the fix is yours. Let me know if I should explicitly add you as a co-author of the commit.
440fa77
to
80a9dda
Compare
""" | ||
Retrieve Table rows indexes by value slice. | ||
""" | ||
if isinstance(item, tuple): | ||
if ( |
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 note that this block is identical to
astropy/astropy/table/index.py
Lines 950 to 953 in 9cd4f4f
if isinstance(item, tuple): | |
key, item = item | |
else: | |
key = self.table.primary_key |
So I suppose it should be updated as well, and probably even abstracted away in a helper function to avoid repeated code.
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.
On the other hand I don't know if that would fix anything currently broken. In other words, I don't know that iloc
needs it.
80a9dda
to
288186d
Compare
rebased to resolve a merge conflict |
I'm not sure whether RTD failures are related or even reproducible. @pllim can you retrigger please ? |
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
Interesting... It fails again but at a new place |
thank you very much ! |
RTD green now! |
I'm looking at this now... |
One quick comment is that we should treat this as a feature enhancement not a bug. The original code specifically disallowed this case, so it was not really a bug. It does make me wonder if the original developer had some reason to be worried about opening up the multi-index case, but so far it looks ok. I'm going to need to play around with this a little out of your branch so no need to make the bug -> feature change just yet. |
@neutrinoceros - here is my playing in the gist below. Interestingly for me it actually works fine with I might suggest writing the test more like what I did. For this test we can trust that |
Very interesting, thank you very much ! |
I dug into it, and found that the root cause is that astropy/astropy/table/sorted_array.py Line 152 in dfe5d93
and in the example you wrote using a |
288186d
to
d7d5540
Compare
Actually, even a simple index will break: import astropy.units as u
from astropy.table import QTable
t = QTable({"a": u.Quantity([0], unit="m")})
t.add_index(["a"])
t.loc[t["a"][0]] fails with Traceback (most recent call last):
File "/Users/clm/dev/astropy-project/coordinated/astropy/t.py", line 6, in <module>
t.loc[t["a"][0]]
~~~~~^^^^^^^^^^^
File "/Users/clm/dev/astropy-project/coordinated/astropy/astropy/table/index.py", line 888, in __getitem__
rows = self._get_rows(item)
^^^^^^^^^^^^^^^^^^^^
File "/Users/clm/dev/astropy-project/coordinated/astropy/astropy/table/index.py", line 867, in _get_rows
for key in item:
File "/Users/clm/dev/astropy-project/coordinated/astropy/astropy/units/quantity.py", line 1283, in __iter__
raise TypeError(
TypeError: 'Quantity' object with a scalar value is not iterable (same error on t.loc[t["a"][0].value] So, it seems to me that either we have a different bug on our hand (in which case it should be reported separately and not block this PR), or the test case needs to be adapted, depending on wether this behaviour is intentional or not. What do you think @taldcroft ? |
I opened #16036 to discuss this issue separately. Meanwhile, I'll drop the test case using |
d7d5540
to
c784960
Compare
c784960
to
9436b95
Compare
9436b95
to
d674245
Compare
d674245
to
2b01fab
Compare
Description
Fixes #13176
I need to refine the test, it's currently run 3 times with no variations because of how I introduced it in a heavily parametrized test class.
Opening as a draft for now to see if it already survives full CI.