blob: 89dda5e95d118d5ab737b7da8e2da6a0baa53405 [file] [log] [blame]
Guido van Rossum4acc25b2000-02-02 15:10:15 +00001"""File-like objects that read from or write to a string buffer.
2
3This implements (nearly) all stdio methods.
4
5f = StringIO() # ready for writing
6f = StringIO(buf) # ready for reading
7f.close() # explicitly release resources held
8flag = f.isatty() # always false
9pos = f.tell() # get current position
10f.seek(pos) # set current position
11f.seek(pos, mode) # mode 0: absolute; 1: relative; 2: relative to EOF
12buf = f.read() # read until EOF
13buf = f.read(n) # read up to n bytes
14buf = f.readline() # read until end of line ('\n') or EOF
15list = f.readlines()# list of f.readline() results until EOF
Fred Drakee0a7f4f2000-09-28 04:21:06 +000016f.truncate([size]) # truncate file at to at most size (default: current pos)
Guido van Rossum4acc25b2000-02-02 15:10:15 +000017f.write(buf) # write at current position
18f.writelines(list) # for line in list: f.write(line)
19f.getvalue() # return whole file's contents as a string
20
21Notes:
22- Using a real file is often faster (but less convenient).
Guido van Rossum98d9fd32000-02-28 15:12:25 +000023- There's also a much faster implementation in C, called cStringIO, but
24 it's not subclassable.
Guido van Rossum4acc25b2000-02-02 15:10:15 +000025- fileno() is left unimplemented so that code which uses it triggers
26 an exception early.
27- Seeking far beyond EOF and then writing will insert real null
28 bytes that occupy space in the buffer.
29- There's a simple test set (see end of this file).
30"""
Barry Warsawc7ed0e32000-12-12 23:12:23 +000031try:
Barry Warsawc1401312000-12-12 23:16:51 +000032 from errno import EINVAL
Barry Warsawc7ed0e32000-12-12 23:12:23 +000033except ImportError:
Barry Warsawc1401312000-12-12 23:16:51 +000034 EINVAL = 22
Barry Warsawc7ed0e32000-12-12 23:12:23 +000035
Skip Montanaroe99d5ea2001-01-20 19:54:20 +000036__all__ = ["StringIO"]
37
Guido van Rossum85d89451994-06-23 11:53:27 +000038class StringIO:
Tim Peters8ac14952002-05-23 15:15:30 +000039 """class StringIO([buffer])
40
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +000041 When a StringIO object is created, it can be initialized to an existing
42 string by passing the string to the constructor. If no string is given,
Tim Peters8ac14952002-05-23 15:15:30 +000043 the StringIO will start empty.
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +000044
45 The StringIO object can accept either Unicode or 8-bit strings, but
46 mixing the two may take some care. If both are used, 8-bit strings that
47 cannot be interpreted as 7-bit ASCII (that use the 8th bit) will cause
Tim Peters8ac14952002-05-23 15:15:30 +000048 a UnicodeError to be raised when getvalue() is called.
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +000049 """
Barry Warsawc1401312000-12-12 23:16:51 +000050 def __init__(self, buf = ''):
Marc-André Lemburgf853be92002-01-06 17:15:05 +000051 # Force self.buf to be a string or unicode
Walter Dörwald65230a22002-06-03 15:58:32 +000052 if not isinstance(buf, basestring):
Marc-André Lemburgf853be92002-01-06 17:15:05 +000053 buf = str(buf)
54 self.buf = buf
Fred Drakea63bd1c2000-12-13 20:23:11 +000055 self.len = len(buf)
56 self.buflist = []
57 self.pos = 0
58 self.closed = 0
59 self.softspace = 0
Barry Warsawc1401312000-12-12 23:16:51 +000060
Barry Warsawbdefa0b2001-09-22 04:34:54 +000061 def __iter__(self):
Guido van Rossumc1265bd2003-01-31 16:04:15 +000062 return self
63
64 def next(self):
65 if self.closed:
66 raise StopIteration
67 r = self.readline()
68 if not r:
69 raise StopIteration
70 return r
Barry Warsawbdefa0b2001-09-22 04:34:54 +000071
Barry Warsawc1401312000-12-12 23:16:51 +000072 def close(self):
Tim Peters8ac14952002-05-23 15:15:30 +000073 """Free the memory buffer.
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +000074 """
Fred Drakea63bd1c2000-12-13 20:23:11 +000075 if not self.closed:
76 self.closed = 1
77 del self.buf, self.pos
Barry Warsawc1401312000-12-12 23:16:51 +000078
79 def isatty(self):
Fred Drakea63bd1c2000-12-13 20:23:11 +000080 if self.closed:
81 raise ValueError, "I/O operation on closed file"
Guido van Rossum8ca162f2002-04-07 06:36:23 +000082 return False
Barry Warsawc1401312000-12-12 23:16:51 +000083
84 def seek(self, pos, mode = 0):
Fred Drakea63bd1c2000-12-13 20:23:11 +000085 if self.closed:
86 raise ValueError, "I/O operation on closed file"
87 if self.buflist:
Marc-André Lemburg85d6edf2001-02-09 13:37:37 +000088 self.buf += ''.join(self.buflist)
Fred Drakea63bd1c2000-12-13 20:23:11 +000089 self.buflist = []
90 if mode == 1:
91 pos += self.pos
92 elif mode == 2:
93 pos += self.len
94 self.pos = max(0, pos)
Barry Warsawc1401312000-12-12 23:16:51 +000095
96 def tell(self):
Fred Drakea63bd1c2000-12-13 20:23:11 +000097 if self.closed:
98 raise ValueError, "I/O operation on closed file"
99 return self.pos
Barry Warsawc1401312000-12-12 23:16:51 +0000100
101 def read(self, n = -1):
Fred Drakea63bd1c2000-12-13 20:23:11 +0000102 if self.closed:
103 raise ValueError, "I/O operation on closed file"
104 if self.buflist:
Marc-André Lemburg85d6edf2001-02-09 13:37:37 +0000105 self.buf += ''.join(self.buflist)
Fred Drakea63bd1c2000-12-13 20:23:11 +0000106 self.buflist = []
107 if n < 0:
108 newpos = self.len
109 else:
110 newpos = min(self.pos+n, self.len)
111 r = self.buf[self.pos:newpos]
112 self.pos = newpos
113 return r
Barry Warsawc1401312000-12-12 23:16:51 +0000114
115 def readline(self, length=None):
Fred Drakea63bd1c2000-12-13 20:23:11 +0000116 if self.closed:
117 raise ValueError, "I/O operation on closed file"
118 if self.buflist:
Marc-André Lemburg85d6edf2001-02-09 13:37:37 +0000119 self.buf += ''.join(self.buflist)
Fred Drakea63bd1c2000-12-13 20:23:11 +0000120 self.buflist = []
121 i = self.buf.find('\n', self.pos)
122 if i < 0:
123 newpos = self.len
124 else:
125 newpos = i+1
126 if length is not None:
127 if self.pos + length < newpos:
128 newpos = self.pos + length
129 r = self.buf[self.pos:newpos]
130 self.pos = newpos
131 return r
Barry Warsawc1401312000-12-12 23:16:51 +0000132
133 def readlines(self, sizehint = 0):
Fred Drakea63bd1c2000-12-13 20:23:11 +0000134 total = 0
135 lines = []
136 line = self.readline()
137 while line:
138 lines.append(line)
139 total += len(line)
140 if 0 < sizehint <= total:
141 break
142 line = self.readline()
143 return lines
Barry Warsawc1401312000-12-12 23:16:51 +0000144
145 def truncate(self, size=None):
Fred Drakea63bd1c2000-12-13 20:23:11 +0000146 if self.closed:
147 raise ValueError, "I/O operation on closed file"
148 if size is None:
149 size = self.pos
150 elif size < 0:
151 raise IOError(EINVAL, "Negative size not allowed")
152 elif size < self.pos:
153 self.pos = size
154 self.buf = self.getvalue()[:size]
Barry Warsawc1401312000-12-12 23:16:51 +0000155
156 def write(self, s):
Fred Drakea63bd1c2000-12-13 20:23:11 +0000157 if self.closed:
158 raise ValueError, "I/O operation on closed file"
159 if not s: return
Marc-André Lemburgf853be92002-01-06 17:15:05 +0000160 # Force s to be a string or unicode
Walter Dörwald65230a22002-06-03 15:58:32 +0000161 if not isinstance(s, basestring):
Marc-André Lemburgf853be92002-01-06 17:15:05 +0000162 s = str(s)
Fred Draked679e092002-09-17 18:10:34 +0000163 if self.pos == self.len:
164 self.buflist.append(s)
165 self.len = self.pos = self.pos + len(s)
166 return
Fred Drakea63bd1c2000-12-13 20:23:11 +0000167 if self.pos > self.len:
168 self.buflist.append('\0'*(self.pos - self.len))
169 self.len = self.pos
170 newpos = self.pos + len(s)
171 if self.pos < self.len:
172 if self.buflist:
Marc-André Lemburg85d6edf2001-02-09 13:37:37 +0000173 self.buf += ''.join(self.buflist)
Fred Drakea63bd1c2000-12-13 20:23:11 +0000174 self.buflist = []
175 self.buflist = [self.buf[:self.pos], s, self.buf[newpos:]]
176 self.buf = ''
177 if newpos > self.len:
178 self.len = newpos
179 else:
180 self.buflist.append(s)
181 self.len = newpos
182 self.pos = newpos
Barry Warsawc1401312000-12-12 23:16:51 +0000183
184 def writelines(self, list):
Marc-André Lemburg85d6edf2001-02-09 13:37:37 +0000185 self.write(''.join(list))
Barry Warsawc1401312000-12-12 23:16:51 +0000186
187 def flush(self):
Fred Drakea63bd1c2000-12-13 20:23:11 +0000188 if self.closed:
189 raise ValueError, "I/O operation on closed file"
Barry Warsawc1401312000-12-12 23:16:51 +0000190
191 def getvalue(self):
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +0000192 """
193 Retrieve the entire contents of the "file" at any time before
194 the StringIO object's close() method is called.
195
196 The StringIO object can accept either Unicode or 8-bit strings,
197 but mixing the two may take some care. If both are used, 8-bit
198 strings that cannot be interpreted as 7-bit ASCII (that use the
199 8th bit) will cause a UnicodeError to be raised when getvalue()
Tim Peters8ac14952002-05-23 15:15:30 +0000200 is called.
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +0000201 """
Fred Drakea63bd1c2000-12-13 20:23:11 +0000202 if self.buflist:
Marc-André Lemburg85d6edf2001-02-09 13:37:37 +0000203 self.buf += ''.join(self.buflist)
Fred Drakea63bd1c2000-12-13 20:23:11 +0000204 self.buflist = []
205 return self.buf
Guido van Rossum85d89451994-06-23 11:53:27 +0000206
207
208# A little test suite
209
210def test():
Barry Warsawc1401312000-12-12 23:16:51 +0000211 import sys
212 if sys.argv[1:]:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000213 file = sys.argv[1]
Barry Warsawc1401312000-12-12 23:16:51 +0000214 else:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000215 file = '/etc/passwd'
Barry Warsawc1401312000-12-12 23:16:51 +0000216 lines = open(file, 'r').readlines()
217 text = open(file, 'r').read()
218 f = StringIO()
219 for line in lines[:-2]:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000220 f.write(line)
Barry Warsawc1401312000-12-12 23:16:51 +0000221 f.writelines(lines[-2:])
222 if f.getvalue() != text:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000223 raise RuntimeError, 'write failed'
Barry Warsawc1401312000-12-12 23:16:51 +0000224 length = f.tell()
225 print 'File length =', length
226 f.seek(len(lines[0]))
227 f.write(lines[1])
228 f.seek(0)
229 print 'First line =', `f.readline()`
Neal Norwitz9fb289d2002-02-11 17:52:18 +0000230 print 'Position =', f.tell()
Barry Warsawc1401312000-12-12 23:16:51 +0000231 line = f.readline()
232 print 'Second line =', `line`
233 f.seek(-len(line), 1)
234 line2 = f.read(len(line))
235 if line != line2:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000236 raise RuntimeError, 'bad result after seek back'
Barry Warsawc1401312000-12-12 23:16:51 +0000237 f.seek(len(line2), 1)
238 list = f.readlines()
239 line = list[-1]
240 f.seek(f.tell() - len(line))
241 line2 = f.read()
242 if line != line2:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000243 raise RuntimeError, 'bad result after seek back from EOF'
Barry Warsawc1401312000-12-12 23:16:51 +0000244 print 'Read', len(list), 'more lines'
245 print 'File length =', f.tell()
246 if f.tell() != length:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000247 raise RuntimeError, 'bad length'
Barry Warsawc1401312000-12-12 23:16:51 +0000248 f.close()
Guido van Rossum85d89451994-06-23 11:53:27 +0000249
250if __name__ == '__main__':
Barry Warsawc1401312000-12-12 23:16:51 +0000251 test()