Thanks to @jonrsharpe, I came to question myself on some trick to code. Here is what I reached :
class RewindableFile(file):
def __init__(self, *args, **kwargs):
nb_backup = kwargs.pop('nb_backup', 1)
super(RewindableFile, self).__init__(*args, **kwargs)
self._nb_backup = nb_backup
self._backups = []
self._time_anchor = 0
def next(self):
if self._time_anchor >= 0:
item = super(RewindableFile, self).next()
self._backup(item)
return item
else:
item = self._forward()
return item
def rewind(self):
self._time_anchor = self._time_anchor - 1
time_bound = min(self._nb_backup, len(self._backups))
if self._time_anchor < -time_bound:
raise Exception('You have gone too far in history...')
def __iter__(self):
return self
def _backup(self, row):
self._backups.append(row)
extra_items = len(self._backups) - self._nb_backup
if extra_items > 0:
del self._backups[0:extra_items]
def _forward(self):
item = self._backups[self._time_anchor]
self._time_anchor = self._time_anchor + 1
return item
And how I use it :
with RewindableFile('csv.csv', 'rb') as f:
def test_kwd_and_rewind(x):
if x[0] != 'KEYWORD':
return True
else:
f.rewind()
return False
reader = csv.reader(f)
header = takewhile(test_kwd_and_rewind, reader)
for row in header:
print(row)
print('End of header')
for row in reader:
print(row)
I could have also overload read
and readline
functions to save the jump
.
But I don't need them here.