Remove compatibility code which forced loading all HDUs on close#6082
Remove compatibility code which forced loading all HDUs on close#6082bsipocz merged 6 commits intoastropy:masterfrom
Conversation
|
Yay. Still needs a change log. |
|
@pllim - yep, I should play the "guess PR number" game ;) |
astropy/io/fits/tests/test_image.py
Outdated
| assert phdr['FILENAME'] == 'labq01i3q_rawtag.fits' | ||
|
|
||
| @raises(ValueError) | ||
| @raises(IndexError) |
There was a problem hiding this comment.
The only "unexpected" change is this: with the new behavior the index error when accessing the HDU happens before the ValueError that was raised when trying to access the data. So I think it's fine.
There was a problem hiding this comment.
Someone who currently catches that as ValueError will need to change their code, so this needs to be mentioned in your change log.
There was a problem hiding this comment.
Shouldn't we use the contextmanager instead? Doesn't have to be for all tests but since we're changing this one it might be a perfect opportunity.
There was a problem hiding this comment.
@saimn , do you plan to address the context manager comment?
There was a problem hiding this comment.
@embray - Thanks for reviewing this! You're right about the exception message that should be more helpful, I will implement this. But I'm also confused by your last sentence, is it possible to have _read_all = True if the file is not completely read ?
There was a problem hiding this comment.
@embray - self._read_all is set to True when the file is closed (https://github.com/astropy/astropy/blob/master/astropy/io/fits/hdu/hdulist.py#L1146). So it would be necessary to keep the part of the code deleted in this PR which computes self._total_read ?
There must be a way to know if the file was fully read (with the EOFError block I guess), but currently it is not possible, so the commit I just pushed modifies the exception message unconditionally for now.
Maybe it's good enough ? I mean is it useful to add more complexity to something already quite complex, just to get a more correct exception message for a very specific case.
There was a problem hiding this comment.
I mean, maybe this is actually a bit tricky to determine, but my thinking was that you know the size of the file, and when you read a header you know, at least for a well-formed file, how many bytes should be left in the file (for the data in that HDU). And if there are more bytes beyond the end of the data then you haven't read the whole file yet. There could still be more HDUs.
There was a problem hiding this comment.
Yes I agree it could be done, I'm just not sure of the best way. And self._read_all should already give this information, so is it better to add a new way to know if the file was fully read ? Instead why not simply removing the line that set self._read_all to True when the file is closed ? I guess this line is there to avoid running again the beginnning of _read_next_hdu, but if the file is closed it's possible anyway to return earlier.
|
Guess the PR number games have been successful for me. 😉 |
CHANGES.rst
Outdated
| [#5929] | ||
|
|
||
| - Remove compatibility code which forced loading all HDUs on close. The old | ||
| behavior can be used with `lazy_load_hdus=False`. Because of this change, |
There was a problem hiding this comment.
always use double backticks in the changelog, we never do intersphinx linking from here. Fixing this and the next line will get rid of the docs build error on travis, too.
There was a problem hiding this comment.
oops sorry, and yet I know it ...
pllim
left a comment
There was a problem hiding this comment.
Aside of minor comments, LGTM. Also need squashing (and maybe rebase while you are at it)?
|
|
||
| def test_open_3(self): | ||
| # Test that HDUs cannot be accessed after the file was closed | ||
| r = fits.open(self.data('test0.fits')) |
There was a problem hiding this comment.
Should we also test the context manager (since that is how we recommend open be done anyway, or at least I do) or does it not matter?
There was a problem hiding this comment.
It does not really matter here as the file is closed just after.
CHANGES.rst
Outdated
| - Remove compatibility code which forced loading all HDUs on close. The old | ||
| behavior can be used with ``lazy_load_hdus=False``. Because of this change, | ||
| trying to access the ``.data`` attribute from an HDU which is not loaded now | ||
| raises a IndexError instead of a ValueError. [#6082] |
There was a problem hiding this comment.
Nitpick: Also add double-backticks to IndexError and ValueError.
There was a problem hiding this comment.
Ok, I found the two versions in the CHANGES file, so I was not sure which one is preferred.
|
@pllim - Rebased and squashed. |
| # the deprecation period has passed. | ||
| if self._file and self._file.closed and self._total_read is not None: | ||
| if index > self._total_read - 1: | ||
| warnings.warn(textwrap.dedent( |
There was a problem hiding this comment.
What a shame, we lose the most verbose warning message I've ever seen... 😄
|
It's a good sign that the tests are passing and the changes look alright. :) |
|
I have one small-ish comment, but otherwise LGTM thanks @saimn ! |
|
Thank you @embray for reviewing this! |
|
Not sure if the tests failures are real or related to some pytest change (errors in |
|
Ok, so the test failures are indeed related to 88315b3 and the Example before 88315b3, where After 88315b3, |
|
What PR was that commit tied to? My GitHub-fu is insufficient to sniff that out. |
|
@pllim - To this one, that is the 3rd commit here. |
|
Oh... 😅 😅 😅 |
|
Hehe ! The goal of this commit was to have different messages for the |
|
I'm not sure how related the following is, but I thought I'd mention it here before opening a separate issue. I also apologize for not having time to check against the current master branch, but I only have AstroPy 1.3.3 easily at hand. In Sherpa we do "interesting" things for some of our file I/O, including trying to read in a file as FITS when it may not be. This ends up creating Running this script (AstroPy 1.3.3 and Python 3.5) produces the warning: |
|
@DougBurke - I see the same warning on master. |
|
@DougBurke - This warning is perfectly normal, as the file is not closed in your example (you should add a |
|
Just curious, what if you set |
|
@pllim (assuming you're talkiing to me; threading is not ideal here!) - I get the same warning if I use the following program: |
|
Ooh okay, understood, in this case because of the exception the |
|
Is it worth me opening a new ticket for this issue then @saimn ? |
|
@DougBurke , yes. |
|
As GitHub has already noted, I've created #6168 to track this - thanks for the input and sorry for highjacking this PR. |
|
So, back to my open files issue (#6082 (comment)): I found why most of the tests do not raise an error with |
Closes astropy#5582. astropy#5065 implemented lazy loading of HDUs in fits files. But it did it in a way that maintains backwards compatibility at the expense of performance, loading the remaining HDUs to allow read the headers after the file was closed. Basically this reverts 5c66c2d
|
I think I found the culprit, the function I added to handle the IndexError was keeping a reference to the HDUList object, preventing the file pointer to be closed by the gc ... |
|
@saimn does this change mean that my proposed change at #6168 (comment) isn't needed, or are they separate issues? |
|
@DougBurke - It's not related, but it makes me think about a workaround for your issue (to avoid the |
|
And tests pass now 🕺 🎉 |
|
Ok I think it's good to go now ! |
|
There was agreement on this above, so merging this now. Thanks @saimn! |
|
@saimn - thanks for the suggestion in #6082 (comment) - unfortunately our code isn't written in a way that lets us easily use this approach, but I'll keep it in mind as we refactor. |
Closes #5582, following the discussion there, i.e. Option 2: Remove the compatibility behavior for which almost everybody agreed. To get the old behavior, users can use
lazy_load_hdus=Falsewhich is equivalent by forcing the reading of all HDUs. So basically this reverts 5c66c2d. And the global option forlazy_load_hdusexists already, so I just added a test to make sure it works.ping @embray