python (3.12.0)
1 """Unit tests for memory-based file-like objects.
2 StringIO -- for unicode strings
3 BytesIO -- for bytes
4 """
5
6 import unittest
7 from test import support
8
9 import io
10 import _pyio as pyio
11 import pickle
12 import sys
13
14 class ESC[4;38;5;81mIntLike:
15 def __init__(self, num):
16 self._num = num
17 def __index__(self):
18 return self._num
19 __int__ = __index__
20
21 class ESC[4;38;5;81mMemorySeekTestMixin:
22
23 def testInit(self):
24 buf = self.buftype("1234567890")
25 bytesIo = self.ioclass(buf)
26
27 def testRead(self):
28 buf = self.buftype("1234567890")
29 bytesIo = self.ioclass(buf)
30
31 self.assertEqual(buf[:1], bytesIo.read(1))
32 self.assertEqual(buf[1:5], bytesIo.read(4))
33 self.assertEqual(buf[5:], bytesIo.read(900))
34 self.assertEqual(self.EOF, bytesIo.read())
35
36 def testReadNoArgs(self):
37 buf = self.buftype("1234567890")
38 bytesIo = self.ioclass(buf)
39
40 self.assertEqual(buf, bytesIo.read())
41 self.assertEqual(self.EOF, bytesIo.read())
42
43 def testSeek(self):
44 buf = self.buftype("1234567890")
45 bytesIo = self.ioclass(buf)
46
47 bytesIo.read(5)
48 bytesIo.seek(0)
49 self.assertEqual(buf, bytesIo.read())
50
51 bytesIo.seek(3)
52 self.assertEqual(buf[3:], bytesIo.read())
53 self.assertRaises(TypeError, bytesIo.seek, 0.0)
54
55 def testTell(self):
56 buf = self.buftype("1234567890")
57 bytesIo = self.ioclass(buf)
58
59 self.assertEqual(0, bytesIo.tell())
60 bytesIo.seek(5)
61 self.assertEqual(5, bytesIo.tell())
62 bytesIo.seek(10000)
63 self.assertEqual(10000, bytesIo.tell())
64
65
66 class ESC[4;38;5;81mMemoryTestMixin:
67
68 def test_detach(self):
69 buf = self.ioclass()
70 self.assertRaises(self.UnsupportedOperation, buf.detach)
71
72 def write_ops(self, f, t):
73 self.assertEqual(f.write(t("blah.")), 5)
74 self.assertEqual(f.seek(0), 0)
75 self.assertEqual(f.write(t("Hello.")), 6)
76 self.assertEqual(f.tell(), 6)
77 self.assertEqual(f.seek(5), 5)
78 self.assertEqual(f.tell(), 5)
79 self.assertEqual(f.write(t(" world\n\n\n")), 9)
80 self.assertEqual(f.seek(0), 0)
81 self.assertEqual(f.write(t("h")), 1)
82 self.assertEqual(f.truncate(12), 12)
83 self.assertEqual(f.tell(), 1)
84
85 def test_write(self):
86 buf = self.buftype("hello world\n")
87 memio = self.ioclass(buf)
88
89 self.write_ops(memio, self.buftype)
90 self.assertEqual(memio.getvalue(), buf)
91 memio = self.ioclass()
92 self.write_ops(memio, self.buftype)
93 self.assertEqual(memio.getvalue(), buf)
94 self.assertRaises(TypeError, memio.write, None)
95 memio.close()
96 self.assertRaises(ValueError, memio.write, self.buftype(""))
97
98 def test_writelines(self):
99 buf = self.buftype("1234567890")
100 memio = self.ioclass()
101
102 self.assertEqual(memio.writelines([buf] * 100), None)
103 self.assertEqual(memio.getvalue(), buf * 100)
104 memio.writelines([])
105 self.assertEqual(memio.getvalue(), buf * 100)
106 memio = self.ioclass()
107 self.assertRaises(TypeError, memio.writelines, [buf] + [1])
108 self.assertEqual(memio.getvalue(), buf)
109 self.assertRaises(TypeError, memio.writelines, None)
110 memio.close()
111 self.assertRaises(ValueError, memio.writelines, [])
112
113 def test_writelines_error(self):
114 memio = self.ioclass()
115 def error_gen():
116 yield self.buftype('spam')
117 raise KeyboardInterrupt
118
119 self.assertRaises(KeyboardInterrupt, memio.writelines, error_gen())
120
121 def test_truncate(self):
122 buf = self.buftype("1234567890")
123 memio = self.ioclass(buf)
124
125 self.assertRaises(ValueError, memio.truncate, -1)
126 self.assertRaises(ValueError, memio.truncate, IntLike(-1))
127 memio.seek(6)
128 self.assertEqual(memio.truncate(IntLike(8)), 8)
129 self.assertEqual(memio.getvalue(), buf[:8])
130 self.assertEqual(memio.truncate(), 6)
131 self.assertEqual(memio.getvalue(), buf[:6])
132 self.assertEqual(memio.truncate(4), 4)
133 self.assertEqual(memio.getvalue(), buf[:4])
134 self.assertEqual(memio.tell(), 6)
135 memio.seek(0, 2)
136 memio.write(buf)
137 self.assertEqual(memio.getvalue(), buf[:4] + buf)
138 pos = memio.tell()
139 self.assertEqual(memio.truncate(None), pos)
140 self.assertEqual(memio.tell(), pos)
141 self.assertRaises(TypeError, memio.truncate, '0')
142 memio.close()
143 self.assertRaises(ValueError, memio.truncate, 0)
144 self.assertRaises(ValueError, memio.truncate, IntLike(0))
145
146 def test_init(self):
147 buf = self.buftype("1234567890")
148 memio = self.ioclass(buf)
149 self.assertEqual(memio.getvalue(), buf)
150 memio = self.ioclass(None)
151 self.assertEqual(memio.getvalue(), self.EOF)
152 memio.__init__(buf * 2)
153 self.assertEqual(memio.getvalue(), buf * 2)
154 memio.__init__(buf)
155 self.assertEqual(memio.getvalue(), buf)
156 self.assertRaises(TypeError, memio.__init__, [])
157
158 def test_read(self):
159 buf = self.buftype("1234567890")
160 memio = self.ioclass(buf)
161
162 self.assertEqual(memio.read(0), self.EOF)
163 self.assertEqual(memio.read(1), buf[:1])
164 self.assertEqual(memio.read(4), buf[1:5])
165 self.assertEqual(memio.read(900), buf[5:])
166 self.assertEqual(memio.read(), self.EOF)
167 memio.seek(0)
168 self.assertEqual(memio.read(IntLike(0)), self.EOF)
169 self.assertEqual(memio.read(IntLike(1)), buf[:1])
170 self.assertEqual(memio.read(IntLike(4)), buf[1:5])
171 self.assertEqual(memio.read(IntLike(900)), buf[5:])
172 memio.seek(0)
173 self.assertEqual(memio.read(), buf)
174 self.assertEqual(memio.read(), self.EOF)
175 self.assertEqual(memio.tell(), 10)
176 memio.seek(0)
177 self.assertEqual(memio.read(-1), buf)
178 memio.seek(0)
179 self.assertEqual(memio.read(IntLike(-1)), buf)
180 memio.seek(0)
181 self.assertEqual(type(memio.read()), type(buf))
182 memio.seek(100)
183 self.assertEqual(type(memio.read()), type(buf))
184 memio.seek(0)
185 self.assertEqual(memio.read(None), buf)
186 self.assertRaises(TypeError, memio.read, '')
187 memio.seek(len(buf) + 1)
188 self.assertEqual(memio.read(1), self.EOF)
189 memio.seek(len(buf) + 1)
190 self.assertEqual(memio.read(IntLike(1)), self.EOF)
191 memio.seek(len(buf) + 1)
192 self.assertEqual(memio.read(), self.EOF)
193 memio.close()
194 self.assertRaises(ValueError, memio.read)
195
196 def test_readline(self):
197 buf = self.buftype("1234567890\n")
198 memio = self.ioclass(buf * 2)
199
200 self.assertEqual(memio.readline(0), self.EOF)
201 self.assertEqual(memio.readline(IntLike(0)), self.EOF)
202 self.assertEqual(memio.readline(), buf)
203 self.assertEqual(memio.readline(), buf)
204 self.assertEqual(memio.readline(), self.EOF)
205 memio.seek(0)
206 self.assertEqual(memio.readline(5), buf[:5])
207 self.assertEqual(memio.readline(5), buf[5:10])
208 self.assertEqual(memio.readline(5), buf[10:15])
209 memio.seek(0)
210 self.assertEqual(memio.readline(IntLike(5)), buf[:5])
211 self.assertEqual(memio.readline(IntLike(5)), buf[5:10])
212 self.assertEqual(memio.readline(IntLike(5)), buf[10:15])
213 memio.seek(0)
214 self.assertEqual(memio.readline(-1), buf)
215 memio.seek(0)
216 self.assertEqual(memio.readline(IntLike(-1)), buf)
217 memio.seek(0)
218 self.assertEqual(memio.readline(0), self.EOF)
219 self.assertEqual(memio.readline(IntLike(0)), self.EOF)
220 # Issue #24989: Buffer overread
221 memio.seek(len(buf) * 2 + 1)
222 self.assertEqual(memio.readline(), self.EOF)
223
224 buf = self.buftype("1234567890\n")
225 memio = self.ioclass((buf * 3)[:-1])
226 self.assertEqual(memio.readline(), buf)
227 self.assertEqual(memio.readline(), buf)
228 self.assertEqual(memio.readline(), buf[:-1])
229 self.assertEqual(memio.readline(), self.EOF)
230 memio.seek(0)
231 self.assertEqual(type(memio.readline()), type(buf))
232 self.assertEqual(memio.readline(), buf)
233 self.assertRaises(TypeError, memio.readline, '')
234 memio.close()
235 self.assertRaises(ValueError, memio.readline)
236
237 def test_readlines(self):
238 buf = self.buftype("1234567890\n")
239 memio = self.ioclass(buf * 10)
240
241 self.assertEqual(memio.readlines(), [buf] * 10)
242 memio.seek(5)
243 self.assertEqual(memio.readlines(), [buf[5:]] + [buf] * 9)
244 memio.seek(0)
245 self.assertEqual(memio.readlines(15), [buf] * 2)
246 memio.seek(0)
247 self.assertEqual(memio.readlines(-1), [buf] * 10)
248 memio.seek(0)
249 self.assertEqual(memio.readlines(0), [buf] * 10)
250 memio.seek(0)
251 self.assertEqual(type(memio.readlines()[0]), type(buf))
252 memio.seek(0)
253 self.assertEqual(memio.readlines(None), [buf] * 10)
254 self.assertRaises(TypeError, memio.readlines, '')
255 # Issue #24989: Buffer overread
256 memio.seek(len(buf) * 10 + 1)
257 self.assertEqual(memio.readlines(), [])
258 memio.close()
259 self.assertRaises(ValueError, memio.readlines)
260
261 def test_iterator(self):
262 buf = self.buftype("1234567890\n")
263 memio = self.ioclass(buf * 10)
264
265 self.assertEqual(iter(memio), memio)
266 self.assertTrue(hasattr(memio, '__iter__'))
267 self.assertTrue(hasattr(memio, '__next__'))
268 i = 0
269 for line in memio:
270 self.assertEqual(line, buf)
271 i += 1
272 self.assertEqual(i, 10)
273 memio.seek(0)
274 i = 0
275 for line in memio:
276 self.assertEqual(line, buf)
277 i += 1
278 self.assertEqual(i, 10)
279 # Issue #24989: Buffer overread
280 memio.seek(len(buf) * 10 + 1)
281 self.assertEqual(list(memio), [])
282 memio = self.ioclass(buf * 2)
283 memio.close()
284 self.assertRaises(ValueError, memio.__next__)
285
286 def test_getvalue(self):
287 buf = self.buftype("1234567890")
288 memio = self.ioclass(buf)
289
290 self.assertEqual(memio.getvalue(), buf)
291 memio.read()
292 self.assertEqual(memio.getvalue(), buf)
293 self.assertEqual(type(memio.getvalue()), type(buf))
294 memio = self.ioclass(buf * 1000)
295 self.assertEqual(memio.getvalue()[-3:], self.buftype("890"))
296 memio = self.ioclass(buf)
297 memio.close()
298 self.assertRaises(ValueError, memio.getvalue)
299
300 def test_seek(self):
301 buf = self.buftype("1234567890")
302 memio = self.ioclass(buf)
303
304 memio.read(5)
305 self.assertRaises(ValueError, memio.seek, -1)
306 self.assertRaises(ValueError, memio.seek, 1, -1)
307 self.assertRaises(ValueError, memio.seek, 1, 3)
308 self.assertEqual(memio.seek(0), 0)
309 self.assertEqual(memio.seek(0, 0), 0)
310 self.assertEqual(memio.read(), buf)
311 self.assertEqual(memio.seek(3), 3)
312 self.assertEqual(memio.seek(0, 1), 3)
313 self.assertEqual(memio.read(), buf[3:])
314 self.assertEqual(memio.seek(len(buf)), len(buf))
315 self.assertEqual(memio.read(), self.EOF)
316 memio.seek(len(buf) + 1)
317 self.assertEqual(memio.read(), self.EOF)
318 self.assertEqual(memio.seek(0, 2), len(buf))
319 self.assertEqual(memio.read(), self.EOF)
320 memio.close()
321 self.assertRaises(ValueError, memio.seek, 0)
322
323 def test_overseek(self):
324 buf = self.buftype("1234567890")
325 memio = self.ioclass(buf)
326
327 self.assertEqual(memio.seek(len(buf) + 1), 11)
328 self.assertEqual(memio.read(), self.EOF)
329 self.assertEqual(memio.tell(), 11)
330 self.assertEqual(memio.getvalue(), buf)
331 memio.write(self.EOF)
332 self.assertEqual(memio.getvalue(), buf)
333 memio.write(buf)
334 self.assertEqual(memio.getvalue(), buf + self.buftype('\0') + buf)
335
336 def test_tell(self):
337 buf = self.buftype("1234567890")
338 memio = self.ioclass(buf)
339
340 self.assertEqual(memio.tell(), 0)
341 memio.seek(5)
342 self.assertEqual(memio.tell(), 5)
343 memio.seek(10000)
344 self.assertEqual(memio.tell(), 10000)
345 memio.close()
346 self.assertRaises(ValueError, memio.tell)
347
348 def test_flush(self):
349 buf = self.buftype("1234567890")
350 memio = self.ioclass(buf)
351
352 self.assertEqual(memio.flush(), None)
353
354 def test_flags(self):
355 memio = self.ioclass()
356
357 self.assertEqual(memio.writable(), True)
358 self.assertEqual(memio.readable(), True)
359 self.assertEqual(memio.seekable(), True)
360 self.assertEqual(memio.isatty(), False)
361 self.assertEqual(memio.closed, False)
362 memio.close()
363 self.assertRaises(ValueError, memio.writable)
364 self.assertRaises(ValueError, memio.readable)
365 self.assertRaises(ValueError, memio.seekable)
366 self.assertRaises(ValueError, memio.isatty)
367 self.assertEqual(memio.closed, True)
368
369 def test_subclassing(self):
370 buf = self.buftype("1234567890")
371 def test1():
372 class ESC[4;38;5;81mMemIO(ESC[4;38;5;149mselfESC[4;38;5;149m.ESC[4;38;5;149mioclass):
373 pass
374 m = MemIO(buf)
375 return m.getvalue()
376 def test2():
377 class ESC[4;38;5;81mMemIO(ESC[4;38;5;149mselfESC[4;38;5;149m.ESC[4;38;5;149mioclass):
378 def __init__(me, a, b):
379 self.ioclass.__init__(me, a)
380 m = MemIO(buf, None)
381 return m.getvalue()
382 self.assertEqual(test1(), buf)
383 self.assertEqual(test2(), buf)
384
385 def test_instance_dict_leak(self):
386 # Test case for issue #6242.
387 # This will be caught by regrtest.py -R if this leak.
388 for _ in range(100):
389 memio = self.ioclass()
390 memio.foo = 1
391
392 def test_pickling(self):
393 buf = self.buftype("1234567890")
394 memio = self.ioclass(buf)
395 memio.foo = 42
396 memio.seek(2)
397
398 class ESC[4;38;5;81mPickleTestMemIO(ESC[4;38;5;149mselfESC[4;38;5;149m.ESC[4;38;5;149mioclass):
399 def __init__(me, initvalue, foo):
400 self.ioclass.__init__(me, initvalue)
401 me.foo = foo
402 # __getnewargs__ is undefined on purpose. This checks that PEP 307
403 # is used to provide pickling support.
404
405 # Pickle expects the class to be on the module level. Here we use a
406 # little hack to allow the PickleTestMemIO class to derive from
407 # self.ioclass without having to define all combinations explicitly on
408 # the module-level.
409 import __main__
410 PickleTestMemIO.__module__ = '__main__'
411 PickleTestMemIO.__qualname__ = PickleTestMemIO.__name__
412 __main__.PickleTestMemIO = PickleTestMemIO
413 submemio = PickleTestMemIO(buf, 80)
414 submemio.seek(2)
415
416 # We only support pickle protocol 2 and onward since we use extended
417 # __reduce__ API of PEP 307 to provide pickling support.
418 for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
419 for obj in (memio, submemio):
420 obj2 = pickle.loads(pickle.dumps(obj, protocol=proto))
421 self.assertEqual(obj.getvalue(), obj2.getvalue())
422 self.assertEqual(obj.__class__, obj2.__class__)
423 self.assertEqual(obj.foo, obj2.foo)
424 self.assertEqual(obj.tell(), obj2.tell())
425 obj2.close()
426 self.assertRaises(ValueError, pickle.dumps, obj2, proto)
427 del __main__.PickleTestMemIO
428
429
430 class ESC[4;38;5;81mPyBytesIOTest(ESC[4;38;5;149mMemoryTestMixin, ESC[4;38;5;149mMemorySeekTestMixin, ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
431 # Test _pyio.BytesIO; class also inherited for testing C implementation
432
433 UnsupportedOperation = pyio.UnsupportedOperation
434
435 @staticmethod
436 def buftype(s):
437 return s.encode("ascii")
438 ioclass = pyio.BytesIO
439 EOF = b""
440
441 def test_getbuffer(self):
442 memio = self.ioclass(b"1234567890")
443 buf = memio.getbuffer()
444 self.assertEqual(bytes(buf), b"1234567890")
445 memio.seek(5)
446 buf = memio.getbuffer()
447 self.assertEqual(bytes(buf), b"1234567890")
448 # Trying to change the size of the BytesIO while a buffer is exported
449 # raises a BufferError.
450 self.assertRaises(BufferError, memio.write, b'x' * 100)
451 self.assertRaises(BufferError, memio.truncate)
452 self.assertRaises(BufferError, memio.close)
453 self.assertFalse(memio.closed)
454 # Mutating the buffer updates the BytesIO
455 buf[3:6] = b"abc"
456 self.assertEqual(bytes(buf), b"123abc7890")
457 self.assertEqual(memio.getvalue(), b"123abc7890")
458 # After the buffer gets released, we can resize and close the BytesIO
459 # again
460 del buf
461 support.gc_collect()
462 memio.truncate()
463 memio.close()
464 self.assertRaises(ValueError, memio.getbuffer)
465
466 def test_read1(self):
467 buf = self.buftype("1234567890")
468 self.assertEqual(self.ioclass(buf).read1(), buf)
469 self.assertEqual(self.ioclass(buf).read1(-1), buf)
470
471 def test_readinto(self):
472 buf = self.buftype("1234567890")
473 memio = self.ioclass(buf)
474
475 b = bytearray(b"hello")
476 self.assertEqual(memio.readinto(b), 5)
477 self.assertEqual(b, b"12345")
478 self.assertEqual(memio.readinto(b), 5)
479 self.assertEqual(b, b"67890")
480 self.assertEqual(memio.readinto(b), 0)
481 self.assertEqual(b, b"67890")
482 b = bytearray(b"hello world")
483 memio.seek(0)
484 self.assertEqual(memio.readinto(b), 10)
485 self.assertEqual(b, b"1234567890d")
486 b = bytearray(b"")
487 memio.seek(0)
488 self.assertEqual(memio.readinto(b), 0)
489 self.assertEqual(b, b"")
490 self.assertRaises(TypeError, memio.readinto, '')
491 import array
492 a = array.array('b', b"hello world")
493 memio = self.ioclass(buf)
494 memio.readinto(a)
495 self.assertEqual(a.tobytes(), b"1234567890d")
496 memio.close()
497 self.assertRaises(ValueError, memio.readinto, b)
498 memio = self.ioclass(b"123")
499 b = bytearray()
500 memio.seek(42)
501 memio.readinto(b)
502 self.assertEqual(b, b"")
503
504 def test_relative_seek(self):
505 buf = self.buftype("1234567890")
506 memio = self.ioclass(buf)
507
508 self.assertEqual(memio.seek(-1, 1), 0)
509 self.assertEqual(memio.seek(3, 1), 3)
510 self.assertEqual(memio.seek(-4, 1), 0)
511 self.assertEqual(memio.seek(-1, 2), 9)
512 self.assertEqual(memio.seek(1, 1), 10)
513 self.assertEqual(memio.seek(1, 2), 11)
514 memio.seek(-3, 2)
515 self.assertEqual(memio.read(), buf[-3:])
516 memio.seek(0)
517 memio.seek(1, 1)
518 self.assertEqual(memio.read(), buf[1:])
519
520 def test_unicode(self):
521 memio = self.ioclass()
522
523 self.assertRaises(TypeError, self.ioclass, "1234567890")
524 self.assertRaises(TypeError, memio.write, "1234567890")
525 self.assertRaises(TypeError, memio.writelines, ["1234567890"])
526
527 def test_bytes_array(self):
528 buf = b"1234567890"
529 import array
530 a = array.array('b', list(buf))
531 memio = self.ioclass(a)
532 self.assertEqual(memio.getvalue(), buf)
533 self.assertEqual(memio.write(a), 10)
534 self.assertEqual(memio.getvalue(), buf)
535
536 def test_issue5449(self):
537 buf = self.buftype("1234567890")
538 self.ioclass(initial_bytes=buf)
539 self.assertRaises(TypeError, self.ioclass, buf, foo=None)
540
541
542 class ESC[4;38;5;81mTextIOTestMixin:
543
544 def test_newlines_property(self):
545 memio = self.ioclass(newline=None)
546 # The C StringIO decodes newlines in write() calls, but the Python
547 # implementation only does when reading. This function forces them to
548 # be decoded for testing.
549 def force_decode():
550 memio.seek(0)
551 memio.read()
552 self.assertEqual(memio.newlines, None)
553 memio.write("a\n")
554 force_decode()
555 self.assertEqual(memio.newlines, "\n")
556 memio.write("b\r\n")
557 force_decode()
558 self.assertEqual(memio.newlines, ("\n", "\r\n"))
559 memio.write("c\rd")
560 force_decode()
561 self.assertEqual(memio.newlines, ("\r", "\n", "\r\n"))
562
563 def test_relative_seek(self):
564 memio = self.ioclass()
565
566 self.assertRaises(OSError, memio.seek, -1, 1)
567 self.assertRaises(OSError, memio.seek, 3, 1)
568 self.assertRaises(OSError, memio.seek, -3, 1)
569 self.assertRaises(OSError, memio.seek, -1, 2)
570 self.assertRaises(OSError, memio.seek, 1, 1)
571 self.assertRaises(OSError, memio.seek, 1, 2)
572
573 def test_textio_properties(self):
574 memio = self.ioclass()
575
576 # These are just dummy values but we nevertheless check them for fear
577 # of unexpected breakage.
578 self.assertIsNone(memio.encoding)
579 self.assertIsNone(memio.errors)
580 self.assertFalse(memio.line_buffering)
581
582 def test_newline_default(self):
583 memio = self.ioclass("a\nb\r\nc\rd")
584 self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"])
585 self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
586
587 memio = self.ioclass()
588 self.assertEqual(memio.write("a\nb\r\nc\rd"), 8)
589 memio.seek(0)
590 self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"])
591 self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
592
593 def test_newline_none(self):
594 # newline=None
595 memio = self.ioclass("a\nb\r\nc\rd", newline=None)
596 self.assertEqual(list(memio), ["a\n", "b\n", "c\n", "d"])
597 memio.seek(0)
598 self.assertEqual(memio.read(1), "a")
599 self.assertEqual(memio.read(2), "\nb")
600 self.assertEqual(memio.read(2), "\nc")
601 self.assertEqual(memio.read(1), "\n")
602 self.assertEqual(memio.getvalue(), "a\nb\nc\nd")
603
604 memio = self.ioclass(newline=None)
605 self.assertEqual(2, memio.write("a\n"))
606 self.assertEqual(3, memio.write("b\r\n"))
607 self.assertEqual(3, memio.write("c\rd"))
608 memio.seek(0)
609 self.assertEqual(memio.read(), "a\nb\nc\nd")
610 self.assertEqual(memio.getvalue(), "a\nb\nc\nd")
611
612 memio = self.ioclass("a\r\nb", newline=None)
613 self.assertEqual(memio.read(3), "a\nb")
614
615 def test_newline_empty(self):
616 # newline=""
617 memio = self.ioclass("a\nb\r\nc\rd", newline="")
618 self.assertEqual(list(memio), ["a\n", "b\r\n", "c\r", "d"])
619 memio.seek(0)
620 self.assertEqual(memio.read(4), "a\nb\r")
621 self.assertEqual(memio.read(2), "\nc")
622 self.assertEqual(memio.read(1), "\r")
623 self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
624
625 memio = self.ioclass(newline="")
626 self.assertEqual(2, memio.write("a\n"))
627 self.assertEqual(2, memio.write("b\r"))
628 self.assertEqual(2, memio.write("\nc"))
629 self.assertEqual(2, memio.write("\rd"))
630 memio.seek(0)
631 self.assertEqual(list(memio), ["a\n", "b\r\n", "c\r", "d"])
632 self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
633
634 def test_newline_lf(self):
635 # newline="\n"
636 memio = self.ioclass("a\nb\r\nc\rd", newline="\n")
637 self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"])
638 self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
639
640 memio = self.ioclass(newline="\n")
641 self.assertEqual(memio.write("a\nb\r\nc\rd"), 8)
642 memio.seek(0)
643 self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"])
644 self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd")
645
646 def test_newline_cr(self):
647 # newline="\r"
648 memio = self.ioclass("a\nb\r\nc\rd", newline="\r")
649 self.assertEqual(memio.read(), "a\rb\r\rc\rd")
650 memio.seek(0)
651 self.assertEqual(list(memio), ["a\r", "b\r", "\r", "c\r", "d"])
652 self.assertEqual(memio.getvalue(), "a\rb\r\rc\rd")
653
654 memio = self.ioclass(newline="\r")
655 self.assertEqual(memio.write("a\nb\r\nc\rd"), 8)
656 memio.seek(0)
657 self.assertEqual(list(memio), ["a\r", "b\r", "\r", "c\r", "d"])
658 memio.seek(0)
659 self.assertEqual(memio.readlines(), ["a\r", "b\r", "\r", "c\r", "d"])
660 self.assertEqual(memio.getvalue(), "a\rb\r\rc\rd")
661
662 def test_newline_crlf(self):
663 # newline="\r\n"
664 memio = self.ioclass("a\nb\r\nc\rd", newline="\r\n")
665 self.assertEqual(memio.read(), "a\r\nb\r\r\nc\rd")
666 memio.seek(0)
667 self.assertEqual(list(memio), ["a\r\n", "b\r\r\n", "c\rd"])
668 memio.seek(0)
669 self.assertEqual(memio.readlines(), ["a\r\n", "b\r\r\n", "c\rd"])
670 self.assertEqual(memio.getvalue(), "a\r\nb\r\r\nc\rd")
671
672 memio = self.ioclass(newline="\r\n")
673 self.assertEqual(memio.write("a\nb\r\nc\rd"), 8)
674 memio.seek(0)
675 self.assertEqual(list(memio), ["a\r\n", "b\r\r\n", "c\rd"])
676 self.assertEqual(memio.getvalue(), "a\r\nb\r\r\nc\rd")
677
678 def test_issue5265(self):
679 # StringIO can duplicate newlines in universal newlines mode
680 memio = self.ioclass("a\r\nb\r\n", newline=None)
681 self.assertEqual(memio.read(5), "a\nb\n")
682 self.assertEqual(memio.getvalue(), "a\nb\n")
683
684 def test_newline_argument(self):
685 self.assertRaises(TypeError, self.ioclass, newline=b"\n")
686 self.assertRaises(ValueError, self.ioclass, newline="error")
687 # These should not raise an error
688 for newline in (None, "", "\n", "\r", "\r\n"):
689 self.ioclass(newline=newline)
690
691
692 class ESC[4;38;5;81mPyStringIOTest(ESC[4;38;5;149mMemoryTestMixin, ESC[4;38;5;149mMemorySeekTestMixin,
693 ESC[4;38;5;149mTextIOTestMixin, ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
694 buftype = str
695 ioclass = pyio.StringIO
696 UnsupportedOperation = pyio.UnsupportedOperation
697 EOF = ""
698
699 def test_lone_surrogates(self):
700 # Issue #20424
701 memio = self.ioclass('\ud800')
702 self.assertEqual(memio.read(), '\ud800')
703
704 memio = self.ioclass()
705 memio.write('\ud800')
706 self.assertEqual(memio.getvalue(), '\ud800')
707
708
709 class ESC[4;38;5;81mPyStringIOPickleTest(ESC[4;38;5;149mTextIOTestMixin, ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
710 """Test if pickle restores properly the internal state of StringIO.
711 """
712 buftype = str
713 UnsupportedOperation = pyio.UnsupportedOperation
714 EOF = ""
715
716 class ESC[4;38;5;81mioclass(ESC[4;38;5;149mpyioESC[4;38;5;149m.ESC[4;38;5;149mStringIO):
717 def __new__(cls, *args, **kwargs):
718 return pickle.loads(pickle.dumps(pyio.StringIO(*args, **kwargs)))
719 def __init__(self, *args, **kwargs):
720 pass
721
722
723 class ESC[4;38;5;81mCBytesIOTest(ESC[4;38;5;149mPyBytesIOTest):
724 ioclass = io.BytesIO
725 UnsupportedOperation = io.UnsupportedOperation
726
727 def test_getstate(self):
728 memio = self.ioclass()
729 state = memio.__getstate__()
730 self.assertEqual(len(state), 3)
731 bytearray(state[0]) # Check if state[0] supports the buffer interface.
732 self.assertIsInstance(state[1], int)
733 if state[2] is not None:
734 self.assertIsInstance(state[2], dict)
735 memio.close()
736 self.assertRaises(ValueError, memio.__getstate__)
737
738 def test_setstate(self):
739 # This checks whether __setstate__ does proper input validation.
740 memio = self.ioclass()
741 memio.__setstate__((b"no error", 0, None))
742 memio.__setstate__((bytearray(b"no error"), 0, None))
743 memio.__setstate__((b"no error", 0, {'spam': 3}))
744 self.assertRaises(ValueError, memio.__setstate__, (b"", -1, None))
745 self.assertRaises(TypeError, memio.__setstate__, ("unicode", 0, None))
746 self.assertRaises(TypeError, memio.__setstate__, (b"", 0.0, None))
747 self.assertRaises(TypeError, memio.__setstate__, (b"", 0, 0))
748 self.assertRaises(TypeError, memio.__setstate__, (b"len-test", 0))
749 self.assertRaises(TypeError, memio.__setstate__)
750 self.assertRaises(TypeError, memio.__setstate__, 0)
751 memio.close()
752 self.assertRaises(ValueError, memio.__setstate__, (b"closed", 0, None))
753
754 check_sizeof = support.check_sizeof
755
756 @support.cpython_only
757 def test_sizeof(self):
758 basesize = support.calcobjsize('P2n2Pn')
759 check = self.check_sizeof
760 self.assertEqual(object.__sizeof__(io.BytesIO()), basesize)
761 check(io.BytesIO(), basesize )
762 n = 1000 # use a variable to prevent constant folding
763 check(io.BytesIO(b'a' * n), basesize + sys.getsizeof(b'a' * n))
764
765 # Various tests of copy-on-write behaviour for BytesIO.
766
767 def _test_cow_mutation(self, mutation):
768 # Common code for all BytesIO copy-on-write mutation tests.
769 imm = b' ' * 1024
770 old_rc = sys.getrefcount(imm)
771 memio = self.ioclass(imm)
772 self.assertEqual(sys.getrefcount(imm), old_rc + 1)
773 mutation(memio)
774 self.assertEqual(sys.getrefcount(imm), old_rc)
775
776 @support.cpython_only
777 def test_cow_truncate(self):
778 # Ensure truncate causes a copy.
779 def mutation(memio):
780 memio.truncate(1)
781 self._test_cow_mutation(mutation)
782
783 @support.cpython_only
784 def test_cow_write(self):
785 # Ensure write that would not cause a resize still results in a copy.
786 def mutation(memio):
787 memio.seek(0)
788 memio.write(b'foo')
789 self._test_cow_mutation(mutation)
790
791 @support.cpython_only
792 def test_cow_setstate(self):
793 # __setstate__ should cause buffer to be released.
794 memio = self.ioclass(b'foooooo')
795 state = memio.__getstate__()
796 def mutation(memio):
797 memio.__setstate__(state)
798 self._test_cow_mutation(mutation)
799
800 @support.cpython_only
801 def test_cow_mutable(self):
802 # BytesIO should accept only Bytes for copy-on-write sharing, since
803 # arbitrary buffer-exporting objects like bytearray() aren't guaranteed
804 # to be immutable.
805 ba = bytearray(1024)
806 old_rc = sys.getrefcount(ba)
807 memio = self.ioclass(ba)
808 self.assertEqual(sys.getrefcount(ba), old_rc)
809
810 class ESC[4;38;5;81mCStringIOTest(ESC[4;38;5;149mPyStringIOTest):
811 ioclass = io.StringIO
812 UnsupportedOperation = io.UnsupportedOperation
813
814 # XXX: For the Python version of io.StringIO, this is highly
815 # dependent on the encoding used for the underlying buffer.
816 def test_widechar(self):
817 buf = self.buftype("\U0002030a\U00020347")
818 memio = self.ioclass(buf)
819
820 self.assertEqual(memio.getvalue(), buf)
821 self.assertEqual(memio.write(buf), len(buf))
822 self.assertEqual(memio.tell(), len(buf))
823 self.assertEqual(memio.getvalue(), buf)
824 self.assertEqual(memio.write(buf), len(buf))
825 self.assertEqual(memio.tell(), len(buf) * 2)
826 self.assertEqual(memio.getvalue(), buf + buf)
827
828 def test_getstate(self):
829 memio = self.ioclass()
830 state = memio.__getstate__()
831 self.assertEqual(len(state), 4)
832 self.assertIsInstance(state[0], str)
833 self.assertIsInstance(state[1], str)
834 self.assertIsInstance(state[2], int)
835 if state[3] is not None:
836 self.assertIsInstance(state[3], dict)
837 memio.close()
838 self.assertRaises(ValueError, memio.__getstate__)
839
840 def test_setstate(self):
841 # This checks whether __setstate__ does proper input validation.
842 memio = self.ioclass()
843 memio.__setstate__(("no error", "\n", 0, None))
844 memio.__setstate__(("no error", "", 0, {'spam': 3}))
845 self.assertRaises(ValueError, memio.__setstate__, ("", "f", 0, None))
846 self.assertRaises(ValueError, memio.__setstate__, ("", "", -1, None))
847 self.assertRaises(TypeError, memio.__setstate__, (b"", "", 0, None))
848 self.assertRaises(TypeError, memio.__setstate__, ("", b"", 0, None))
849 self.assertRaises(TypeError, memio.__setstate__, ("", "", 0.0, None))
850 self.assertRaises(TypeError, memio.__setstate__, ("", "", 0, 0))
851 self.assertRaises(TypeError, memio.__setstate__, ("len-test", 0))
852 self.assertRaises(TypeError, memio.__setstate__)
853 self.assertRaises(TypeError, memio.__setstate__, 0)
854 memio.close()
855 self.assertRaises(ValueError, memio.__setstate__, ("closed", "", 0, None))
856
857
858 class ESC[4;38;5;81mCStringIOPickleTest(ESC[4;38;5;149mPyStringIOPickleTest):
859 UnsupportedOperation = io.UnsupportedOperation
860
861 class ESC[4;38;5;81mioclass(ESC[4;38;5;149mioESC[4;38;5;149m.ESC[4;38;5;149mStringIO):
862 def __new__(cls, *args, **kwargs):
863 return pickle.loads(pickle.dumps(io.StringIO(*args, **kwargs)))
864 def __init__(self, *args, **kwargs):
865 pass
866
867
868 if __name__ == '__main__':
869 unittest.main()