1"""Unit tests for memory-based file-like objects. 2StringIO -- for unicode strings 3BytesIO -- for bytes 4""" 5 6import unittest 7from test import support 8 9import io 10import _pyio as pyio 11import pickle 12import sys 13 14class IntLike: 15 def __init__(self, num): 16 self._num = num 17 def __index__(self): 18 return self._num 19 __int__ = __index__ 20 21class MemorySeekTestMixin: 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 66class MemoryTestMixin: 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 MemIO(self.ioclass): 373 pass 374 m = MemIO(buf) 375 return m.getvalue() 376 def test2(): 377 class MemIO(self.ioclass): 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 PickleTestMemIO(self.ioclass): 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 430class PyBytesIOTest(MemoryTestMixin, MemorySeekTestMixin, unittest.TestCase): 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 542class TextIOTestMixin: 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 692class PyStringIOTest(MemoryTestMixin, MemorySeekTestMixin, 693 TextIOTestMixin, unittest.TestCase): 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 709class PyStringIOPickleTest(TextIOTestMixin, unittest.TestCase): 710 """Test if pickle restores properly the internal state of StringIO. 711 """ 712 buftype = str 713 UnsupportedOperation = pyio.UnsupportedOperation 714 EOF = "" 715 716 class ioclass(pyio.StringIO): 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 723class CBytesIOTest(PyBytesIOTest): 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 810class CStringIOTest(PyStringIOTest): 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 858class CStringIOPickleTest(PyStringIOPickleTest): 859 UnsupportedOperation = io.UnsupportedOperation 860 861 class ioclass(io.StringIO): 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 868if __name__ == '__main__': 869 unittest.main() 870