--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pvl/syslog/file.py Sun Jan 13 01:50:25 2013 +0200
@@ -0,0 +1,73 @@
+"""
+ Iterate over lines in file-like objects (without buffering lines!), write (flushing output).
+"""
+
+import logging; log = logging.getLogger('pvl.syslog.file')
+
+class File (object) :
+ """
+ Follow a file-like object, reading lines until no more are available. Never raises EOFError.
+
+ Works with python file objects that buffer readlines() when using e.g. `tail -f ... | python -u ...`.
+
+ readline() may block once there is no more input available, or may return None for evermore.
+
+ There is no fileno(), this is not pollable. At all. Don't even iterate on this with a timeout.
+ XXX: should this really return None? Might really be better to raise EOFError.. except that readlines() should return normally at EOF...
+ """
+
+ @classmethod
+ def open (cls, path, mode='r', **opts) :
+ return cls(open(path, mode), **opts)
+
+ EOL = '\n'
+
+ def __init__ (self, file) :
+ log.debug("%s", file)
+
+ self.file = file
+
+ def readline (self) :
+ """
+ Reads a line from the file, without trailing \n.
+
+ Returns None on EOF.
+ """
+
+ line = self.file.readline()
+
+ if not line :
+ line = None
+ else :
+ line = line.rstrip('\r\n')
+
+ log.debug("%s", line)
+
+ return line
+
+ def readlines (self) :
+ """
+ Reads any available lines from the file.
+ """
+
+ while True :
+ line = self.readline()
+
+ if line is None :
+ return
+ else :
+ yield line
+
+ __iter__ = readlines
+
+ def writeline (self, line, eol=EOL) :
+ """
+ Write out line, flushing.
+ """
+
+ self.file.write(line)
+ self.file.write(eol)
+ self.file.flush()
+
+ __call__ = writeline
+