1 | """Unit tests for memory-based file-like objects.
|
---|
2 | StringIO -- for unicode strings
|
---|
3 | BytesIO -- for bytes
|
---|
4 | """
|
---|
5 |
|
---|
6 | from __future__ import unicode_literals
|
---|
7 | from __future__ import print_function
|
---|
8 |
|
---|
9 | import unittest
|
---|
10 | from test import test_support as support
|
---|
11 |
|
---|
12 | import io
|
---|
13 | import _pyio as pyio
|
---|
14 | import pickle
|
---|
15 |
|
---|
16 | class MemorySeekTestMixin:
|
---|
17 |
|
---|
18 | def testInit(self):
|
---|
19 | buf = self.buftype("1234567890")
|
---|
20 | bytesIo = self.ioclass(buf)
|
---|
21 |
|
---|
22 | def testRead(self):
|
---|
23 | buf = self.buftype("1234567890")
|
---|
24 | bytesIo = self.ioclass(buf)
|
---|
25 |
|
---|
26 | self.assertEqual(buf[:1], bytesIo.read(1))
|
---|
27 | self.assertEqual(buf[1:5], bytesIo.read(4))
|
---|
28 | self.assertEqual(buf[5:], bytesIo.read(900))
|
---|
29 | self.assertEqual(self.EOF, bytesIo.read())
|
---|
30 |
|
---|
31 | def testReadNoArgs(self):
|
---|
32 | buf = self.buftype("1234567890")
|
---|
33 | bytesIo = self.ioclass(buf)
|
---|
34 |
|
---|
35 | self.assertEqual(buf, bytesIo.read())
|
---|
36 | self.assertEqual(self.EOF, bytesIo.read())
|
---|
37 |
|
---|
38 | def testSeek(self):
|
---|
39 | buf = self.buftype("1234567890")
|
---|
40 | bytesIo = self.ioclass(buf)
|
---|
41 |
|
---|
42 | bytesIo.read(5)
|
---|
43 | bytesIo.seek(0)
|
---|
44 | self.assertEqual(buf, bytesIo.read())
|
---|
45 |
|
---|
46 | bytesIo.seek(3)
|
---|
47 | self.assertEqual(buf[3:], bytesIo.read())
|
---|
48 | self.assertRaises(TypeError, bytesIo.seek, 0.0)
|
---|
49 |
|
---|
50 | def testTell(self):
|
---|
51 | buf = self.buftype("1234567890")
|
---|
52 | bytesIo = self.ioclass(buf)
|
---|
53 |
|
---|
54 | self.assertEqual(0, bytesIo.tell())
|
---|
55 | bytesIo.seek(5)
|
---|
56 | self.assertEqual(5, bytesIo.tell())
|
---|
57 | bytesIo.seek(10000)
|
---|
58 | self.assertEqual(10000, bytesIo.tell())
|
---|
59 |
|
---|
60 |
|
---|
61 | class MemoryTestMixin:
|
---|
62 |
|
---|
63 | def test_detach(self):
|
---|
64 | buf = self.ioclass()
|
---|
65 | self.assertRaises(self.UnsupportedOperation, buf.detach)
|
---|
66 |
|
---|
67 | def write_ops(self, f, t):
|
---|
68 | self.assertEqual(f.write(t("blah.")), 5)
|
---|
69 | self.assertEqual(f.seek(0), 0)
|
---|
70 | self.assertEqual(f.write(t("Hello.")), 6)
|
---|
71 | self.assertEqual(f.tell(), 6)
|
---|
72 | self.assertEqual(f.seek(5), 5)
|
---|
73 | self.assertEqual(f.tell(), 5)
|
---|
74 | self.assertEqual(f.write(t(" world\n\n\n")), 9)
|
---|
75 | self.assertEqual(f.seek(0), 0)
|
---|
76 | self.assertEqual(f.write(t("h")), 1)
|
---|
77 | self.assertEqual(f.truncate(12), 12)
|
---|
78 | self.assertEqual(f.tell(), 1)
|
---|
79 |
|
---|
80 | def test_write(self):
|
---|
81 | buf = self.buftype("hello world\n")
|
---|
82 | memio = self.ioclass(buf)
|
---|
83 |
|
---|
84 | self.write_ops(memio, self.buftype)
|
---|
85 | self.assertEqual(memio.getvalue(), buf)
|
---|
86 | memio = self.ioclass()
|
---|
87 | self.write_ops(memio, self.buftype)
|
---|
88 | self.assertEqual(memio.getvalue(), buf)
|
---|
89 | self.assertRaises(TypeError, memio.write, None)
|
---|
90 | memio.close()
|
---|
91 | self.assertRaises(ValueError, memio.write, self.buftype(""))
|
---|
92 |
|
---|
93 | def test_writelines(self):
|
---|
94 | buf = self.buftype("1234567890")
|
---|
95 | memio = self.ioclass()
|
---|
96 |
|
---|
97 | self.assertEqual(memio.writelines([buf] * 100), None)
|
---|
98 | self.assertEqual(memio.getvalue(), buf * 100)
|
---|
99 | memio.writelines([])
|
---|
100 | self.assertEqual(memio.getvalue(), buf * 100)
|
---|
101 | memio = self.ioclass()
|
---|
102 | self.assertRaises(TypeError, memio.writelines, [buf] + [1])
|
---|
103 | self.assertEqual(memio.getvalue(), buf)
|
---|
104 | self.assertRaises(TypeError, memio.writelines, None)
|
---|
105 | memio.close()
|
---|
106 | self.assertRaises(ValueError, memio.writelines, [])
|
---|
107 |
|
---|
108 | def test_writelines_error(self):
|
---|
109 | memio = self.ioclass()
|
---|
110 | def error_gen():
|
---|
111 | yield self.buftype('spam')
|
---|
112 | raise KeyboardInterrupt
|
---|
113 |
|
---|
114 | self.assertRaises(KeyboardInterrupt, memio.writelines, error_gen())
|
---|
115 |
|
---|
116 | def test_truncate(self):
|
---|
117 | buf = self.buftype("1234567890")
|
---|
118 | memio = self.ioclass(buf)
|
---|
119 |
|
---|
120 | self.assertRaises(ValueError, memio.truncate, -1)
|
---|
121 | memio.seek(6)
|
---|
122 | self.assertEqual(memio.truncate(), 6)
|
---|
123 | self.assertEqual(memio.getvalue(), buf[:6])
|
---|
124 | self.assertEqual(memio.truncate(4), 4)
|
---|
125 | self.assertEqual(memio.getvalue(), buf[:4])
|
---|
126 | # truncate() accepts long objects
|
---|
127 | self.assertEqual(memio.truncate(4L), 4)
|
---|
128 | self.assertEqual(memio.getvalue(), buf[:4])
|
---|
129 | self.assertEqual(memio.tell(), 6)
|
---|
130 | memio.seek(0, 2)
|
---|
131 | memio.write(buf)
|
---|
132 | self.assertEqual(memio.getvalue(), buf[:4] + buf)
|
---|
133 | pos = memio.tell()
|
---|
134 | self.assertEqual(memio.truncate(None), pos)
|
---|
135 | self.assertEqual(memio.tell(), pos)
|
---|
136 | self.assertRaises(TypeError, memio.truncate, '0')
|
---|
137 | memio.close()
|
---|
138 | self.assertRaises(ValueError, memio.truncate, 0)
|
---|
139 |
|
---|
140 | def test_init(self):
|
---|
141 | buf = self.buftype("1234567890")
|
---|
142 | memio = self.ioclass(buf)
|
---|
143 | self.assertEqual(memio.getvalue(), buf)
|
---|
144 | memio = self.ioclass(None)
|
---|
145 | self.assertEqual(memio.getvalue(), self.EOF)
|
---|
146 | memio.__init__(buf * 2)
|
---|
147 | self.assertEqual(memio.getvalue(), buf * 2)
|
---|
148 | memio.__init__(buf)
|
---|
149 | self.assertEqual(memio.getvalue(), buf)
|
---|
150 |
|
---|
151 | def test_read(self):
|
---|
152 | buf = self.buftype("1234567890")
|
---|
153 | memio = self.ioclass(buf)
|
---|
154 |
|
---|
155 | self.assertEqual(memio.read(0), self.EOF)
|
---|
156 | self.assertEqual(memio.read(1), buf[:1])
|
---|
157 | # read() accepts long objects
|
---|
158 | self.assertEqual(memio.read(4L), buf[1:5])
|
---|
159 | self.assertEqual(memio.read(900), buf[5:])
|
---|
160 | self.assertEqual(memio.read(), self.EOF)
|
---|
161 | memio.seek(0)
|
---|
162 | self.assertEqual(memio.read(), buf)
|
---|
163 | self.assertEqual(memio.read(), self.EOF)
|
---|
164 | self.assertEqual(memio.tell(), 10)
|
---|
165 | memio.seek(0)
|
---|
166 | self.assertEqual(memio.read(-1), buf)
|
---|
167 | memio.seek(0)
|
---|
168 | self.assertEqual(type(memio.read()), type(buf))
|
---|
169 | memio.seek(100)
|
---|
170 | self.assertEqual(type(memio.read()), type(buf))
|
---|
171 | memio.seek(0)
|
---|
172 | self.assertEqual(memio.read(None), buf)
|
---|
173 | self.assertRaises(TypeError, memio.read, '')
|
---|
174 | memio.close()
|
---|
175 | self.assertRaises(ValueError, memio.read)
|
---|
176 |
|
---|
177 | def test_readline(self):
|
---|
178 | buf = self.buftype("1234567890\n")
|
---|
179 | memio = self.ioclass(buf * 2)
|
---|
180 |
|
---|
181 | self.assertEqual(memio.readline(0), self.EOF)
|
---|
182 | self.assertEqual(memio.readline(), buf)
|
---|
183 | self.assertEqual(memio.readline(), buf)
|
---|
184 | self.assertEqual(memio.readline(), self.EOF)
|
---|
185 | memio.seek(0)
|
---|
186 | self.assertEqual(memio.readline(5), buf[:5])
|
---|
187 | # readline() accepts long objects
|
---|
188 | self.assertEqual(memio.readline(5L), buf[5:10])
|
---|
189 | self.assertEqual(memio.readline(5), buf[10:15])
|
---|
190 | memio.seek(0)
|
---|
191 | self.assertEqual(memio.readline(-1), buf)
|
---|
192 | memio.seek(0)
|
---|
193 | self.assertEqual(memio.readline(0), self.EOF)
|
---|
194 |
|
---|
195 | buf = self.buftype("1234567890\n")
|
---|
196 | memio = self.ioclass((buf * 3)[:-1])
|
---|
197 | self.assertEqual(memio.readline(), buf)
|
---|
198 | self.assertEqual(memio.readline(), buf)
|
---|
199 | self.assertEqual(memio.readline(), buf[:-1])
|
---|
200 | self.assertEqual(memio.readline(), self.EOF)
|
---|
201 | memio.seek(0)
|
---|
202 | self.assertEqual(type(memio.readline()), type(buf))
|
---|
203 | self.assertEqual(memio.readline(), buf)
|
---|
204 | self.assertRaises(TypeError, memio.readline, '')
|
---|
205 | memio.close()
|
---|
206 | self.assertRaises(ValueError, memio.readline)
|
---|
207 |
|
---|
208 | def test_readlines(self):
|
---|
209 | buf = self.buftype("1234567890\n")
|
---|
210 | memio = self.ioclass(buf * 10)
|
---|
211 |
|
---|
212 | self.assertEqual(memio.readlines(), [buf] * 10)
|
---|
213 | memio.seek(5)
|
---|
214 | self.assertEqual(memio.readlines(), [buf[5:]] + [buf] * 9)
|
---|
215 | memio.seek(0)
|
---|
216 | # readlines() accepts long objects
|
---|
217 | self.assertEqual(memio.readlines(15L), [buf] * 2)
|
---|
218 | memio.seek(0)
|
---|
219 | self.assertEqual(memio.readlines(-1), [buf] * 10)
|
---|
220 | memio.seek(0)
|
---|
221 | self.assertEqual(memio.readlines(0), [buf] * 10)
|
---|
222 | memio.seek(0)
|
---|
223 | self.assertEqual(type(memio.readlines()[0]), type(buf))
|
---|
224 | memio.seek(0)
|
---|
225 | self.assertEqual(memio.readlines(None), [buf] * 10)
|
---|
226 | self.assertRaises(TypeError, memio.readlines, '')
|
---|
227 | memio.close()
|
---|
228 | self.assertRaises(ValueError, memio.readlines)
|
---|
229 |
|
---|
230 | def test_iterator(self):
|
---|
231 | buf = self.buftype("1234567890\n")
|
---|
232 | memio = self.ioclass(buf * 10)
|
---|
233 |
|
---|
234 | self.assertEqual(iter(memio), memio)
|
---|
235 | self.assertTrue(hasattr(memio, '__iter__'))
|
---|
236 | self.assertTrue(hasattr(memio, 'next'))
|
---|
237 | i = 0
|
---|
238 | for line in memio:
|
---|
239 | self.assertEqual(line, buf)
|
---|
240 | i += 1
|
---|
241 | self.assertEqual(i, 10)
|
---|
242 | memio.seek(0)
|
---|
243 | i = 0
|
---|
244 | for line in memio:
|
---|
245 | self.assertEqual(line, buf)
|
---|
246 | i += 1
|
---|
247 | self.assertEqual(i, 10)
|
---|
248 | memio = self.ioclass(buf * 2)
|
---|
249 | memio.close()
|
---|
250 | self.assertRaises(ValueError, next, memio)
|
---|
251 |
|
---|
252 | def test_getvalue(self):
|
---|
253 | buf = self.buftype("1234567890")
|
---|
254 | memio = self.ioclass(buf)
|
---|
255 |
|
---|
256 | self.assertEqual(memio.getvalue(), buf)
|
---|
257 | memio.read()
|
---|
258 | self.assertEqual(memio.getvalue(), buf)
|
---|
259 | self.assertEqual(type(memio.getvalue()), type(buf))
|
---|
260 | memio = self.ioclass(buf * 1000)
|
---|
261 | self.assertEqual(memio.getvalue()[-3:], self.buftype("890"))
|
---|
262 | memio = self.ioclass(buf)
|
---|
263 | memio.close()
|
---|
264 | self.assertRaises(ValueError, memio.getvalue)
|
---|
265 |
|
---|
266 | def test_seek(self):
|
---|
267 | buf = self.buftype("1234567890")
|
---|
268 | memio = self.ioclass(buf)
|
---|
269 |
|
---|
270 | memio.read(5)
|
---|
271 | self.assertRaises(ValueError, memio.seek, -1)
|
---|
272 | self.assertRaises(ValueError, memio.seek, 1, -1)
|
---|
273 | self.assertRaises(ValueError, memio.seek, 1, 3)
|
---|
274 | self.assertEqual(memio.seek(0), 0)
|
---|
275 | self.assertEqual(memio.seek(0, 0), 0)
|
---|
276 | self.assertEqual(memio.read(), buf)
|
---|
277 | self.assertEqual(memio.seek(3), 3)
|
---|
278 | # seek() accepts long objects
|
---|
279 | self.assertEqual(memio.seek(3L), 3)
|
---|
280 | self.assertEqual(memio.seek(0, 1), 3)
|
---|
281 | self.assertEqual(memio.read(), buf[3:])
|
---|
282 | self.assertEqual(memio.seek(len(buf)), len(buf))
|
---|
283 | self.assertEqual(memio.read(), self.EOF)
|
---|
284 | memio.seek(len(buf) + 1)
|
---|
285 | self.assertEqual(memio.read(), self.EOF)
|
---|
286 | self.assertEqual(memio.seek(0, 2), len(buf))
|
---|
287 | self.assertEqual(memio.read(), self.EOF)
|
---|
288 | memio.close()
|
---|
289 | self.assertRaises(ValueError, memio.seek, 0)
|
---|
290 |
|
---|
291 | def test_overseek(self):
|
---|
292 | buf = self.buftype("1234567890")
|
---|
293 | memio = self.ioclass(buf)
|
---|
294 |
|
---|
295 | self.assertEqual(memio.seek(len(buf) + 1), 11)
|
---|
296 | self.assertEqual(memio.read(), self.EOF)
|
---|
297 | self.assertEqual(memio.tell(), 11)
|
---|
298 | self.assertEqual(memio.getvalue(), buf)
|
---|
299 | memio.write(self.EOF)
|
---|
300 | self.assertEqual(memio.getvalue(), buf)
|
---|
301 | memio.write(buf)
|
---|
302 | self.assertEqual(memio.getvalue(), buf + self.buftype('\0') + buf)
|
---|
303 |
|
---|
304 | def test_tell(self):
|
---|
305 | buf = self.buftype("1234567890")
|
---|
306 | memio = self.ioclass(buf)
|
---|
307 |
|
---|
308 | self.assertEqual(memio.tell(), 0)
|
---|
309 | memio.seek(5)
|
---|
310 | self.assertEqual(memio.tell(), 5)
|
---|
311 | memio.seek(10000)
|
---|
312 | self.assertEqual(memio.tell(), 10000)
|
---|
313 | memio.close()
|
---|
314 | self.assertRaises(ValueError, memio.tell)
|
---|
315 |
|
---|
316 | def test_flush(self):
|
---|
317 | buf = self.buftype("1234567890")
|
---|
318 | memio = self.ioclass(buf)
|
---|
319 |
|
---|
320 | self.assertEqual(memio.flush(), None)
|
---|
321 |
|
---|
322 | def test_flags(self):
|
---|
323 | memio = self.ioclass()
|
---|
324 |
|
---|
325 | self.assertEqual(memio.writable(), True)
|
---|
326 | self.assertEqual(memio.readable(), True)
|
---|
327 | self.assertEqual(memio.seekable(), True)
|
---|
328 | self.assertEqual(memio.isatty(), False)
|
---|
329 | self.assertEqual(memio.closed, False)
|
---|
330 | memio.close()
|
---|
331 | self.assertRaises(ValueError, memio.writable)
|
---|
332 | self.assertRaises(ValueError, memio.readable)
|
---|
333 | self.assertRaises(ValueError, memio.seekable)
|
---|
334 | self.assertRaises(ValueError, memio.isatty)
|
---|
335 | self.assertEqual(memio.closed, True)
|
---|
336 |
|
---|
337 | def test_subclassing(self):
|
---|
338 | buf = self.buftype("1234567890")
|
---|
339 | def test1():
|
---|
340 | class MemIO(self.ioclass):
|
---|
341 | pass
|
---|
342 | m = MemIO(buf)
|
---|
343 | return m.getvalue()
|
---|
344 | def test2():
|
---|
345 | class MemIO(self.ioclass):
|
---|
346 | def __init__(me, a, b):
|
---|
347 | self.ioclass.__init__(me, a)
|
---|
348 | m = MemIO(buf, None)
|
---|
349 | return m.getvalue()
|
---|
350 | self.assertEqual(test1(), buf)
|
---|
351 | self.assertEqual(test2(), buf)
|
---|
352 |
|
---|
353 | def test_instance_dict_leak(self):
|
---|
354 | # Test case for issue #6242.
|
---|
355 | # This will be caught by regrtest.py -R if this leak.
|
---|
356 | for _ in range(100):
|
---|
357 | memio = self.ioclass()
|
---|
358 | memio.foo = 1
|
---|
359 |
|
---|
360 | def test_pickling(self):
|
---|
361 | buf = self.buftype("1234567890")
|
---|
362 | memio = self.ioclass(buf)
|
---|
363 | memio.foo = 42
|
---|
364 | memio.seek(2)
|
---|
365 |
|
---|
366 | class PickleTestMemIO(self.ioclass):
|
---|
367 | def __init__(me, initvalue, foo):
|
---|
368 | self.ioclass.__init__(me, initvalue)
|
---|
369 | me.foo = foo
|
---|
370 | # __getnewargs__ is undefined on purpose. This checks that PEP 307
|
---|
371 | # is used to provide pickling support.
|
---|
372 |
|
---|
373 | # Pickle expects the class to be on the module level. Here we use a
|
---|
374 | # little hack to allow the PickleTestMemIO class to derive from
|
---|
375 | # self.ioclass without having to define all combinations explicitly on
|
---|
376 | # the module-level.
|
---|
377 | import __main__
|
---|
378 | PickleTestMemIO.__module__ = '__main__'
|
---|
379 | __main__.PickleTestMemIO = PickleTestMemIO
|
---|
380 | submemio = PickleTestMemIO(buf, 80)
|
---|
381 | submemio.seek(2)
|
---|
382 |
|
---|
383 | # We only support pickle protocol 2 and onward since we use extended
|
---|
384 | # __reduce__ API of PEP 307 to provide pickling support.
|
---|
385 | for proto in range(2, pickle.HIGHEST_PROTOCOL):
|
---|
386 | for obj in (memio, submemio):
|
---|
387 | obj2 = pickle.loads(pickle.dumps(obj, protocol=proto))
|
---|
388 | self.assertEqual(obj.getvalue(), obj2.getvalue())
|
---|
389 | self.assertEqual(obj.__class__, obj2.__class__)
|
---|
390 | self.assertEqual(obj.foo, obj2.foo)
|
---|
391 | self.assertEqual(obj.tell(), obj2.tell())
|
---|
392 | obj.close()
|
---|
393 | self.assertRaises(ValueError, pickle.dumps, obj, proto)
|
---|
394 | del __main__.PickleTestMemIO
|
---|
395 |
|
---|
396 |
|
---|
397 | class PyBytesIOTest(MemoryTestMixin, MemorySeekTestMixin, unittest.TestCase):
|
---|
398 |
|
---|
399 | UnsupportedOperation = pyio.UnsupportedOperation
|
---|
400 |
|
---|
401 | @staticmethod
|
---|
402 | def buftype(s):
|
---|
403 | return s.encode("ascii")
|
---|
404 | ioclass = pyio.BytesIO
|
---|
405 | EOF = b""
|
---|
406 |
|
---|
407 | def test_read1(self):
|
---|
408 | buf = self.buftype("1234567890")
|
---|
409 | memio = self.ioclass(buf)
|
---|
410 |
|
---|
411 | self.assertRaises(TypeError, memio.read1)
|
---|
412 | self.assertEqual(memio.read(), buf)
|
---|
413 |
|
---|
414 | def test_readinto(self):
|
---|
415 | buf = self.buftype("1234567890")
|
---|
416 | memio = self.ioclass(buf)
|
---|
417 |
|
---|
418 | b = bytearray(b"hello")
|
---|
419 | self.assertEqual(memio.readinto(b), 5)
|
---|
420 | self.assertEqual(b, b"12345")
|
---|
421 | self.assertEqual(memio.readinto(b), 5)
|
---|
422 | self.assertEqual(b, b"67890")
|
---|
423 | self.assertEqual(memio.readinto(b), 0)
|
---|
424 | self.assertEqual(b, b"67890")
|
---|
425 | b = bytearray(b"hello world")
|
---|
426 | memio.seek(0)
|
---|
427 | self.assertEqual(memio.readinto(b), 10)
|
---|
428 | self.assertEqual(b, b"1234567890d")
|
---|
429 | b = bytearray(b"")
|
---|
430 | memio.seek(0)
|
---|
431 | self.assertEqual(memio.readinto(b), 0)
|
---|
432 | self.assertEqual(b, b"")
|
---|
433 | self.assertRaises(TypeError, memio.readinto, '')
|
---|
434 | import array
|
---|
435 | a = array.array(b'b', b"hello world")
|
---|
436 | memio = self.ioclass(buf)
|
---|
437 | memio.readinto(a)
|
---|
438 | self.assertEqual(a.tostring(), b"1234567890d")
|
---|
439 | memio.close()
|
---|
440 | self.assertRaises(ValueError, memio.readinto, b)
|
---|
441 | memio = self.ioclass(b"123")
|
---|
442 | b = bytearray()
|
---|
443 | memio.seek(42)
|
---|
444 | memio.readinto(b)
|
---|
445 | self.assertEqual(b, b"")
|
---|
446 |
|
---|
447 | def test_relative_seek(self):
|
---|
448 | buf = self.buftype("1234567890")
|
---|
449 | memio = self.ioclass(buf)
|
---|
450 |
|
---|
451 | self.assertEqual(memio.seek(-1, 1), 0)
|
---|
452 | self.assertEqual(memio.seek(3, 1), 3)
|
---|
453 | self.assertEqual(memio.seek(-4, 1), 0)
|
---|
454 | self.assertEqual(memio.seek(-1, 2), 9)
|
---|
455 | self.assertEqual(memio.seek(1, 1), 10)
|
---|
456 | self.assertEqual(memio.seek(1, 2), 11)
|
---|
457 | memio.seek(-3, 2)
|
---|
458 | self.assertEqual(memio.read(), buf[-3:])
|
---|
459 | memio.seek(0)
|
---|
460 | memio.seek(1, 1)
|
---|
461 | self.assertEqual(memio.read(), buf[1:])
|
---|
462 |
|
---|
463 | def test_unicode(self):
|
---|
464 | memio = self.ioclass()
|
---|
465 |
|
---|
466 | self.assertRaises(TypeError, self.ioclass, "1234567890")
|
---|
467 | self.assertRaises(TypeError, memio.write, "1234567890")
|
---|
468 | self.assertRaises(TypeError, memio.writelines, ["1234567890"])
|
---|
469 |
|
---|
470 | def test_bytes_array(self):
|
---|
471 | buf = b"1234567890"
|
---|
472 | import array
|
---|
473 | a = array.array(b'b', buf)
|
---|
474 | memio = self.ioclass(a)
|
---|
475 | self.assertEqual(memio.getvalue(), buf)
|
---|
476 | self.assertEqual(memio.write(a), 10)
|
---|
477 | self.assertEqual(memio.getvalue(), buf)
|
---|
478 |
|
---|
479 | def test_issue5449(self):
|
---|
480 | buf = self.buftype("1234567890")
|
---|
481 | self.ioclass(initial_bytes=buf)
|
---|
482 | self.assertRaises(TypeError, self.ioclass, buf, foo=None)
|
---|
483 |
|
---|
484 |
|
---|
485 | class TextIOTestMixin:
|
---|
486 |
|
---|
487 | def test_newlines_property(self):
|
---|
488 | memio = self.ioclass(newline=None)
|
---|
489 | # The C StringIO decodes newlines in write() calls, but the Python
|
---|
490 | # implementation only does when reading. This function forces them to
|
---|
491 | # be decoded for testing.
|
---|
492 | def force_decode():
|
---|
493 | memio.seek(0)
|
---|
494 | memio.read()
|
---|
495 | self.assertEqual(memio.newlines, None)
|
---|
496 | memio.write("a\n")
|
---|
497 | force_decode()
|
---|
498 | self.assertEqual(memio.newlines, "\n")
|
---|
499 | memio.write("b\r\n")
|
---|
500 | force_decode()
|
---|
501 | self.assertEqual(memio.newlines, ("\n", "\r\n"))
|
---|
502 | memio.write("c\rd")
|
---|
503 | force_decode()
|
---|
504 | self.assertEqual(memio.newlines, ("\r", "\n", "\r\n"))
|
---|
505 |
|
---|
506 | def test_relative_seek(self):
|
---|
507 | memio = self.ioclass()
|
---|
508 |
|
---|
509 | self.assertRaises(IOError, memio.seek, -1, 1)
|
---|
510 | self.assertRaises(IOError, memio.seek, 3, 1)
|
---|
511 | self.assertRaises(IOError, memio.seek, -3, 1)
|
---|
512 | self.assertRaises(IOError, memio.seek, -1, 2)
|
---|
513 | self.assertRaises(IOError, memio.seek, 1, 1)
|
---|
514 | self.assertRaises(IOError, memio.seek, 1, 2)
|
---|
515 |
|
---|
516 | def test_textio_properties(self):
|
---|
517 | memio = self.ioclass()
|
---|
518 |
|
---|
519 | # These are just dummy values but we nevertheless check them for fear
|
---|
520 | # of unexpected breakage.
|
---|
521 | self.assertIsNone(memio.encoding)
|
---|
522 | self.assertIsNone(memio.errors)
|
---|
523 | self.assertFalse(memio.line_buffering)
|
---|
524 |
|
---|
525 | def test_newline_none(self):
|
---|
526 | # newline=None
|
---|
527 | memio = self.ioclass("a\nb\r\nc\rd", newline=None)
|
---|
528 | self.assertEqual(list(memio), ["a\n", "b\n", "c\n", "d"])
|
---|
529 | memio.seek(0)
|
---|
530 | self.assertEqual(memio.read(1), "a")
|
---|
531 | self.assertEqual(memio.read(2), "\nb")
|
---|
532 | self.assertEqual(memio.read(2), "\nc")
|
---|
533 | self.assertEqual(memio.read(1), "\n")
|
---|
534 | memio = self.ioclass(newline=None)
|
---|
535 | self.assertEqual(2, memio.write("a\n"))
|
---|
536 | self.assertEqual(3, memio.write("b\r\n"))
|
---|
537 | self.assertEqual(3, memio.write("c\rd"))
|
---|
538 | memio.seek(0)
|
---|
539 | self.assertEqual(memio.read(), "a\nb\nc\nd")
|
---|
540 | memio = self.ioclass("a\r\nb", newline=None)
|
---|
541 | self.assertEqual(memio.read(3), "a\nb")
|
---|
542 |
|
---|
543 | def test_newline_empty(self):
|
---|
544 | # newline=""
|
---|
545 | memio = self.ioclass("a\nb\r\nc\rd", newline="")
|
---|
546 | self.assertEqual(list(memio), ["a\n", "b\r\n", "c\r", "d"])
|
---|
547 | memio.seek(0)
|
---|
548 | self.assertEqual(memio.read(4), "a\nb\r")
|
---|
549 | self.assertEqual(memio.read(2), "\nc")
|
---|
550 | self.assertEqual(memio.read(1), "\r")
|
---|
551 | memio = self.ioclass(newline="")
|
---|
552 | self.assertEqual(2, memio.write("a\n"))
|
---|
553 | self.assertEqual(2, memio.write("b\r"))
|
---|
554 | self.assertEqual(2, memio.write("\nc"))
|
---|
555 | self.assertEqual(2, memio.write("\rd"))
|
---|
556 | memio.seek(0)
|
---|
557 | self.assertEqual(list(memio), ["a\n", "b\r\n", "c\r", "d"])
|
---|
558 |
|
---|
559 | def test_newline_lf(self):
|
---|
560 | # newline="\n"
|
---|
561 | memio = self.ioclass("a\nb\r\nc\rd")
|
---|
562 | self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"])
|
---|
563 |
|
---|
564 | def test_newline_cr(self):
|
---|
565 | # newline="\r"
|
---|
566 | memio = self.ioclass("a\nb\r\nc\rd", newline="\r")
|
---|
567 | self.assertEqual(memio.read(), "a\rb\r\rc\rd")
|
---|
568 | memio.seek(0)
|
---|
569 | self.assertEqual(list(memio), ["a\r", "b\r", "\r", "c\r", "d"])
|
---|
570 |
|
---|
571 | def test_newline_crlf(self):
|
---|
572 | # newline="\r\n"
|
---|
573 | memio = self.ioclass("a\nb\r\nc\rd", newline="\r\n")
|
---|
574 | self.assertEqual(memio.read(), "a\r\nb\r\r\nc\rd")
|
---|
575 | memio.seek(0)
|
---|
576 | self.assertEqual(list(memio), ["a\r\n", "b\r\r\n", "c\rd"])
|
---|
577 |
|
---|
578 | def test_issue5265(self):
|
---|
579 | # StringIO can duplicate newlines in universal newlines mode
|
---|
580 | memio = self.ioclass("a\r\nb\r\n", newline=None)
|
---|
581 | self.assertEqual(memio.read(5), "a\nb\n")
|
---|
582 |
|
---|
583 |
|
---|
584 | class PyStringIOTest(MemoryTestMixin, MemorySeekTestMixin,
|
---|
585 | TextIOTestMixin, unittest.TestCase):
|
---|
586 | buftype = unicode
|
---|
587 | ioclass = pyio.StringIO
|
---|
588 | UnsupportedOperation = pyio.UnsupportedOperation
|
---|
589 | EOF = ""
|
---|
590 |
|
---|
591 |
|
---|
592 | class PyStringIOPickleTest(TextIOTestMixin, unittest.TestCase):
|
---|
593 | """Test if pickle restores properly the internal state of StringIO.
|
---|
594 | """
|
---|
595 | buftype = unicode
|
---|
596 | UnsupportedOperation = pyio.UnsupportedOperation
|
---|
597 | EOF = ""
|
---|
598 |
|
---|
599 | class ioclass(pyio.StringIO):
|
---|
600 | def __new__(cls, *args, **kwargs):
|
---|
601 | return pickle.loads(pickle.dumps(pyio.StringIO(*args, **kwargs)))
|
---|
602 | def __init__(self, *args, **kwargs):
|
---|
603 | pass
|
---|
604 |
|
---|
605 |
|
---|
606 | class CBytesIOTest(PyBytesIOTest):
|
---|
607 | ioclass = io.BytesIO
|
---|
608 | UnsupportedOperation = io.UnsupportedOperation
|
---|
609 |
|
---|
610 | test_bytes_array = unittest.skip(
|
---|
611 | "array.array() does not have the new buffer API"
|
---|
612 | )(PyBytesIOTest.test_bytes_array)
|
---|
613 |
|
---|
614 |
|
---|
615 | def test_getstate(self):
|
---|
616 | memio = self.ioclass()
|
---|
617 | state = memio.__getstate__()
|
---|
618 | self.assertEqual(len(state), 3)
|
---|
619 | bytearray(state[0]) # Check if state[0] supports the buffer interface.
|
---|
620 | self.assertIsInstance(state[1], int)
|
---|
621 | self.assertTrue(isinstance(state[2], dict) or state[2] is None)
|
---|
622 | memio.close()
|
---|
623 | self.assertRaises(ValueError, memio.__getstate__)
|
---|
624 |
|
---|
625 | def test_setstate(self):
|
---|
626 | # This checks whether __setstate__ does proper input validation.
|
---|
627 | memio = self.ioclass()
|
---|
628 | memio.__setstate__((b"no error", 0, None))
|
---|
629 | memio.__setstate__((bytearray(b"no error"), 0, None))
|
---|
630 | memio.__setstate__((b"no error", 0, {'spam': 3}))
|
---|
631 | self.assertRaises(ValueError, memio.__setstate__, (b"", -1, None))
|
---|
632 | self.assertRaises(TypeError, memio.__setstate__, ("unicode", 0, None))
|
---|
633 | self.assertRaises(TypeError, memio.__setstate__, (b"", 0.0, None))
|
---|
634 | self.assertRaises(TypeError, memio.__setstate__, (b"", 0, 0))
|
---|
635 | self.assertRaises(TypeError, memio.__setstate__, (b"len-test", 0))
|
---|
636 | self.assertRaises(TypeError, memio.__setstate__)
|
---|
637 | self.assertRaises(TypeError, memio.__setstate__, 0)
|
---|
638 | memio.close()
|
---|
639 | self.assertRaises(ValueError, memio.__setstate__, (b"closed", 0, None))
|
---|
640 |
|
---|
641 | check_sizeof = support.check_sizeof
|
---|
642 |
|
---|
643 | @support.cpython_only
|
---|
644 | def test_sizeof(self):
|
---|
645 | basesize = support.calcobjsize(b'P2PP2P')
|
---|
646 | check = self.check_sizeof
|
---|
647 | self.assertEqual(object.__sizeof__(io.BytesIO()), basesize)
|
---|
648 | check(io.BytesIO(), basesize )
|
---|
649 | check(io.BytesIO(b'a'), basesize + 1 + 1 )
|
---|
650 | check(io.BytesIO(b'a' * 1000), basesize + 1000 + 1 )
|
---|
651 |
|
---|
652 | class CStringIOTest(PyStringIOTest):
|
---|
653 | ioclass = io.StringIO
|
---|
654 | UnsupportedOperation = io.UnsupportedOperation
|
---|
655 |
|
---|
656 | # XXX: For the Python version of io.StringIO, this is highly
|
---|
657 | # dependent on the encoding used for the underlying buffer.
|
---|
658 | def test_widechar(self):
|
---|
659 | buf = self.buftype("\U0002030a\U00020347")
|
---|
660 | memio = self.ioclass(buf)
|
---|
661 |
|
---|
662 | self.assertEqual(memio.getvalue(), buf)
|
---|
663 | self.assertEqual(memio.write(buf), len(buf))
|
---|
664 | self.assertEqual(memio.tell(), len(buf))
|
---|
665 | self.assertEqual(memio.getvalue(), buf)
|
---|
666 | self.assertEqual(memio.write(buf), len(buf))
|
---|
667 | self.assertEqual(memio.tell(), len(buf) * 2)
|
---|
668 | self.assertEqual(memio.getvalue(), buf + buf)
|
---|
669 |
|
---|
670 | def test_getstate(self):
|
---|
671 | memio = self.ioclass()
|
---|
672 | state = memio.__getstate__()
|
---|
673 | self.assertEqual(len(state), 4)
|
---|
674 | self.assertIsInstance(state[0], unicode)
|
---|
675 | self.assertIsInstance(state[1], str)
|
---|
676 | self.assertIsInstance(state[2], int)
|
---|
677 | self.assertTrue(isinstance(state[3], dict) or state[3] is None)
|
---|
678 | memio.close()
|
---|
679 | self.assertRaises(ValueError, memio.__getstate__)
|
---|
680 |
|
---|
681 | def test_setstate(self):
|
---|
682 | # This checks whether __setstate__ does proper input validation.
|
---|
683 | memio = self.ioclass()
|
---|
684 | memio.__setstate__(("no error", "\n", 0, None))
|
---|
685 | memio.__setstate__(("no error", "", 0, {'spam': 3}))
|
---|
686 | self.assertRaises(ValueError, memio.__setstate__, ("", "f", 0, None))
|
---|
687 | self.assertRaises(ValueError, memio.__setstate__, ("", "", -1, None))
|
---|
688 | self.assertRaises(TypeError, memio.__setstate__, (b"", "", 0, None))
|
---|
689 | # trunk is more tolerant than py3k on the type of the newline param
|
---|
690 | #self.assertRaises(TypeError, memio.__setstate__, ("", b"", 0, None))
|
---|
691 | self.assertRaises(TypeError, memio.__setstate__, ("", "", 0.0, None))
|
---|
692 | self.assertRaises(TypeError, memio.__setstate__, ("", "", 0, 0))
|
---|
693 | self.assertRaises(TypeError, memio.__setstate__, ("len-test", 0))
|
---|
694 | self.assertRaises(TypeError, memio.__setstate__)
|
---|
695 | self.assertRaises(TypeError, memio.__setstate__, 0)
|
---|
696 | memio.close()
|
---|
697 | self.assertRaises(ValueError, memio.__setstate__, ("closed", "", 0, None))
|
---|
698 |
|
---|
699 |
|
---|
700 | class CStringIOPickleTest(PyStringIOPickleTest):
|
---|
701 | UnsupportedOperation = io.UnsupportedOperation
|
---|
702 |
|
---|
703 | class ioclass(io.StringIO):
|
---|
704 | def __new__(cls, *args, **kwargs):
|
---|
705 | return pickle.loads(pickle.dumps(io.StringIO(*args, **kwargs),
|
---|
706 | protocol=2))
|
---|
707 | def __init__(self, *args, **kwargs):
|
---|
708 | pass
|
---|
709 |
|
---|
710 |
|
---|
711 | def test_main():
|
---|
712 | tests = [PyBytesIOTest, PyStringIOTest, CBytesIOTest, CStringIOTest,
|
---|
713 | PyStringIOPickleTest, CStringIOPickleTest]
|
---|
714 | support.run_unittest(*tests)
|
---|
715 |
|
---|
716 | if __name__ == '__main__':
|
---|
717 | test_main()
|
---|