Esempio n. 1
0
    def _open_fileobj(self, fileobj, mode):
        """Open a FITS file from a file object or a GzipFile object."""

        closed = fileobj_closed(fileobj)
        fmode = fileobj_mode(fileobj) or PYTHON_MODES[mode]

        if not closed:
            # In some cases (like on Python 3) a file opened for appending
            # still shows a mode of 'r+', hence the extra check for the append
            # case
            if ((mode == 'append' and fmode not in ('ab+', 'rb+')) or
                (mode != 'append' and PYTHON_MODES[mode] != fmode)):
                raise ValueError(
                    "Input mode '%s' (%s) does not match mode of the "
                    "input file (%s)." % (mode, PYTHON_MODES[mode], fmode))
            self.__file = fileobj
        elif isfile(fileobj):
            self.__file = fileobj_open(self.name, PYTHON_MODES[mode])
            # Return to the beginning of the file--in Python 3 when opening in
            # append mode the file pointer is at the end of the file
            self.__file.seek(0)
        else:
            self.__file = gzip.open(self.name, PYTHON_MODES[mode])
Esempio n. 2
0
    def writeto(self, fileobj, output_verify='exception', clobber=False,
                checksum=False):
        """
        Write the `HDUList` to a new file.

        Parameters
        ----------
        fileobj : file path, file object or file-like object
            File to write to.  If a file object, must be opened for
            append (ab+).

        output_verify : str
            Output verification option.  Must be one of ``"fix"``,
            ``"silentfix"``, ``"ignore"``, ``"warn"``, or
            ``"exception"``.  See :ref:`verify` for more info.

        clobber : bool
            When `True`, overwrite the output file if exists.

        checksum : bool
            When `True` adds both ``DATASUM`` and ``CHECKSUM`` cards
            to the headers of all HDU's written to the file.
        """

        if (len(self) == 0):
            warnings.warn("There is nothing to write.")
            return

        self.verify(option=output_verify)

        # check if the file object is closed
        closed = fileobj_closed(fileobj)
        fmode = fileobj_mode(fileobj) or 'ab+'
        filename = fileobj_name(fileobj)

        # check if the output file already exists
        if (isfile(fileobj) or
            isinstance(fileobj, (basestring, gzip.GzipFile))):
            if (os.path.exists(filename) and os.path.getsize(filename) != 0):
                if clobber:
                    warnings.warn("Overwriting existing file '%s'." % filename)
                    if not closed:
                        fileobj.close()
                    os.remove(filename)
                else:
                    raise IOError("File '%s' already exists." % filename)
        elif (hasattr(fileobj, 'len') and fileobj.len > 0):
            if clobber:
                warnings.warn("Overwriting existing file '%s'." % filename)
                name.truncate(0)
            else:
                raise IOError("File '%s' already exists." % filename)

        # make sure the EXTEND keyword is there if there is extension
        self.update_extend()

        mode = 'copyonwrite'
        for key, val in PYTHON_MODES.iteritems():
            if val == fmode:
                mode = key
                break

        hdulist = fitsopen(fileobj, mode=mode)

        for hdu in self:
            hdu._prewriteto(checksum=checksum)
            try:
                hdu._writeto(hdulist.__file)
            finally:
                hdu._postwriteto()
        hdulist.close(output_verify=output_verify, closed=closed)
