# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Library General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # Copyright 2002-2003 Michael D. Stenner # Michael D. Stenner class MiscFile: """FileObject-like class for "wrapping" things that read and write. Basically, I wrote this to deal with SSL Sockets. Regular sockets have a .makefile method to create a file object. (actually, that's where I took the vast majority of this code from) This allows you to create a file object from functions that read and write. For example: import socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((host, port)) ssl_sock = socket.ssl(sock) file_obj = MiscFile(ssl.read, ssl.write, sock.close) line = file_obj.readline() file_obj.write('good morning') Notes: * the passed in read function is expected to strictly respect it's size arg. If it ever returns less data than requested, MiscFile will interpret it as an EOF (or non-blocking read) and return. * when used for writing, you could have trouble with double-buffering. This object buffers data. If the wrapping functions also buffer, things could get extra-wierd with no benefit. To avoid that, disable write-buffering by setting bufsize = 0. """ def __init__(self, readfunc=None, writefunc=None, closefunc=None, mode='r', bufsize=-1): self._read = readfunc self._write = writefunc self._close = closefunc if bufsize < 0: # can be zero or more bufsize = 512 self._rbufsize = max(1, bufsize) # can't be zero self._wbufsize = bufsize # zero means unbuffered self._wbuf = self._rbuf = "" self.closed = 0 def __del__(self): self.close() def write(self, data): self._wbuf = self._wbuf + data if self._wbufsize == 1: if '\n' in data: self.flush() else: if len(self._wbuf) >= self._wbufsize: self.flush() def flush(self): if self._wbuf: self._write(self._wbuf) self._wbuf = "" def close(self): if not self.closed: self.closed = 1 if not self._close is None: return self._close() def writelines(self, list): self._wbuf = self._wbuf + ''.join(list) self.flush() def read(self, n=-1): if n >= 0: return self._read_fixed(n) else: return self._read_all() def _read_fixed(self, n): # read a fixed amount k = len(self._rbuf) if n <= k: data = self._rbuf[:n] self._rbuf = self._rbuf[n:] return data n = n - k L = [self._rbuf] self._rbuf = "" while n > 0: target = max(n, self._rbufsize) new = self._read(target) #if not new: break k = len(new) if k > n: L.append(new[:n]) self._rbuf = new[n:] break L.append(new) if k < target: break # EOF n = n - k return "".join(L) def _read_all(self): # read all that's available k = max(512, self._rbufsize) L = [self._rbuf] self._rbuf = "" while 1: new = self._read(k) L.append(new) if len(new) < k: break # EOF k = min(k*2, 1024**2) return "".join(L) def readline(self, limit=-1): data = "" i = self._rbuf.find('\n') while i < 0 and not (0 < limit <= len(self._rbuf)): new = self._read(self._rbufsize) if not new: break i = new.find('\n') if i >= 0: i = i + len(self._rbuf) self._rbuf = self._rbuf + new if i < 0: i = len(self._rbuf) else: i = i+1 if 0 <= limit < len(self._rbuf): i = limit data, self._rbuf = self._rbuf[:i], self._rbuf[i:] return data def readlines(self, sizehint=0): total = 0 list = [] while 1: line = self.readline() if not line: break list.append(line) total += len(line) if sizehint and total >= sizehint: break return list def test(): import sys, time # normal read test: f = MiscFile(sys.stdin.read) print f.read(10) print '-------' print f.read() if __name__ == '__main__': test()