History

add hg and python

cinap_lenrek committed 15 years ago

Commit 4bb9e221 parent 987265c3706 files · +1228772 −-233Browse files

Showing the changes to sys/lib/python/StringIO.py (1 of 3706 files). Show all

Unified · Split

sys/lib/python/StringIO.py+323−0
@@ -0,0 +1,323 @@
1+r"""File-like objects that read from or write to a string buffer.
2+
3+This implements (nearly) all stdio methods.
4+
5+f = StringIO() # ready for writing
6+f = StringIO(buf) # ready for reading
7+f.close() # explicitly release resources held
8+flag = f.isatty() # always false
9+pos = f.tell() # get current position
10+f.seek(pos) # set current position
11+f.seek(pos, mode) # mode 0: absolute; 1: relative; 2: relative to EOF
12+buf = f.read() # read until EOF
13+buf = f.read(n) # read up to n bytes
14+buf = f.readline() # read until end of line ('\n') or EOF
15+list = f.readlines()# list of f.readline() results until EOF
16+f.truncate([size]) # truncate file at to at most size (default: current pos)
17+f.write(buf) # write at current position
18+f.writelines(list) # for line in list: f.write(line)
19+f.getvalue() # return whole file's contents as a string
20+
21+Notes:
22+- Using a real file is often faster (but less convenient).
23+- There's also a much faster implementation in C, called cStringIO, but
24+ it's not subclassable.
25+- 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+"""
31+try:
32+ from errno import EINVAL
33+except ImportError:
34+ EINVAL = 22
35+
36+__all__ = ["StringIO"]
37+
38+def _complain_ifclosed(closed):
39+ if closed:
40+ raise ValueError, "I/O operation on closed file"
41+
42+class StringIO:
43+ """class StringIO([buffer])
44+
45+ When a StringIO object is created, it can be initialized to an existing
46+ string by passing the string to the constructor. If no string is given,
47+ the StringIO will start empty.
48+
49+ The StringIO object can accept either Unicode or 8-bit strings, but
50+ mixing the two may take some care. If both are used, 8-bit strings that
51+ cannot be interpreted as 7-bit ASCII (that use the 8th bit) will cause
52+ a UnicodeError to be raised when getvalue() is called.
53+ """
54+ def __init__(self, buf = ''):
55+ # Force self.buf to be a string or unicode
56+ if not isinstance(buf, basestring):
57+ buf = str(buf)
58+ self.buf = buf
59+ self.len = len(buf)
60+ self.buflist = []
61+ self.pos = 0
62+ self.closed = False
63+ self.softspace = 0
64+
65+ def __iter__(self):
66+ return self
67+
68+ def next(self):
69+ """A file object is its own iterator, for example iter(f) returns f
70+ (unless f is closed). When a file is used as an iterator, typically
71+ in a for loop (for example, for line in f: print line), the next()
72+ method is called repeatedly. This method returns the next input line,
73+ or raises StopIteration when EOF is hit.
74+ """
75+ _complain_ifclosed(self.closed)
76+ r = self.readline()
77+ if not r:
78+ raise StopIteration
79+ return r
80+
81+ def close(self):
82+ """Free the memory buffer.
83+ """
84+ if not self.closed:
85+ self.closed = True
86+ del self.buf, self.pos
87+
88+ def isatty(self):
89+ """Returns False because StringIO objects are not connected to a
90+ tty-like device.
91+ """
92+ _complain_ifclosed(self.closed)
93+ return False
94+
95+ def seek(self, pos, mode = 0):
96+ """Set the file's current position.
97+
98+ The mode argument is optional and defaults to 0 (absolute file
99+ positioning); other values are 1 (seek relative to the current
100+ position) and 2 (seek relative to the file's end).
101+
102+ There is no return value.
103+ """
104+ _complain_ifclosed(self.closed)
105+ if self.buflist:
106+ self.buf += ''.join(self.buflist)
107+ self.buflist = []
108+ if mode == 1:
109+ pos += self.pos
110+ elif mode == 2:
111+ pos += self.len
112+ self.pos = max(0, pos)
113+
114+ def tell(self):
115+ """Return the file's current position."""
116+ _complain_ifclosed(self.closed)
117+ return self.pos
118+
119+ def read(self, n = -1):
120+ """Read at most size bytes from the file
121+ (less if the read hits EOF before obtaining size bytes).
122+
123+ If the size argument is negative or omitted, read all data until EOF
124+ is reached. The bytes are returned as a string object. An empty
125+ string is returned when EOF is encountered immediately.
126+ """
127+ _complain_ifclosed(self.closed)
128+ if self.buflist:
129+ self.buf += ''.join(self.buflist)
130+ self.buflist = []
131+ if n < 0:
132+ newpos = self.len
133+ else:
134+ newpos = min(self.pos+n, self.len)
135+ r = self.buf[self.pos:newpos]
136+ self.pos = newpos
137+ return r
138+
139+ def readline(self, length=None):
140+ r"""Read one entire line from the file.
141+
142+ A trailing newline character is kept in the string (but may be absent
143+ when a file ends with an incomplete line). If the size argument is
144+ present and non-negative, it is a maximum byte count (including the
145+ trailing newline) and an incomplete line may be returned.
146+
147+ An empty string is returned only when EOF is encountered immediately.
148+
149+ Note: Unlike stdio's fgets(), the returned string contains null
150+ characters ('\0') if they occurred in the input.
151+ """
152+ _complain_ifclosed(self.closed)
153+ if self.buflist:
154+ self.buf += ''.join(self.buflist)
155+ self.buflist = []
156+ i = self.buf.find('\n', self.pos)
157+ if i < 0:
158+ newpos = self.len
159+ else:
160+ newpos = i+1
161+ if length is not None:
162+ if self.pos + length < newpos:
163+ newpos = self.pos + length
164+ r = self.buf[self.pos:newpos]
165+ self.pos = newpos
166+ return r
167+
168+ def readlines(self, sizehint = 0):
169+ """Read until EOF using readline() and return a list containing the
170+ lines thus read.
171+
172+ If the optional sizehint argument is present, instead of reading up
173+ to EOF, whole lines totalling approximately sizehint bytes (or more
174+ to accommodate a final whole line).
175+ """
176+ total = 0
177+ lines = []
178+ line = self.readline()
179+ while line:
180+ lines.append(line)
181+ total += len(line)
182+ if 0 < sizehint <= total:
183+ break
184+ line = self.readline()
185+ return lines
186+
187+ def truncate(self, size=None):
188+ """Truncate the file's size.
189+
190+ If the optional size argument is present, the file is truncated to
191+ (at most) that size. The size defaults to the current position.
192+ The current file position is not changed unless the position
193+ is beyond the new file size.
194+
195+ If the specified size exceeds the file's current size, the
196+ file remains unchanged.
197+ """
198+ _complain_ifclosed(self.closed)
199+ if size is None:
200+ size = self.pos
201+ elif size < 0:
202+ raise IOError(EINVAL, "Negative size not allowed")
203+ elif size < self.pos:
204+ self.pos = size
205+ self.buf = self.getvalue()[:size]
206+ self.len = size
207+
208+ def write(self, s):
209+ """Write a string to the file.
210+
211+ There is no return value.
212+ """
213+ _complain_ifclosed(self.closed)
214+ if not s: return
215+ # Force s to be a string or unicode
216+ if not isinstance(s, basestring):
217+ s = str(s)
218+ spos = self.pos
219+ slen = self.len
220+ if spos == slen:
221+ self.buflist.append(s)
222+ self.len = self.pos = spos + len(s)
223+ return
224+ if spos > slen:
225+ self.buflist.append('\0'*(spos - slen))
226+ slen = spos
227+ newpos = spos + len(s)
228+ if spos < slen:
229+ if self.buflist:
230+ self.buf += ''.join(self.buflist)
231+ self.buflist = [self.buf[:spos], s, self.buf[newpos:]]
232+ self.buf = ''
233+ if newpos > slen:
234+ slen = newpos
235+ else:
236+ self.buflist.append(s)
237+ slen = newpos
238+ self.len = slen
239+ self.pos = newpos
240+
241+ def writelines(self, iterable):
242+ """Write a sequence of strings to the file. The sequence can be any
243+ iterable object producing strings, typically a list of strings. There
244+ is no return value.
245+
246+ (The name is intended to match readlines(); writelines() does not add
247+ line separators.)
248+ """
249+ write = self.write
250+ for line in iterable:
251+ write(line)
252+
253+ def flush(self):
254+ """Flush the internal buffer
255+ """
256+ _complain_ifclosed(self.closed)
257+
258+ def getvalue(self):
259+ """
260+ Retrieve the entire contents of the "file" at any time before
261+ the StringIO object's close() method is called.
262+
263+ The StringIO object can accept either Unicode or 8-bit strings,
264+ but mixing the two may take some care. If both are used, 8-bit
265+ strings that cannot be interpreted as 7-bit ASCII (that use the
266+ 8th bit) will cause a UnicodeError to be raised when getvalue()
267+ is called.
268+ """
269+ if self.buflist:
270+ self.buf += ''.join(self.buflist)
271+ self.buflist = []
272+ return self.buf
273+
274+
275+# A little test suite
276+
277+def test():
278+ import sys
279+ if sys.argv[1:]:
280+ file = sys.argv[1]
281+ else:
282+ file = '/etc/passwd'
283+ lines = open(file, 'r').readlines()
284+ text = open(file, 'r').read()
285+ f = StringIO()
286+ for line in lines[:-2]:
287+ f.write(line)
288+ f.writelines(lines[-2:])
289+ if f.getvalue() != text:
290+ raise RuntimeError, 'write failed'
291+ length = f.tell()
292+ print 'File length =', length
293+ f.seek(len(lines[0]))
294+ f.write(lines[1])
295+ f.seek(0)
296+ print 'First line =', repr(f.readline())
297+ print 'Position =', f.tell()
298+ line = f.readline()
299+ print 'Second line =', repr(line)
300+ f.seek(-len(line), 1)
301+ line2 = f.read(len(line))
302+ if line != line2:
303+ raise RuntimeError, 'bad result after seek back'
304+ f.seek(len(line2), 1)
305+ list = f.readlines()
306+ line = list[-1]
307+ f.seek(f.tell() - len(line))
308+ line2 = f.read()
309+ if line != line2:
310+ raise RuntimeError, 'bad result after seek back from EOF'
311+ print 'Read', len(list), 'more lines'
312+ print 'File length =', f.tell()
313+ if f.tell() != length:
314+ raise RuntimeError, 'bad length'
315+ f.truncate(length/2)
316+ f.seek(0, 2)
317+ print 'Truncated length =', f.tell()
318+ if f.tell() != length/2:
319+ raise RuntimeError, 'truncate did not adjust length'
320+ f.close()
321+
322+if __name__ == '__main__':
323+ test()

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t