def _open_filename(self, filename, mode): """Open a FITS file from a filename string.""" 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 self.__file = gzip.open(self.name, PYTHON_MODES[mode]) 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)
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])
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