+## {{{ http://code.activestate.com/recipes/439045/ (r2)
+#!/usr/bin/env python
+# -*-mode: python; coding: iso-8859-1 -*-
+#
+# Copyright (c) Peter Astrand <astrand@cendio.se>
+# $Id$
+# $URL$
+
+import string
+
+class BackwardsReader:
+ """Read a file line by line, backwards"""
+
+ def readline(self):
+ while 1:
+ newline_pos = string.rfind(self.buf, "\n")
+ pos = self.file.tell()
+ if newline_pos != -1:
+ # Found a newline
+ line = self.buf[newline_pos+1:]
+ self.buf = self.buf[:newline_pos]
+ if pos != 0 or newline_pos != 0 or self.trailing_newline:
+ line += "\n"
+ return line
+ else:
+ if pos == 0:
+ # Start-of-file
+ return ""
+ else:
+ # Need to fill buffer
+ toread = min(self.BLKSIZE, pos)
+ self.file.seek(-toread, 1)
+ self.buf = self.file.read(toread) + self.buf
+ self.file.seek(-toread, 1)
+ if pos - toread == 0:
+ self.buf = "\n" + self.buf
+
+ def __init__(self, file, BLKSIZE=4096):
+ self.file = file
+ self.BLKSIZE = BLKSIZE
+ self.buf = ""
+ self.file.seek(-1, 2)
+ self.trailing_newline = 0
+ lastchar = self.file.read(1)
+ if lastchar == "\n":
+ self.trailing_newline = 1
+ self.file.seek(-1, 2)