Skip to content

Regression in io.fits due to undefined variable #5594

Closed

Description

@astrofrog

@mwcraig @embray - I'm running into the following failure in glue due to the recent changes in io.fits:

    def _read_next_hdu(self):
        """
            Lazily load a single HDU from the fileobj or data string the `HDUList`
            was opened from, unless no further HDUs are found.
    
            Returns True if a new HDU was loaded, or False otherwise.
            """
    
        if self._read_all:
            return False
    
        saved_compression_enabled = compressed.COMPRESSION_ENABLED
        fileobj, data, kwargs = self._file, self._data, self._open_kwargs
    
        try:
            self._in_read_next_hdu = True
    
            if ('disable_image_compression' in kwargs and
                kwargs['disable_image_compression']):
                compressed.COMPRESSION_ENABLED = False
    
            # read all HDUs
            try:
                if fileobj is not None:
                    try:
                        # Make sure we're back to the end of the last read
                        # HDU
                        if len(self) > 0:
                            last = self[len(self) - 1]
                            if last._data_offset is not None:
                                offset = last._data_offset + last._data_size
                                fileobj.seek(offset, os.SEEK_SET)
    
                        hdu = _BaseHDU.readfrom(fileobj, **kwargs)
                    except EOFError:
                        self._read_all = True
                        return False
                    except ValueError:
                        # A ValueError can occur when trying to perform I/O
                        # on a closed file
                        if fileobj.closed:
                            self._read_all = True
                            return False
                        else:
                            raise
                    except IOError:
                        if fileobj.writeonly:
                            self._read_all = True
                            return False
                        else:
                            raise
                else:
                    if not data:
                        self._read_all = True
                        return False
                    hdu = _BaseHDU.fromstring(data, **kwargs)
                    self._data = data[hdu._data_offset + hdu._data_size:]
    
                super(HDUList, self).append(hdu)
                if len(self) == 1:
                    # Check for an extension HDU and update the EXTEND
                    # keyword of the primary HDU accordingly
                    self.update_extend()
    
                hdu._new = False
                if 'checksum' in kwargs:
                    hdu._output_checksum = kwargs['checksum']
            # check in the case there is extra space after the last HDU or
            # corrupted HDU
            except (VerifyError, ValueError) as exc:
                warnings.warn(
                    'Error validating header for HDU #{} (note: Astropy '
                    'uses zero-based indexing).\n{}\n'
                    'There may be extra bytes after the last HDU or the '
                    'file is corrupted.'.format(
>                       len(hdulist), indent(str(exc))), VerifyWarning)
E                       NameError: global name 'hdulist' is not defined

../../../miniconda/envs/test/lib/python2.7/site-packages/astropy/io/fits/hdu/hdulist.py:1150: NameError
============================ pytest-warning summary ============================

