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