1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
|
#
# Copyright (C) 2010 Wikkid Developers.
#
# This software is licensed under the GNU Affero General Public License
# version 3 (see the file LICENSE).
"""A method of iterating over file contents
This stops us reading the entire file into memory when we serve it.
"""
class FileIterable(object):
"""An iterable file-like object."""
def __init__(self, filename, start=None, stop=None):
self.filename = filename
self.start = start
self.stop = stop
def __iter__(self):
return FileIterator(self.filename, self.start, self.stop)
def app_iter_range(self, start, stop):
return self.__class__(self.filename, start, stop)
class FileIterator(object):
"""Iterate over a file.
FileIterable provides a simple file iterator, optionally allowing the
user to specify start and end ranges for the file.
"""
chunk_size = 4096
def __init__(self, filename, start, stop):
self.filename = filename
self.fileobj = open(self.filename, 'rb')
if start:
self.fileobj.seek(start)
if stop is not None:
self.length = stop - start
else:
self.length = None
def __iter__(self):
return self
def __next__(self):
if self.length is not None and self.length <= 0:
raise StopIteration
chunk = self.fileobj.read(self.chunk_size)
if not chunk:
raise StopIteration
if self.length is not None:
self.length -= len(chunk)
if self.length < 0:
# Chop off the extra:
chunk = chunk[:self.length]
return chunk
|