Activity

  1. added
    Affects-devPRs and issues that do not impact an existing Astropy release
    on Dec 12, 2016
  2. changed the title [-]Regression in glue due to undefined variable[/-] [+]Regression in io.fits due to undefined variable[/+] on Dec 12, 2016
  3. mwcraig commented on Dec 12, 2016

    @mwcraig
    Member

    I can fix up later today as part of #5589 or someone could push to that branch. Looks like an easy fix, but a regression test should be added for it too.

    Or a separate PR, of course.

  4. mwcraig commented on Dec 12, 2016

    @mwcraig
    Member

    @astrofrog -- do you have a short way to trigger this error? Ideally I'd add a test for it (the fix is easy) but I'm not having nay luck hitting that chunk of the code.

  5. astrofrog commented on Dec 12, 2016

    @astrofrog
    MemberAuthor

    @mwcraig - yep, any file that is not a FITS file that has unicode:

    In [6]: with open('test.fits', 'w') as f:
       ...:     f.write('Ceçi ne marche pas')
       ...:     
    
    In [7]: fits.open('test.fits')
    ---------------------------------------------------------------------------
    UnicodeDecodeError                        Traceback (most recent call last)
    /Users/tom/Dropbox/Code/Astropy/astropy/astropy/io/fits/hdu/hdulist.py in _read_next_hdu(self)
       1107 
    -> 1108                         hdu = _BaseHDU.readfrom(fileobj, **kwargs)
       1109                     except EOFError:
    
    /Users/tom/Dropbox/Code/Astropy/astropy/astropy/io/fits/hdu/base.py in readfrom(cls, fileobj, checksum, ignore_missing_end, **kwargs)
        328                                      ignore_missing_end=ignore_missing_end,
    --> 329                                      **kwargs)
        330 
    
    /Users/tom/Dropbox/Code/Astropy/astropy/astropy/io/fits/hdu/base.py in _readfrom_internal(cls, data, header, checksum, ignore_missing_end, **kwargs)
        393                 header_offset = data.tell()
    --> 394                 header = Header.fromfile(data, endcard=not ignore_missing_end)
        395             hdu_fileobj = data
    
    /Users/tom/Dropbox/Code/Astropy/astropy/astropy/io/fits/header.py in fromfile(cls, fileobj, sep, endcard, padding)
        449             return cls._from_blocks(block_iter, is_binary, sep, endcard,
    --> 450                                     padding)[1]
        451         finally:
    
    /Users/tom/Dropbox/Code/Astropy/astropy/astropy/io/fits/header.py in _from_blocks(cls, block_iter, is_binary, sep, endcard, padding)
        497 
    --> 498             read_blocks.append(decode_ascii(block))
        499 
    
    /Users/tom/Dropbox/Code/Astropy/astropy/astropy/io/fits/py3compat.py in decode_ascii(s)
         29         if isinstance(s, bytes):
    ---> 30             return s.decode('ascii')
         31         elif (isinstance(s, numpy.ndarray) and
    
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 2: ordinal not in range(128)
    
    During handling of the above exception, another exception occurred:
    
    NameError                                 Traceback (most recent call last)
    <ipython-input-7-add7824ea4ef> in <module>()
    ----> 1 fits.open('test.fits')
    
    /Users/tom/Dropbox/Code/Astropy/astropy/astropy/io/fits/hdu/hdulist.py in fitsopen(name, mode, memmap, save_backup, cache, lazy_load_hdus, **kwargs)
        164 
        165     return HDUList.fromfile(name, mode, memmap, save_backup, cache,
    --> 166                             lazy_load_hdus, **kwargs)
        167 
        168 
    
    /Users/tom/Dropbox/Code/Astropy/astropy/astropy/io/fits/hdu/hdulist.py in fromfile(cls, fileobj, mode, memmap, save_backup, cache, lazy_load_hdus, **kwargs)
        375         return cls._readfrom(fileobj=fileobj, mode=mode, memmap=memmap,
        376                              save_backup=save_backup, cache=cache,
    --> 377                              lazy_load_hdus=lazy_load_hdus, **kwargs)
        378 
        379     @classmethod
    
    /Users/tom/Dropbox/Code/Astropy/astropy/astropy/io/fits/hdu/hdulist.py in _readfrom(cls, fileobj, data, mode, memmap, save_backup, cache, lazy_load_hdus, **kwargs)
       1011 
       1012         # Make sure at least the PRIMARY HDU can be read
    -> 1013         read_one = hdulist._read_next_hdu()
       1014         # If we're trying to read only and no header units were found,
       1015         # raise and exception
    
    /Users/tom/Dropbox/Code/Astropy/astropy/astropy/io/fits/hdu/hdulist.py in _read_next_hdu(self)
       1148                     'There may be extra bytes after the last HDU or the '
       1149                     'file is corrupted.'.format(
    -> 1150                         len(hdulist), indent(str(exc))), VerifyWarning)
       1151                 del exc
       1152                 self._read_all = True
    
    NameError: name 'hdulist' is not defined
  6. mwcraig commented on Dec 12, 2016

    @mwcraig
    Member

    Thanks! Never would have come up with that...

  7. embray commented on Dec 13, 2016

    @embray
    Member

    Definitely an under-tested corner case :P

  8. astrofrog commented on Dec 13, 2016

    @astrofrog
    MemberAuthor

    @embray @mwcraig - just for some background, I use fits.open(filename) as a way to determine if a file is a FITS file. There might be a better way?

  9. mwcraig commented on Dec 13, 2016

    @mwcraig
    Member

    There is astropy.io.fits.connect.is_fits at

    def is_fits(origin, filepath, fileobj, *args, **kwargs):
    though it does not open a file if you give it the path as a string.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Affects-devPRs and issues that do not impact an existing Astropy releaseBugio.fits

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions