This repository has been archived on 2020-03-24. You can view files and clone it, but cannot push or open issues or pull requests.
quay/util/registry/generatorfile.py
Joseph Schorr 30ede029d5 Fix GeneratorFile for working with BufferedReader
The user files system uses a BufferedReader along with the magic library to determine the mime type of the user file being served. Currently, BufferedReader fails with an exception on Swift storage, because Swift storage returns a GeneratorFile, which is missing the `readable()` method.
2016-06-23 13:40:57 -04:00

88 lines
No EOL
2.3 KiB
Python

def _complain_ifclosed(closed):
if closed:
raise ValueError, "I/O operation on closed file"
class GeneratorFile(object):
""" File-like object which wraps a Python generator to produce the file contents.
Modeled on StringIO and comments on the file-like interface copied from there.
"""
def __init__(self, generator):
self._generator = generator
self._closed = False
self._buf = ''
self._position = 0
def __iter__(self):
return self
def tell(self):
"""Return the file's current position, like stdio's ftell()."""
_complain_ifclosed(self._closed)
return self._position
def next(self):
"""A file object is its own iterator, for example iter(f) returns f
(unless f is closed). When a file is used as an iterator, typically
in a for loop (for example, for line in f: print line), the next()
method is called repeatedly. This method returns the next input line,
or raises StopIteration when EOF is hit.
"""
_complain_ifclosed(self._closed)
r = self.read()
if not r:
raise StopIteration
return r
def readable(self):
return not self._closed
def readline(self):
buf = []
while True:
c = self.read(size=1)
buf.append(c)
if c == '\n' or c == '':
return ''.join(buf)
def flush(self):
_complain_ifclosed(self._closed)
def read(self, size=-1):
"""Read at most size bytes from the file
(less if the read hits EOF before obtaining size bytes).
If the size argument is negative or omitted, read all data until EOF
is reached. The bytes are returned as a string object. An empty
string is returned when EOF is encountered immediately.
"""
_complain_ifclosed(self._closed)
buf = self._buf
while size < 0 or len(buf) < size:
try:
buf = buf + self._generator.next()
except StopIteration:
break
returned = ''
if size >= 1:
self._buf = buf[size:]
returned = buf[:size]
else:
self._buf = ''
returned = buf
self._position = self._position + len(returned)
return returned
def seek(self):
raise NotImplementedError
def close(self):
self._closed = True
del self._buf
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
self._closed = True