Esempio n. 3
0
    def __init__(self, fileobj=None, mode='readonly', memmap=False):
        if fileobj is None:
            self.__file = None
            self.closed = False
            self.mode = mode
            self.memmap = memmap
            self.compression = None
            self.readonly = False
            self.writeonly = False
            self.simulateonly = True
            return
        else:
            self.simulateonly = False

        if mode not in PYTHON_MODES:
            raise ValueError("Mode '%s' not recognized" % mode)

        if (isinstance(fileobj, basestring) and mode != 'append' and
            not os.path.exists(fileobj) and
            not os.path.splitdrive(fileobj)[0]):
                #
                # Not writing file and file does not exist on local machine and
                # name does not begin with a drive letter (Windows), try to
                # get it over the web.
                #
            self.name, _ = urllib.urlretrieve(fileobj)
        else:
            self.name = fileobj_name(fileobj)

        self.closed = False
        self.mode = mode
        self.memmap = memmap

        # Underlying fileobj is a file-like object, but an actual file object
        self.file_like = False

        # More defaults to be adjusted below as necessary
        self.compression = None
        self.readonly = False
        self.writeonly = False

        # Initialize the internal self.__file object
        if isfile(fileobj) or isinstance(fileobj, gzip.GzipFile):
            closed = fileobj_closed(fileobj)
            fmode = fileobj_mode(fileobj) or PYTHON_MODES[mode]

            if not closed:
                # In some cases (like on Python 3) a file opened for
                # appending still shows a mode of 'r+', hence the extra
                # check for the append case
                if ((mode == 'append' and fmode not in ('ab+', 'rb+')) or
                    (mode != 'append' and PYTHON_MODES[mode] != fmode)):
                    raise ValueError(
                        "Input mode '%s' (%s) does not match mode of the "
                        "input file (%s)." % (mode, PYTHON_MODES[mode], fmode))
                self.__file = fileobj
            elif isfile(fileobj):
                self.__file = fileobj_open(self.name, PYTHON_MODES[mode])
                # Return to the beginning of the file--in Python 3 when
                # opening in append mode the file pointer is at the end of
                # the file
                self.__file.seek(0)
            else:
                self.__file = gzip.open(self.name, PYTHON_MODES[mode])
        elif isinstance(fileobj, basestring):
            if os.path.exists(self.name):
                with fileobj_open(self.name, 'rb') as f:
                    magic = f.read(4)
            else:
                magic = ''.encode('raw-unicode-escape')
            ext = os.path.splitext(self.name)[1]
            if ext == '.gz' or magic.startswith(GZIP_MAGIC):
                # Handle gzip files
                if mode in ['update', 'append']:
                    raise IOError(
                          "Writing to gzipped fits files is not currently "
                          "supported")
                self.__file = gzip.open(self.name)
                self.compression = 'gzip'
            elif ext == '.zip' or magic.startswith(PKZIP_MAGIC):
                # Handle zip files
                if mode in ['update', 'append']:
                    raise IOError(
                          "Writing to zipped fits files is not currently "
                          "supported")
                zfile = zipfile.ZipFile(self.name)
                namelist = zfile.namelist()
                if len(namelist) != 1:
                    raise IOError(
                      "Zip files with multiple members are not supported.")
                self.__file = tempfile.NamedTemporaryFile(suffix='.fits')
                self.__file.write(zfile.read(namelist[0]))
                zfile.close()
                self.compression = 'zip'
            else:
                self.__file = fileobj_open(self.name, PYTHON_MODES[mode])
                # Make certain we're back at the beginning of the file
            self.__file.seek(0)
        else:
            # We are dealing with a file like object.
            # Assume it is open.
            self.file_like = True
            self.__file = fileobj

            # If there is not seek or tell methods then set the mode to
            # output streaming.
            if (not hasattr(self.__file, 'seek') or
                not hasattr(self.__file, 'tell')):
                self.mode = mode = 'ostream'

            if (self.mode in ('copyonwrite', 'update', 'append') and
                not hasattr(self.__file, 'write')):
                raise IOError("File-like object does not have a 'write' "
                              "method, required for mode '%s'."
                              % self.mode)

            if (self.mode in ('readonly', 'denywrite') and
                not hasattr(self.__file, 'read')):
                raise IOError("File-like object does not have a 'read' "
                              "method, required for mode %r."
                              % self.mode)

        if isinstance(fileobj, gzip.GzipFile):
            self.compression = 'gzip'
        elif isinstance(fileobj, zipfile.ZipFile):
            # Reading from zip files is supported but not writing (yet)
            self.compression = 'zip'

        if (mode in ('readonly', 'copyonwrite', 'denywrite') or
                (self.compression and mode == 'update')):
            self.readonly = True
        elif (mode == 'ostream' or
                (self.compression and mode == 'append')):
            self.writeonly = True

        # For 'ab+' mode, the pointer is at the end after the open in
        # Linux, but is at the beginning in Solaris.
        if (mode == 'ostream' or self.compression or
            not hasattr(self.__file, 'seek')):
            # For output stream start with a truncated file.
            # For compressed files we can't really guess at the size
            self.size = 0
        else:
            pos = self.__file.tell()
            self.__file.seek(0, 2)
            self.size = self.__file.tell()
            self.__file.seek(pos)

        if self.memmap and not isfile(self.__file):
            self.memmap = False