17db96d56Sopenharmony_ci"""Unit tests for the io module.""" 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ci# Tests of io are scattered over the test suite: 47db96d56Sopenharmony_ci# * test_bufio - tests file buffering 57db96d56Sopenharmony_ci# * test_memoryio - tests BytesIO and StringIO 67db96d56Sopenharmony_ci# * test_fileio - tests FileIO 77db96d56Sopenharmony_ci# * test_file - tests the file interface 87db96d56Sopenharmony_ci# * test_io - tests everything else in the io module 97db96d56Sopenharmony_ci# * test_univnewlines - tests universal newline support 107db96d56Sopenharmony_ci# * test_largefile - tests operations on a file greater than 2**32 bytes 117db96d56Sopenharmony_ci# (only enabled with -ulargefile) 127db96d56Sopenharmony_ci 137db96d56Sopenharmony_ci################################################################################ 147db96d56Sopenharmony_ci# ATTENTION TEST WRITERS!!! 157db96d56Sopenharmony_ci################################################################################ 167db96d56Sopenharmony_ci# When writing tests for io, it's important to test both the C and Python 177db96d56Sopenharmony_ci# implementations. This is usually done by writing a base test that refers to 187db96d56Sopenharmony_ci# the type it is testing as an attribute. Then it provides custom subclasses to 197db96d56Sopenharmony_ci# test both implementations. This file has lots of examples. 207db96d56Sopenharmony_ci################################################################################ 217db96d56Sopenharmony_ci 227db96d56Sopenharmony_ciimport abc 237db96d56Sopenharmony_ciimport array 247db96d56Sopenharmony_ciimport errno 257db96d56Sopenharmony_ciimport locale 267db96d56Sopenharmony_ciimport os 277db96d56Sopenharmony_ciimport pickle 287db96d56Sopenharmony_ciimport random 297db96d56Sopenharmony_ciimport signal 307db96d56Sopenharmony_ciimport sys 317db96d56Sopenharmony_ciimport textwrap 327db96d56Sopenharmony_ciimport threading 337db96d56Sopenharmony_ciimport time 347db96d56Sopenharmony_ciimport unittest 357db96d56Sopenharmony_ciimport warnings 367db96d56Sopenharmony_ciimport weakref 377db96d56Sopenharmony_cifrom collections import deque, UserList 387db96d56Sopenharmony_cifrom itertools import cycle, count 397db96d56Sopenharmony_cifrom test import support 407db96d56Sopenharmony_cifrom test.support.script_helper import ( 417db96d56Sopenharmony_ci assert_python_ok, assert_python_failure, run_python_until_end) 427db96d56Sopenharmony_cifrom test.support import import_helper 437db96d56Sopenharmony_cifrom test.support import os_helper 447db96d56Sopenharmony_cifrom test.support import threading_helper 457db96d56Sopenharmony_cifrom test.support import warnings_helper 467db96d56Sopenharmony_cifrom test.support import skip_if_sanitizer 477db96d56Sopenharmony_cifrom test.support.os_helper import FakePath 487db96d56Sopenharmony_ci 497db96d56Sopenharmony_ciimport codecs 507db96d56Sopenharmony_ciimport io # C implementation of io 517db96d56Sopenharmony_ciimport _pyio as pyio # Python implementation of io 527db96d56Sopenharmony_ci 537db96d56Sopenharmony_citry: 547db96d56Sopenharmony_ci import ctypes 557db96d56Sopenharmony_ciexcept ImportError: 567db96d56Sopenharmony_ci def byteslike(*pos, **kw): 577db96d56Sopenharmony_ci return array.array("b", bytes(*pos, **kw)) 587db96d56Sopenharmony_cielse: 597db96d56Sopenharmony_ci def byteslike(*pos, **kw): 607db96d56Sopenharmony_ci """Create a bytes-like object having no string or sequence methods""" 617db96d56Sopenharmony_ci data = bytes(*pos, **kw) 627db96d56Sopenharmony_ci obj = EmptyStruct() 637db96d56Sopenharmony_ci ctypes.resize(obj, len(data)) 647db96d56Sopenharmony_ci memoryview(obj).cast("B")[:] = data 657db96d56Sopenharmony_ci return obj 667db96d56Sopenharmony_ci class EmptyStruct(ctypes.Structure): 677db96d56Sopenharmony_ci pass 687db96d56Sopenharmony_ci 697db96d56Sopenharmony_ci# Does io.IOBase finalizer log the exception if the close() method fails? 707db96d56Sopenharmony_ci# The exception is ignored silently by default in release build. 717db96d56Sopenharmony_ciIOBASE_EMITS_UNRAISABLE = (hasattr(sys, "gettotalrefcount") or sys.flags.dev_mode) 727db96d56Sopenharmony_ci 737db96d56Sopenharmony_ci 747db96d56Sopenharmony_cidef _default_chunk_size(): 757db96d56Sopenharmony_ci """Get the default TextIOWrapper chunk size""" 767db96d56Sopenharmony_ci with open(__file__, "r", encoding="latin-1") as f: 777db96d56Sopenharmony_ci return f._CHUNK_SIZE 787db96d56Sopenharmony_ci 797db96d56Sopenharmony_cirequires_alarm = unittest.skipUnless( 807db96d56Sopenharmony_ci hasattr(signal, "alarm"), "test requires signal.alarm()" 817db96d56Sopenharmony_ci) 827db96d56Sopenharmony_ci 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ciclass MockRawIOWithoutRead: 857db96d56Sopenharmony_ci """A RawIO implementation without read(), so as to exercise the default 867db96d56Sopenharmony_ci RawIO.read() which calls readinto().""" 877db96d56Sopenharmony_ci 887db96d56Sopenharmony_ci def __init__(self, read_stack=()): 897db96d56Sopenharmony_ci self._read_stack = list(read_stack) 907db96d56Sopenharmony_ci self._write_stack = [] 917db96d56Sopenharmony_ci self._reads = 0 927db96d56Sopenharmony_ci self._extraneous_reads = 0 937db96d56Sopenharmony_ci 947db96d56Sopenharmony_ci def write(self, b): 957db96d56Sopenharmony_ci self._write_stack.append(bytes(b)) 967db96d56Sopenharmony_ci return len(b) 977db96d56Sopenharmony_ci 987db96d56Sopenharmony_ci def writable(self): 997db96d56Sopenharmony_ci return True 1007db96d56Sopenharmony_ci 1017db96d56Sopenharmony_ci def fileno(self): 1027db96d56Sopenharmony_ci return 42 1037db96d56Sopenharmony_ci 1047db96d56Sopenharmony_ci def readable(self): 1057db96d56Sopenharmony_ci return True 1067db96d56Sopenharmony_ci 1077db96d56Sopenharmony_ci def seekable(self): 1087db96d56Sopenharmony_ci return True 1097db96d56Sopenharmony_ci 1107db96d56Sopenharmony_ci def seek(self, pos, whence): 1117db96d56Sopenharmony_ci return 0 # wrong but we gotta return something 1127db96d56Sopenharmony_ci 1137db96d56Sopenharmony_ci def tell(self): 1147db96d56Sopenharmony_ci return 0 # same comment as above 1157db96d56Sopenharmony_ci 1167db96d56Sopenharmony_ci def readinto(self, buf): 1177db96d56Sopenharmony_ci self._reads += 1 1187db96d56Sopenharmony_ci max_len = len(buf) 1197db96d56Sopenharmony_ci try: 1207db96d56Sopenharmony_ci data = self._read_stack[0] 1217db96d56Sopenharmony_ci except IndexError: 1227db96d56Sopenharmony_ci self._extraneous_reads += 1 1237db96d56Sopenharmony_ci return 0 1247db96d56Sopenharmony_ci if data is None: 1257db96d56Sopenharmony_ci del self._read_stack[0] 1267db96d56Sopenharmony_ci return None 1277db96d56Sopenharmony_ci n = len(data) 1287db96d56Sopenharmony_ci if len(data) <= max_len: 1297db96d56Sopenharmony_ci del self._read_stack[0] 1307db96d56Sopenharmony_ci buf[:n] = data 1317db96d56Sopenharmony_ci return n 1327db96d56Sopenharmony_ci else: 1337db96d56Sopenharmony_ci buf[:] = data[:max_len] 1347db96d56Sopenharmony_ci self._read_stack[0] = data[max_len:] 1357db96d56Sopenharmony_ci return max_len 1367db96d56Sopenharmony_ci 1377db96d56Sopenharmony_ci def truncate(self, pos=None): 1387db96d56Sopenharmony_ci return pos 1397db96d56Sopenharmony_ci 1407db96d56Sopenharmony_ciclass CMockRawIOWithoutRead(MockRawIOWithoutRead, io.RawIOBase): 1417db96d56Sopenharmony_ci pass 1427db96d56Sopenharmony_ci 1437db96d56Sopenharmony_ciclass PyMockRawIOWithoutRead(MockRawIOWithoutRead, pyio.RawIOBase): 1447db96d56Sopenharmony_ci pass 1457db96d56Sopenharmony_ci 1467db96d56Sopenharmony_ci 1477db96d56Sopenharmony_ciclass MockRawIO(MockRawIOWithoutRead): 1487db96d56Sopenharmony_ci 1497db96d56Sopenharmony_ci def read(self, n=None): 1507db96d56Sopenharmony_ci self._reads += 1 1517db96d56Sopenharmony_ci try: 1527db96d56Sopenharmony_ci return self._read_stack.pop(0) 1537db96d56Sopenharmony_ci except: 1547db96d56Sopenharmony_ci self._extraneous_reads += 1 1557db96d56Sopenharmony_ci return b"" 1567db96d56Sopenharmony_ci 1577db96d56Sopenharmony_ciclass CMockRawIO(MockRawIO, io.RawIOBase): 1587db96d56Sopenharmony_ci pass 1597db96d56Sopenharmony_ci 1607db96d56Sopenharmony_ciclass PyMockRawIO(MockRawIO, pyio.RawIOBase): 1617db96d56Sopenharmony_ci pass 1627db96d56Sopenharmony_ci 1637db96d56Sopenharmony_ci 1647db96d56Sopenharmony_ciclass MisbehavedRawIO(MockRawIO): 1657db96d56Sopenharmony_ci def write(self, b): 1667db96d56Sopenharmony_ci return super().write(b) * 2 1677db96d56Sopenharmony_ci 1687db96d56Sopenharmony_ci def read(self, n=None): 1697db96d56Sopenharmony_ci return super().read(n) * 2 1707db96d56Sopenharmony_ci 1717db96d56Sopenharmony_ci def seek(self, pos, whence): 1727db96d56Sopenharmony_ci return -123 1737db96d56Sopenharmony_ci 1747db96d56Sopenharmony_ci def tell(self): 1757db96d56Sopenharmony_ci return -456 1767db96d56Sopenharmony_ci 1777db96d56Sopenharmony_ci def readinto(self, buf): 1787db96d56Sopenharmony_ci super().readinto(buf) 1797db96d56Sopenharmony_ci return len(buf) * 5 1807db96d56Sopenharmony_ci 1817db96d56Sopenharmony_ciclass CMisbehavedRawIO(MisbehavedRawIO, io.RawIOBase): 1827db96d56Sopenharmony_ci pass 1837db96d56Sopenharmony_ci 1847db96d56Sopenharmony_ciclass PyMisbehavedRawIO(MisbehavedRawIO, pyio.RawIOBase): 1857db96d56Sopenharmony_ci pass 1867db96d56Sopenharmony_ci 1877db96d56Sopenharmony_ci 1887db96d56Sopenharmony_ciclass SlowFlushRawIO(MockRawIO): 1897db96d56Sopenharmony_ci def __init__(self): 1907db96d56Sopenharmony_ci super().__init__() 1917db96d56Sopenharmony_ci self.in_flush = threading.Event() 1927db96d56Sopenharmony_ci 1937db96d56Sopenharmony_ci def flush(self): 1947db96d56Sopenharmony_ci self.in_flush.set() 1957db96d56Sopenharmony_ci time.sleep(0.25) 1967db96d56Sopenharmony_ci 1977db96d56Sopenharmony_ciclass CSlowFlushRawIO(SlowFlushRawIO, io.RawIOBase): 1987db96d56Sopenharmony_ci pass 1997db96d56Sopenharmony_ci 2007db96d56Sopenharmony_ciclass PySlowFlushRawIO(SlowFlushRawIO, pyio.RawIOBase): 2017db96d56Sopenharmony_ci pass 2027db96d56Sopenharmony_ci 2037db96d56Sopenharmony_ci 2047db96d56Sopenharmony_ciclass CloseFailureIO(MockRawIO): 2057db96d56Sopenharmony_ci closed = 0 2067db96d56Sopenharmony_ci 2077db96d56Sopenharmony_ci def close(self): 2087db96d56Sopenharmony_ci if not self.closed: 2097db96d56Sopenharmony_ci self.closed = 1 2107db96d56Sopenharmony_ci raise OSError 2117db96d56Sopenharmony_ci 2127db96d56Sopenharmony_ciclass CCloseFailureIO(CloseFailureIO, io.RawIOBase): 2137db96d56Sopenharmony_ci pass 2147db96d56Sopenharmony_ci 2157db96d56Sopenharmony_ciclass PyCloseFailureIO(CloseFailureIO, pyio.RawIOBase): 2167db96d56Sopenharmony_ci pass 2177db96d56Sopenharmony_ci 2187db96d56Sopenharmony_ci 2197db96d56Sopenharmony_ciclass MockFileIO: 2207db96d56Sopenharmony_ci 2217db96d56Sopenharmony_ci def __init__(self, data): 2227db96d56Sopenharmony_ci self.read_history = [] 2237db96d56Sopenharmony_ci super().__init__(data) 2247db96d56Sopenharmony_ci 2257db96d56Sopenharmony_ci def read(self, n=None): 2267db96d56Sopenharmony_ci res = super().read(n) 2277db96d56Sopenharmony_ci self.read_history.append(None if res is None else len(res)) 2287db96d56Sopenharmony_ci return res 2297db96d56Sopenharmony_ci 2307db96d56Sopenharmony_ci def readinto(self, b): 2317db96d56Sopenharmony_ci res = super().readinto(b) 2327db96d56Sopenharmony_ci self.read_history.append(res) 2337db96d56Sopenharmony_ci return res 2347db96d56Sopenharmony_ci 2357db96d56Sopenharmony_ciclass CMockFileIO(MockFileIO, io.BytesIO): 2367db96d56Sopenharmony_ci pass 2377db96d56Sopenharmony_ci 2387db96d56Sopenharmony_ciclass PyMockFileIO(MockFileIO, pyio.BytesIO): 2397db96d56Sopenharmony_ci pass 2407db96d56Sopenharmony_ci 2417db96d56Sopenharmony_ci 2427db96d56Sopenharmony_ciclass MockUnseekableIO: 2437db96d56Sopenharmony_ci def seekable(self): 2447db96d56Sopenharmony_ci return False 2457db96d56Sopenharmony_ci 2467db96d56Sopenharmony_ci def seek(self, *args): 2477db96d56Sopenharmony_ci raise self.UnsupportedOperation("not seekable") 2487db96d56Sopenharmony_ci 2497db96d56Sopenharmony_ci def tell(self, *args): 2507db96d56Sopenharmony_ci raise self.UnsupportedOperation("not seekable") 2517db96d56Sopenharmony_ci 2527db96d56Sopenharmony_ci def truncate(self, *args): 2537db96d56Sopenharmony_ci raise self.UnsupportedOperation("not seekable") 2547db96d56Sopenharmony_ci 2557db96d56Sopenharmony_ciclass CMockUnseekableIO(MockUnseekableIO, io.BytesIO): 2567db96d56Sopenharmony_ci UnsupportedOperation = io.UnsupportedOperation 2577db96d56Sopenharmony_ci 2587db96d56Sopenharmony_ciclass PyMockUnseekableIO(MockUnseekableIO, pyio.BytesIO): 2597db96d56Sopenharmony_ci UnsupportedOperation = pyio.UnsupportedOperation 2607db96d56Sopenharmony_ci 2617db96d56Sopenharmony_ci 2627db96d56Sopenharmony_ciclass MockNonBlockWriterIO: 2637db96d56Sopenharmony_ci 2647db96d56Sopenharmony_ci def __init__(self): 2657db96d56Sopenharmony_ci self._write_stack = [] 2667db96d56Sopenharmony_ci self._blocker_char = None 2677db96d56Sopenharmony_ci 2687db96d56Sopenharmony_ci def pop_written(self): 2697db96d56Sopenharmony_ci s = b"".join(self._write_stack) 2707db96d56Sopenharmony_ci self._write_stack[:] = [] 2717db96d56Sopenharmony_ci return s 2727db96d56Sopenharmony_ci 2737db96d56Sopenharmony_ci def block_on(self, char): 2747db96d56Sopenharmony_ci """Block when a given char is encountered.""" 2757db96d56Sopenharmony_ci self._blocker_char = char 2767db96d56Sopenharmony_ci 2777db96d56Sopenharmony_ci def readable(self): 2787db96d56Sopenharmony_ci return True 2797db96d56Sopenharmony_ci 2807db96d56Sopenharmony_ci def seekable(self): 2817db96d56Sopenharmony_ci return True 2827db96d56Sopenharmony_ci 2837db96d56Sopenharmony_ci def seek(self, pos, whence=0): 2847db96d56Sopenharmony_ci # naive implementation, enough for tests 2857db96d56Sopenharmony_ci return 0 2867db96d56Sopenharmony_ci 2877db96d56Sopenharmony_ci def writable(self): 2887db96d56Sopenharmony_ci return True 2897db96d56Sopenharmony_ci 2907db96d56Sopenharmony_ci def write(self, b): 2917db96d56Sopenharmony_ci b = bytes(b) 2927db96d56Sopenharmony_ci n = -1 2937db96d56Sopenharmony_ci if self._blocker_char: 2947db96d56Sopenharmony_ci try: 2957db96d56Sopenharmony_ci n = b.index(self._blocker_char) 2967db96d56Sopenharmony_ci except ValueError: 2977db96d56Sopenharmony_ci pass 2987db96d56Sopenharmony_ci else: 2997db96d56Sopenharmony_ci if n > 0: 3007db96d56Sopenharmony_ci # write data up to the first blocker 3017db96d56Sopenharmony_ci self._write_stack.append(b[:n]) 3027db96d56Sopenharmony_ci return n 3037db96d56Sopenharmony_ci else: 3047db96d56Sopenharmony_ci # cancel blocker and indicate would block 3057db96d56Sopenharmony_ci self._blocker_char = None 3067db96d56Sopenharmony_ci return None 3077db96d56Sopenharmony_ci self._write_stack.append(b) 3087db96d56Sopenharmony_ci return len(b) 3097db96d56Sopenharmony_ci 3107db96d56Sopenharmony_ciclass CMockNonBlockWriterIO(MockNonBlockWriterIO, io.RawIOBase): 3117db96d56Sopenharmony_ci BlockingIOError = io.BlockingIOError 3127db96d56Sopenharmony_ci 3137db96d56Sopenharmony_ciclass PyMockNonBlockWriterIO(MockNonBlockWriterIO, pyio.RawIOBase): 3147db96d56Sopenharmony_ci BlockingIOError = pyio.BlockingIOError 3157db96d56Sopenharmony_ci 3167db96d56Sopenharmony_ci 3177db96d56Sopenharmony_ciclass IOTest(unittest.TestCase): 3187db96d56Sopenharmony_ci 3197db96d56Sopenharmony_ci def setUp(self): 3207db96d56Sopenharmony_ci os_helper.unlink(os_helper.TESTFN) 3217db96d56Sopenharmony_ci 3227db96d56Sopenharmony_ci def tearDown(self): 3237db96d56Sopenharmony_ci os_helper.unlink(os_helper.TESTFN) 3247db96d56Sopenharmony_ci 3257db96d56Sopenharmony_ci def write_ops(self, f): 3267db96d56Sopenharmony_ci self.assertEqual(f.write(b"blah."), 5) 3277db96d56Sopenharmony_ci f.truncate(0) 3287db96d56Sopenharmony_ci self.assertEqual(f.tell(), 5) 3297db96d56Sopenharmony_ci f.seek(0) 3307db96d56Sopenharmony_ci 3317db96d56Sopenharmony_ci self.assertEqual(f.write(b"blah."), 5) 3327db96d56Sopenharmony_ci self.assertEqual(f.seek(0), 0) 3337db96d56Sopenharmony_ci self.assertEqual(f.write(b"Hello."), 6) 3347db96d56Sopenharmony_ci self.assertEqual(f.tell(), 6) 3357db96d56Sopenharmony_ci self.assertEqual(f.seek(-1, 1), 5) 3367db96d56Sopenharmony_ci self.assertEqual(f.tell(), 5) 3377db96d56Sopenharmony_ci buffer = bytearray(b" world\n\n\n") 3387db96d56Sopenharmony_ci self.assertEqual(f.write(buffer), 9) 3397db96d56Sopenharmony_ci buffer[:] = b"*" * 9 # Overwrite our copy of the data 3407db96d56Sopenharmony_ci self.assertEqual(f.seek(0), 0) 3417db96d56Sopenharmony_ci self.assertEqual(f.write(b"h"), 1) 3427db96d56Sopenharmony_ci self.assertEqual(f.seek(-1, 2), 13) 3437db96d56Sopenharmony_ci self.assertEqual(f.tell(), 13) 3447db96d56Sopenharmony_ci 3457db96d56Sopenharmony_ci self.assertEqual(f.truncate(12), 12) 3467db96d56Sopenharmony_ci self.assertEqual(f.tell(), 13) 3477db96d56Sopenharmony_ci self.assertRaises(TypeError, f.seek, 0.0) 3487db96d56Sopenharmony_ci 3497db96d56Sopenharmony_ci def read_ops(self, f, buffered=False): 3507db96d56Sopenharmony_ci data = f.read(5) 3517db96d56Sopenharmony_ci self.assertEqual(data, b"hello") 3527db96d56Sopenharmony_ci data = byteslike(data) 3537db96d56Sopenharmony_ci self.assertEqual(f.readinto(data), 5) 3547db96d56Sopenharmony_ci self.assertEqual(bytes(data), b" worl") 3557db96d56Sopenharmony_ci data = bytearray(5) 3567db96d56Sopenharmony_ci self.assertEqual(f.readinto(data), 2) 3577db96d56Sopenharmony_ci self.assertEqual(len(data), 5) 3587db96d56Sopenharmony_ci self.assertEqual(data[:2], b"d\n") 3597db96d56Sopenharmony_ci self.assertEqual(f.seek(0), 0) 3607db96d56Sopenharmony_ci self.assertEqual(f.read(20), b"hello world\n") 3617db96d56Sopenharmony_ci self.assertEqual(f.read(1), b"") 3627db96d56Sopenharmony_ci self.assertEqual(f.readinto(byteslike(b"x")), 0) 3637db96d56Sopenharmony_ci self.assertEqual(f.seek(-6, 2), 6) 3647db96d56Sopenharmony_ci self.assertEqual(f.read(5), b"world") 3657db96d56Sopenharmony_ci self.assertEqual(f.read(0), b"") 3667db96d56Sopenharmony_ci self.assertEqual(f.readinto(byteslike()), 0) 3677db96d56Sopenharmony_ci self.assertEqual(f.seek(-6, 1), 5) 3687db96d56Sopenharmony_ci self.assertEqual(f.read(5), b" worl") 3697db96d56Sopenharmony_ci self.assertEqual(f.tell(), 10) 3707db96d56Sopenharmony_ci self.assertRaises(TypeError, f.seek, 0.0) 3717db96d56Sopenharmony_ci if buffered: 3727db96d56Sopenharmony_ci f.seek(0) 3737db96d56Sopenharmony_ci self.assertEqual(f.read(), b"hello world\n") 3747db96d56Sopenharmony_ci f.seek(6) 3757db96d56Sopenharmony_ci self.assertEqual(f.read(), b"world\n") 3767db96d56Sopenharmony_ci self.assertEqual(f.read(), b"") 3777db96d56Sopenharmony_ci f.seek(0) 3787db96d56Sopenharmony_ci data = byteslike(5) 3797db96d56Sopenharmony_ci self.assertEqual(f.readinto1(data), 5) 3807db96d56Sopenharmony_ci self.assertEqual(bytes(data), b"hello") 3817db96d56Sopenharmony_ci 3827db96d56Sopenharmony_ci LARGE = 2**31 3837db96d56Sopenharmony_ci 3847db96d56Sopenharmony_ci def large_file_ops(self, f): 3857db96d56Sopenharmony_ci assert f.readable() 3867db96d56Sopenharmony_ci assert f.writable() 3877db96d56Sopenharmony_ci try: 3887db96d56Sopenharmony_ci self.assertEqual(f.seek(self.LARGE), self.LARGE) 3897db96d56Sopenharmony_ci except (OverflowError, ValueError): 3907db96d56Sopenharmony_ci self.skipTest("no largefile support") 3917db96d56Sopenharmony_ci self.assertEqual(f.tell(), self.LARGE) 3927db96d56Sopenharmony_ci self.assertEqual(f.write(b"xxx"), 3) 3937db96d56Sopenharmony_ci self.assertEqual(f.tell(), self.LARGE + 3) 3947db96d56Sopenharmony_ci self.assertEqual(f.seek(-1, 1), self.LARGE + 2) 3957db96d56Sopenharmony_ci self.assertEqual(f.truncate(), self.LARGE + 2) 3967db96d56Sopenharmony_ci self.assertEqual(f.tell(), self.LARGE + 2) 3977db96d56Sopenharmony_ci self.assertEqual(f.seek(0, 2), self.LARGE + 2) 3987db96d56Sopenharmony_ci self.assertEqual(f.truncate(self.LARGE + 1), self.LARGE + 1) 3997db96d56Sopenharmony_ci self.assertEqual(f.tell(), self.LARGE + 2) 4007db96d56Sopenharmony_ci self.assertEqual(f.seek(0, 2), self.LARGE + 1) 4017db96d56Sopenharmony_ci self.assertEqual(f.seek(-1, 2), self.LARGE) 4027db96d56Sopenharmony_ci self.assertEqual(f.read(2), b"x") 4037db96d56Sopenharmony_ci 4047db96d56Sopenharmony_ci def test_invalid_operations(self): 4057db96d56Sopenharmony_ci # Try writing on a file opened in read mode and vice-versa. 4067db96d56Sopenharmony_ci exc = self.UnsupportedOperation 4077db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "w", encoding="utf-8") as fp: 4087db96d56Sopenharmony_ci self.assertRaises(exc, fp.read) 4097db96d56Sopenharmony_ci self.assertRaises(exc, fp.readline) 4107db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "wb") as fp: 4117db96d56Sopenharmony_ci self.assertRaises(exc, fp.read) 4127db96d56Sopenharmony_ci self.assertRaises(exc, fp.readline) 4137db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "wb", buffering=0) as fp: 4147db96d56Sopenharmony_ci self.assertRaises(exc, fp.read) 4157db96d56Sopenharmony_ci self.assertRaises(exc, fp.readline) 4167db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "rb", buffering=0) as fp: 4177db96d56Sopenharmony_ci self.assertRaises(exc, fp.write, b"blah") 4187db96d56Sopenharmony_ci self.assertRaises(exc, fp.writelines, [b"blah\n"]) 4197db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "rb") as fp: 4207db96d56Sopenharmony_ci self.assertRaises(exc, fp.write, b"blah") 4217db96d56Sopenharmony_ci self.assertRaises(exc, fp.writelines, [b"blah\n"]) 4227db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "r", encoding="utf-8") as fp: 4237db96d56Sopenharmony_ci self.assertRaises(exc, fp.write, "blah") 4247db96d56Sopenharmony_ci self.assertRaises(exc, fp.writelines, ["blah\n"]) 4257db96d56Sopenharmony_ci # Non-zero seeking from current or end pos 4267db96d56Sopenharmony_ci self.assertRaises(exc, fp.seek, 1, self.SEEK_CUR) 4277db96d56Sopenharmony_ci self.assertRaises(exc, fp.seek, -1, self.SEEK_END) 4287db96d56Sopenharmony_ci 4297db96d56Sopenharmony_ci @unittest.skipIf( 4307db96d56Sopenharmony_ci support.is_emscripten, "fstat() of a pipe fd is not supported" 4317db96d56Sopenharmony_ci ) 4327db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()") 4337db96d56Sopenharmony_ci def test_optional_abilities(self): 4347db96d56Sopenharmony_ci # Test for OSError when optional APIs are not supported 4357db96d56Sopenharmony_ci # The purpose of this test is to try fileno(), reading, writing and 4367db96d56Sopenharmony_ci # seeking operations with various objects that indicate they do not 4377db96d56Sopenharmony_ci # support these operations. 4387db96d56Sopenharmony_ci 4397db96d56Sopenharmony_ci def pipe_reader(): 4407db96d56Sopenharmony_ci [r, w] = os.pipe() 4417db96d56Sopenharmony_ci os.close(w) # So that read() is harmless 4427db96d56Sopenharmony_ci return self.FileIO(r, "r") 4437db96d56Sopenharmony_ci 4447db96d56Sopenharmony_ci def pipe_writer(): 4457db96d56Sopenharmony_ci [r, w] = os.pipe() 4467db96d56Sopenharmony_ci self.addCleanup(os.close, r) 4477db96d56Sopenharmony_ci # Guarantee that we can write into the pipe without blocking 4487db96d56Sopenharmony_ci thread = threading.Thread(target=os.read, args=(r, 100)) 4497db96d56Sopenharmony_ci thread.start() 4507db96d56Sopenharmony_ci self.addCleanup(thread.join) 4517db96d56Sopenharmony_ci return self.FileIO(w, "w") 4527db96d56Sopenharmony_ci 4537db96d56Sopenharmony_ci def buffered_reader(): 4547db96d56Sopenharmony_ci return self.BufferedReader(self.MockUnseekableIO()) 4557db96d56Sopenharmony_ci 4567db96d56Sopenharmony_ci def buffered_writer(): 4577db96d56Sopenharmony_ci return self.BufferedWriter(self.MockUnseekableIO()) 4587db96d56Sopenharmony_ci 4597db96d56Sopenharmony_ci def buffered_random(): 4607db96d56Sopenharmony_ci return self.BufferedRandom(self.BytesIO()) 4617db96d56Sopenharmony_ci 4627db96d56Sopenharmony_ci def buffered_rw_pair(): 4637db96d56Sopenharmony_ci return self.BufferedRWPair(self.MockUnseekableIO(), 4647db96d56Sopenharmony_ci self.MockUnseekableIO()) 4657db96d56Sopenharmony_ci 4667db96d56Sopenharmony_ci def text_reader(): 4677db96d56Sopenharmony_ci class UnseekableReader(self.MockUnseekableIO): 4687db96d56Sopenharmony_ci writable = self.BufferedIOBase.writable 4697db96d56Sopenharmony_ci write = self.BufferedIOBase.write 4707db96d56Sopenharmony_ci return self.TextIOWrapper(UnseekableReader(), "ascii") 4717db96d56Sopenharmony_ci 4727db96d56Sopenharmony_ci def text_writer(): 4737db96d56Sopenharmony_ci class UnseekableWriter(self.MockUnseekableIO): 4747db96d56Sopenharmony_ci readable = self.BufferedIOBase.readable 4757db96d56Sopenharmony_ci read = self.BufferedIOBase.read 4767db96d56Sopenharmony_ci return self.TextIOWrapper(UnseekableWriter(), "ascii") 4777db96d56Sopenharmony_ci 4787db96d56Sopenharmony_ci tests = ( 4797db96d56Sopenharmony_ci (pipe_reader, "fr"), (pipe_writer, "fw"), 4807db96d56Sopenharmony_ci (buffered_reader, "r"), (buffered_writer, "w"), 4817db96d56Sopenharmony_ci (buffered_random, "rws"), (buffered_rw_pair, "rw"), 4827db96d56Sopenharmony_ci (text_reader, "r"), (text_writer, "w"), 4837db96d56Sopenharmony_ci (self.BytesIO, "rws"), (self.StringIO, "rws"), 4847db96d56Sopenharmony_ci ) 4857db96d56Sopenharmony_ci for [test, abilities] in tests: 4867db96d56Sopenharmony_ci with self.subTest(test), test() as obj: 4877db96d56Sopenharmony_ci readable = "r" in abilities 4887db96d56Sopenharmony_ci self.assertEqual(obj.readable(), readable) 4897db96d56Sopenharmony_ci writable = "w" in abilities 4907db96d56Sopenharmony_ci self.assertEqual(obj.writable(), writable) 4917db96d56Sopenharmony_ci 4927db96d56Sopenharmony_ci if isinstance(obj, self.TextIOBase): 4937db96d56Sopenharmony_ci data = "3" 4947db96d56Sopenharmony_ci elif isinstance(obj, (self.BufferedIOBase, self.RawIOBase)): 4957db96d56Sopenharmony_ci data = b"3" 4967db96d56Sopenharmony_ci else: 4977db96d56Sopenharmony_ci self.fail("Unknown base class") 4987db96d56Sopenharmony_ci 4997db96d56Sopenharmony_ci if "f" in abilities: 5007db96d56Sopenharmony_ci obj.fileno() 5017db96d56Sopenharmony_ci else: 5027db96d56Sopenharmony_ci self.assertRaises(OSError, obj.fileno) 5037db96d56Sopenharmony_ci 5047db96d56Sopenharmony_ci if readable: 5057db96d56Sopenharmony_ci obj.read(1) 5067db96d56Sopenharmony_ci obj.read() 5077db96d56Sopenharmony_ci else: 5087db96d56Sopenharmony_ci self.assertRaises(OSError, obj.read, 1) 5097db96d56Sopenharmony_ci self.assertRaises(OSError, obj.read) 5107db96d56Sopenharmony_ci 5117db96d56Sopenharmony_ci if writable: 5127db96d56Sopenharmony_ci obj.write(data) 5137db96d56Sopenharmony_ci else: 5147db96d56Sopenharmony_ci self.assertRaises(OSError, obj.write, data) 5157db96d56Sopenharmony_ci 5167db96d56Sopenharmony_ci if sys.platform.startswith("win") and test in ( 5177db96d56Sopenharmony_ci pipe_reader, pipe_writer): 5187db96d56Sopenharmony_ci # Pipes seem to appear as seekable on Windows 5197db96d56Sopenharmony_ci continue 5207db96d56Sopenharmony_ci seekable = "s" in abilities 5217db96d56Sopenharmony_ci self.assertEqual(obj.seekable(), seekable) 5227db96d56Sopenharmony_ci 5237db96d56Sopenharmony_ci if seekable: 5247db96d56Sopenharmony_ci obj.tell() 5257db96d56Sopenharmony_ci obj.seek(0) 5267db96d56Sopenharmony_ci else: 5277db96d56Sopenharmony_ci self.assertRaises(OSError, obj.tell) 5287db96d56Sopenharmony_ci self.assertRaises(OSError, obj.seek, 0) 5297db96d56Sopenharmony_ci 5307db96d56Sopenharmony_ci if writable and seekable: 5317db96d56Sopenharmony_ci obj.truncate() 5327db96d56Sopenharmony_ci obj.truncate(0) 5337db96d56Sopenharmony_ci else: 5347db96d56Sopenharmony_ci self.assertRaises(OSError, obj.truncate) 5357db96d56Sopenharmony_ci self.assertRaises(OSError, obj.truncate, 0) 5367db96d56Sopenharmony_ci 5377db96d56Sopenharmony_ci def test_open_handles_NUL_chars(self): 5387db96d56Sopenharmony_ci fn_with_NUL = 'foo\0bar' 5397db96d56Sopenharmony_ci self.assertRaises(ValueError, self.open, fn_with_NUL, 'w', encoding="utf-8") 5407db96d56Sopenharmony_ci 5417db96d56Sopenharmony_ci bytes_fn = bytes(fn_with_NUL, 'ascii') 5427db96d56Sopenharmony_ci with warnings.catch_warnings(): 5437db96d56Sopenharmony_ci warnings.simplefilter("ignore", DeprecationWarning) 5447db96d56Sopenharmony_ci self.assertRaises(ValueError, self.open, bytes_fn, 'w', encoding="utf-8") 5457db96d56Sopenharmony_ci 5467db96d56Sopenharmony_ci def test_raw_file_io(self): 5477db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "wb", buffering=0) as f: 5487db96d56Sopenharmony_ci self.assertEqual(f.readable(), False) 5497db96d56Sopenharmony_ci self.assertEqual(f.writable(), True) 5507db96d56Sopenharmony_ci self.assertEqual(f.seekable(), True) 5517db96d56Sopenharmony_ci self.write_ops(f) 5527db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "rb", buffering=0) as f: 5537db96d56Sopenharmony_ci self.assertEqual(f.readable(), True) 5547db96d56Sopenharmony_ci self.assertEqual(f.writable(), False) 5557db96d56Sopenharmony_ci self.assertEqual(f.seekable(), True) 5567db96d56Sopenharmony_ci self.read_ops(f) 5577db96d56Sopenharmony_ci 5587db96d56Sopenharmony_ci def test_buffered_file_io(self): 5597db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "wb") as f: 5607db96d56Sopenharmony_ci self.assertEqual(f.readable(), False) 5617db96d56Sopenharmony_ci self.assertEqual(f.writable(), True) 5627db96d56Sopenharmony_ci self.assertEqual(f.seekable(), True) 5637db96d56Sopenharmony_ci self.write_ops(f) 5647db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "rb") as f: 5657db96d56Sopenharmony_ci self.assertEqual(f.readable(), True) 5667db96d56Sopenharmony_ci self.assertEqual(f.writable(), False) 5677db96d56Sopenharmony_ci self.assertEqual(f.seekable(), True) 5687db96d56Sopenharmony_ci self.read_ops(f, True) 5697db96d56Sopenharmony_ci 5707db96d56Sopenharmony_ci def test_readline(self): 5717db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "wb") as f: 5727db96d56Sopenharmony_ci f.write(b"abc\ndef\nxyzzy\nfoo\x00bar\nanother line") 5737db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "rb") as f: 5747db96d56Sopenharmony_ci self.assertEqual(f.readline(), b"abc\n") 5757db96d56Sopenharmony_ci self.assertEqual(f.readline(10), b"def\n") 5767db96d56Sopenharmony_ci self.assertEqual(f.readline(2), b"xy") 5777db96d56Sopenharmony_ci self.assertEqual(f.readline(4), b"zzy\n") 5787db96d56Sopenharmony_ci self.assertEqual(f.readline(), b"foo\x00bar\n") 5797db96d56Sopenharmony_ci self.assertEqual(f.readline(None), b"another line") 5807db96d56Sopenharmony_ci self.assertRaises(TypeError, f.readline, 5.3) 5817db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "r", encoding="utf-8") as f: 5827db96d56Sopenharmony_ci self.assertRaises(TypeError, f.readline, 5.3) 5837db96d56Sopenharmony_ci 5847db96d56Sopenharmony_ci def test_readline_nonsizeable(self): 5857db96d56Sopenharmony_ci # Issue #30061 5867db96d56Sopenharmony_ci # Crash when readline() returns an object without __len__ 5877db96d56Sopenharmony_ci class R(self.IOBase): 5887db96d56Sopenharmony_ci def readline(self): 5897db96d56Sopenharmony_ci return None 5907db96d56Sopenharmony_ci self.assertRaises((TypeError, StopIteration), next, R()) 5917db96d56Sopenharmony_ci 5927db96d56Sopenharmony_ci def test_next_nonsizeable(self): 5937db96d56Sopenharmony_ci # Issue #30061 5947db96d56Sopenharmony_ci # Crash when __next__() returns an object without __len__ 5957db96d56Sopenharmony_ci class R(self.IOBase): 5967db96d56Sopenharmony_ci def __next__(self): 5977db96d56Sopenharmony_ci return None 5987db96d56Sopenharmony_ci self.assertRaises(TypeError, R().readlines, 1) 5997db96d56Sopenharmony_ci 6007db96d56Sopenharmony_ci def test_raw_bytes_io(self): 6017db96d56Sopenharmony_ci f = self.BytesIO() 6027db96d56Sopenharmony_ci self.write_ops(f) 6037db96d56Sopenharmony_ci data = f.getvalue() 6047db96d56Sopenharmony_ci self.assertEqual(data, b"hello world\n") 6057db96d56Sopenharmony_ci f = self.BytesIO(data) 6067db96d56Sopenharmony_ci self.read_ops(f, True) 6077db96d56Sopenharmony_ci 6087db96d56Sopenharmony_ci def test_large_file_ops(self): 6097db96d56Sopenharmony_ci # On Windows and Mac OSX this test consumes large resources; It takes 6107db96d56Sopenharmony_ci # a long time to build the >2 GiB file and takes >2 GiB of disk space 6117db96d56Sopenharmony_ci # therefore the resource must be enabled to run this test. 6127db96d56Sopenharmony_ci if sys.platform[:3] == 'win' or sys.platform == 'darwin': 6137db96d56Sopenharmony_ci support.requires( 6147db96d56Sopenharmony_ci 'largefile', 6157db96d56Sopenharmony_ci 'test requires %s bytes and a long time to run' % self.LARGE) 6167db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "w+b", 0) as f: 6177db96d56Sopenharmony_ci self.large_file_ops(f) 6187db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "w+b") as f: 6197db96d56Sopenharmony_ci self.large_file_ops(f) 6207db96d56Sopenharmony_ci 6217db96d56Sopenharmony_ci def test_with_open(self): 6227db96d56Sopenharmony_ci for bufsize in (0, 100): 6237db96d56Sopenharmony_ci f = None 6247db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "wb", bufsize) as f: 6257db96d56Sopenharmony_ci f.write(b"xxx") 6267db96d56Sopenharmony_ci self.assertEqual(f.closed, True) 6277db96d56Sopenharmony_ci f = None 6287db96d56Sopenharmony_ci try: 6297db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "wb", bufsize) as f: 6307db96d56Sopenharmony_ci 1/0 6317db96d56Sopenharmony_ci except ZeroDivisionError: 6327db96d56Sopenharmony_ci self.assertEqual(f.closed, True) 6337db96d56Sopenharmony_ci else: 6347db96d56Sopenharmony_ci self.fail("1/0 didn't raise an exception") 6357db96d56Sopenharmony_ci 6367db96d56Sopenharmony_ci # issue 5008 6377db96d56Sopenharmony_ci def test_append_mode_tell(self): 6387db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "wb") as f: 6397db96d56Sopenharmony_ci f.write(b"xxx") 6407db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "ab", buffering=0) as f: 6417db96d56Sopenharmony_ci self.assertEqual(f.tell(), 3) 6427db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "ab") as f: 6437db96d56Sopenharmony_ci self.assertEqual(f.tell(), 3) 6447db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "a", encoding="utf-8") as f: 6457db96d56Sopenharmony_ci self.assertGreater(f.tell(), 0) 6467db96d56Sopenharmony_ci 6477db96d56Sopenharmony_ci def test_destructor(self): 6487db96d56Sopenharmony_ci record = [] 6497db96d56Sopenharmony_ci class MyFileIO(self.FileIO): 6507db96d56Sopenharmony_ci def __del__(self): 6517db96d56Sopenharmony_ci record.append(1) 6527db96d56Sopenharmony_ci try: 6537db96d56Sopenharmony_ci f = super().__del__ 6547db96d56Sopenharmony_ci except AttributeError: 6557db96d56Sopenharmony_ci pass 6567db96d56Sopenharmony_ci else: 6577db96d56Sopenharmony_ci f() 6587db96d56Sopenharmony_ci def close(self): 6597db96d56Sopenharmony_ci record.append(2) 6607db96d56Sopenharmony_ci super().close() 6617db96d56Sopenharmony_ci def flush(self): 6627db96d56Sopenharmony_ci record.append(3) 6637db96d56Sopenharmony_ci super().flush() 6647db96d56Sopenharmony_ci with warnings_helper.check_warnings(('', ResourceWarning)): 6657db96d56Sopenharmony_ci f = MyFileIO(os_helper.TESTFN, "wb") 6667db96d56Sopenharmony_ci f.write(b"xxx") 6677db96d56Sopenharmony_ci del f 6687db96d56Sopenharmony_ci support.gc_collect() 6697db96d56Sopenharmony_ci self.assertEqual(record, [1, 2, 3]) 6707db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "rb") as f: 6717db96d56Sopenharmony_ci self.assertEqual(f.read(), b"xxx") 6727db96d56Sopenharmony_ci 6737db96d56Sopenharmony_ci def _check_base_destructor(self, base): 6747db96d56Sopenharmony_ci record = [] 6757db96d56Sopenharmony_ci class MyIO(base): 6767db96d56Sopenharmony_ci def __init__(self): 6777db96d56Sopenharmony_ci # This exercises the availability of attributes on object 6787db96d56Sopenharmony_ci # destruction. 6797db96d56Sopenharmony_ci # (in the C version, close() is called by the tp_dealloc 6807db96d56Sopenharmony_ci # function, not by __del__) 6817db96d56Sopenharmony_ci self.on_del = 1 6827db96d56Sopenharmony_ci self.on_close = 2 6837db96d56Sopenharmony_ci self.on_flush = 3 6847db96d56Sopenharmony_ci def __del__(self): 6857db96d56Sopenharmony_ci record.append(self.on_del) 6867db96d56Sopenharmony_ci try: 6877db96d56Sopenharmony_ci f = super().__del__ 6887db96d56Sopenharmony_ci except AttributeError: 6897db96d56Sopenharmony_ci pass 6907db96d56Sopenharmony_ci else: 6917db96d56Sopenharmony_ci f() 6927db96d56Sopenharmony_ci def close(self): 6937db96d56Sopenharmony_ci record.append(self.on_close) 6947db96d56Sopenharmony_ci super().close() 6957db96d56Sopenharmony_ci def flush(self): 6967db96d56Sopenharmony_ci record.append(self.on_flush) 6977db96d56Sopenharmony_ci super().flush() 6987db96d56Sopenharmony_ci f = MyIO() 6997db96d56Sopenharmony_ci del f 7007db96d56Sopenharmony_ci support.gc_collect() 7017db96d56Sopenharmony_ci self.assertEqual(record, [1, 2, 3]) 7027db96d56Sopenharmony_ci 7037db96d56Sopenharmony_ci def test_IOBase_destructor(self): 7047db96d56Sopenharmony_ci self._check_base_destructor(self.IOBase) 7057db96d56Sopenharmony_ci 7067db96d56Sopenharmony_ci def test_RawIOBase_destructor(self): 7077db96d56Sopenharmony_ci self._check_base_destructor(self.RawIOBase) 7087db96d56Sopenharmony_ci 7097db96d56Sopenharmony_ci def test_BufferedIOBase_destructor(self): 7107db96d56Sopenharmony_ci self._check_base_destructor(self.BufferedIOBase) 7117db96d56Sopenharmony_ci 7127db96d56Sopenharmony_ci def test_TextIOBase_destructor(self): 7137db96d56Sopenharmony_ci self._check_base_destructor(self.TextIOBase) 7147db96d56Sopenharmony_ci 7157db96d56Sopenharmony_ci def test_close_flushes(self): 7167db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "wb") as f: 7177db96d56Sopenharmony_ci f.write(b"xxx") 7187db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "rb") as f: 7197db96d56Sopenharmony_ci self.assertEqual(f.read(), b"xxx") 7207db96d56Sopenharmony_ci 7217db96d56Sopenharmony_ci def test_array_writes(self): 7227db96d56Sopenharmony_ci a = array.array('i', range(10)) 7237db96d56Sopenharmony_ci n = len(a.tobytes()) 7247db96d56Sopenharmony_ci def check(f): 7257db96d56Sopenharmony_ci with f: 7267db96d56Sopenharmony_ci self.assertEqual(f.write(a), n) 7277db96d56Sopenharmony_ci f.writelines((a,)) 7287db96d56Sopenharmony_ci check(self.BytesIO()) 7297db96d56Sopenharmony_ci check(self.FileIO(os_helper.TESTFN, "w")) 7307db96d56Sopenharmony_ci check(self.BufferedWriter(self.MockRawIO())) 7317db96d56Sopenharmony_ci check(self.BufferedRandom(self.MockRawIO())) 7327db96d56Sopenharmony_ci check(self.BufferedRWPair(self.MockRawIO(), self.MockRawIO())) 7337db96d56Sopenharmony_ci 7347db96d56Sopenharmony_ci def test_closefd(self): 7357db96d56Sopenharmony_ci self.assertRaises(ValueError, self.open, os_helper.TESTFN, 'w', 7367db96d56Sopenharmony_ci encoding="utf-8", closefd=False) 7377db96d56Sopenharmony_ci 7387db96d56Sopenharmony_ci def test_read_closed(self): 7397db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "w", encoding="utf-8") as f: 7407db96d56Sopenharmony_ci f.write("egg\n") 7417db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "r", encoding="utf-8") as f: 7427db96d56Sopenharmony_ci file = self.open(f.fileno(), "r", encoding="utf-8", closefd=False) 7437db96d56Sopenharmony_ci self.assertEqual(file.read(), "egg\n") 7447db96d56Sopenharmony_ci file.seek(0) 7457db96d56Sopenharmony_ci file.close() 7467db96d56Sopenharmony_ci self.assertRaises(ValueError, file.read) 7477db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "rb") as f: 7487db96d56Sopenharmony_ci file = self.open(f.fileno(), "rb", closefd=False) 7497db96d56Sopenharmony_ci self.assertEqual(file.read()[:3], b"egg") 7507db96d56Sopenharmony_ci file.close() 7517db96d56Sopenharmony_ci self.assertRaises(ValueError, file.readinto, bytearray(1)) 7527db96d56Sopenharmony_ci 7537db96d56Sopenharmony_ci def test_no_closefd_with_filename(self): 7547db96d56Sopenharmony_ci # can't use closefd in combination with a file name 7557db96d56Sopenharmony_ci self.assertRaises(ValueError, self.open, os_helper.TESTFN, "r", 7567db96d56Sopenharmony_ci encoding="utf-8", closefd=False) 7577db96d56Sopenharmony_ci 7587db96d56Sopenharmony_ci def test_closefd_attr(self): 7597db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "wb") as f: 7607db96d56Sopenharmony_ci f.write(b"egg\n") 7617db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "r", encoding="utf-8") as f: 7627db96d56Sopenharmony_ci self.assertEqual(f.buffer.raw.closefd, True) 7637db96d56Sopenharmony_ci file = self.open(f.fileno(), "r", encoding="utf-8", closefd=False) 7647db96d56Sopenharmony_ci self.assertEqual(file.buffer.raw.closefd, False) 7657db96d56Sopenharmony_ci 7667db96d56Sopenharmony_ci def test_garbage_collection(self): 7677db96d56Sopenharmony_ci # FileIO objects are collected, and collecting them flushes 7687db96d56Sopenharmony_ci # all data to disk. 7697db96d56Sopenharmony_ci with warnings_helper.check_warnings(('', ResourceWarning)): 7707db96d56Sopenharmony_ci f = self.FileIO(os_helper.TESTFN, "wb") 7717db96d56Sopenharmony_ci f.write(b"abcxxx") 7727db96d56Sopenharmony_ci f.f = f 7737db96d56Sopenharmony_ci wr = weakref.ref(f) 7747db96d56Sopenharmony_ci del f 7757db96d56Sopenharmony_ci support.gc_collect() 7767db96d56Sopenharmony_ci self.assertIsNone(wr(), wr) 7777db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "rb") as f: 7787db96d56Sopenharmony_ci self.assertEqual(f.read(), b"abcxxx") 7797db96d56Sopenharmony_ci 7807db96d56Sopenharmony_ci def test_unbounded_file(self): 7817db96d56Sopenharmony_ci # Issue #1174606: reading from an unbounded stream such as /dev/zero. 7827db96d56Sopenharmony_ci zero = "/dev/zero" 7837db96d56Sopenharmony_ci if not os.path.exists(zero): 7847db96d56Sopenharmony_ci self.skipTest("{0} does not exist".format(zero)) 7857db96d56Sopenharmony_ci if sys.maxsize > 0x7FFFFFFF: 7867db96d56Sopenharmony_ci self.skipTest("test can only run in a 32-bit address space") 7877db96d56Sopenharmony_ci if support.real_max_memuse < support._2G: 7887db96d56Sopenharmony_ci self.skipTest("test requires at least 2 GiB of memory") 7897db96d56Sopenharmony_ci with self.open(zero, "rb", buffering=0) as f: 7907db96d56Sopenharmony_ci self.assertRaises(OverflowError, f.read) 7917db96d56Sopenharmony_ci with self.open(zero, "rb") as f: 7927db96d56Sopenharmony_ci self.assertRaises(OverflowError, f.read) 7937db96d56Sopenharmony_ci with self.open(zero, "r") as f: 7947db96d56Sopenharmony_ci self.assertRaises(OverflowError, f.read) 7957db96d56Sopenharmony_ci 7967db96d56Sopenharmony_ci def check_flush_error_on_close(self, *args, **kwargs): 7977db96d56Sopenharmony_ci # Test that the file is closed despite failed flush 7987db96d56Sopenharmony_ci # and that flush() is called before file closed. 7997db96d56Sopenharmony_ci f = self.open(*args, **kwargs) 8007db96d56Sopenharmony_ci closed = [] 8017db96d56Sopenharmony_ci def bad_flush(): 8027db96d56Sopenharmony_ci closed[:] = [f.closed] 8037db96d56Sopenharmony_ci raise OSError() 8047db96d56Sopenharmony_ci f.flush = bad_flush 8057db96d56Sopenharmony_ci self.assertRaises(OSError, f.close) # exception not swallowed 8067db96d56Sopenharmony_ci self.assertTrue(f.closed) 8077db96d56Sopenharmony_ci self.assertTrue(closed) # flush() called 8087db96d56Sopenharmony_ci self.assertFalse(closed[0]) # flush() called before file closed 8097db96d56Sopenharmony_ci f.flush = lambda: None # break reference loop 8107db96d56Sopenharmony_ci 8117db96d56Sopenharmony_ci def test_flush_error_on_close(self): 8127db96d56Sopenharmony_ci # raw file 8137db96d56Sopenharmony_ci # Issue #5700: io.FileIO calls flush() after file closed 8147db96d56Sopenharmony_ci self.check_flush_error_on_close(os_helper.TESTFN, 'wb', buffering=0) 8157db96d56Sopenharmony_ci fd = os.open(os_helper.TESTFN, os.O_WRONLY|os.O_CREAT) 8167db96d56Sopenharmony_ci self.check_flush_error_on_close(fd, 'wb', buffering=0) 8177db96d56Sopenharmony_ci fd = os.open(os_helper.TESTFN, os.O_WRONLY|os.O_CREAT) 8187db96d56Sopenharmony_ci self.check_flush_error_on_close(fd, 'wb', buffering=0, closefd=False) 8197db96d56Sopenharmony_ci os.close(fd) 8207db96d56Sopenharmony_ci # buffered io 8217db96d56Sopenharmony_ci self.check_flush_error_on_close(os_helper.TESTFN, 'wb') 8227db96d56Sopenharmony_ci fd = os.open(os_helper.TESTFN, os.O_WRONLY|os.O_CREAT) 8237db96d56Sopenharmony_ci self.check_flush_error_on_close(fd, 'wb') 8247db96d56Sopenharmony_ci fd = os.open(os_helper.TESTFN, os.O_WRONLY|os.O_CREAT) 8257db96d56Sopenharmony_ci self.check_flush_error_on_close(fd, 'wb', closefd=False) 8267db96d56Sopenharmony_ci os.close(fd) 8277db96d56Sopenharmony_ci # text io 8287db96d56Sopenharmony_ci self.check_flush_error_on_close(os_helper.TESTFN, 'w', encoding="utf-8") 8297db96d56Sopenharmony_ci fd = os.open(os_helper.TESTFN, os.O_WRONLY|os.O_CREAT) 8307db96d56Sopenharmony_ci self.check_flush_error_on_close(fd, 'w', encoding="utf-8") 8317db96d56Sopenharmony_ci fd = os.open(os_helper.TESTFN, os.O_WRONLY|os.O_CREAT) 8327db96d56Sopenharmony_ci self.check_flush_error_on_close(fd, 'w', encoding="utf-8", closefd=False) 8337db96d56Sopenharmony_ci os.close(fd) 8347db96d56Sopenharmony_ci 8357db96d56Sopenharmony_ci def test_multi_close(self): 8367db96d56Sopenharmony_ci f = self.open(os_helper.TESTFN, "wb", buffering=0) 8377db96d56Sopenharmony_ci f.close() 8387db96d56Sopenharmony_ci f.close() 8397db96d56Sopenharmony_ci f.close() 8407db96d56Sopenharmony_ci self.assertRaises(ValueError, f.flush) 8417db96d56Sopenharmony_ci 8427db96d56Sopenharmony_ci def test_RawIOBase_read(self): 8437db96d56Sopenharmony_ci # Exercise the default limited RawIOBase.read(n) implementation (which 8447db96d56Sopenharmony_ci # calls readinto() internally). 8457db96d56Sopenharmony_ci rawio = self.MockRawIOWithoutRead((b"abc", b"d", None, b"efg", None)) 8467db96d56Sopenharmony_ci self.assertEqual(rawio.read(2), b"ab") 8477db96d56Sopenharmony_ci self.assertEqual(rawio.read(2), b"c") 8487db96d56Sopenharmony_ci self.assertEqual(rawio.read(2), b"d") 8497db96d56Sopenharmony_ci self.assertEqual(rawio.read(2), None) 8507db96d56Sopenharmony_ci self.assertEqual(rawio.read(2), b"ef") 8517db96d56Sopenharmony_ci self.assertEqual(rawio.read(2), b"g") 8527db96d56Sopenharmony_ci self.assertEqual(rawio.read(2), None) 8537db96d56Sopenharmony_ci self.assertEqual(rawio.read(2), b"") 8547db96d56Sopenharmony_ci 8557db96d56Sopenharmony_ci def test_types_have_dict(self): 8567db96d56Sopenharmony_ci test = ( 8577db96d56Sopenharmony_ci self.IOBase(), 8587db96d56Sopenharmony_ci self.RawIOBase(), 8597db96d56Sopenharmony_ci self.TextIOBase(), 8607db96d56Sopenharmony_ci self.StringIO(), 8617db96d56Sopenharmony_ci self.BytesIO() 8627db96d56Sopenharmony_ci ) 8637db96d56Sopenharmony_ci for obj in test: 8647db96d56Sopenharmony_ci self.assertTrue(hasattr(obj, "__dict__")) 8657db96d56Sopenharmony_ci 8667db96d56Sopenharmony_ci def test_opener(self): 8677db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "w", encoding="utf-8") as f: 8687db96d56Sopenharmony_ci f.write("egg\n") 8697db96d56Sopenharmony_ci fd = os.open(os_helper.TESTFN, os.O_RDONLY) 8707db96d56Sopenharmony_ci def opener(path, flags): 8717db96d56Sopenharmony_ci return fd 8727db96d56Sopenharmony_ci with self.open("non-existent", "r", encoding="utf-8", opener=opener) as f: 8737db96d56Sopenharmony_ci self.assertEqual(f.read(), "egg\n") 8747db96d56Sopenharmony_ci 8757db96d56Sopenharmony_ci def test_bad_opener_negative_1(self): 8767db96d56Sopenharmony_ci # Issue #27066. 8777db96d56Sopenharmony_ci def badopener(fname, flags): 8787db96d56Sopenharmony_ci return -1 8797db96d56Sopenharmony_ci with self.assertRaises(ValueError) as cm: 8807db96d56Sopenharmony_ci open('non-existent', 'r', opener=badopener) 8817db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), 'opener returned -1') 8827db96d56Sopenharmony_ci 8837db96d56Sopenharmony_ci def test_bad_opener_other_negative(self): 8847db96d56Sopenharmony_ci # Issue #27066. 8857db96d56Sopenharmony_ci def badopener(fname, flags): 8867db96d56Sopenharmony_ci return -2 8877db96d56Sopenharmony_ci with self.assertRaises(ValueError) as cm: 8887db96d56Sopenharmony_ci open('non-existent', 'r', opener=badopener) 8897db96d56Sopenharmony_ci self.assertEqual(str(cm.exception), 'opener returned -2') 8907db96d56Sopenharmony_ci 8917db96d56Sopenharmony_ci def test_opener_invalid_fd(self): 8927db96d56Sopenharmony_ci # Check that OSError is raised with error code EBADF if the 8937db96d56Sopenharmony_ci # opener returns an invalid file descriptor (see gh-82212). 8947db96d56Sopenharmony_ci fd = os_helper.make_bad_fd() 8957db96d56Sopenharmony_ci with self.assertRaises(OSError) as cm: 8967db96d56Sopenharmony_ci self.open('foo', opener=lambda name, flags: fd) 8977db96d56Sopenharmony_ci self.assertEqual(cm.exception.errno, errno.EBADF) 8987db96d56Sopenharmony_ci 8997db96d56Sopenharmony_ci def test_fileio_closefd(self): 9007db96d56Sopenharmony_ci # Issue #4841 9017db96d56Sopenharmony_ci with self.open(__file__, 'rb') as f1, \ 9027db96d56Sopenharmony_ci self.open(__file__, 'rb') as f2: 9037db96d56Sopenharmony_ci fileio = self.FileIO(f1.fileno(), closefd=False) 9047db96d56Sopenharmony_ci # .__init__() must not close f1 9057db96d56Sopenharmony_ci fileio.__init__(f2.fileno(), closefd=False) 9067db96d56Sopenharmony_ci f1.readline() 9077db96d56Sopenharmony_ci # .close() must not close f2 9087db96d56Sopenharmony_ci fileio.close() 9097db96d56Sopenharmony_ci f2.readline() 9107db96d56Sopenharmony_ci 9117db96d56Sopenharmony_ci def test_nonbuffered_textio(self): 9127db96d56Sopenharmony_ci with warnings_helper.check_no_resource_warning(self): 9137db96d56Sopenharmony_ci with self.assertRaises(ValueError): 9147db96d56Sopenharmony_ci self.open(os_helper.TESTFN, 'w', encoding="utf-8", buffering=0) 9157db96d56Sopenharmony_ci 9167db96d56Sopenharmony_ci def test_invalid_newline(self): 9177db96d56Sopenharmony_ci with warnings_helper.check_no_resource_warning(self): 9187db96d56Sopenharmony_ci with self.assertRaises(ValueError): 9197db96d56Sopenharmony_ci self.open(os_helper.TESTFN, 'w', encoding="utf-8", newline='invalid') 9207db96d56Sopenharmony_ci 9217db96d56Sopenharmony_ci def test_buffered_readinto_mixin(self): 9227db96d56Sopenharmony_ci # Test the implementation provided by BufferedIOBase 9237db96d56Sopenharmony_ci class Stream(self.BufferedIOBase): 9247db96d56Sopenharmony_ci def read(self, size): 9257db96d56Sopenharmony_ci return b"12345" 9267db96d56Sopenharmony_ci read1 = read 9277db96d56Sopenharmony_ci stream = Stream() 9287db96d56Sopenharmony_ci for method in ("readinto", "readinto1"): 9297db96d56Sopenharmony_ci with self.subTest(method): 9307db96d56Sopenharmony_ci buffer = byteslike(5) 9317db96d56Sopenharmony_ci self.assertEqual(getattr(stream, method)(buffer), 5) 9327db96d56Sopenharmony_ci self.assertEqual(bytes(buffer), b"12345") 9337db96d56Sopenharmony_ci 9347db96d56Sopenharmony_ci def test_fspath_support(self): 9357db96d56Sopenharmony_ci def check_path_succeeds(path): 9367db96d56Sopenharmony_ci with self.open(path, "w", encoding="utf-8") as f: 9377db96d56Sopenharmony_ci f.write("egg\n") 9387db96d56Sopenharmony_ci 9397db96d56Sopenharmony_ci with self.open(path, "r", encoding="utf-8") as f: 9407db96d56Sopenharmony_ci self.assertEqual(f.read(), "egg\n") 9417db96d56Sopenharmony_ci 9427db96d56Sopenharmony_ci check_path_succeeds(FakePath(os_helper.TESTFN)) 9437db96d56Sopenharmony_ci check_path_succeeds(FakePath(os.fsencode(os_helper.TESTFN))) 9447db96d56Sopenharmony_ci 9457db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "w", encoding="utf-8") as f: 9467db96d56Sopenharmony_ci bad_path = FakePath(f.fileno()) 9477db96d56Sopenharmony_ci with self.assertRaises(TypeError): 9487db96d56Sopenharmony_ci self.open(bad_path, 'w', encoding="utf-8") 9497db96d56Sopenharmony_ci 9507db96d56Sopenharmony_ci bad_path = FakePath(None) 9517db96d56Sopenharmony_ci with self.assertRaises(TypeError): 9527db96d56Sopenharmony_ci self.open(bad_path, 'w', encoding="utf-8") 9537db96d56Sopenharmony_ci 9547db96d56Sopenharmony_ci bad_path = FakePath(FloatingPointError) 9557db96d56Sopenharmony_ci with self.assertRaises(FloatingPointError): 9567db96d56Sopenharmony_ci self.open(bad_path, 'w', encoding="utf-8") 9577db96d56Sopenharmony_ci 9587db96d56Sopenharmony_ci # ensure that refcounting is correct with some error conditions 9597db96d56Sopenharmony_ci with self.assertRaisesRegex(ValueError, 'read/write/append mode'): 9607db96d56Sopenharmony_ci self.open(FakePath(os_helper.TESTFN), 'rwxa', encoding="utf-8") 9617db96d56Sopenharmony_ci 9627db96d56Sopenharmony_ci def test_RawIOBase_readall(self): 9637db96d56Sopenharmony_ci # Exercise the default unlimited RawIOBase.read() and readall() 9647db96d56Sopenharmony_ci # implementations. 9657db96d56Sopenharmony_ci rawio = self.MockRawIOWithoutRead((b"abc", b"d", b"efg")) 9667db96d56Sopenharmony_ci self.assertEqual(rawio.read(), b"abcdefg") 9677db96d56Sopenharmony_ci rawio = self.MockRawIOWithoutRead((b"abc", b"d", b"efg")) 9687db96d56Sopenharmony_ci self.assertEqual(rawio.readall(), b"abcdefg") 9697db96d56Sopenharmony_ci 9707db96d56Sopenharmony_ci def test_BufferedIOBase_readinto(self): 9717db96d56Sopenharmony_ci # Exercise the default BufferedIOBase.readinto() and readinto1() 9727db96d56Sopenharmony_ci # implementations (which call read() or read1() internally). 9737db96d56Sopenharmony_ci class Reader(self.BufferedIOBase): 9747db96d56Sopenharmony_ci def __init__(self, avail): 9757db96d56Sopenharmony_ci self.avail = avail 9767db96d56Sopenharmony_ci def read(self, size): 9777db96d56Sopenharmony_ci result = self.avail[:size] 9787db96d56Sopenharmony_ci self.avail = self.avail[size:] 9797db96d56Sopenharmony_ci return result 9807db96d56Sopenharmony_ci def read1(self, size): 9817db96d56Sopenharmony_ci """Returns no more than 5 bytes at once""" 9827db96d56Sopenharmony_ci return self.read(min(size, 5)) 9837db96d56Sopenharmony_ci tests = ( 9847db96d56Sopenharmony_ci # (test method, total data available, read buffer size, expected 9857db96d56Sopenharmony_ci # read size) 9867db96d56Sopenharmony_ci ("readinto", 10, 5, 5), 9877db96d56Sopenharmony_ci ("readinto", 10, 6, 6), # More than read1() can return 9887db96d56Sopenharmony_ci ("readinto", 5, 6, 5), # Buffer larger than total available 9897db96d56Sopenharmony_ci ("readinto", 6, 7, 6), 9907db96d56Sopenharmony_ci ("readinto", 10, 0, 0), # Empty buffer 9917db96d56Sopenharmony_ci ("readinto1", 10, 5, 5), # Result limited to single read1() call 9927db96d56Sopenharmony_ci ("readinto1", 10, 6, 5), # Buffer larger than read1() can return 9937db96d56Sopenharmony_ci ("readinto1", 5, 6, 5), # Buffer larger than total available 9947db96d56Sopenharmony_ci ("readinto1", 6, 7, 5), 9957db96d56Sopenharmony_ci ("readinto1", 10, 0, 0), # Empty buffer 9967db96d56Sopenharmony_ci ) 9977db96d56Sopenharmony_ci UNUSED_BYTE = 0x81 9987db96d56Sopenharmony_ci for test in tests: 9997db96d56Sopenharmony_ci with self.subTest(test): 10007db96d56Sopenharmony_ci method, avail, request, result = test 10017db96d56Sopenharmony_ci reader = Reader(bytes(range(avail))) 10027db96d56Sopenharmony_ci buffer = bytearray((UNUSED_BYTE,) * request) 10037db96d56Sopenharmony_ci method = getattr(reader, method) 10047db96d56Sopenharmony_ci self.assertEqual(method(buffer), result) 10057db96d56Sopenharmony_ci self.assertEqual(len(buffer), request) 10067db96d56Sopenharmony_ci self.assertSequenceEqual(buffer[:result], range(result)) 10077db96d56Sopenharmony_ci unused = (UNUSED_BYTE,) * (request - result) 10087db96d56Sopenharmony_ci self.assertSequenceEqual(buffer[result:], unused) 10097db96d56Sopenharmony_ci self.assertEqual(len(reader.avail), avail - result) 10107db96d56Sopenharmony_ci 10117db96d56Sopenharmony_ci def test_close_assert(self): 10127db96d56Sopenharmony_ci class R(self.IOBase): 10137db96d56Sopenharmony_ci def __setattr__(self, name, value): 10147db96d56Sopenharmony_ci pass 10157db96d56Sopenharmony_ci def flush(self): 10167db96d56Sopenharmony_ci raise OSError() 10177db96d56Sopenharmony_ci f = R() 10187db96d56Sopenharmony_ci # This would cause an assertion failure. 10197db96d56Sopenharmony_ci self.assertRaises(OSError, f.close) 10207db96d56Sopenharmony_ci 10217db96d56Sopenharmony_ci # Silence destructor error 10227db96d56Sopenharmony_ci R.flush = lambda self: None 10237db96d56Sopenharmony_ci 10247db96d56Sopenharmony_ci 10257db96d56Sopenharmony_ciclass CIOTest(IOTest): 10267db96d56Sopenharmony_ci 10277db96d56Sopenharmony_ci def test_IOBase_finalize(self): 10287db96d56Sopenharmony_ci # Issue #12149: segmentation fault on _PyIOBase_finalize when both a 10297db96d56Sopenharmony_ci # class which inherits IOBase and an object of this class are caught 10307db96d56Sopenharmony_ci # in a reference cycle and close() is already in the method cache. 10317db96d56Sopenharmony_ci class MyIO(self.IOBase): 10327db96d56Sopenharmony_ci def close(self): 10337db96d56Sopenharmony_ci pass 10347db96d56Sopenharmony_ci 10357db96d56Sopenharmony_ci # create an instance to populate the method cache 10367db96d56Sopenharmony_ci MyIO() 10377db96d56Sopenharmony_ci obj = MyIO() 10387db96d56Sopenharmony_ci obj.obj = obj 10397db96d56Sopenharmony_ci wr = weakref.ref(obj) 10407db96d56Sopenharmony_ci del MyIO 10417db96d56Sopenharmony_ci del obj 10427db96d56Sopenharmony_ci support.gc_collect() 10437db96d56Sopenharmony_ci self.assertIsNone(wr(), wr) 10447db96d56Sopenharmony_ci 10457db96d56Sopenharmony_ciclass PyIOTest(IOTest): 10467db96d56Sopenharmony_ci pass 10477db96d56Sopenharmony_ci 10487db96d56Sopenharmony_ci 10497db96d56Sopenharmony_ci@support.cpython_only 10507db96d56Sopenharmony_ciclass APIMismatchTest(unittest.TestCase): 10517db96d56Sopenharmony_ci 10527db96d56Sopenharmony_ci def test_RawIOBase_io_in_pyio_match(self): 10537db96d56Sopenharmony_ci """Test that pyio RawIOBase class has all c RawIOBase methods""" 10547db96d56Sopenharmony_ci mismatch = support.detect_api_mismatch(pyio.RawIOBase, io.RawIOBase, 10557db96d56Sopenharmony_ci ignore=('__weakref__',)) 10567db96d56Sopenharmony_ci self.assertEqual(mismatch, set(), msg='Python RawIOBase does not have all C RawIOBase methods') 10577db96d56Sopenharmony_ci 10587db96d56Sopenharmony_ci def test_RawIOBase_pyio_in_io_match(self): 10597db96d56Sopenharmony_ci """Test that c RawIOBase class has all pyio RawIOBase methods""" 10607db96d56Sopenharmony_ci mismatch = support.detect_api_mismatch(io.RawIOBase, pyio.RawIOBase) 10617db96d56Sopenharmony_ci self.assertEqual(mismatch, set(), msg='C RawIOBase does not have all Python RawIOBase methods') 10627db96d56Sopenharmony_ci 10637db96d56Sopenharmony_ci 10647db96d56Sopenharmony_ciclass CommonBufferedTests: 10657db96d56Sopenharmony_ci # Tests common to BufferedReader, BufferedWriter and BufferedRandom 10667db96d56Sopenharmony_ci 10677db96d56Sopenharmony_ci def test_detach(self): 10687db96d56Sopenharmony_ci raw = self.MockRawIO() 10697db96d56Sopenharmony_ci buf = self.tp(raw) 10707db96d56Sopenharmony_ci self.assertIs(buf.detach(), raw) 10717db96d56Sopenharmony_ci self.assertRaises(ValueError, buf.detach) 10727db96d56Sopenharmony_ci 10737db96d56Sopenharmony_ci repr(buf) # Should still work 10747db96d56Sopenharmony_ci 10757db96d56Sopenharmony_ci def test_fileno(self): 10767db96d56Sopenharmony_ci rawio = self.MockRawIO() 10777db96d56Sopenharmony_ci bufio = self.tp(rawio) 10787db96d56Sopenharmony_ci 10797db96d56Sopenharmony_ci self.assertEqual(42, bufio.fileno()) 10807db96d56Sopenharmony_ci 10817db96d56Sopenharmony_ci def test_invalid_args(self): 10827db96d56Sopenharmony_ci rawio = self.MockRawIO() 10837db96d56Sopenharmony_ci bufio = self.tp(rawio) 10847db96d56Sopenharmony_ci # Invalid whence 10857db96d56Sopenharmony_ci self.assertRaises(ValueError, bufio.seek, 0, -1) 10867db96d56Sopenharmony_ci self.assertRaises(ValueError, bufio.seek, 0, 9) 10877db96d56Sopenharmony_ci 10887db96d56Sopenharmony_ci def test_override_destructor(self): 10897db96d56Sopenharmony_ci tp = self.tp 10907db96d56Sopenharmony_ci record = [] 10917db96d56Sopenharmony_ci class MyBufferedIO(tp): 10927db96d56Sopenharmony_ci def __del__(self): 10937db96d56Sopenharmony_ci record.append(1) 10947db96d56Sopenharmony_ci try: 10957db96d56Sopenharmony_ci f = super().__del__ 10967db96d56Sopenharmony_ci except AttributeError: 10977db96d56Sopenharmony_ci pass 10987db96d56Sopenharmony_ci else: 10997db96d56Sopenharmony_ci f() 11007db96d56Sopenharmony_ci def close(self): 11017db96d56Sopenharmony_ci record.append(2) 11027db96d56Sopenharmony_ci super().close() 11037db96d56Sopenharmony_ci def flush(self): 11047db96d56Sopenharmony_ci record.append(3) 11057db96d56Sopenharmony_ci super().flush() 11067db96d56Sopenharmony_ci rawio = self.MockRawIO() 11077db96d56Sopenharmony_ci bufio = MyBufferedIO(rawio) 11087db96d56Sopenharmony_ci del bufio 11097db96d56Sopenharmony_ci support.gc_collect() 11107db96d56Sopenharmony_ci self.assertEqual(record, [1, 2, 3]) 11117db96d56Sopenharmony_ci 11127db96d56Sopenharmony_ci def test_context_manager(self): 11137db96d56Sopenharmony_ci # Test usability as a context manager 11147db96d56Sopenharmony_ci rawio = self.MockRawIO() 11157db96d56Sopenharmony_ci bufio = self.tp(rawio) 11167db96d56Sopenharmony_ci def _with(): 11177db96d56Sopenharmony_ci with bufio: 11187db96d56Sopenharmony_ci pass 11197db96d56Sopenharmony_ci _with() 11207db96d56Sopenharmony_ci # bufio should now be closed, and using it a second time should raise 11217db96d56Sopenharmony_ci # a ValueError. 11227db96d56Sopenharmony_ci self.assertRaises(ValueError, _with) 11237db96d56Sopenharmony_ci 11247db96d56Sopenharmony_ci def test_error_through_destructor(self): 11257db96d56Sopenharmony_ci # Test that the exception state is not modified by a destructor, 11267db96d56Sopenharmony_ci # even if close() fails. 11277db96d56Sopenharmony_ci rawio = self.CloseFailureIO() 11287db96d56Sopenharmony_ci with support.catch_unraisable_exception() as cm: 11297db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 11307db96d56Sopenharmony_ci self.tp(rawio).xyzzy 11317db96d56Sopenharmony_ci 11327db96d56Sopenharmony_ci if not IOBASE_EMITS_UNRAISABLE: 11337db96d56Sopenharmony_ci self.assertIsNone(cm.unraisable) 11347db96d56Sopenharmony_ci elif cm.unraisable is not None: 11357db96d56Sopenharmony_ci self.assertEqual(cm.unraisable.exc_type, OSError) 11367db96d56Sopenharmony_ci 11377db96d56Sopenharmony_ci def test_repr(self): 11387db96d56Sopenharmony_ci raw = self.MockRawIO() 11397db96d56Sopenharmony_ci b = self.tp(raw) 11407db96d56Sopenharmony_ci clsname = r"(%s\.)?%s" % (self.tp.__module__, self.tp.__qualname__) 11417db96d56Sopenharmony_ci self.assertRegex(repr(b), "<%s>" % clsname) 11427db96d56Sopenharmony_ci raw.name = "dummy" 11437db96d56Sopenharmony_ci self.assertRegex(repr(b), "<%s name='dummy'>" % clsname) 11447db96d56Sopenharmony_ci raw.name = b"dummy" 11457db96d56Sopenharmony_ci self.assertRegex(repr(b), "<%s name=b'dummy'>" % clsname) 11467db96d56Sopenharmony_ci 11477db96d56Sopenharmony_ci def test_recursive_repr(self): 11487db96d56Sopenharmony_ci # Issue #25455 11497db96d56Sopenharmony_ci raw = self.MockRawIO() 11507db96d56Sopenharmony_ci b = self.tp(raw) 11517db96d56Sopenharmony_ci with support.swap_attr(raw, 'name', b): 11527db96d56Sopenharmony_ci try: 11537db96d56Sopenharmony_ci repr(b) # Should not crash 11547db96d56Sopenharmony_ci except RuntimeError: 11557db96d56Sopenharmony_ci pass 11567db96d56Sopenharmony_ci 11577db96d56Sopenharmony_ci def test_flush_error_on_close(self): 11587db96d56Sopenharmony_ci # Test that buffered file is closed despite failed flush 11597db96d56Sopenharmony_ci # and that flush() is called before file closed. 11607db96d56Sopenharmony_ci raw = self.MockRawIO() 11617db96d56Sopenharmony_ci closed = [] 11627db96d56Sopenharmony_ci def bad_flush(): 11637db96d56Sopenharmony_ci closed[:] = [b.closed, raw.closed] 11647db96d56Sopenharmony_ci raise OSError() 11657db96d56Sopenharmony_ci raw.flush = bad_flush 11667db96d56Sopenharmony_ci b = self.tp(raw) 11677db96d56Sopenharmony_ci self.assertRaises(OSError, b.close) # exception not swallowed 11687db96d56Sopenharmony_ci self.assertTrue(b.closed) 11697db96d56Sopenharmony_ci self.assertTrue(raw.closed) 11707db96d56Sopenharmony_ci self.assertTrue(closed) # flush() called 11717db96d56Sopenharmony_ci self.assertFalse(closed[0]) # flush() called before file closed 11727db96d56Sopenharmony_ci self.assertFalse(closed[1]) 11737db96d56Sopenharmony_ci raw.flush = lambda: None # break reference loop 11747db96d56Sopenharmony_ci 11757db96d56Sopenharmony_ci def test_close_error_on_close(self): 11767db96d56Sopenharmony_ci raw = self.MockRawIO() 11777db96d56Sopenharmony_ci def bad_flush(): 11787db96d56Sopenharmony_ci raise OSError('flush') 11797db96d56Sopenharmony_ci def bad_close(): 11807db96d56Sopenharmony_ci raise OSError('close') 11817db96d56Sopenharmony_ci raw.close = bad_close 11827db96d56Sopenharmony_ci b = self.tp(raw) 11837db96d56Sopenharmony_ci b.flush = bad_flush 11847db96d56Sopenharmony_ci with self.assertRaises(OSError) as err: # exception not swallowed 11857db96d56Sopenharmony_ci b.close() 11867db96d56Sopenharmony_ci self.assertEqual(err.exception.args, ('close',)) 11877db96d56Sopenharmony_ci self.assertIsInstance(err.exception.__context__, OSError) 11887db96d56Sopenharmony_ci self.assertEqual(err.exception.__context__.args, ('flush',)) 11897db96d56Sopenharmony_ci self.assertFalse(b.closed) 11907db96d56Sopenharmony_ci 11917db96d56Sopenharmony_ci # Silence destructor error 11927db96d56Sopenharmony_ci raw.close = lambda: None 11937db96d56Sopenharmony_ci b.flush = lambda: None 11947db96d56Sopenharmony_ci 11957db96d56Sopenharmony_ci def test_nonnormalized_close_error_on_close(self): 11967db96d56Sopenharmony_ci # Issue #21677 11977db96d56Sopenharmony_ci raw = self.MockRawIO() 11987db96d56Sopenharmony_ci def bad_flush(): 11997db96d56Sopenharmony_ci raise non_existing_flush 12007db96d56Sopenharmony_ci def bad_close(): 12017db96d56Sopenharmony_ci raise non_existing_close 12027db96d56Sopenharmony_ci raw.close = bad_close 12037db96d56Sopenharmony_ci b = self.tp(raw) 12047db96d56Sopenharmony_ci b.flush = bad_flush 12057db96d56Sopenharmony_ci with self.assertRaises(NameError) as err: # exception not swallowed 12067db96d56Sopenharmony_ci b.close() 12077db96d56Sopenharmony_ci self.assertIn('non_existing_close', str(err.exception)) 12087db96d56Sopenharmony_ci self.assertIsInstance(err.exception.__context__, NameError) 12097db96d56Sopenharmony_ci self.assertIn('non_existing_flush', str(err.exception.__context__)) 12107db96d56Sopenharmony_ci self.assertFalse(b.closed) 12117db96d56Sopenharmony_ci 12127db96d56Sopenharmony_ci # Silence destructor error 12137db96d56Sopenharmony_ci b.flush = lambda: None 12147db96d56Sopenharmony_ci raw.close = lambda: None 12157db96d56Sopenharmony_ci 12167db96d56Sopenharmony_ci def test_multi_close(self): 12177db96d56Sopenharmony_ci raw = self.MockRawIO() 12187db96d56Sopenharmony_ci b = self.tp(raw) 12197db96d56Sopenharmony_ci b.close() 12207db96d56Sopenharmony_ci b.close() 12217db96d56Sopenharmony_ci b.close() 12227db96d56Sopenharmony_ci self.assertRaises(ValueError, b.flush) 12237db96d56Sopenharmony_ci 12247db96d56Sopenharmony_ci def test_unseekable(self): 12257db96d56Sopenharmony_ci bufio = self.tp(self.MockUnseekableIO(b"A" * 10)) 12267db96d56Sopenharmony_ci self.assertRaises(self.UnsupportedOperation, bufio.tell) 12277db96d56Sopenharmony_ci self.assertRaises(self.UnsupportedOperation, bufio.seek, 0) 12287db96d56Sopenharmony_ci 12297db96d56Sopenharmony_ci def test_readonly_attributes(self): 12307db96d56Sopenharmony_ci raw = self.MockRawIO() 12317db96d56Sopenharmony_ci buf = self.tp(raw) 12327db96d56Sopenharmony_ci x = self.MockRawIO() 12337db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 12347db96d56Sopenharmony_ci buf.raw = x 12357db96d56Sopenharmony_ci 12367db96d56Sopenharmony_ci 12377db96d56Sopenharmony_ciclass SizeofTest: 12387db96d56Sopenharmony_ci 12397db96d56Sopenharmony_ci @support.cpython_only 12407db96d56Sopenharmony_ci def test_sizeof(self): 12417db96d56Sopenharmony_ci bufsize1 = 4096 12427db96d56Sopenharmony_ci bufsize2 = 8192 12437db96d56Sopenharmony_ci rawio = self.MockRawIO() 12447db96d56Sopenharmony_ci bufio = self.tp(rawio, buffer_size=bufsize1) 12457db96d56Sopenharmony_ci size = sys.getsizeof(bufio) - bufsize1 12467db96d56Sopenharmony_ci rawio = self.MockRawIO() 12477db96d56Sopenharmony_ci bufio = self.tp(rawio, buffer_size=bufsize2) 12487db96d56Sopenharmony_ci self.assertEqual(sys.getsizeof(bufio), size + bufsize2) 12497db96d56Sopenharmony_ci 12507db96d56Sopenharmony_ci @support.cpython_only 12517db96d56Sopenharmony_ci def test_buffer_freeing(self) : 12527db96d56Sopenharmony_ci bufsize = 4096 12537db96d56Sopenharmony_ci rawio = self.MockRawIO() 12547db96d56Sopenharmony_ci bufio = self.tp(rawio, buffer_size=bufsize) 12557db96d56Sopenharmony_ci size = sys.getsizeof(bufio) - bufsize 12567db96d56Sopenharmony_ci bufio.close() 12577db96d56Sopenharmony_ci self.assertEqual(sys.getsizeof(bufio), size) 12587db96d56Sopenharmony_ci 12597db96d56Sopenharmony_ciclass BufferedReaderTest(unittest.TestCase, CommonBufferedTests): 12607db96d56Sopenharmony_ci read_mode = "rb" 12617db96d56Sopenharmony_ci 12627db96d56Sopenharmony_ci def test_constructor(self): 12637db96d56Sopenharmony_ci rawio = self.MockRawIO([b"abc"]) 12647db96d56Sopenharmony_ci bufio = self.tp(rawio) 12657db96d56Sopenharmony_ci bufio.__init__(rawio) 12667db96d56Sopenharmony_ci bufio.__init__(rawio, buffer_size=1024) 12677db96d56Sopenharmony_ci bufio.__init__(rawio, buffer_size=16) 12687db96d56Sopenharmony_ci self.assertEqual(b"abc", bufio.read()) 12697db96d56Sopenharmony_ci self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=0) 12707db96d56Sopenharmony_ci self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-16) 12717db96d56Sopenharmony_ci self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-1) 12727db96d56Sopenharmony_ci rawio = self.MockRawIO([b"abc"]) 12737db96d56Sopenharmony_ci bufio.__init__(rawio) 12747db96d56Sopenharmony_ci self.assertEqual(b"abc", bufio.read()) 12757db96d56Sopenharmony_ci 12767db96d56Sopenharmony_ci def test_uninitialized(self): 12777db96d56Sopenharmony_ci bufio = self.tp.__new__(self.tp) 12787db96d56Sopenharmony_ci del bufio 12797db96d56Sopenharmony_ci bufio = self.tp.__new__(self.tp) 12807db96d56Sopenharmony_ci self.assertRaisesRegex((ValueError, AttributeError), 12817db96d56Sopenharmony_ci 'uninitialized|has no attribute', 12827db96d56Sopenharmony_ci bufio.read, 0) 12837db96d56Sopenharmony_ci bufio.__init__(self.MockRawIO()) 12847db96d56Sopenharmony_ci self.assertEqual(bufio.read(0), b'') 12857db96d56Sopenharmony_ci 12867db96d56Sopenharmony_ci def test_read(self): 12877db96d56Sopenharmony_ci for arg in (None, 7): 12887db96d56Sopenharmony_ci rawio = self.MockRawIO((b"abc", b"d", b"efg")) 12897db96d56Sopenharmony_ci bufio = self.tp(rawio) 12907db96d56Sopenharmony_ci self.assertEqual(b"abcdefg", bufio.read(arg)) 12917db96d56Sopenharmony_ci # Invalid args 12927db96d56Sopenharmony_ci self.assertRaises(ValueError, bufio.read, -2) 12937db96d56Sopenharmony_ci 12947db96d56Sopenharmony_ci def test_read1(self): 12957db96d56Sopenharmony_ci rawio = self.MockRawIO((b"abc", b"d", b"efg")) 12967db96d56Sopenharmony_ci bufio = self.tp(rawio) 12977db96d56Sopenharmony_ci self.assertEqual(b"a", bufio.read(1)) 12987db96d56Sopenharmony_ci self.assertEqual(b"b", bufio.read1(1)) 12997db96d56Sopenharmony_ci self.assertEqual(rawio._reads, 1) 13007db96d56Sopenharmony_ci self.assertEqual(b"", bufio.read1(0)) 13017db96d56Sopenharmony_ci self.assertEqual(b"c", bufio.read1(100)) 13027db96d56Sopenharmony_ci self.assertEqual(rawio._reads, 1) 13037db96d56Sopenharmony_ci self.assertEqual(b"d", bufio.read1(100)) 13047db96d56Sopenharmony_ci self.assertEqual(rawio._reads, 2) 13057db96d56Sopenharmony_ci self.assertEqual(b"efg", bufio.read1(100)) 13067db96d56Sopenharmony_ci self.assertEqual(rawio._reads, 3) 13077db96d56Sopenharmony_ci self.assertEqual(b"", bufio.read1(100)) 13087db96d56Sopenharmony_ci self.assertEqual(rawio._reads, 4) 13097db96d56Sopenharmony_ci 13107db96d56Sopenharmony_ci def test_read1_arbitrary(self): 13117db96d56Sopenharmony_ci rawio = self.MockRawIO((b"abc", b"d", b"efg")) 13127db96d56Sopenharmony_ci bufio = self.tp(rawio) 13137db96d56Sopenharmony_ci self.assertEqual(b"a", bufio.read(1)) 13147db96d56Sopenharmony_ci self.assertEqual(b"bc", bufio.read1()) 13157db96d56Sopenharmony_ci self.assertEqual(b"d", bufio.read1()) 13167db96d56Sopenharmony_ci self.assertEqual(b"efg", bufio.read1(-1)) 13177db96d56Sopenharmony_ci self.assertEqual(rawio._reads, 3) 13187db96d56Sopenharmony_ci self.assertEqual(b"", bufio.read1()) 13197db96d56Sopenharmony_ci self.assertEqual(rawio._reads, 4) 13207db96d56Sopenharmony_ci 13217db96d56Sopenharmony_ci def test_readinto(self): 13227db96d56Sopenharmony_ci rawio = self.MockRawIO((b"abc", b"d", b"efg")) 13237db96d56Sopenharmony_ci bufio = self.tp(rawio) 13247db96d56Sopenharmony_ci b = bytearray(2) 13257db96d56Sopenharmony_ci self.assertEqual(bufio.readinto(b), 2) 13267db96d56Sopenharmony_ci self.assertEqual(b, b"ab") 13277db96d56Sopenharmony_ci self.assertEqual(bufio.readinto(b), 2) 13287db96d56Sopenharmony_ci self.assertEqual(b, b"cd") 13297db96d56Sopenharmony_ci self.assertEqual(bufio.readinto(b), 2) 13307db96d56Sopenharmony_ci self.assertEqual(b, b"ef") 13317db96d56Sopenharmony_ci self.assertEqual(bufio.readinto(b), 1) 13327db96d56Sopenharmony_ci self.assertEqual(b, b"gf") 13337db96d56Sopenharmony_ci self.assertEqual(bufio.readinto(b), 0) 13347db96d56Sopenharmony_ci self.assertEqual(b, b"gf") 13357db96d56Sopenharmony_ci rawio = self.MockRawIO((b"abc", None)) 13367db96d56Sopenharmony_ci bufio = self.tp(rawio) 13377db96d56Sopenharmony_ci self.assertEqual(bufio.readinto(b), 2) 13387db96d56Sopenharmony_ci self.assertEqual(b, b"ab") 13397db96d56Sopenharmony_ci self.assertEqual(bufio.readinto(b), 1) 13407db96d56Sopenharmony_ci self.assertEqual(b, b"cb") 13417db96d56Sopenharmony_ci 13427db96d56Sopenharmony_ci def test_readinto1(self): 13437db96d56Sopenharmony_ci buffer_size = 10 13447db96d56Sopenharmony_ci rawio = self.MockRawIO((b"abc", b"de", b"fgh", b"jkl")) 13457db96d56Sopenharmony_ci bufio = self.tp(rawio, buffer_size=buffer_size) 13467db96d56Sopenharmony_ci b = bytearray(2) 13477db96d56Sopenharmony_ci self.assertEqual(bufio.peek(3), b'abc') 13487db96d56Sopenharmony_ci self.assertEqual(rawio._reads, 1) 13497db96d56Sopenharmony_ci self.assertEqual(bufio.readinto1(b), 2) 13507db96d56Sopenharmony_ci self.assertEqual(b, b"ab") 13517db96d56Sopenharmony_ci self.assertEqual(rawio._reads, 1) 13527db96d56Sopenharmony_ci self.assertEqual(bufio.readinto1(b), 1) 13537db96d56Sopenharmony_ci self.assertEqual(b[:1], b"c") 13547db96d56Sopenharmony_ci self.assertEqual(rawio._reads, 1) 13557db96d56Sopenharmony_ci self.assertEqual(bufio.readinto1(b), 2) 13567db96d56Sopenharmony_ci self.assertEqual(b, b"de") 13577db96d56Sopenharmony_ci self.assertEqual(rawio._reads, 2) 13587db96d56Sopenharmony_ci b = bytearray(2*buffer_size) 13597db96d56Sopenharmony_ci self.assertEqual(bufio.peek(3), b'fgh') 13607db96d56Sopenharmony_ci self.assertEqual(rawio._reads, 3) 13617db96d56Sopenharmony_ci self.assertEqual(bufio.readinto1(b), 6) 13627db96d56Sopenharmony_ci self.assertEqual(b[:6], b"fghjkl") 13637db96d56Sopenharmony_ci self.assertEqual(rawio._reads, 4) 13647db96d56Sopenharmony_ci 13657db96d56Sopenharmony_ci def test_readinto_array(self): 13667db96d56Sopenharmony_ci buffer_size = 60 13677db96d56Sopenharmony_ci data = b"a" * 26 13687db96d56Sopenharmony_ci rawio = self.MockRawIO((data,)) 13697db96d56Sopenharmony_ci bufio = self.tp(rawio, buffer_size=buffer_size) 13707db96d56Sopenharmony_ci 13717db96d56Sopenharmony_ci # Create an array with element size > 1 byte 13727db96d56Sopenharmony_ci b = array.array('i', b'x' * 32) 13737db96d56Sopenharmony_ci assert len(b) != 16 13747db96d56Sopenharmony_ci 13757db96d56Sopenharmony_ci # Read into it. We should get as many *bytes* as we can fit into b 13767db96d56Sopenharmony_ci # (which is more than the number of elements) 13777db96d56Sopenharmony_ci n = bufio.readinto(b) 13787db96d56Sopenharmony_ci self.assertGreater(n, len(b)) 13797db96d56Sopenharmony_ci 13807db96d56Sopenharmony_ci # Check that old contents of b are preserved 13817db96d56Sopenharmony_ci bm = memoryview(b).cast('B') 13827db96d56Sopenharmony_ci self.assertLess(n, len(bm)) 13837db96d56Sopenharmony_ci self.assertEqual(bm[:n], data[:n]) 13847db96d56Sopenharmony_ci self.assertEqual(bm[n:], b'x' * (len(bm[n:]))) 13857db96d56Sopenharmony_ci 13867db96d56Sopenharmony_ci def test_readinto1_array(self): 13877db96d56Sopenharmony_ci buffer_size = 60 13887db96d56Sopenharmony_ci data = b"a" * 26 13897db96d56Sopenharmony_ci rawio = self.MockRawIO((data,)) 13907db96d56Sopenharmony_ci bufio = self.tp(rawio, buffer_size=buffer_size) 13917db96d56Sopenharmony_ci 13927db96d56Sopenharmony_ci # Create an array with element size > 1 byte 13937db96d56Sopenharmony_ci b = array.array('i', b'x' * 32) 13947db96d56Sopenharmony_ci assert len(b) != 16 13957db96d56Sopenharmony_ci 13967db96d56Sopenharmony_ci # Read into it. We should get as many *bytes* as we can fit into b 13977db96d56Sopenharmony_ci # (which is more than the number of elements) 13987db96d56Sopenharmony_ci n = bufio.readinto1(b) 13997db96d56Sopenharmony_ci self.assertGreater(n, len(b)) 14007db96d56Sopenharmony_ci 14017db96d56Sopenharmony_ci # Check that old contents of b are preserved 14027db96d56Sopenharmony_ci bm = memoryview(b).cast('B') 14037db96d56Sopenharmony_ci self.assertLess(n, len(bm)) 14047db96d56Sopenharmony_ci self.assertEqual(bm[:n], data[:n]) 14057db96d56Sopenharmony_ci self.assertEqual(bm[n:], b'x' * (len(bm[n:]))) 14067db96d56Sopenharmony_ci 14077db96d56Sopenharmony_ci def test_readlines(self): 14087db96d56Sopenharmony_ci def bufio(): 14097db96d56Sopenharmony_ci rawio = self.MockRawIO((b"abc\n", b"d\n", b"ef")) 14107db96d56Sopenharmony_ci return self.tp(rawio) 14117db96d56Sopenharmony_ci self.assertEqual(bufio().readlines(), [b"abc\n", b"d\n", b"ef"]) 14127db96d56Sopenharmony_ci self.assertEqual(bufio().readlines(5), [b"abc\n", b"d\n"]) 14137db96d56Sopenharmony_ci self.assertEqual(bufio().readlines(None), [b"abc\n", b"d\n", b"ef"]) 14147db96d56Sopenharmony_ci 14157db96d56Sopenharmony_ci def test_buffering(self): 14167db96d56Sopenharmony_ci data = b"abcdefghi" 14177db96d56Sopenharmony_ci dlen = len(data) 14187db96d56Sopenharmony_ci 14197db96d56Sopenharmony_ci tests = [ 14207db96d56Sopenharmony_ci [ 100, [ 3, 1, 4, 8 ], [ dlen, 0 ] ], 14217db96d56Sopenharmony_ci [ 100, [ 3, 3, 3], [ dlen ] ], 14227db96d56Sopenharmony_ci [ 4, [ 1, 2, 4, 2 ], [ 4, 4, 1 ] ], 14237db96d56Sopenharmony_ci ] 14247db96d56Sopenharmony_ci 14257db96d56Sopenharmony_ci for bufsize, buf_read_sizes, raw_read_sizes in tests: 14267db96d56Sopenharmony_ci rawio = self.MockFileIO(data) 14277db96d56Sopenharmony_ci bufio = self.tp(rawio, buffer_size=bufsize) 14287db96d56Sopenharmony_ci pos = 0 14297db96d56Sopenharmony_ci for nbytes in buf_read_sizes: 14307db96d56Sopenharmony_ci self.assertEqual(bufio.read(nbytes), data[pos:pos+nbytes]) 14317db96d56Sopenharmony_ci pos += nbytes 14327db96d56Sopenharmony_ci # this is mildly implementation-dependent 14337db96d56Sopenharmony_ci self.assertEqual(rawio.read_history, raw_read_sizes) 14347db96d56Sopenharmony_ci 14357db96d56Sopenharmony_ci def test_read_non_blocking(self): 14367db96d56Sopenharmony_ci # Inject some None's in there to simulate EWOULDBLOCK 14377db96d56Sopenharmony_ci rawio = self.MockRawIO((b"abc", b"d", None, b"efg", None, None, None)) 14387db96d56Sopenharmony_ci bufio = self.tp(rawio) 14397db96d56Sopenharmony_ci self.assertEqual(b"abcd", bufio.read(6)) 14407db96d56Sopenharmony_ci self.assertEqual(b"e", bufio.read(1)) 14417db96d56Sopenharmony_ci self.assertEqual(b"fg", bufio.read()) 14427db96d56Sopenharmony_ci self.assertEqual(b"", bufio.peek(1)) 14437db96d56Sopenharmony_ci self.assertIsNone(bufio.read()) 14447db96d56Sopenharmony_ci self.assertEqual(b"", bufio.read()) 14457db96d56Sopenharmony_ci 14467db96d56Sopenharmony_ci rawio = self.MockRawIO((b"a", None, None)) 14477db96d56Sopenharmony_ci self.assertEqual(b"a", rawio.readall()) 14487db96d56Sopenharmony_ci self.assertIsNone(rawio.readall()) 14497db96d56Sopenharmony_ci 14507db96d56Sopenharmony_ci def test_read_past_eof(self): 14517db96d56Sopenharmony_ci rawio = self.MockRawIO((b"abc", b"d", b"efg")) 14527db96d56Sopenharmony_ci bufio = self.tp(rawio) 14537db96d56Sopenharmony_ci 14547db96d56Sopenharmony_ci self.assertEqual(b"abcdefg", bufio.read(9000)) 14557db96d56Sopenharmony_ci 14567db96d56Sopenharmony_ci def test_read_all(self): 14577db96d56Sopenharmony_ci rawio = self.MockRawIO((b"abc", b"d", b"efg")) 14587db96d56Sopenharmony_ci bufio = self.tp(rawio) 14597db96d56Sopenharmony_ci 14607db96d56Sopenharmony_ci self.assertEqual(b"abcdefg", bufio.read()) 14617db96d56Sopenharmony_ci 14627db96d56Sopenharmony_ci @support.requires_resource('cpu') 14637db96d56Sopenharmony_ci @threading_helper.requires_working_threading() 14647db96d56Sopenharmony_ci def test_threads(self): 14657db96d56Sopenharmony_ci try: 14667db96d56Sopenharmony_ci # Write out many bytes with exactly the same number of 0's, 14677db96d56Sopenharmony_ci # 1's... 255's. This will help us check that concurrent reading 14687db96d56Sopenharmony_ci # doesn't duplicate or forget contents. 14697db96d56Sopenharmony_ci N = 1000 14707db96d56Sopenharmony_ci l = list(range(256)) * N 14717db96d56Sopenharmony_ci random.shuffle(l) 14727db96d56Sopenharmony_ci s = bytes(bytearray(l)) 14737db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "wb") as f: 14747db96d56Sopenharmony_ci f.write(s) 14757db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, self.read_mode, buffering=0) as raw: 14767db96d56Sopenharmony_ci bufio = self.tp(raw, 8) 14777db96d56Sopenharmony_ci errors = [] 14787db96d56Sopenharmony_ci results = [] 14797db96d56Sopenharmony_ci def f(): 14807db96d56Sopenharmony_ci try: 14817db96d56Sopenharmony_ci # Intra-buffer read then buffer-flushing read 14827db96d56Sopenharmony_ci for n in cycle([1, 19]): 14837db96d56Sopenharmony_ci s = bufio.read(n) 14847db96d56Sopenharmony_ci if not s: 14857db96d56Sopenharmony_ci break 14867db96d56Sopenharmony_ci # list.append() is atomic 14877db96d56Sopenharmony_ci results.append(s) 14887db96d56Sopenharmony_ci except Exception as e: 14897db96d56Sopenharmony_ci errors.append(e) 14907db96d56Sopenharmony_ci raise 14917db96d56Sopenharmony_ci threads = [threading.Thread(target=f) for x in range(20)] 14927db96d56Sopenharmony_ci with threading_helper.start_threads(threads): 14937db96d56Sopenharmony_ci time.sleep(0.02) # yield 14947db96d56Sopenharmony_ci self.assertFalse(errors, 14957db96d56Sopenharmony_ci "the following exceptions were caught: %r" % errors) 14967db96d56Sopenharmony_ci s = b''.join(results) 14977db96d56Sopenharmony_ci for i in range(256): 14987db96d56Sopenharmony_ci c = bytes(bytearray([i])) 14997db96d56Sopenharmony_ci self.assertEqual(s.count(c), N) 15007db96d56Sopenharmony_ci finally: 15017db96d56Sopenharmony_ci os_helper.unlink(os_helper.TESTFN) 15027db96d56Sopenharmony_ci 15037db96d56Sopenharmony_ci def test_unseekable(self): 15047db96d56Sopenharmony_ci bufio = self.tp(self.MockUnseekableIO(b"A" * 10)) 15057db96d56Sopenharmony_ci self.assertRaises(self.UnsupportedOperation, bufio.tell) 15067db96d56Sopenharmony_ci self.assertRaises(self.UnsupportedOperation, bufio.seek, 0) 15077db96d56Sopenharmony_ci bufio.read(1) 15087db96d56Sopenharmony_ci self.assertRaises(self.UnsupportedOperation, bufio.seek, 0) 15097db96d56Sopenharmony_ci self.assertRaises(self.UnsupportedOperation, bufio.tell) 15107db96d56Sopenharmony_ci 15117db96d56Sopenharmony_ci def test_misbehaved_io(self): 15127db96d56Sopenharmony_ci rawio = self.MisbehavedRawIO((b"abc", b"d", b"efg")) 15137db96d56Sopenharmony_ci bufio = self.tp(rawio) 15147db96d56Sopenharmony_ci self.assertRaises(OSError, bufio.seek, 0) 15157db96d56Sopenharmony_ci self.assertRaises(OSError, bufio.tell) 15167db96d56Sopenharmony_ci 15177db96d56Sopenharmony_ci # Silence destructor error 15187db96d56Sopenharmony_ci bufio.close = lambda: None 15197db96d56Sopenharmony_ci 15207db96d56Sopenharmony_ci def test_no_extraneous_read(self): 15217db96d56Sopenharmony_ci # Issue #9550; when the raw IO object has satisfied the read request, 15227db96d56Sopenharmony_ci # we should not issue any additional reads, otherwise it may block 15237db96d56Sopenharmony_ci # (e.g. socket). 15247db96d56Sopenharmony_ci bufsize = 16 15257db96d56Sopenharmony_ci for n in (2, bufsize - 1, bufsize, bufsize + 1, bufsize * 2): 15267db96d56Sopenharmony_ci rawio = self.MockRawIO([b"x" * n]) 15277db96d56Sopenharmony_ci bufio = self.tp(rawio, bufsize) 15287db96d56Sopenharmony_ci self.assertEqual(bufio.read(n), b"x" * n) 15297db96d56Sopenharmony_ci # Simple case: one raw read is enough to satisfy the request. 15307db96d56Sopenharmony_ci self.assertEqual(rawio._extraneous_reads, 0, 15317db96d56Sopenharmony_ci "failed for {}: {} != 0".format(n, rawio._extraneous_reads)) 15327db96d56Sopenharmony_ci # A more complex case where two raw reads are needed to satisfy 15337db96d56Sopenharmony_ci # the request. 15347db96d56Sopenharmony_ci rawio = self.MockRawIO([b"x" * (n - 1), b"x"]) 15357db96d56Sopenharmony_ci bufio = self.tp(rawio, bufsize) 15367db96d56Sopenharmony_ci self.assertEqual(bufio.read(n), b"x" * n) 15377db96d56Sopenharmony_ci self.assertEqual(rawio._extraneous_reads, 0, 15387db96d56Sopenharmony_ci "failed for {}: {} != 0".format(n, rawio._extraneous_reads)) 15397db96d56Sopenharmony_ci 15407db96d56Sopenharmony_ci def test_read_on_closed(self): 15417db96d56Sopenharmony_ci # Issue #23796 15427db96d56Sopenharmony_ci b = io.BufferedReader(io.BytesIO(b"12")) 15437db96d56Sopenharmony_ci b.read(1) 15447db96d56Sopenharmony_ci b.close() 15457db96d56Sopenharmony_ci self.assertRaises(ValueError, b.peek) 15467db96d56Sopenharmony_ci self.assertRaises(ValueError, b.read1, 1) 15477db96d56Sopenharmony_ci 15487db96d56Sopenharmony_ci def test_truncate_on_read_only(self): 15497db96d56Sopenharmony_ci rawio = self.MockFileIO(b"abc") 15507db96d56Sopenharmony_ci bufio = self.tp(rawio) 15517db96d56Sopenharmony_ci self.assertFalse(bufio.writable()) 15527db96d56Sopenharmony_ci self.assertRaises(self.UnsupportedOperation, bufio.truncate) 15537db96d56Sopenharmony_ci self.assertRaises(self.UnsupportedOperation, bufio.truncate, 0) 15547db96d56Sopenharmony_ci 15557db96d56Sopenharmony_ci 15567db96d56Sopenharmony_ciclass CBufferedReaderTest(BufferedReaderTest, SizeofTest): 15577db96d56Sopenharmony_ci tp = io.BufferedReader 15587db96d56Sopenharmony_ci 15597db96d56Sopenharmony_ci @skip_if_sanitizer(memory=True, address=True, reason= "sanitizer defaults to crashing " 15607db96d56Sopenharmony_ci "instead of returning NULL for malloc failure.") 15617db96d56Sopenharmony_ci def test_constructor(self): 15627db96d56Sopenharmony_ci BufferedReaderTest.test_constructor(self) 15637db96d56Sopenharmony_ci # The allocation can succeed on 32-bit builds, e.g. with more 15647db96d56Sopenharmony_ci # than 2 GiB RAM and a 64-bit kernel. 15657db96d56Sopenharmony_ci if sys.maxsize > 0x7FFFFFFF: 15667db96d56Sopenharmony_ci rawio = self.MockRawIO() 15677db96d56Sopenharmony_ci bufio = self.tp(rawio) 15687db96d56Sopenharmony_ci self.assertRaises((OverflowError, MemoryError, ValueError), 15697db96d56Sopenharmony_ci bufio.__init__, rawio, sys.maxsize) 15707db96d56Sopenharmony_ci 15717db96d56Sopenharmony_ci def test_initialization(self): 15727db96d56Sopenharmony_ci rawio = self.MockRawIO([b"abc"]) 15737db96d56Sopenharmony_ci bufio = self.tp(rawio) 15747db96d56Sopenharmony_ci self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=0) 15757db96d56Sopenharmony_ci self.assertRaises(ValueError, bufio.read) 15767db96d56Sopenharmony_ci self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-16) 15777db96d56Sopenharmony_ci self.assertRaises(ValueError, bufio.read) 15787db96d56Sopenharmony_ci self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-1) 15797db96d56Sopenharmony_ci self.assertRaises(ValueError, bufio.read) 15807db96d56Sopenharmony_ci 15817db96d56Sopenharmony_ci def test_misbehaved_io_read(self): 15827db96d56Sopenharmony_ci rawio = self.MisbehavedRawIO((b"abc", b"d", b"efg")) 15837db96d56Sopenharmony_ci bufio = self.tp(rawio) 15847db96d56Sopenharmony_ci # _pyio.BufferedReader seems to implement reading different, so that 15857db96d56Sopenharmony_ci # checking this is not so easy. 15867db96d56Sopenharmony_ci self.assertRaises(OSError, bufio.read, 10) 15877db96d56Sopenharmony_ci 15887db96d56Sopenharmony_ci def test_garbage_collection(self): 15897db96d56Sopenharmony_ci # C BufferedReader objects are collected. 15907db96d56Sopenharmony_ci # The Python version has __del__, so it ends into gc.garbage instead 15917db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, os_helper.TESTFN) 15927db96d56Sopenharmony_ci with warnings_helper.check_warnings(('', ResourceWarning)): 15937db96d56Sopenharmony_ci rawio = self.FileIO(os_helper.TESTFN, "w+b") 15947db96d56Sopenharmony_ci f = self.tp(rawio) 15957db96d56Sopenharmony_ci f.f = f 15967db96d56Sopenharmony_ci wr = weakref.ref(f) 15977db96d56Sopenharmony_ci del f 15987db96d56Sopenharmony_ci support.gc_collect() 15997db96d56Sopenharmony_ci self.assertIsNone(wr(), wr) 16007db96d56Sopenharmony_ci 16017db96d56Sopenharmony_ci def test_args_error(self): 16027db96d56Sopenharmony_ci # Issue #17275 16037db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, "BufferedReader"): 16047db96d56Sopenharmony_ci self.tp(io.BytesIO(), 1024, 1024, 1024) 16057db96d56Sopenharmony_ci 16067db96d56Sopenharmony_ci def test_bad_readinto_value(self): 16077db96d56Sopenharmony_ci rawio = io.BufferedReader(io.BytesIO(b"12")) 16087db96d56Sopenharmony_ci rawio.readinto = lambda buf: -1 16097db96d56Sopenharmony_ci bufio = self.tp(rawio) 16107db96d56Sopenharmony_ci with self.assertRaises(OSError) as cm: 16117db96d56Sopenharmony_ci bufio.readline() 16127db96d56Sopenharmony_ci self.assertIsNone(cm.exception.__cause__) 16137db96d56Sopenharmony_ci 16147db96d56Sopenharmony_ci def test_bad_readinto_type(self): 16157db96d56Sopenharmony_ci rawio = io.BufferedReader(io.BytesIO(b"12")) 16167db96d56Sopenharmony_ci rawio.readinto = lambda buf: b'' 16177db96d56Sopenharmony_ci bufio = self.tp(rawio) 16187db96d56Sopenharmony_ci with self.assertRaises(OSError) as cm: 16197db96d56Sopenharmony_ci bufio.readline() 16207db96d56Sopenharmony_ci self.assertIsInstance(cm.exception.__cause__, TypeError) 16217db96d56Sopenharmony_ci 16227db96d56Sopenharmony_ci 16237db96d56Sopenharmony_ciclass PyBufferedReaderTest(BufferedReaderTest): 16247db96d56Sopenharmony_ci tp = pyio.BufferedReader 16257db96d56Sopenharmony_ci 16267db96d56Sopenharmony_ci 16277db96d56Sopenharmony_ciclass BufferedWriterTest(unittest.TestCase, CommonBufferedTests): 16287db96d56Sopenharmony_ci write_mode = "wb" 16297db96d56Sopenharmony_ci 16307db96d56Sopenharmony_ci def test_constructor(self): 16317db96d56Sopenharmony_ci rawio = self.MockRawIO() 16327db96d56Sopenharmony_ci bufio = self.tp(rawio) 16337db96d56Sopenharmony_ci bufio.__init__(rawio) 16347db96d56Sopenharmony_ci bufio.__init__(rawio, buffer_size=1024) 16357db96d56Sopenharmony_ci bufio.__init__(rawio, buffer_size=16) 16367db96d56Sopenharmony_ci self.assertEqual(3, bufio.write(b"abc")) 16377db96d56Sopenharmony_ci bufio.flush() 16387db96d56Sopenharmony_ci self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=0) 16397db96d56Sopenharmony_ci self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-16) 16407db96d56Sopenharmony_ci self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-1) 16417db96d56Sopenharmony_ci bufio.__init__(rawio) 16427db96d56Sopenharmony_ci self.assertEqual(3, bufio.write(b"ghi")) 16437db96d56Sopenharmony_ci bufio.flush() 16447db96d56Sopenharmony_ci self.assertEqual(b"".join(rawio._write_stack), b"abcghi") 16457db96d56Sopenharmony_ci 16467db96d56Sopenharmony_ci def test_uninitialized(self): 16477db96d56Sopenharmony_ci bufio = self.tp.__new__(self.tp) 16487db96d56Sopenharmony_ci del bufio 16497db96d56Sopenharmony_ci bufio = self.tp.__new__(self.tp) 16507db96d56Sopenharmony_ci self.assertRaisesRegex((ValueError, AttributeError), 16517db96d56Sopenharmony_ci 'uninitialized|has no attribute', 16527db96d56Sopenharmony_ci bufio.write, b'') 16537db96d56Sopenharmony_ci bufio.__init__(self.MockRawIO()) 16547db96d56Sopenharmony_ci self.assertEqual(bufio.write(b''), 0) 16557db96d56Sopenharmony_ci 16567db96d56Sopenharmony_ci def test_detach_flush(self): 16577db96d56Sopenharmony_ci raw = self.MockRawIO() 16587db96d56Sopenharmony_ci buf = self.tp(raw) 16597db96d56Sopenharmony_ci buf.write(b"howdy!") 16607db96d56Sopenharmony_ci self.assertFalse(raw._write_stack) 16617db96d56Sopenharmony_ci buf.detach() 16627db96d56Sopenharmony_ci self.assertEqual(raw._write_stack, [b"howdy!"]) 16637db96d56Sopenharmony_ci 16647db96d56Sopenharmony_ci def test_write(self): 16657db96d56Sopenharmony_ci # Write to the buffered IO but don't overflow the buffer. 16667db96d56Sopenharmony_ci writer = self.MockRawIO() 16677db96d56Sopenharmony_ci bufio = self.tp(writer, 8) 16687db96d56Sopenharmony_ci bufio.write(b"abc") 16697db96d56Sopenharmony_ci self.assertFalse(writer._write_stack) 16707db96d56Sopenharmony_ci buffer = bytearray(b"def") 16717db96d56Sopenharmony_ci bufio.write(buffer) 16727db96d56Sopenharmony_ci buffer[:] = b"***" # Overwrite our copy of the data 16737db96d56Sopenharmony_ci bufio.flush() 16747db96d56Sopenharmony_ci self.assertEqual(b"".join(writer._write_stack), b"abcdef") 16757db96d56Sopenharmony_ci 16767db96d56Sopenharmony_ci def test_write_overflow(self): 16777db96d56Sopenharmony_ci writer = self.MockRawIO() 16787db96d56Sopenharmony_ci bufio = self.tp(writer, 8) 16797db96d56Sopenharmony_ci contents = b"abcdefghijklmnop" 16807db96d56Sopenharmony_ci for n in range(0, len(contents), 3): 16817db96d56Sopenharmony_ci bufio.write(contents[n:n+3]) 16827db96d56Sopenharmony_ci flushed = b"".join(writer._write_stack) 16837db96d56Sopenharmony_ci # At least (total - 8) bytes were implicitly flushed, perhaps more 16847db96d56Sopenharmony_ci # depending on the implementation. 16857db96d56Sopenharmony_ci self.assertTrue(flushed.startswith(contents[:-8]), flushed) 16867db96d56Sopenharmony_ci 16877db96d56Sopenharmony_ci def check_writes(self, intermediate_func): 16887db96d56Sopenharmony_ci # Lots of writes, test the flushed output is as expected. 16897db96d56Sopenharmony_ci contents = bytes(range(256)) * 1000 16907db96d56Sopenharmony_ci n = 0 16917db96d56Sopenharmony_ci writer = self.MockRawIO() 16927db96d56Sopenharmony_ci bufio = self.tp(writer, 13) 16937db96d56Sopenharmony_ci # Generator of write sizes: repeat each N 15 times then proceed to N+1 16947db96d56Sopenharmony_ci def gen_sizes(): 16957db96d56Sopenharmony_ci for size in count(1): 16967db96d56Sopenharmony_ci for i in range(15): 16977db96d56Sopenharmony_ci yield size 16987db96d56Sopenharmony_ci sizes = gen_sizes() 16997db96d56Sopenharmony_ci while n < len(contents): 17007db96d56Sopenharmony_ci size = min(next(sizes), len(contents) - n) 17017db96d56Sopenharmony_ci self.assertEqual(bufio.write(contents[n:n+size]), size) 17027db96d56Sopenharmony_ci intermediate_func(bufio) 17037db96d56Sopenharmony_ci n += size 17047db96d56Sopenharmony_ci bufio.flush() 17057db96d56Sopenharmony_ci self.assertEqual(contents, b"".join(writer._write_stack)) 17067db96d56Sopenharmony_ci 17077db96d56Sopenharmony_ci def test_writes(self): 17087db96d56Sopenharmony_ci self.check_writes(lambda bufio: None) 17097db96d56Sopenharmony_ci 17107db96d56Sopenharmony_ci def test_writes_and_flushes(self): 17117db96d56Sopenharmony_ci self.check_writes(lambda bufio: bufio.flush()) 17127db96d56Sopenharmony_ci 17137db96d56Sopenharmony_ci def test_writes_and_seeks(self): 17147db96d56Sopenharmony_ci def _seekabs(bufio): 17157db96d56Sopenharmony_ci pos = bufio.tell() 17167db96d56Sopenharmony_ci bufio.seek(pos + 1, 0) 17177db96d56Sopenharmony_ci bufio.seek(pos - 1, 0) 17187db96d56Sopenharmony_ci bufio.seek(pos, 0) 17197db96d56Sopenharmony_ci self.check_writes(_seekabs) 17207db96d56Sopenharmony_ci def _seekrel(bufio): 17217db96d56Sopenharmony_ci pos = bufio.seek(0, 1) 17227db96d56Sopenharmony_ci bufio.seek(+1, 1) 17237db96d56Sopenharmony_ci bufio.seek(-1, 1) 17247db96d56Sopenharmony_ci bufio.seek(pos, 0) 17257db96d56Sopenharmony_ci self.check_writes(_seekrel) 17267db96d56Sopenharmony_ci 17277db96d56Sopenharmony_ci def test_writes_and_truncates(self): 17287db96d56Sopenharmony_ci self.check_writes(lambda bufio: bufio.truncate(bufio.tell())) 17297db96d56Sopenharmony_ci 17307db96d56Sopenharmony_ci def test_write_non_blocking(self): 17317db96d56Sopenharmony_ci raw = self.MockNonBlockWriterIO() 17327db96d56Sopenharmony_ci bufio = self.tp(raw, 8) 17337db96d56Sopenharmony_ci 17347db96d56Sopenharmony_ci self.assertEqual(bufio.write(b"abcd"), 4) 17357db96d56Sopenharmony_ci self.assertEqual(bufio.write(b"efghi"), 5) 17367db96d56Sopenharmony_ci # 1 byte will be written, the rest will be buffered 17377db96d56Sopenharmony_ci raw.block_on(b"k") 17387db96d56Sopenharmony_ci self.assertEqual(bufio.write(b"jklmn"), 5) 17397db96d56Sopenharmony_ci 17407db96d56Sopenharmony_ci # 8 bytes will be written, 8 will be buffered and the rest will be lost 17417db96d56Sopenharmony_ci raw.block_on(b"0") 17427db96d56Sopenharmony_ci try: 17437db96d56Sopenharmony_ci bufio.write(b"opqrwxyz0123456789") 17447db96d56Sopenharmony_ci except self.BlockingIOError as e: 17457db96d56Sopenharmony_ci written = e.characters_written 17467db96d56Sopenharmony_ci else: 17477db96d56Sopenharmony_ci self.fail("BlockingIOError should have been raised") 17487db96d56Sopenharmony_ci self.assertEqual(written, 16) 17497db96d56Sopenharmony_ci self.assertEqual(raw.pop_written(), 17507db96d56Sopenharmony_ci b"abcdefghijklmnopqrwxyz") 17517db96d56Sopenharmony_ci 17527db96d56Sopenharmony_ci self.assertEqual(bufio.write(b"ABCDEFGHI"), 9) 17537db96d56Sopenharmony_ci s = raw.pop_written() 17547db96d56Sopenharmony_ci # Previously buffered bytes were flushed 17557db96d56Sopenharmony_ci self.assertTrue(s.startswith(b"01234567A"), s) 17567db96d56Sopenharmony_ci 17577db96d56Sopenharmony_ci def test_write_and_rewind(self): 17587db96d56Sopenharmony_ci raw = io.BytesIO() 17597db96d56Sopenharmony_ci bufio = self.tp(raw, 4) 17607db96d56Sopenharmony_ci self.assertEqual(bufio.write(b"abcdef"), 6) 17617db96d56Sopenharmony_ci self.assertEqual(bufio.tell(), 6) 17627db96d56Sopenharmony_ci bufio.seek(0, 0) 17637db96d56Sopenharmony_ci self.assertEqual(bufio.write(b"XY"), 2) 17647db96d56Sopenharmony_ci bufio.seek(6, 0) 17657db96d56Sopenharmony_ci self.assertEqual(raw.getvalue(), b"XYcdef") 17667db96d56Sopenharmony_ci self.assertEqual(bufio.write(b"123456"), 6) 17677db96d56Sopenharmony_ci bufio.flush() 17687db96d56Sopenharmony_ci self.assertEqual(raw.getvalue(), b"XYcdef123456") 17697db96d56Sopenharmony_ci 17707db96d56Sopenharmony_ci def test_flush(self): 17717db96d56Sopenharmony_ci writer = self.MockRawIO() 17727db96d56Sopenharmony_ci bufio = self.tp(writer, 8) 17737db96d56Sopenharmony_ci bufio.write(b"abc") 17747db96d56Sopenharmony_ci bufio.flush() 17757db96d56Sopenharmony_ci self.assertEqual(b"abc", writer._write_stack[0]) 17767db96d56Sopenharmony_ci 17777db96d56Sopenharmony_ci def test_writelines(self): 17787db96d56Sopenharmony_ci l = [b'ab', b'cd', b'ef'] 17797db96d56Sopenharmony_ci writer = self.MockRawIO() 17807db96d56Sopenharmony_ci bufio = self.tp(writer, 8) 17817db96d56Sopenharmony_ci bufio.writelines(l) 17827db96d56Sopenharmony_ci bufio.flush() 17837db96d56Sopenharmony_ci self.assertEqual(b''.join(writer._write_stack), b'abcdef') 17847db96d56Sopenharmony_ci 17857db96d56Sopenharmony_ci def test_writelines_userlist(self): 17867db96d56Sopenharmony_ci l = UserList([b'ab', b'cd', b'ef']) 17877db96d56Sopenharmony_ci writer = self.MockRawIO() 17887db96d56Sopenharmony_ci bufio = self.tp(writer, 8) 17897db96d56Sopenharmony_ci bufio.writelines(l) 17907db96d56Sopenharmony_ci bufio.flush() 17917db96d56Sopenharmony_ci self.assertEqual(b''.join(writer._write_stack), b'abcdef') 17927db96d56Sopenharmony_ci 17937db96d56Sopenharmony_ci def test_writelines_error(self): 17947db96d56Sopenharmony_ci writer = self.MockRawIO() 17957db96d56Sopenharmony_ci bufio = self.tp(writer, 8) 17967db96d56Sopenharmony_ci self.assertRaises(TypeError, bufio.writelines, [1, 2, 3]) 17977db96d56Sopenharmony_ci self.assertRaises(TypeError, bufio.writelines, None) 17987db96d56Sopenharmony_ci self.assertRaises(TypeError, bufio.writelines, 'abc') 17997db96d56Sopenharmony_ci 18007db96d56Sopenharmony_ci def test_destructor(self): 18017db96d56Sopenharmony_ci writer = self.MockRawIO() 18027db96d56Sopenharmony_ci bufio = self.tp(writer, 8) 18037db96d56Sopenharmony_ci bufio.write(b"abc") 18047db96d56Sopenharmony_ci del bufio 18057db96d56Sopenharmony_ci support.gc_collect() 18067db96d56Sopenharmony_ci self.assertEqual(b"abc", writer._write_stack[0]) 18077db96d56Sopenharmony_ci 18087db96d56Sopenharmony_ci def test_truncate(self): 18097db96d56Sopenharmony_ci # Truncate implicitly flushes the buffer. 18107db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, os_helper.TESTFN) 18117db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, self.write_mode, buffering=0) as raw: 18127db96d56Sopenharmony_ci bufio = self.tp(raw, 8) 18137db96d56Sopenharmony_ci bufio.write(b"abcdef") 18147db96d56Sopenharmony_ci self.assertEqual(bufio.truncate(3), 3) 18157db96d56Sopenharmony_ci self.assertEqual(bufio.tell(), 6) 18167db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "rb", buffering=0) as f: 18177db96d56Sopenharmony_ci self.assertEqual(f.read(), b"abc") 18187db96d56Sopenharmony_ci 18197db96d56Sopenharmony_ci def test_truncate_after_write(self): 18207db96d56Sopenharmony_ci # Ensure that truncate preserves the file position after 18217db96d56Sopenharmony_ci # writes longer than the buffer size. 18227db96d56Sopenharmony_ci # Issue: https://bugs.python.org/issue32228 18237db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, os_helper.TESTFN) 18247db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "wb") as f: 18257db96d56Sopenharmony_ci # Fill with some buffer 18267db96d56Sopenharmony_ci f.write(b'\x00' * 10000) 18277db96d56Sopenharmony_ci buffer_sizes = [8192, 4096, 200] 18287db96d56Sopenharmony_ci for buffer_size in buffer_sizes: 18297db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "r+b", buffering=buffer_size) as f: 18307db96d56Sopenharmony_ci f.write(b'\x00' * (buffer_size + 1)) 18317db96d56Sopenharmony_ci # After write write_pos and write_end are set to 0 18327db96d56Sopenharmony_ci f.read(1) 18337db96d56Sopenharmony_ci # read operation makes sure that pos != raw_pos 18347db96d56Sopenharmony_ci f.truncate() 18357db96d56Sopenharmony_ci self.assertEqual(f.tell(), buffer_size + 2) 18367db96d56Sopenharmony_ci 18377db96d56Sopenharmony_ci @support.requires_resource('cpu') 18387db96d56Sopenharmony_ci @threading_helper.requires_working_threading() 18397db96d56Sopenharmony_ci def test_threads(self): 18407db96d56Sopenharmony_ci try: 18417db96d56Sopenharmony_ci # Write out many bytes from many threads and test they were 18427db96d56Sopenharmony_ci # all flushed. 18437db96d56Sopenharmony_ci N = 1000 18447db96d56Sopenharmony_ci contents = bytes(range(256)) * N 18457db96d56Sopenharmony_ci sizes = cycle([1, 19]) 18467db96d56Sopenharmony_ci n = 0 18477db96d56Sopenharmony_ci queue = deque() 18487db96d56Sopenharmony_ci while n < len(contents): 18497db96d56Sopenharmony_ci size = next(sizes) 18507db96d56Sopenharmony_ci queue.append(contents[n:n+size]) 18517db96d56Sopenharmony_ci n += size 18527db96d56Sopenharmony_ci del contents 18537db96d56Sopenharmony_ci # We use a real file object because it allows us to 18547db96d56Sopenharmony_ci # exercise situations where the GIL is released before 18557db96d56Sopenharmony_ci # writing the buffer to the raw streams. This is in addition 18567db96d56Sopenharmony_ci # to concurrency issues due to switching threads in the middle 18577db96d56Sopenharmony_ci # of Python code. 18587db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, self.write_mode, buffering=0) as raw: 18597db96d56Sopenharmony_ci bufio = self.tp(raw, 8) 18607db96d56Sopenharmony_ci errors = [] 18617db96d56Sopenharmony_ci def f(): 18627db96d56Sopenharmony_ci try: 18637db96d56Sopenharmony_ci while True: 18647db96d56Sopenharmony_ci try: 18657db96d56Sopenharmony_ci s = queue.popleft() 18667db96d56Sopenharmony_ci except IndexError: 18677db96d56Sopenharmony_ci return 18687db96d56Sopenharmony_ci bufio.write(s) 18697db96d56Sopenharmony_ci except Exception as e: 18707db96d56Sopenharmony_ci errors.append(e) 18717db96d56Sopenharmony_ci raise 18727db96d56Sopenharmony_ci threads = [threading.Thread(target=f) for x in range(20)] 18737db96d56Sopenharmony_ci with threading_helper.start_threads(threads): 18747db96d56Sopenharmony_ci time.sleep(0.02) # yield 18757db96d56Sopenharmony_ci self.assertFalse(errors, 18767db96d56Sopenharmony_ci "the following exceptions were caught: %r" % errors) 18777db96d56Sopenharmony_ci bufio.close() 18787db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "rb") as f: 18797db96d56Sopenharmony_ci s = f.read() 18807db96d56Sopenharmony_ci for i in range(256): 18817db96d56Sopenharmony_ci self.assertEqual(s.count(bytes([i])), N) 18827db96d56Sopenharmony_ci finally: 18837db96d56Sopenharmony_ci os_helper.unlink(os_helper.TESTFN) 18847db96d56Sopenharmony_ci 18857db96d56Sopenharmony_ci def test_misbehaved_io(self): 18867db96d56Sopenharmony_ci rawio = self.MisbehavedRawIO() 18877db96d56Sopenharmony_ci bufio = self.tp(rawio, 5) 18887db96d56Sopenharmony_ci self.assertRaises(OSError, bufio.seek, 0) 18897db96d56Sopenharmony_ci self.assertRaises(OSError, bufio.tell) 18907db96d56Sopenharmony_ci self.assertRaises(OSError, bufio.write, b"abcdef") 18917db96d56Sopenharmony_ci 18927db96d56Sopenharmony_ci # Silence destructor error 18937db96d56Sopenharmony_ci bufio.close = lambda: None 18947db96d56Sopenharmony_ci 18957db96d56Sopenharmony_ci def test_max_buffer_size_removal(self): 18967db96d56Sopenharmony_ci with self.assertRaises(TypeError): 18977db96d56Sopenharmony_ci self.tp(self.MockRawIO(), 8, 12) 18987db96d56Sopenharmony_ci 18997db96d56Sopenharmony_ci def test_write_error_on_close(self): 19007db96d56Sopenharmony_ci raw = self.MockRawIO() 19017db96d56Sopenharmony_ci def bad_write(b): 19027db96d56Sopenharmony_ci raise OSError() 19037db96d56Sopenharmony_ci raw.write = bad_write 19047db96d56Sopenharmony_ci b = self.tp(raw) 19057db96d56Sopenharmony_ci b.write(b'spam') 19067db96d56Sopenharmony_ci self.assertRaises(OSError, b.close) # exception not swallowed 19077db96d56Sopenharmony_ci self.assertTrue(b.closed) 19087db96d56Sopenharmony_ci 19097db96d56Sopenharmony_ci @threading_helper.requires_working_threading() 19107db96d56Sopenharmony_ci def test_slow_close_from_thread(self): 19117db96d56Sopenharmony_ci # Issue #31976 19127db96d56Sopenharmony_ci rawio = self.SlowFlushRawIO() 19137db96d56Sopenharmony_ci bufio = self.tp(rawio, 8) 19147db96d56Sopenharmony_ci t = threading.Thread(target=bufio.close) 19157db96d56Sopenharmony_ci t.start() 19167db96d56Sopenharmony_ci rawio.in_flush.wait() 19177db96d56Sopenharmony_ci self.assertRaises(ValueError, bufio.write, b'spam') 19187db96d56Sopenharmony_ci self.assertTrue(bufio.closed) 19197db96d56Sopenharmony_ci t.join() 19207db96d56Sopenharmony_ci 19217db96d56Sopenharmony_ci 19227db96d56Sopenharmony_ci 19237db96d56Sopenharmony_ciclass CBufferedWriterTest(BufferedWriterTest, SizeofTest): 19247db96d56Sopenharmony_ci tp = io.BufferedWriter 19257db96d56Sopenharmony_ci 19267db96d56Sopenharmony_ci @skip_if_sanitizer(memory=True, address=True, reason= "sanitizer defaults to crashing " 19277db96d56Sopenharmony_ci "instead of returning NULL for malloc failure.") 19287db96d56Sopenharmony_ci def test_constructor(self): 19297db96d56Sopenharmony_ci BufferedWriterTest.test_constructor(self) 19307db96d56Sopenharmony_ci # The allocation can succeed on 32-bit builds, e.g. with more 19317db96d56Sopenharmony_ci # than 2 GiB RAM and a 64-bit kernel. 19327db96d56Sopenharmony_ci if sys.maxsize > 0x7FFFFFFF: 19337db96d56Sopenharmony_ci rawio = self.MockRawIO() 19347db96d56Sopenharmony_ci bufio = self.tp(rawio) 19357db96d56Sopenharmony_ci self.assertRaises((OverflowError, MemoryError, ValueError), 19367db96d56Sopenharmony_ci bufio.__init__, rawio, sys.maxsize) 19377db96d56Sopenharmony_ci 19387db96d56Sopenharmony_ci def test_initialization(self): 19397db96d56Sopenharmony_ci rawio = self.MockRawIO() 19407db96d56Sopenharmony_ci bufio = self.tp(rawio) 19417db96d56Sopenharmony_ci self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=0) 19427db96d56Sopenharmony_ci self.assertRaises(ValueError, bufio.write, b"def") 19437db96d56Sopenharmony_ci self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-16) 19447db96d56Sopenharmony_ci self.assertRaises(ValueError, bufio.write, b"def") 19457db96d56Sopenharmony_ci self.assertRaises(ValueError, bufio.__init__, rawio, buffer_size=-1) 19467db96d56Sopenharmony_ci self.assertRaises(ValueError, bufio.write, b"def") 19477db96d56Sopenharmony_ci 19487db96d56Sopenharmony_ci def test_garbage_collection(self): 19497db96d56Sopenharmony_ci # C BufferedWriter objects are collected, and collecting them flushes 19507db96d56Sopenharmony_ci # all data to disk. 19517db96d56Sopenharmony_ci # The Python version has __del__, so it ends into gc.garbage instead 19527db96d56Sopenharmony_ci self.addCleanup(os_helper.unlink, os_helper.TESTFN) 19537db96d56Sopenharmony_ci with warnings_helper.check_warnings(('', ResourceWarning)): 19547db96d56Sopenharmony_ci rawio = self.FileIO(os_helper.TESTFN, "w+b") 19557db96d56Sopenharmony_ci f = self.tp(rawio) 19567db96d56Sopenharmony_ci f.write(b"123xxx") 19577db96d56Sopenharmony_ci f.x = f 19587db96d56Sopenharmony_ci wr = weakref.ref(f) 19597db96d56Sopenharmony_ci del f 19607db96d56Sopenharmony_ci support.gc_collect() 19617db96d56Sopenharmony_ci self.assertIsNone(wr(), wr) 19627db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "rb") as f: 19637db96d56Sopenharmony_ci self.assertEqual(f.read(), b"123xxx") 19647db96d56Sopenharmony_ci 19657db96d56Sopenharmony_ci def test_args_error(self): 19667db96d56Sopenharmony_ci # Issue #17275 19677db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, "BufferedWriter"): 19687db96d56Sopenharmony_ci self.tp(io.BytesIO(), 1024, 1024, 1024) 19697db96d56Sopenharmony_ci 19707db96d56Sopenharmony_ci 19717db96d56Sopenharmony_ciclass PyBufferedWriterTest(BufferedWriterTest): 19727db96d56Sopenharmony_ci tp = pyio.BufferedWriter 19737db96d56Sopenharmony_ci 19747db96d56Sopenharmony_ciclass BufferedRWPairTest(unittest.TestCase): 19757db96d56Sopenharmony_ci 19767db96d56Sopenharmony_ci def test_constructor(self): 19777db96d56Sopenharmony_ci pair = self.tp(self.MockRawIO(), self.MockRawIO()) 19787db96d56Sopenharmony_ci self.assertFalse(pair.closed) 19797db96d56Sopenharmony_ci 19807db96d56Sopenharmony_ci def test_uninitialized(self): 19817db96d56Sopenharmony_ci pair = self.tp.__new__(self.tp) 19827db96d56Sopenharmony_ci del pair 19837db96d56Sopenharmony_ci pair = self.tp.__new__(self.tp) 19847db96d56Sopenharmony_ci self.assertRaisesRegex((ValueError, AttributeError), 19857db96d56Sopenharmony_ci 'uninitialized|has no attribute', 19867db96d56Sopenharmony_ci pair.read, 0) 19877db96d56Sopenharmony_ci self.assertRaisesRegex((ValueError, AttributeError), 19887db96d56Sopenharmony_ci 'uninitialized|has no attribute', 19897db96d56Sopenharmony_ci pair.write, b'') 19907db96d56Sopenharmony_ci pair.__init__(self.MockRawIO(), self.MockRawIO()) 19917db96d56Sopenharmony_ci self.assertEqual(pair.read(0), b'') 19927db96d56Sopenharmony_ci self.assertEqual(pair.write(b''), 0) 19937db96d56Sopenharmony_ci 19947db96d56Sopenharmony_ci def test_detach(self): 19957db96d56Sopenharmony_ci pair = self.tp(self.MockRawIO(), self.MockRawIO()) 19967db96d56Sopenharmony_ci self.assertRaises(self.UnsupportedOperation, pair.detach) 19977db96d56Sopenharmony_ci 19987db96d56Sopenharmony_ci def test_constructor_max_buffer_size_removal(self): 19997db96d56Sopenharmony_ci with self.assertRaises(TypeError): 20007db96d56Sopenharmony_ci self.tp(self.MockRawIO(), self.MockRawIO(), 8, 12) 20017db96d56Sopenharmony_ci 20027db96d56Sopenharmony_ci def test_constructor_with_not_readable(self): 20037db96d56Sopenharmony_ci class NotReadable(MockRawIO): 20047db96d56Sopenharmony_ci def readable(self): 20057db96d56Sopenharmony_ci return False 20067db96d56Sopenharmony_ci 20077db96d56Sopenharmony_ci self.assertRaises(OSError, self.tp, NotReadable(), self.MockRawIO()) 20087db96d56Sopenharmony_ci 20097db96d56Sopenharmony_ci def test_constructor_with_not_writeable(self): 20107db96d56Sopenharmony_ci class NotWriteable(MockRawIO): 20117db96d56Sopenharmony_ci def writable(self): 20127db96d56Sopenharmony_ci return False 20137db96d56Sopenharmony_ci 20147db96d56Sopenharmony_ci self.assertRaises(OSError, self.tp, self.MockRawIO(), NotWriteable()) 20157db96d56Sopenharmony_ci 20167db96d56Sopenharmony_ci def test_read(self): 20177db96d56Sopenharmony_ci pair = self.tp(self.BytesIO(b"abcdef"), self.MockRawIO()) 20187db96d56Sopenharmony_ci 20197db96d56Sopenharmony_ci self.assertEqual(pair.read(3), b"abc") 20207db96d56Sopenharmony_ci self.assertEqual(pair.read(1), b"d") 20217db96d56Sopenharmony_ci self.assertEqual(pair.read(), b"ef") 20227db96d56Sopenharmony_ci pair = self.tp(self.BytesIO(b"abc"), self.MockRawIO()) 20237db96d56Sopenharmony_ci self.assertEqual(pair.read(None), b"abc") 20247db96d56Sopenharmony_ci 20257db96d56Sopenharmony_ci def test_readlines(self): 20267db96d56Sopenharmony_ci pair = lambda: self.tp(self.BytesIO(b"abc\ndef\nh"), self.MockRawIO()) 20277db96d56Sopenharmony_ci self.assertEqual(pair().readlines(), [b"abc\n", b"def\n", b"h"]) 20287db96d56Sopenharmony_ci self.assertEqual(pair().readlines(), [b"abc\n", b"def\n", b"h"]) 20297db96d56Sopenharmony_ci self.assertEqual(pair().readlines(5), [b"abc\n", b"def\n"]) 20307db96d56Sopenharmony_ci 20317db96d56Sopenharmony_ci def test_read1(self): 20327db96d56Sopenharmony_ci # .read1() is delegated to the underlying reader object, so this test 20337db96d56Sopenharmony_ci # can be shallow. 20347db96d56Sopenharmony_ci pair = self.tp(self.BytesIO(b"abcdef"), self.MockRawIO()) 20357db96d56Sopenharmony_ci 20367db96d56Sopenharmony_ci self.assertEqual(pair.read1(3), b"abc") 20377db96d56Sopenharmony_ci self.assertEqual(pair.read1(), b"def") 20387db96d56Sopenharmony_ci 20397db96d56Sopenharmony_ci def test_readinto(self): 20407db96d56Sopenharmony_ci for method in ("readinto", "readinto1"): 20417db96d56Sopenharmony_ci with self.subTest(method): 20427db96d56Sopenharmony_ci pair = self.tp(self.BytesIO(b"abcdef"), self.MockRawIO()) 20437db96d56Sopenharmony_ci 20447db96d56Sopenharmony_ci data = byteslike(b'\0' * 5) 20457db96d56Sopenharmony_ci self.assertEqual(getattr(pair, method)(data), 5) 20467db96d56Sopenharmony_ci self.assertEqual(bytes(data), b"abcde") 20477db96d56Sopenharmony_ci 20487db96d56Sopenharmony_ci def test_write(self): 20497db96d56Sopenharmony_ci w = self.MockRawIO() 20507db96d56Sopenharmony_ci pair = self.tp(self.MockRawIO(), w) 20517db96d56Sopenharmony_ci 20527db96d56Sopenharmony_ci pair.write(b"abc") 20537db96d56Sopenharmony_ci pair.flush() 20547db96d56Sopenharmony_ci buffer = bytearray(b"def") 20557db96d56Sopenharmony_ci pair.write(buffer) 20567db96d56Sopenharmony_ci buffer[:] = b"***" # Overwrite our copy of the data 20577db96d56Sopenharmony_ci pair.flush() 20587db96d56Sopenharmony_ci self.assertEqual(w._write_stack, [b"abc", b"def"]) 20597db96d56Sopenharmony_ci 20607db96d56Sopenharmony_ci def test_peek(self): 20617db96d56Sopenharmony_ci pair = self.tp(self.BytesIO(b"abcdef"), self.MockRawIO()) 20627db96d56Sopenharmony_ci 20637db96d56Sopenharmony_ci self.assertTrue(pair.peek(3).startswith(b"abc")) 20647db96d56Sopenharmony_ci self.assertEqual(pair.read(3), b"abc") 20657db96d56Sopenharmony_ci 20667db96d56Sopenharmony_ci def test_readable(self): 20677db96d56Sopenharmony_ci pair = self.tp(self.MockRawIO(), self.MockRawIO()) 20687db96d56Sopenharmony_ci self.assertTrue(pair.readable()) 20697db96d56Sopenharmony_ci 20707db96d56Sopenharmony_ci def test_writeable(self): 20717db96d56Sopenharmony_ci pair = self.tp(self.MockRawIO(), self.MockRawIO()) 20727db96d56Sopenharmony_ci self.assertTrue(pair.writable()) 20737db96d56Sopenharmony_ci 20747db96d56Sopenharmony_ci def test_seekable(self): 20757db96d56Sopenharmony_ci # BufferedRWPairs are never seekable, even if their readers and writers 20767db96d56Sopenharmony_ci # are. 20777db96d56Sopenharmony_ci pair = self.tp(self.MockRawIO(), self.MockRawIO()) 20787db96d56Sopenharmony_ci self.assertFalse(pair.seekable()) 20797db96d56Sopenharmony_ci 20807db96d56Sopenharmony_ci # .flush() is delegated to the underlying writer object and has been 20817db96d56Sopenharmony_ci # tested in the test_write method. 20827db96d56Sopenharmony_ci 20837db96d56Sopenharmony_ci def test_close_and_closed(self): 20847db96d56Sopenharmony_ci pair = self.tp(self.MockRawIO(), self.MockRawIO()) 20857db96d56Sopenharmony_ci self.assertFalse(pair.closed) 20867db96d56Sopenharmony_ci pair.close() 20877db96d56Sopenharmony_ci self.assertTrue(pair.closed) 20887db96d56Sopenharmony_ci 20897db96d56Sopenharmony_ci def test_reader_close_error_on_close(self): 20907db96d56Sopenharmony_ci def reader_close(): 20917db96d56Sopenharmony_ci reader_non_existing 20927db96d56Sopenharmony_ci reader = self.MockRawIO() 20937db96d56Sopenharmony_ci reader.close = reader_close 20947db96d56Sopenharmony_ci writer = self.MockRawIO() 20957db96d56Sopenharmony_ci pair = self.tp(reader, writer) 20967db96d56Sopenharmony_ci with self.assertRaises(NameError) as err: 20977db96d56Sopenharmony_ci pair.close() 20987db96d56Sopenharmony_ci self.assertIn('reader_non_existing', str(err.exception)) 20997db96d56Sopenharmony_ci self.assertTrue(pair.closed) 21007db96d56Sopenharmony_ci self.assertFalse(reader.closed) 21017db96d56Sopenharmony_ci self.assertTrue(writer.closed) 21027db96d56Sopenharmony_ci 21037db96d56Sopenharmony_ci # Silence destructor error 21047db96d56Sopenharmony_ci reader.close = lambda: None 21057db96d56Sopenharmony_ci 21067db96d56Sopenharmony_ci def test_writer_close_error_on_close(self): 21077db96d56Sopenharmony_ci def writer_close(): 21087db96d56Sopenharmony_ci writer_non_existing 21097db96d56Sopenharmony_ci reader = self.MockRawIO() 21107db96d56Sopenharmony_ci writer = self.MockRawIO() 21117db96d56Sopenharmony_ci writer.close = writer_close 21127db96d56Sopenharmony_ci pair = self.tp(reader, writer) 21137db96d56Sopenharmony_ci with self.assertRaises(NameError) as err: 21147db96d56Sopenharmony_ci pair.close() 21157db96d56Sopenharmony_ci self.assertIn('writer_non_existing', str(err.exception)) 21167db96d56Sopenharmony_ci self.assertFalse(pair.closed) 21177db96d56Sopenharmony_ci self.assertTrue(reader.closed) 21187db96d56Sopenharmony_ci self.assertFalse(writer.closed) 21197db96d56Sopenharmony_ci 21207db96d56Sopenharmony_ci # Silence destructor error 21217db96d56Sopenharmony_ci writer.close = lambda: None 21227db96d56Sopenharmony_ci writer = None 21237db96d56Sopenharmony_ci 21247db96d56Sopenharmony_ci # Ignore BufferedWriter (of the BufferedRWPair) unraisable exception 21257db96d56Sopenharmony_ci with support.catch_unraisable_exception(): 21267db96d56Sopenharmony_ci # Ignore BufferedRWPair unraisable exception 21277db96d56Sopenharmony_ci with support.catch_unraisable_exception(): 21287db96d56Sopenharmony_ci pair = None 21297db96d56Sopenharmony_ci support.gc_collect() 21307db96d56Sopenharmony_ci support.gc_collect() 21317db96d56Sopenharmony_ci 21327db96d56Sopenharmony_ci def test_reader_writer_close_error_on_close(self): 21337db96d56Sopenharmony_ci def reader_close(): 21347db96d56Sopenharmony_ci reader_non_existing 21357db96d56Sopenharmony_ci def writer_close(): 21367db96d56Sopenharmony_ci writer_non_existing 21377db96d56Sopenharmony_ci reader = self.MockRawIO() 21387db96d56Sopenharmony_ci reader.close = reader_close 21397db96d56Sopenharmony_ci writer = self.MockRawIO() 21407db96d56Sopenharmony_ci writer.close = writer_close 21417db96d56Sopenharmony_ci pair = self.tp(reader, writer) 21427db96d56Sopenharmony_ci with self.assertRaises(NameError) as err: 21437db96d56Sopenharmony_ci pair.close() 21447db96d56Sopenharmony_ci self.assertIn('reader_non_existing', str(err.exception)) 21457db96d56Sopenharmony_ci self.assertIsInstance(err.exception.__context__, NameError) 21467db96d56Sopenharmony_ci self.assertIn('writer_non_existing', str(err.exception.__context__)) 21477db96d56Sopenharmony_ci self.assertFalse(pair.closed) 21487db96d56Sopenharmony_ci self.assertFalse(reader.closed) 21497db96d56Sopenharmony_ci self.assertFalse(writer.closed) 21507db96d56Sopenharmony_ci 21517db96d56Sopenharmony_ci # Silence destructor error 21527db96d56Sopenharmony_ci reader.close = lambda: None 21537db96d56Sopenharmony_ci writer.close = lambda: None 21547db96d56Sopenharmony_ci 21557db96d56Sopenharmony_ci def test_isatty(self): 21567db96d56Sopenharmony_ci class SelectableIsAtty(MockRawIO): 21577db96d56Sopenharmony_ci def __init__(self, isatty): 21587db96d56Sopenharmony_ci MockRawIO.__init__(self) 21597db96d56Sopenharmony_ci self._isatty = isatty 21607db96d56Sopenharmony_ci 21617db96d56Sopenharmony_ci def isatty(self): 21627db96d56Sopenharmony_ci return self._isatty 21637db96d56Sopenharmony_ci 21647db96d56Sopenharmony_ci pair = self.tp(SelectableIsAtty(False), SelectableIsAtty(False)) 21657db96d56Sopenharmony_ci self.assertFalse(pair.isatty()) 21667db96d56Sopenharmony_ci 21677db96d56Sopenharmony_ci pair = self.tp(SelectableIsAtty(True), SelectableIsAtty(False)) 21687db96d56Sopenharmony_ci self.assertTrue(pair.isatty()) 21697db96d56Sopenharmony_ci 21707db96d56Sopenharmony_ci pair = self.tp(SelectableIsAtty(False), SelectableIsAtty(True)) 21717db96d56Sopenharmony_ci self.assertTrue(pair.isatty()) 21727db96d56Sopenharmony_ci 21737db96d56Sopenharmony_ci pair = self.tp(SelectableIsAtty(True), SelectableIsAtty(True)) 21747db96d56Sopenharmony_ci self.assertTrue(pair.isatty()) 21757db96d56Sopenharmony_ci 21767db96d56Sopenharmony_ci def test_weakref_clearing(self): 21777db96d56Sopenharmony_ci brw = self.tp(self.MockRawIO(), self.MockRawIO()) 21787db96d56Sopenharmony_ci ref = weakref.ref(brw) 21797db96d56Sopenharmony_ci brw = None 21807db96d56Sopenharmony_ci ref = None # Shouldn't segfault. 21817db96d56Sopenharmony_ci 21827db96d56Sopenharmony_ciclass CBufferedRWPairTest(BufferedRWPairTest): 21837db96d56Sopenharmony_ci tp = io.BufferedRWPair 21847db96d56Sopenharmony_ci 21857db96d56Sopenharmony_ciclass PyBufferedRWPairTest(BufferedRWPairTest): 21867db96d56Sopenharmony_ci tp = pyio.BufferedRWPair 21877db96d56Sopenharmony_ci 21887db96d56Sopenharmony_ci 21897db96d56Sopenharmony_ciclass BufferedRandomTest(BufferedReaderTest, BufferedWriterTest): 21907db96d56Sopenharmony_ci read_mode = "rb+" 21917db96d56Sopenharmony_ci write_mode = "wb+" 21927db96d56Sopenharmony_ci 21937db96d56Sopenharmony_ci def test_constructor(self): 21947db96d56Sopenharmony_ci BufferedReaderTest.test_constructor(self) 21957db96d56Sopenharmony_ci BufferedWriterTest.test_constructor(self) 21967db96d56Sopenharmony_ci 21977db96d56Sopenharmony_ci def test_uninitialized(self): 21987db96d56Sopenharmony_ci BufferedReaderTest.test_uninitialized(self) 21997db96d56Sopenharmony_ci BufferedWriterTest.test_uninitialized(self) 22007db96d56Sopenharmony_ci 22017db96d56Sopenharmony_ci def test_read_and_write(self): 22027db96d56Sopenharmony_ci raw = self.MockRawIO((b"asdf", b"ghjk")) 22037db96d56Sopenharmony_ci rw = self.tp(raw, 8) 22047db96d56Sopenharmony_ci 22057db96d56Sopenharmony_ci self.assertEqual(b"as", rw.read(2)) 22067db96d56Sopenharmony_ci rw.write(b"ddd") 22077db96d56Sopenharmony_ci rw.write(b"eee") 22087db96d56Sopenharmony_ci self.assertFalse(raw._write_stack) # Buffer writes 22097db96d56Sopenharmony_ci self.assertEqual(b"ghjk", rw.read()) 22107db96d56Sopenharmony_ci self.assertEqual(b"dddeee", raw._write_stack[0]) 22117db96d56Sopenharmony_ci 22127db96d56Sopenharmony_ci def test_seek_and_tell(self): 22137db96d56Sopenharmony_ci raw = self.BytesIO(b"asdfghjkl") 22147db96d56Sopenharmony_ci rw = self.tp(raw) 22157db96d56Sopenharmony_ci 22167db96d56Sopenharmony_ci self.assertEqual(b"as", rw.read(2)) 22177db96d56Sopenharmony_ci self.assertEqual(2, rw.tell()) 22187db96d56Sopenharmony_ci rw.seek(0, 0) 22197db96d56Sopenharmony_ci self.assertEqual(b"asdf", rw.read(4)) 22207db96d56Sopenharmony_ci 22217db96d56Sopenharmony_ci rw.write(b"123f") 22227db96d56Sopenharmony_ci rw.seek(0, 0) 22237db96d56Sopenharmony_ci self.assertEqual(b"asdf123fl", rw.read()) 22247db96d56Sopenharmony_ci self.assertEqual(9, rw.tell()) 22257db96d56Sopenharmony_ci rw.seek(-4, 2) 22267db96d56Sopenharmony_ci self.assertEqual(5, rw.tell()) 22277db96d56Sopenharmony_ci rw.seek(2, 1) 22287db96d56Sopenharmony_ci self.assertEqual(7, rw.tell()) 22297db96d56Sopenharmony_ci self.assertEqual(b"fl", rw.read(11)) 22307db96d56Sopenharmony_ci rw.flush() 22317db96d56Sopenharmony_ci self.assertEqual(b"asdf123fl", raw.getvalue()) 22327db96d56Sopenharmony_ci 22337db96d56Sopenharmony_ci self.assertRaises(TypeError, rw.seek, 0.0) 22347db96d56Sopenharmony_ci 22357db96d56Sopenharmony_ci def check_flush_and_read(self, read_func): 22367db96d56Sopenharmony_ci raw = self.BytesIO(b"abcdefghi") 22377db96d56Sopenharmony_ci bufio = self.tp(raw) 22387db96d56Sopenharmony_ci 22397db96d56Sopenharmony_ci self.assertEqual(b"ab", read_func(bufio, 2)) 22407db96d56Sopenharmony_ci bufio.write(b"12") 22417db96d56Sopenharmony_ci self.assertEqual(b"ef", read_func(bufio, 2)) 22427db96d56Sopenharmony_ci self.assertEqual(6, bufio.tell()) 22437db96d56Sopenharmony_ci bufio.flush() 22447db96d56Sopenharmony_ci self.assertEqual(6, bufio.tell()) 22457db96d56Sopenharmony_ci self.assertEqual(b"ghi", read_func(bufio)) 22467db96d56Sopenharmony_ci raw.seek(0, 0) 22477db96d56Sopenharmony_ci raw.write(b"XYZ") 22487db96d56Sopenharmony_ci # flush() resets the read buffer 22497db96d56Sopenharmony_ci bufio.flush() 22507db96d56Sopenharmony_ci bufio.seek(0, 0) 22517db96d56Sopenharmony_ci self.assertEqual(b"XYZ", read_func(bufio, 3)) 22527db96d56Sopenharmony_ci 22537db96d56Sopenharmony_ci def test_flush_and_read(self): 22547db96d56Sopenharmony_ci self.check_flush_and_read(lambda bufio, *args: bufio.read(*args)) 22557db96d56Sopenharmony_ci 22567db96d56Sopenharmony_ci def test_flush_and_readinto(self): 22577db96d56Sopenharmony_ci def _readinto(bufio, n=-1): 22587db96d56Sopenharmony_ci b = bytearray(n if n >= 0 else 9999) 22597db96d56Sopenharmony_ci n = bufio.readinto(b) 22607db96d56Sopenharmony_ci return bytes(b[:n]) 22617db96d56Sopenharmony_ci self.check_flush_and_read(_readinto) 22627db96d56Sopenharmony_ci 22637db96d56Sopenharmony_ci def test_flush_and_peek(self): 22647db96d56Sopenharmony_ci def _peek(bufio, n=-1): 22657db96d56Sopenharmony_ci # This relies on the fact that the buffer can contain the whole 22667db96d56Sopenharmony_ci # raw stream, otherwise peek() can return less. 22677db96d56Sopenharmony_ci b = bufio.peek(n) 22687db96d56Sopenharmony_ci if n != -1: 22697db96d56Sopenharmony_ci b = b[:n] 22707db96d56Sopenharmony_ci bufio.seek(len(b), 1) 22717db96d56Sopenharmony_ci return b 22727db96d56Sopenharmony_ci self.check_flush_and_read(_peek) 22737db96d56Sopenharmony_ci 22747db96d56Sopenharmony_ci def test_flush_and_write(self): 22757db96d56Sopenharmony_ci raw = self.BytesIO(b"abcdefghi") 22767db96d56Sopenharmony_ci bufio = self.tp(raw) 22777db96d56Sopenharmony_ci 22787db96d56Sopenharmony_ci bufio.write(b"123") 22797db96d56Sopenharmony_ci bufio.flush() 22807db96d56Sopenharmony_ci bufio.write(b"45") 22817db96d56Sopenharmony_ci bufio.flush() 22827db96d56Sopenharmony_ci bufio.seek(0, 0) 22837db96d56Sopenharmony_ci self.assertEqual(b"12345fghi", raw.getvalue()) 22847db96d56Sopenharmony_ci self.assertEqual(b"12345fghi", bufio.read()) 22857db96d56Sopenharmony_ci 22867db96d56Sopenharmony_ci def test_threads(self): 22877db96d56Sopenharmony_ci BufferedReaderTest.test_threads(self) 22887db96d56Sopenharmony_ci BufferedWriterTest.test_threads(self) 22897db96d56Sopenharmony_ci 22907db96d56Sopenharmony_ci def test_writes_and_peek(self): 22917db96d56Sopenharmony_ci def _peek(bufio): 22927db96d56Sopenharmony_ci bufio.peek(1) 22937db96d56Sopenharmony_ci self.check_writes(_peek) 22947db96d56Sopenharmony_ci def _peek(bufio): 22957db96d56Sopenharmony_ci pos = bufio.tell() 22967db96d56Sopenharmony_ci bufio.seek(-1, 1) 22977db96d56Sopenharmony_ci bufio.peek(1) 22987db96d56Sopenharmony_ci bufio.seek(pos, 0) 22997db96d56Sopenharmony_ci self.check_writes(_peek) 23007db96d56Sopenharmony_ci 23017db96d56Sopenharmony_ci def test_writes_and_reads(self): 23027db96d56Sopenharmony_ci def _read(bufio): 23037db96d56Sopenharmony_ci bufio.seek(-1, 1) 23047db96d56Sopenharmony_ci bufio.read(1) 23057db96d56Sopenharmony_ci self.check_writes(_read) 23067db96d56Sopenharmony_ci 23077db96d56Sopenharmony_ci def test_writes_and_read1s(self): 23087db96d56Sopenharmony_ci def _read1(bufio): 23097db96d56Sopenharmony_ci bufio.seek(-1, 1) 23107db96d56Sopenharmony_ci bufio.read1(1) 23117db96d56Sopenharmony_ci self.check_writes(_read1) 23127db96d56Sopenharmony_ci 23137db96d56Sopenharmony_ci def test_writes_and_readintos(self): 23147db96d56Sopenharmony_ci def _read(bufio): 23157db96d56Sopenharmony_ci bufio.seek(-1, 1) 23167db96d56Sopenharmony_ci bufio.readinto(bytearray(1)) 23177db96d56Sopenharmony_ci self.check_writes(_read) 23187db96d56Sopenharmony_ci 23197db96d56Sopenharmony_ci def test_write_after_readahead(self): 23207db96d56Sopenharmony_ci # Issue #6629: writing after the buffer was filled by readahead should 23217db96d56Sopenharmony_ci # first rewind the raw stream. 23227db96d56Sopenharmony_ci for overwrite_size in [1, 5]: 23237db96d56Sopenharmony_ci raw = self.BytesIO(b"A" * 10) 23247db96d56Sopenharmony_ci bufio = self.tp(raw, 4) 23257db96d56Sopenharmony_ci # Trigger readahead 23267db96d56Sopenharmony_ci self.assertEqual(bufio.read(1), b"A") 23277db96d56Sopenharmony_ci self.assertEqual(bufio.tell(), 1) 23287db96d56Sopenharmony_ci # Overwriting should rewind the raw stream if it needs so 23297db96d56Sopenharmony_ci bufio.write(b"B" * overwrite_size) 23307db96d56Sopenharmony_ci self.assertEqual(bufio.tell(), overwrite_size + 1) 23317db96d56Sopenharmony_ci # If the write size was smaller than the buffer size, flush() and 23327db96d56Sopenharmony_ci # check that rewind happens. 23337db96d56Sopenharmony_ci bufio.flush() 23347db96d56Sopenharmony_ci self.assertEqual(bufio.tell(), overwrite_size + 1) 23357db96d56Sopenharmony_ci s = raw.getvalue() 23367db96d56Sopenharmony_ci self.assertEqual(s, 23377db96d56Sopenharmony_ci b"A" + b"B" * overwrite_size + b"A" * (9 - overwrite_size)) 23387db96d56Sopenharmony_ci 23397db96d56Sopenharmony_ci def test_write_rewind_write(self): 23407db96d56Sopenharmony_ci # Various combinations of reading / writing / seeking backwards / writing again 23417db96d56Sopenharmony_ci def mutate(bufio, pos1, pos2): 23427db96d56Sopenharmony_ci assert pos2 >= pos1 23437db96d56Sopenharmony_ci # Fill the buffer 23447db96d56Sopenharmony_ci bufio.seek(pos1) 23457db96d56Sopenharmony_ci bufio.read(pos2 - pos1) 23467db96d56Sopenharmony_ci bufio.write(b'\x02') 23477db96d56Sopenharmony_ci # This writes earlier than the previous write, but still inside 23487db96d56Sopenharmony_ci # the buffer. 23497db96d56Sopenharmony_ci bufio.seek(pos1) 23507db96d56Sopenharmony_ci bufio.write(b'\x01') 23517db96d56Sopenharmony_ci 23527db96d56Sopenharmony_ci b = b"\x80\x81\x82\x83\x84" 23537db96d56Sopenharmony_ci for i in range(0, len(b)): 23547db96d56Sopenharmony_ci for j in range(i, len(b)): 23557db96d56Sopenharmony_ci raw = self.BytesIO(b) 23567db96d56Sopenharmony_ci bufio = self.tp(raw, 100) 23577db96d56Sopenharmony_ci mutate(bufio, i, j) 23587db96d56Sopenharmony_ci bufio.flush() 23597db96d56Sopenharmony_ci expected = bytearray(b) 23607db96d56Sopenharmony_ci expected[j] = 2 23617db96d56Sopenharmony_ci expected[i] = 1 23627db96d56Sopenharmony_ci self.assertEqual(raw.getvalue(), expected, 23637db96d56Sopenharmony_ci "failed result for i=%d, j=%d" % (i, j)) 23647db96d56Sopenharmony_ci 23657db96d56Sopenharmony_ci def test_truncate_after_read_or_write(self): 23667db96d56Sopenharmony_ci raw = self.BytesIO(b"A" * 10) 23677db96d56Sopenharmony_ci bufio = self.tp(raw, 100) 23687db96d56Sopenharmony_ci self.assertEqual(bufio.read(2), b"AA") # the read buffer gets filled 23697db96d56Sopenharmony_ci self.assertEqual(bufio.truncate(), 2) 23707db96d56Sopenharmony_ci self.assertEqual(bufio.write(b"BB"), 2) # the write buffer increases 23717db96d56Sopenharmony_ci self.assertEqual(bufio.truncate(), 4) 23727db96d56Sopenharmony_ci 23737db96d56Sopenharmony_ci def test_misbehaved_io(self): 23747db96d56Sopenharmony_ci BufferedReaderTest.test_misbehaved_io(self) 23757db96d56Sopenharmony_ci BufferedWriterTest.test_misbehaved_io(self) 23767db96d56Sopenharmony_ci 23777db96d56Sopenharmony_ci def test_interleaved_read_write(self): 23787db96d56Sopenharmony_ci # Test for issue #12213 23797db96d56Sopenharmony_ci with self.BytesIO(b'abcdefgh') as raw: 23807db96d56Sopenharmony_ci with self.tp(raw, 100) as f: 23817db96d56Sopenharmony_ci f.write(b"1") 23827db96d56Sopenharmony_ci self.assertEqual(f.read(1), b'b') 23837db96d56Sopenharmony_ci f.write(b'2') 23847db96d56Sopenharmony_ci self.assertEqual(f.read1(1), b'd') 23857db96d56Sopenharmony_ci f.write(b'3') 23867db96d56Sopenharmony_ci buf = bytearray(1) 23877db96d56Sopenharmony_ci f.readinto(buf) 23887db96d56Sopenharmony_ci self.assertEqual(buf, b'f') 23897db96d56Sopenharmony_ci f.write(b'4') 23907db96d56Sopenharmony_ci self.assertEqual(f.peek(1), b'h') 23917db96d56Sopenharmony_ci f.flush() 23927db96d56Sopenharmony_ci self.assertEqual(raw.getvalue(), b'1b2d3f4h') 23937db96d56Sopenharmony_ci 23947db96d56Sopenharmony_ci with self.BytesIO(b'abc') as raw: 23957db96d56Sopenharmony_ci with self.tp(raw, 100) as f: 23967db96d56Sopenharmony_ci self.assertEqual(f.read(1), b'a') 23977db96d56Sopenharmony_ci f.write(b"2") 23987db96d56Sopenharmony_ci self.assertEqual(f.read(1), b'c') 23997db96d56Sopenharmony_ci f.flush() 24007db96d56Sopenharmony_ci self.assertEqual(raw.getvalue(), b'a2c') 24017db96d56Sopenharmony_ci 24027db96d56Sopenharmony_ci def test_interleaved_readline_write(self): 24037db96d56Sopenharmony_ci with self.BytesIO(b'ab\ncdef\ng\n') as raw: 24047db96d56Sopenharmony_ci with self.tp(raw) as f: 24057db96d56Sopenharmony_ci f.write(b'1') 24067db96d56Sopenharmony_ci self.assertEqual(f.readline(), b'b\n') 24077db96d56Sopenharmony_ci f.write(b'2') 24087db96d56Sopenharmony_ci self.assertEqual(f.readline(), b'def\n') 24097db96d56Sopenharmony_ci f.write(b'3') 24107db96d56Sopenharmony_ci self.assertEqual(f.readline(), b'\n') 24117db96d56Sopenharmony_ci f.flush() 24127db96d56Sopenharmony_ci self.assertEqual(raw.getvalue(), b'1b\n2def\n3\n') 24137db96d56Sopenharmony_ci 24147db96d56Sopenharmony_ci # You can't construct a BufferedRandom over a non-seekable stream. 24157db96d56Sopenharmony_ci test_unseekable = None 24167db96d56Sopenharmony_ci 24177db96d56Sopenharmony_ci # writable() returns True, so there's no point to test it over 24187db96d56Sopenharmony_ci # a writable stream. 24197db96d56Sopenharmony_ci test_truncate_on_read_only = None 24207db96d56Sopenharmony_ci 24217db96d56Sopenharmony_ci 24227db96d56Sopenharmony_ciclass CBufferedRandomTest(BufferedRandomTest, SizeofTest): 24237db96d56Sopenharmony_ci tp = io.BufferedRandom 24247db96d56Sopenharmony_ci 24257db96d56Sopenharmony_ci @skip_if_sanitizer(memory=True, address=True, reason= "sanitizer defaults to crashing " 24267db96d56Sopenharmony_ci "instead of returning NULL for malloc failure.") 24277db96d56Sopenharmony_ci def test_constructor(self): 24287db96d56Sopenharmony_ci BufferedRandomTest.test_constructor(self) 24297db96d56Sopenharmony_ci # The allocation can succeed on 32-bit builds, e.g. with more 24307db96d56Sopenharmony_ci # than 2 GiB RAM and a 64-bit kernel. 24317db96d56Sopenharmony_ci if sys.maxsize > 0x7FFFFFFF: 24327db96d56Sopenharmony_ci rawio = self.MockRawIO() 24337db96d56Sopenharmony_ci bufio = self.tp(rawio) 24347db96d56Sopenharmony_ci self.assertRaises((OverflowError, MemoryError, ValueError), 24357db96d56Sopenharmony_ci bufio.__init__, rawio, sys.maxsize) 24367db96d56Sopenharmony_ci 24377db96d56Sopenharmony_ci def test_garbage_collection(self): 24387db96d56Sopenharmony_ci CBufferedReaderTest.test_garbage_collection(self) 24397db96d56Sopenharmony_ci CBufferedWriterTest.test_garbage_collection(self) 24407db96d56Sopenharmony_ci 24417db96d56Sopenharmony_ci def test_args_error(self): 24427db96d56Sopenharmony_ci # Issue #17275 24437db96d56Sopenharmony_ci with self.assertRaisesRegex(TypeError, "BufferedRandom"): 24447db96d56Sopenharmony_ci self.tp(io.BytesIO(), 1024, 1024, 1024) 24457db96d56Sopenharmony_ci 24467db96d56Sopenharmony_ci 24477db96d56Sopenharmony_ciclass PyBufferedRandomTest(BufferedRandomTest): 24487db96d56Sopenharmony_ci tp = pyio.BufferedRandom 24497db96d56Sopenharmony_ci 24507db96d56Sopenharmony_ci 24517db96d56Sopenharmony_ci# To fully exercise seek/tell, the StatefulIncrementalDecoder has these 24527db96d56Sopenharmony_ci# properties: 24537db96d56Sopenharmony_ci# - A single output character can correspond to many bytes of input. 24547db96d56Sopenharmony_ci# - The number of input bytes to complete the character can be 24557db96d56Sopenharmony_ci# undetermined until the last input byte is received. 24567db96d56Sopenharmony_ci# - The number of input bytes can vary depending on previous input. 24577db96d56Sopenharmony_ci# - A single input byte can correspond to many characters of output. 24587db96d56Sopenharmony_ci# - The number of output characters can be undetermined until the 24597db96d56Sopenharmony_ci# last input byte is received. 24607db96d56Sopenharmony_ci# - The number of output characters can vary depending on previous input. 24617db96d56Sopenharmony_ci 24627db96d56Sopenharmony_ciclass StatefulIncrementalDecoder(codecs.IncrementalDecoder): 24637db96d56Sopenharmony_ci """ 24647db96d56Sopenharmony_ci For testing seek/tell behavior with a stateful, buffering decoder. 24657db96d56Sopenharmony_ci 24667db96d56Sopenharmony_ci Input is a sequence of words. Words may be fixed-length (length set 24677db96d56Sopenharmony_ci by input) or variable-length (period-terminated). In variable-length 24687db96d56Sopenharmony_ci mode, extra periods are ignored. Possible words are: 24697db96d56Sopenharmony_ci - 'i' followed by a number sets the input length, I (maximum 99). 24707db96d56Sopenharmony_ci When I is set to 0, words are space-terminated. 24717db96d56Sopenharmony_ci - 'o' followed by a number sets the output length, O (maximum 99). 24727db96d56Sopenharmony_ci - Any other word is converted into a word followed by a period on 24737db96d56Sopenharmony_ci the output. The output word consists of the input word truncated 24747db96d56Sopenharmony_ci or padded out with hyphens to make its length equal to O. If O 24757db96d56Sopenharmony_ci is 0, the word is output verbatim without truncating or padding. 24767db96d56Sopenharmony_ci I and O are initially set to 1. When I changes, any buffered input is 24777db96d56Sopenharmony_ci re-scanned according to the new I. EOF also terminates the last word. 24787db96d56Sopenharmony_ci """ 24797db96d56Sopenharmony_ci 24807db96d56Sopenharmony_ci def __init__(self, errors='strict'): 24817db96d56Sopenharmony_ci codecs.IncrementalDecoder.__init__(self, errors) 24827db96d56Sopenharmony_ci self.reset() 24837db96d56Sopenharmony_ci 24847db96d56Sopenharmony_ci def __repr__(self): 24857db96d56Sopenharmony_ci return '<SID %x>' % id(self) 24867db96d56Sopenharmony_ci 24877db96d56Sopenharmony_ci def reset(self): 24887db96d56Sopenharmony_ci self.i = 1 24897db96d56Sopenharmony_ci self.o = 1 24907db96d56Sopenharmony_ci self.buffer = bytearray() 24917db96d56Sopenharmony_ci 24927db96d56Sopenharmony_ci def getstate(self): 24937db96d56Sopenharmony_ci i, o = self.i ^ 1, self.o ^ 1 # so that flags = 0 after reset() 24947db96d56Sopenharmony_ci return bytes(self.buffer), i*100 + o 24957db96d56Sopenharmony_ci 24967db96d56Sopenharmony_ci def setstate(self, state): 24977db96d56Sopenharmony_ci buffer, io = state 24987db96d56Sopenharmony_ci self.buffer = bytearray(buffer) 24997db96d56Sopenharmony_ci i, o = divmod(io, 100) 25007db96d56Sopenharmony_ci self.i, self.o = i ^ 1, o ^ 1 25017db96d56Sopenharmony_ci 25027db96d56Sopenharmony_ci def decode(self, input, final=False): 25037db96d56Sopenharmony_ci output = '' 25047db96d56Sopenharmony_ci for b in input: 25057db96d56Sopenharmony_ci if self.i == 0: # variable-length, terminated with period 25067db96d56Sopenharmony_ci if b == ord('.'): 25077db96d56Sopenharmony_ci if self.buffer: 25087db96d56Sopenharmony_ci output += self.process_word() 25097db96d56Sopenharmony_ci else: 25107db96d56Sopenharmony_ci self.buffer.append(b) 25117db96d56Sopenharmony_ci else: # fixed-length, terminate after self.i bytes 25127db96d56Sopenharmony_ci self.buffer.append(b) 25137db96d56Sopenharmony_ci if len(self.buffer) == self.i: 25147db96d56Sopenharmony_ci output += self.process_word() 25157db96d56Sopenharmony_ci if final and self.buffer: # EOF terminates the last word 25167db96d56Sopenharmony_ci output += self.process_word() 25177db96d56Sopenharmony_ci return output 25187db96d56Sopenharmony_ci 25197db96d56Sopenharmony_ci def process_word(self): 25207db96d56Sopenharmony_ci output = '' 25217db96d56Sopenharmony_ci if self.buffer[0] == ord('i'): 25227db96d56Sopenharmony_ci self.i = min(99, int(self.buffer[1:] or 0)) # set input length 25237db96d56Sopenharmony_ci elif self.buffer[0] == ord('o'): 25247db96d56Sopenharmony_ci self.o = min(99, int(self.buffer[1:] or 0)) # set output length 25257db96d56Sopenharmony_ci else: 25267db96d56Sopenharmony_ci output = self.buffer.decode('ascii') 25277db96d56Sopenharmony_ci if len(output) < self.o: 25287db96d56Sopenharmony_ci output += '-'*self.o # pad out with hyphens 25297db96d56Sopenharmony_ci if self.o: 25307db96d56Sopenharmony_ci output = output[:self.o] # truncate to output length 25317db96d56Sopenharmony_ci output += '.' 25327db96d56Sopenharmony_ci self.buffer = bytearray() 25337db96d56Sopenharmony_ci return output 25347db96d56Sopenharmony_ci 25357db96d56Sopenharmony_ci codecEnabled = False 25367db96d56Sopenharmony_ci 25377db96d56Sopenharmony_ci 25387db96d56Sopenharmony_ci# bpo-41919: This method is separated from StatefulIncrementalDecoder to avoid a resource leak 25397db96d56Sopenharmony_ci# when registering codecs and cleanup functions. 25407db96d56Sopenharmony_cidef lookupTestDecoder(name): 25417db96d56Sopenharmony_ci if StatefulIncrementalDecoder.codecEnabled and name == 'test_decoder': 25427db96d56Sopenharmony_ci latin1 = codecs.lookup('latin-1') 25437db96d56Sopenharmony_ci return codecs.CodecInfo( 25447db96d56Sopenharmony_ci name='test_decoder', encode=latin1.encode, decode=None, 25457db96d56Sopenharmony_ci incrementalencoder=None, 25467db96d56Sopenharmony_ci streamreader=None, streamwriter=None, 25477db96d56Sopenharmony_ci incrementaldecoder=StatefulIncrementalDecoder) 25487db96d56Sopenharmony_ci 25497db96d56Sopenharmony_ci 25507db96d56Sopenharmony_ciclass StatefulIncrementalDecoderTest(unittest.TestCase): 25517db96d56Sopenharmony_ci """ 25527db96d56Sopenharmony_ci Make sure the StatefulIncrementalDecoder actually works. 25537db96d56Sopenharmony_ci """ 25547db96d56Sopenharmony_ci 25557db96d56Sopenharmony_ci test_cases = [ 25567db96d56Sopenharmony_ci # I=1, O=1 (fixed-length input == fixed-length output) 25577db96d56Sopenharmony_ci (b'abcd', False, 'a.b.c.d.'), 25587db96d56Sopenharmony_ci # I=0, O=0 (variable-length input, variable-length output) 25597db96d56Sopenharmony_ci (b'oiabcd', True, 'abcd.'), 25607db96d56Sopenharmony_ci # I=0, O=0 (should ignore extra periods) 25617db96d56Sopenharmony_ci (b'oi...abcd...', True, 'abcd.'), 25627db96d56Sopenharmony_ci # I=0, O=6 (variable-length input, fixed-length output) 25637db96d56Sopenharmony_ci (b'i.o6.x.xyz.toolongtofit.', False, 'x-----.xyz---.toolon.'), 25647db96d56Sopenharmony_ci # I=2, O=6 (fixed-length input < fixed-length output) 25657db96d56Sopenharmony_ci (b'i.i2.o6xyz', True, 'xy----.z-----.'), 25667db96d56Sopenharmony_ci # I=6, O=3 (fixed-length input > fixed-length output) 25677db96d56Sopenharmony_ci (b'i.o3.i6.abcdefghijklmnop', True, 'abc.ghi.mno.'), 25687db96d56Sopenharmony_ci # I=0, then 3; O=29, then 15 (with longer output) 25697db96d56Sopenharmony_ci (b'i.o29.a.b.cde.o15.abcdefghijabcdefghij.i3.a.b.c.d.ei00k.l.m', True, 25707db96d56Sopenharmony_ci 'a----------------------------.' + 25717db96d56Sopenharmony_ci 'b----------------------------.' + 25727db96d56Sopenharmony_ci 'cde--------------------------.' + 25737db96d56Sopenharmony_ci 'abcdefghijabcde.' + 25747db96d56Sopenharmony_ci 'a.b------------.' + 25757db96d56Sopenharmony_ci '.c.------------.' + 25767db96d56Sopenharmony_ci 'd.e------------.' + 25777db96d56Sopenharmony_ci 'k--------------.' + 25787db96d56Sopenharmony_ci 'l--------------.' + 25797db96d56Sopenharmony_ci 'm--------------.') 25807db96d56Sopenharmony_ci ] 25817db96d56Sopenharmony_ci 25827db96d56Sopenharmony_ci def test_decoder(self): 25837db96d56Sopenharmony_ci # Try a few one-shot test cases. 25847db96d56Sopenharmony_ci for input, eof, output in self.test_cases: 25857db96d56Sopenharmony_ci d = StatefulIncrementalDecoder() 25867db96d56Sopenharmony_ci self.assertEqual(d.decode(input, eof), output) 25877db96d56Sopenharmony_ci 25887db96d56Sopenharmony_ci # Also test an unfinished decode, followed by forcing EOF. 25897db96d56Sopenharmony_ci d = StatefulIncrementalDecoder() 25907db96d56Sopenharmony_ci self.assertEqual(d.decode(b'oiabcd'), '') 25917db96d56Sopenharmony_ci self.assertEqual(d.decode(b'', 1), 'abcd.') 25927db96d56Sopenharmony_ci 25937db96d56Sopenharmony_ciclass TextIOWrapperTest(unittest.TestCase): 25947db96d56Sopenharmony_ci 25957db96d56Sopenharmony_ci def setUp(self): 25967db96d56Sopenharmony_ci self.testdata = b"AAA\r\nBBB\rCCC\r\nDDD\nEEE\r\n" 25977db96d56Sopenharmony_ci self.normalized = b"AAA\nBBB\nCCC\nDDD\nEEE\n".decode("ascii") 25987db96d56Sopenharmony_ci os_helper.unlink(os_helper.TESTFN) 25997db96d56Sopenharmony_ci codecs.register(lookupTestDecoder) 26007db96d56Sopenharmony_ci self.addCleanup(codecs.unregister, lookupTestDecoder) 26017db96d56Sopenharmony_ci 26027db96d56Sopenharmony_ci def tearDown(self): 26037db96d56Sopenharmony_ci os_helper.unlink(os_helper.TESTFN) 26047db96d56Sopenharmony_ci 26057db96d56Sopenharmony_ci def test_constructor(self): 26067db96d56Sopenharmony_ci r = self.BytesIO(b"\xc3\xa9\n\n") 26077db96d56Sopenharmony_ci b = self.BufferedReader(r, 1000) 26087db96d56Sopenharmony_ci t = self.TextIOWrapper(b, encoding="utf-8") 26097db96d56Sopenharmony_ci t.__init__(b, encoding="latin-1", newline="\r\n") 26107db96d56Sopenharmony_ci self.assertEqual(t.encoding, "latin-1") 26117db96d56Sopenharmony_ci self.assertEqual(t.line_buffering, False) 26127db96d56Sopenharmony_ci t.__init__(b, encoding="utf-8", line_buffering=True) 26137db96d56Sopenharmony_ci self.assertEqual(t.encoding, "utf-8") 26147db96d56Sopenharmony_ci self.assertEqual(t.line_buffering, True) 26157db96d56Sopenharmony_ci self.assertEqual("\xe9\n", t.readline()) 26167db96d56Sopenharmony_ci self.assertRaises(TypeError, t.__init__, b, encoding="utf-8", newline=42) 26177db96d56Sopenharmony_ci self.assertRaises(ValueError, t.__init__, b, encoding="utf-8", newline='xyzzy') 26187db96d56Sopenharmony_ci 26197db96d56Sopenharmony_ci def test_uninitialized(self): 26207db96d56Sopenharmony_ci t = self.TextIOWrapper.__new__(self.TextIOWrapper) 26217db96d56Sopenharmony_ci del t 26227db96d56Sopenharmony_ci t = self.TextIOWrapper.__new__(self.TextIOWrapper) 26237db96d56Sopenharmony_ci self.assertRaises(Exception, repr, t) 26247db96d56Sopenharmony_ci self.assertRaisesRegex((ValueError, AttributeError), 26257db96d56Sopenharmony_ci 'uninitialized|has no attribute', 26267db96d56Sopenharmony_ci t.read, 0) 26277db96d56Sopenharmony_ci t.__init__(self.MockRawIO(), encoding="utf-8") 26287db96d56Sopenharmony_ci self.assertEqual(t.read(0), '') 26297db96d56Sopenharmony_ci 26307db96d56Sopenharmony_ci def test_non_text_encoding_codecs_are_rejected(self): 26317db96d56Sopenharmony_ci # Ensure the constructor complains if passed a codec that isn't 26327db96d56Sopenharmony_ci # marked as a text encoding 26337db96d56Sopenharmony_ci # http://bugs.python.org/issue20404 26347db96d56Sopenharmony_ci r = self.BytesIO() 26357db96d56Sopenharmony_ci b = self.BufferedWriter(r) 26367db96d56Sopenharmony_ci with self.assertRaisesRegex(LookupError, "is not a text encoding"): 26377db96d56Sopenharmony_ci self.TextIOWrapper(b, encoding="hex") 26387db96d56Sopenharmony_ci 26397db96d56Sopenharmony_ci def test_detach(self): 26407db96d56Sopenharmony_ci r = self.BytesIO() 26417db96d56Sopenharmony_ci b = self.BufferedWriter(r) 26427db96d56Sopenharmony_ci t = self.TextIOWrapper(b, encoding="ascii") 26437db96d56Sopenharmony_ci self.assertIs(t.detach(), b) 26447db96d56Sopenharmony_ci 26457db96d56Sopenharmony_ci t = self.TextIOWrapper(b, encoding="ascii") 26467db96d56Sopenharmony_ci t.write("howdy") 26477db96d56Sopenharmony_ci self.assertFalse(r.getvalue()) 26487db96d56Sopenharmony_ci t.detach() 26497db96d56Sopenharmony_ci self.assertEqual(r.getvalue(), b"howdy") 26507db96d56Sopenharmony_ci self.assertRaises(ValueError, t.detach) 26517db96d56Sopenharmony_ci 26527db96d56Sopenharmony_ci # Operations independent of the detached stream should still work 26537db96d56Sopenharmony_ci repr(t) 26547db96d56Sopenharmony_ci self.assertEqual(t.encoding, "ascii") 26557db96d56Sopenharmony_ci self.assertEqual(t.errors, "strict") 26567db96d56Sopenharmony_ci self.assertFalse(t.line_buffering) 26577db96d56Sopenharmony_ci self.assertFalse(t.write_through) 26587db96d56Sopenharmony_ci 26597db96d56Sopenharmony_ci def test_repr(self): 26607db96d56Sopenharmony_ci raw = self.BytesIO("hello".encode("utf-8")) 26617db96d56Sopenharmony_ci b = self.BufferedReader(raw) 26627db96d56Sopenharmony_ci t = self.TextIOWrapper(b, encoding="utf-8") 26637db96d56Sopenharmony_ci modname = self.TextIOWrapper.__module__ 26647db96d56Sopenharmony_ci self.assertRegex(repr(t), 26657db96d56Sopenharmony_ci r"<(%s\.)?TextIOWrapper encoding='utf-8'>" % modname) 26667db96d56Sopenharmony_ci raw.name = "dummy" 26677db96d56Sopenharmony_ci self.assertRegex(repr(t), 26687db96d56Sopenharmony_ci r"<(%s\.)?TextIOWrapper name='dummy' encoding='utf-8'>" % modname) 26697db96d56Sopenharmony_ci t.mode = "r" 26707db96d56Sopenharmony_ci self.assertRegex(repr(t), 26717db96d56Sopenharmony_ci r"<(%s\.)?TextIOWrapper name='dummy' mode='r' encoding='utf-8'>" % modname) 26727db96d56Sopenharmony_ci raw.name = b"dummy" 26737db96d56Sopenharmony_ci self.assertRegex(repr(t), 26747db96d56Sopenharmony_ci r"<(%s\.)?TextIOWrapper name=b'dummy' mode='r' encoding='utf-8'>" % modname) 26757db96d56Sopenharmony_ci 26767db96d56Sopenharmony_ci t.buffer.detach() 26777db96d56Sopenharmony_ci repr(t) # Should not raise an exception 26787db96d56Sopenharmony_ci 26797db96d56Sopenharmony_ci def test_recursive_repr(self): 26807db96d56Sopenharmony_ci # Issue #25455 26817db96d56Sopenharmony_ci raw = self.BytesIO() 26827db96d56Sopenharmony_ci t = self.TextIOWrapper(raw, encoding="utf-8") 26837db96d56Sopenharmony_ci with support.swap_attr(raw, 'name', t): 26847db96d56Sopenharmony_ci try: 26857db96d56Sopenharmony_ci repr(t) # Should not crash 26867db96d56Sopenharmony_ci except RuntimeError: 26877db96d56Sopenharmony_ci pass 26887db96d56Sopenharmony_ci 26897db96d56Sopenharmony_ci def test_line_buffering(self): 26907db96d56Sopenharmony_ci r = self.BytesIO() 26917db96d56Sopenharmony_ci b = self.BufferedWriter(r, 1000) 26927db96d56Sopenharmony_ci t = self.TextIOWrapper(b, encoding="utf-8", newline="\n", line_buffering=True) 26937db96d56Sopenharmony_ci t.write("X") 26947db96d56Sopenharmony_ci self.assertEqual(r.getvalue(), b"") # No flush happened 26957db96d56Sopenharmony_ci t.write("Y\nZ") 26967db96d56Sopenharmony_ci self.assertEqual(r.getvalue(), b"XY\nZ") # All got flushed 26977db96d56Sopenharmony_ci t.write("A\rB") 26987db96d56Sopenharmony_ci self.assertEqual(r.getvalue(), b"XY\nZA\rB") 26997db96d56Sopenharmony_ci 27007db96d56Sopenharmony_ci def test_reconfigure_line_buffering(self): 27017db96d56Sopenharmony_ci r = self.BytesIO() 27027db96d56Sopenharmony_ci b = self.BufferedWriter(r, 1000) 27037db96d56Sopenharmony_ci t = self.TextIOWrapper(b, encoding="utf-8", newline="\n", line_buffering=False) 27047db96d56Sopenharmony_ci t.write("AB\nC") 27057db96d56Sopenharmony_ci self.assertEqual(r.getvalue(), b"") 27067db96d56Sopenharmony_ci 27077db96d56Sopenharmony_ci t.reconfigure(line_buffering=True) # implicit flush 27087db96d56Sopenharmony_ci self.assertEqual(r.getvalue(), b"AB\nC") 27097db96d56Sopenharmony_ci t.write("DEF\nG") 27107db96d56Sopenharmony_ci self.assertEqual(r.getvalue(), b"AB\nCDEF\nG") 27117db96d56Sopenharmony_ci t.write("H") 27127db96d56Sopenharmony_ci self.assertEqual(r.getvalue(), b"AB\nCDEF\nG") 27137db96d56Sopenharmony_ci t.reconfigure(line_buffering=False) # implicit flush 27147db96d56Sopenharmony_ci self.assertEqual(r.getvalue(), b"AB\nCDEF\nGH") 27157db96d56Sopenharmony_ci t.write("IJ") 27167db96d56Sopenharmony_ci self.assertEqual(r.getvalue(), b"AB\nCDEF\nGH") 27177db96d56Sopenharmony_ci 27187db96d56Sopenharmony_ci # Keeping default value 27197db96d56Sopenharmony_ci t.reconfigure() 27207db96d56Sopenharmony_ci t.reconfigure(line_buffering=None) 27217db96d56Sopenharmony_ci self.assertEqual(t.line_buffering, False) 27227db96d56Sopenharmony_ci t.reconfigure(line_buffering=True) 27237db96d56Sopenharmony_ci t.reconfigure() 27247db96d56Sopenharmony_ci t.reconfigure(line_buffering=None) 27257db96d56Sopenharmony_ci self.assertEqual(t.line_buffering, True) 27267db96d56Sopenharmony_ci 27277db96d56Sopenharmony_ci @unittest.skipIf(sys.flags.utf8_mode, "utf-8 mode is enabled") 27287db96d56Sopenharmony_ci def test_default_encoding(self): 27297db96d56Sopenharmony_ci old_environ = dict(os.environ) 27307db96d56Sopenharmony_ci try: 27317db96d56Sopenharmony_ci # try to get a user preferred encoding different than the current 27327db96d56Sopenharmony_ci # locale encoding to check that TextIOWrapper() uses the current 27337db96d56Sopenharmony_ci # locale encoding and not the user preferred encoding 27347db96d56Sopenharmony_ci for key in ('LC_ALL', 'LANG', 'LC_CTYPE'): 27357db96d56Sopenharmony_ci if key in os.environ: 27367db96d56Sopenharmony_ci del os.environ[key] 27377db96d56Sopenharmony_ci 27387db96d56Sopenharmony_ci current_locale_encoding = locale.getencoding() 27397db96d56Sopenharmony_ci b = self.BytesIO() 27407db96d56Sopenharmony_ci with warnings.catch_warnings(): 27417db96d56Sopenharmony_ci warnings.simplefilter("ignore", EncodingWarning) 27427db96d56Sopenharmony_ci t = self.TextIOWrapper(b) 27437db96d56Sopenharmony_ci self.assertEqual(t.encoding, current_locale_encoding) 27447db96d56Sopenharmony_ci finally: 27457db96d56Sopenharmony_ci os.environ.clear() 27467db96d56Sopenharmony_ci os.environ.update(old_environ) 27477db96d56Sopenharmony_ci 27487db96d56Sopenharmony_ci def test_encoding(self): 27497db96d56Sopenharmony_ci # Check the encoding attribute is always set, and valid 27507db96d56Sopenharmony_ci b = self.BytesIO() 27517db96d56Sopenharmony_ci t = self.TextIOWrapper(b, encoding="utf-8") 27527db96d56Sopenharmony_ci self.assertEqual(t.encoding, "utf-8") 27537db96d56Sopenharmony_ci with warnings.catch_warnings(): 27547db96d56Sopenharmony_ci warnings.simplefilter("ignore", EncodingWarning) 27557db96d56Sopenharmony_ci t = self.TextIOWrapper(b) 27567db96d56Sopenharmony_ci self.assertIsNotNone(t.encoding) 27577db96d56Sopenharmony_ci codecs.lookup(t.encoding) 27587db96d56Sopenharmony_ci 27597db96d56Sopenharmony_ci def test_encoding_errors_reading(self): 27607db96d56Sopenharmony_ci # (1) default 27617db96d56Sopenharmony_ci b = self.BytesIO(b"abc\n\xff\n") 27627db96d56Sopenharmony_ci t = self.TextIOWrapper(b, encoding="ascii") 27637db96d56Sopenharmony_ci self.assertRaises(UnicodeError, t.read) 27647db96d56Sopenharmony_ci # (2) explicit strict 27657db96d56Sopenharmony_ci b = self.BytesIO(b"abc\n\xff\n") 27667db96d56Sopenharmony_ci t = self.TextIOWrapper(b, encoding="ascii", errors="strict") 27677db96d56Sopenharmony_ci self.assertRaises(UnicodeError, t.read) 27687db96d56Sopenharmony_ci # (3) ignore 27697db96d56Sopenharmony_ci b = self.BytesIO(b"abc\n\xff\n") 27707db96d56Sopenharmony_ci t = self.TextIOWrapper(b, encoding="ascii", errors="ignore") 27717db96d56Sopenharmony_ci self.assertEqual(t.read(), "abc\n\n") 27727db96d56Sopenharmony_ci # (4) replace 27737db96d56Sopenharmony_ci b = self.BytesIO(b"abc\n\xff\n") 27747db96d56Sopenharmony_ci t = self.TextIOWrapper(b, encoding="ascii", errors="replace") 27757db96d56Sopenharmony_ci self.assertEqual(t.read(), "abc\n\ufffd\n") 27767db96d56Sopenharmony_ci 27777db96d56Sopenharmony_ci def test_encoding_errors_writing(self): 27787db96d56Sopenharmony_ci # (1) default 27797db96d56Sopenharmony_ci b = self.BytesIO() 27807db96d56Sopenharmony_ci t = self.TextIOWrapper(b, encoding="ascii") 27817db96d56Sopenharmony_ci self.assertRaises(UnicodeError, t.write, "\xff") 27827db96d56Sopenharmony_ci # (2) explicit strict 27837db96d56Sopenharmony_ci b = self.BytesIO() 27847db96d56Sopenharmony_ci t = self.TextIOWrapper(b, encoding="ascii", errors="strict") 27857db96d56Sopenharmony_ci self.assertRaises(UnicodeError, t.write, "\xff") 27867db96d56Sopenharmony_ci # (3) ignore 27877db96d56Sopenharmony_ci b = self.BytesIO() 27887db96d56Sopenharmony_ci t = self.TextIOWrapper(b, encoding="ascii", errors="ignore", 27897db96d56Sopenharmony_ci newline="\n") 27907db96d56Sopenharmony_ci t.write("abc\xffdef\n") 27917db96d56Sopenharmony_ci t.flush() 27927db96d56Sopenharmony_ci self.assertEqual(b.getvalue(), b"abcdef\n") 27937db96d56Sopenharmony_ci # (4) replace 27947db96d56Sopenharmony_ci b = self.BytesIO() 27957db96d56Sopenharmony_ci t = self.TextIOWrapper(b, encoding="ascii", errors="replace", 27967db96d56Sopenharmony_ci newline="\n") 27977db96d56Sopenharmony_ci t.write("abc\xffdef\n") 27987db96d56Sopenharmony_ci t.flush() 27997db96d56Sopenharmony_ci self.assertEqual(b.getvalue(), b"abc?def\n") 28007db96d56Sopenharmony_ci 28017db96d56Sopenharmony_ci def test_newlines(self): 28027db96d56Sopenharmony_ci input_lines = [ "unix\n", "windows\r\n", "os9\r", "last\n", "nonl" ] 28037db96d56Sopenharmony_ci 28047db96d56Sopenharmony_ci tests = [ 28057db96d56Sopenharmony_ci [ None, [ 'unix\n', 'windows\n', 'os9\n', 'last\n', 'nonl' ] ], 28067db96d56Sopenharmony_ci [ '', input_lines ], 28077db96d56Sopenharmony_ci [ '\n', [ "unix\n", "windows\r\n", "os9\rlast\n", "nonl" ] ], 28087db96d56Sopenharmony_ci [ '\r\n', [ "unix\nwindows\r\n", "os9\rlast\nnonl" ] ], 28097db96d56Sopenharmony_ci [ '\r', [ "unix\nwindows\r", "\nos9\r", "last\nnonl" ] ], 28107db96d56Sopenharmony_ci ] 28117db96d56Sopenharmony_ci encodings = ( 28127db96d56Sopenharmony_ci 'utf-8', 'latin-1', 28137db96d56Sopenharmony_ci 'utf-16', 'utf-16-le', 'utf-16-be', 28147db96d56Sopenharmony_ci 'utf-32', 'utf-32-le', 'utf-32-be', 28157db96d56Sopenharmony_ci ) 28167db96d56Sopenharmony_ci 28177db96d56Sopenharmony_ci # Try a range of buffer sizes to test the case where \r is the last 28187db96d56Sopenharmony_ci # character in TextIOWrapper._pending_line. 28197db96d56Sopenharmony_ci for encoding in encodings: 28207db96d56Sopenharmony_ci # XXX: str.encode() should return bytes 28217db96d56Sopenharmony_ci data = bytes(''.join(input_lines).encode(encoding)) 28227db96d56Sopenharmony_ci for do_reads in (False, True): 28237db96d56Sopenharmony_ci for bufsize in range(1, 10): 28247db96d56Sopenharmony_ci for newline, exp_lines in tests: 28257db96d56Sopenharmony_ci bufio = self.BufferedReader(self.BytesIO(data), bufsize) 28267db96d56Sopenharmony_ci textio = self.TextIOWrapper(bufio, newline=newline, 28277db96d56Sopenharmony_ci encoding=encoding) 28287db96d56Sopenharmony_ci if do_reads: 28297db96d56Sopenharmony_ci got_lines = [] 28307db96d56Sopenharmony_ci while True: 28317db96d56Sopenharmony_ci c2 = textio.read(2) 28327db96d56Sopenharmony_ci if c2 == '': 28337db96d56Sopenharmony_ci break 28347db96d56Sopenharmony_ci self.assertEqual(len(c2), 2) 28357db96d56Sopenharmony_ci got_lines.append(c2 + textio.readline()) 28367db96d56Sopenharmony_ci else: 28377db96d56Sopenharmony_ci got_lines = list(textio) 28387db96d56Sopenharmony_ci 28397db96d56Sopenharmony_ci for got_line, exp_line in zip(got_lines, exp_lines): 28407db96d56Sopenharmony_ci self.assertEqual(got_line, exp_line) 28417db96d56Sopenharmony_ci self.assertEqual(len(got_lines), len(exp_lines)) 28427db96d56Sopenharmony_ci 28437db96d56Sopenharmony_ci def test_newlines_input(self): 28447db96d56Sopenharmony_ci testdata = b"AAA\nBB\x00B\nCCC\rDDD\rEEE\r\nFFF\r\nGGG" 28457db96d56Sopenharmony_ci normalized = testdata.replace(b"\r\n", b"\n").replace(b"\r", b"\n") 28467db96d56Sopenharmony_ci for newline, expected in [ 28477db96d56Sopenharmony_ci (None, normalized.decode("ascii").splitlines(keepends=True)), 28487db96d56Sopenharmony_ci ("", testdata.decode("ascii").splitlines(keepends=True)), 28497db96d56Sopenharmony_ci ("\n", ["AAA\n", "BB\x00B\n", "CCC\rDDD\rEEE\r\n", "FFF\r\n", "GGG"]), 28507db96d56Sopenharmony_ci ("\r\n", ["AAA\nBB\x00B\nCCC\rDDD\rEEE\r\n", "FFF\r\n", "GGG"]), 28517db96d56Sopenharmony_ci ("\r", ["AAA\nBB\x00B\nCCC\r", "DDD\r", "EEE\r", "\nFFF\r", "\nGGG"]), 28527db96d56Sopenharmony_ci ]: 28537db96d56Sopenharmony_ci buf = self.BytesIO(testdata) 28547db96d56Sopenharmony_ci txt = self.TextIOWrapper(buf, encoding="ascii", newline=newline) 28557db96d56Sopenharmony_ci self.assertEqual(txt.readlines(), expected) 28567db96d56Sopenharmony_ci txt.seek(0) 28577db96d56Sopenharmony_ci self.assertEqual(txt.read(), "".join(expected)) 28587db96d56Sopenharmony_ci 28597db96d56Sopenharmony_ci def test_newlines_output(self): 28607db96d56Sopenharmony_ci testdict = { 28617db96d56Sopenharmony_ci "": b"AAA\nBBB\nCCC\nX\rY\r\nZ", 28627db96d56Sopenharmony_ci "\n": b"AAA\nBBB\nCCC\nX\rY\r\nZ", 28637db96d56Sopenharmony_ci "\r": b"AAA\rBBB\rCCC\rX\rY\r\rZ", 28647db96d56Sopenharmony_ci "\r\n": b"AAA\r\nBBB\r\nCCC\r\nX\rY\r\r\nZ", 28657db96d56Sopenharmony_ci } 28667db96d56Sopenharmony_ci tests = [(None, testdict[os.linesep])] + sorted(testdict.items()) 28677db96d56Sopenharmony_ci for newline, expected in tests: 28687db96d56Sopenharmony_ci buf = self.BytesIO() 28697db96d56Sopenharmony_ci txt = self.TextIOWrapper(buf, encoding="ascii", newline=newline) 28707db96d56Sopenharmony_ci txt.write("AAA\nB") 28717db96d56Sopenharmony_ci txt.write("BB\nCCC\n") 28727db96d56Sopenharmony_ci txt.write("X\rY\r\nZ") 28737db96d56Sopenharmony_ci txt.flush() 28747db96d56Sopenharmony_ci self.assertEqual(buf.closed, False) 28757db96d56Sopenharmony_ci self.assertEqual(buf.getvalue(), expected) 28767db96d56Sopenharmony_ci 28777db96d56Sopenharmony_ci def test_destructor(self): 28787db96d56Sopenharmony_ci l = [] 28797db96d56Sopenharmony_ci base = self.BytesIO 28807db96d56Sopenharmony_ci class MyBytesIO(base): 28817db96d56Sopenharmony_ci def close(self): 28827db96d56Sopenharmony_ci l.append(self.getvalue()) 28837db96d56Sopenharmony_ci base.close(self) 28847db96d56Sopenharmony_ci b = MyBytesIO() 28857db96d56Sopenharmony_ci t = self.TextIOWrapper(b, encoding="ascii") 28867db96d56Sopenharmony_ci t.write("abc") 28877db96d56Sopenharmony_ci del t 28887db96d56Sopenharmony_ci support.gc_collect() 28897db96d56Sopenharmony_ci self.assertEqual([b"abc"], l) 28907db96d56Sopenharmony_ci 28917db96d56Sopenharmony_ci def test_override_destructor(self): 28927db96d56Sopenharmony_ci record = [] 28937db96d56Sopenharmony_ci class MyTextIO(self.TextIOWrapper): 28947db96d56Sopenharmony_ci def __del__(self): 28957db96d56Sopenharmony_ci record.append(1) 28967db96d56Sopenharmony_ci try: 28977db96d56Sopenharmony_ci f = super().__del__ 28987db96d56Sopenharmony_ci except AttributeError: 28997db96d56Sopenharmony_ci pass 29007db96d56Sopenharmony_ci else: 29017db96d56Sopenharmony_ci f() 29027db96d56Sopenharmony_ci def close(self): 29037db96d56Sopenharmony_ci record.append(2) 29047db96d56Sopenharmony_ci super().close() 29057db96d56Sopenharmony_ci def flush(self): 29067db96d56Sopenharmony_ci record.append(3) 29077db96d56Sopenharmony_ci super().flush() 29087db96d56Sopenharmony_ci b = self.BytesIO() 29097db96d56Sopenharmony_ci t = MyTextIO(b, encoding="ascii") 29107db96d56Sopenharmony_ci del t 29117db96d56Sopenharmony_ci support.gc_collect() 29127db96d56Sopenharmony_ci self.assertEqual(record, [1, 2, 3]) 29137db96d56Sopenharmony_ci 29147db96d56Sopenharmony_ci def test_error_through_destructor(self): 29157db96d56Sopenharmony_ci # Test that the exception state is not modified by a destructor, 29167db96d56Sopenharmony_ci # even if close() fails. 29177db96d56Sopenharmony_ci rawio = self.CloseFailureIO() 29187db96d56Sopenharmony_ci with support.catch_unraisable_exception() as cm: 29197db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 29207db96d56Sopenharmony_ci self.TextIOWrapper(rawio, encoding="utf-8").xyzzy 29217db96d56Sopenharmony_ci 29227db96d56Sopenharmony_ci if not IOBASE_EMITS_UNRAISABLE: 29237db96d56Sopenharmony_ci self.assertIsNone(cm.unraisable) 29247db96d56Sopenharmony_ci elif cm.unraisable is not None: 29257db96d56Sopenharmony_ci self.assertEqual(cm.unraisable.exc_type, OSError) 29267db96d56Sopenharmony_ci 29277db96d56Sopenharmony_ci # Systematic tests of the text I/O API 29287db96d56Sopenharmony_ci 29297db96d56Sopenharmony_ci def test_basic_io(self): 29307db96d56Sopenharmony_ci for chunksize in (1, 2, 3, 4, 5, 15, 16, 17, 31, 32, 33, 63, 64, 65): 29317db96d56Sopenharmony_ci for enc in "ascii", "latin-1", "utf-8" :# , "utf-16-be", "utf-16-le": 29327db96d56Sopenharmony_ci f = self.open(os_helper.TESTFN, "w+", encoding=enc) 29337db96d56Sopenharmony_ci f._CHUNK_SIZE = chunksize 29347db96d56Sopenharmony_ci self.assertEqual(f.write("abc"), 3) 29357db96d56Sopenharmony_ci f.close() 29367db96d56Sopenharmony_ci f = self.open(os_helper.TESTFN, "r+", encoding=enc) 29377db96d56Sopenharmony_ci f._CHUNK_SIZE = chunksize 29387db96d56Sopenharmony_ci self.assertEqual(f.tell(), 0) 29397db96d56Sopenharmony_ci self.assertEqual(f.read(), "abc") 29407db96d56Sopenharmony_ci cookie = f.tell() 29417db96d56Sopenharmony_ci self.assertEqual(f.seek(0), 0) 29427db96d56Sopenharmony_ci self.assertEqual(f.read(None), "abc") 29437db96d56Sopenharmony_ci f.seek(0) 29447db96d56Sopenharmony_ci self.assertEqual(f.read(2), "ab") 29457db96d56Sopenharmony_ci self.assertEqual(f.read(1), "c") 29467db96d56Sopenharmony_ci self.assertEqual(f.read(1), "") 29477db96d56Sopenharmony_ci self.assertEqual(f.read(), "") 29487db96d56Sopenharmony_ci self.assertEqual(f.tell(), cookie) 29497db96d56Sopenharmony_ci self.assertEqual(f.seek(0), 0) 29507db96d56Sopenharmony_ci self.assertEqual(f.seek(0, 2), cookie) 29517db96d56Sopenharmony_ci self.assertEqual(f.write("def"), 3) 29527db96d56Sopenharmony_ci self.assertEqual(f.seek(cookie), cookie) 29537db96d56Sopenharmony_ci self.assertEqual(f.read(), "def") 29547db96d56Sopenharmony_ci if enc.startswith("utf"): 29557db96d56Sopenharmony_ci self.multi_line_test(f, enc) 29567db96d56Sopenharmony_ci f.close() 29577db96d56Sopenharmony_ci 29587db96d56Sopenharmony_ci def multi_line_test(self, f, enc): 29597db96d56Sopenharmony_ci f.seek(0) 29607db96d56Sopenharmony_ci f.truncate() 29617db96d56Sopenharmony_ci sample = "s\xff\u0fff\uffff" 29627db96d56Sopenharmony_ci wlines = [] 29637db96d56Sopenharmony_ci for size in (0, 1, 2, 3, 4, 5, 30, 31, 32, 33, 62, 63, 64, 65, 1000): 29647db96d56Sopenharmony_ci chars = [] 29657db96d56Sopenharmony_ci for i in range(size): 29667db96d56Sopenharmony_ci chars.append(sample[i % len(sample)]) 29677db96d56Sopenharmony_ci line = "".join(chars) + "\n" 29687db96d56Sopenharmony_ci wlines.append((f.tell(), line)) 29697db96d56Sopenharmony_ci f.write(line) 29707db96d56Sopenharmony_ci f.seek(0) 29717db96d56Sopenharmony_ci rlines = [] 29727db96d56Sopenharmony_ci while True: 29737db96d56Sopenharmony_ci pos = f.tell() 29747db96d56Sopenharmony_ci line = f.readline() 29757db96d56Sopenharmony_ci if not line: 29767db96d56Sopenharmony_ci break 29777db96d56Sopenharmony_ci rlines.append((pos, line)) 29787db96d56Sopenharmony_ci self.assertEqual(rlines, wlines) 29797db96d56Sopenharmony_ci 29807db96d56Sopenharmony_ci def test_telling(self): 29817db96d56Sopenharmony_ci f = self.open(os_helper.TESTFN, "w+", encoding="utf-8") 29827db96d56Sopenharmony_ci p0 = f.tell() 29837db96d56Sopenharmony_ci f.write("\xff\n") 29847db96d56Sopenharmony_ci p1 = f.tell() 29857db96d56Sopenharmony_ci f.write("\xff\n") 29867db96d56Sopenharmony_ci p2 = f.tell() 29877db96d56Sopenharmony_ci f.seek(0) 29887db96d56Sopenharmony_ci self.assertEqual(f.tell(), p0) 29897db96d56Sopenharmony_ci self.assertEqual(f.readline(), "\xff\n") 29907db96d56Sopenharmony_ci self.assertEqual(f.tell(), p1) 29917db96d56Sopenharmony_ci self.assertEqual(f.readline(), "\xff\n") 29927db96d56Sopenharmony_ci self.assertEqual(f.tell(), p2) 29937db96d56Sopenharmony_ci f.seek(0) 29947db96d56Sopenharmony_ci for line in f: 29957db96d56Sopenharmony_ci self.assertEqual(line, "\xff\n") 29967db96d56Sopenharmony_ci self.assertRaises(OSError, f.tell) 29977db96d56Sopenharmony_ci self.assertEqual(f.tell(), p2) 29987db96d56Sopenharmony_ci f.close() 29997db96d56Sopenharmony_ci 30007db96d56Sopenharmony_ci def test_seeking(self): 30017db96d56Sopenharmony_ci chunk_size = _default_chunk_size() 30027db96d56Sopenharmony_ci prefix_size = chunk_size - 2 30037db96d56Sopenharmony_ci u_prefix = "a" * prefix_size 30047db96d56Sopenharmony_ci prefix = bytes(u_prefix.encode("utf-8")) 30057db96d56Sopenharmony_ci self.assertEqual(len(u_prefix), len(prefix)) 30067db96d56Sopenharmony_ci u_suffix = "\u8888\n" 30077db96d56Sopenharmony_ci suffix = bytes(u_suffix.encode("utf-8")) 30087db96d56Sopenharmony_ci line = prefix + suffix 30097db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "wb") as f: 30107db96d56Sopenharmony_ci f.write(line*2) 30117db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "r", encoding="utf-8") as f: 30127db96d56Sopenharmony_ci s = f.read(prefix_size) 30137db96d56Sopenharmony_ci self.assertEqual(s, str(prefix, "ascii")) 30147db96d56Sopenharmony_ci self.assertEqual(f.tell(), prefix_size) 30157db96d56Sopenharmony_ci self.assertEqual(f.readline(), u_suffix) 30167db96d56Sopenharmony_ci 30177db96d56Sopenharmony_ci def test_seeking_too(self): 30187db96d56Sopenharmony_ci # Regression test for a specific bug 30197db96d56Sopenharmony_ci data = b'\xe0\xbf\xbf\n' 30207db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "wb") as f: 30217db96d56Sopenharmony_ci f.write(data) 30227db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "r", encoding="utf-8") as f: 30237db96d56Sopenharmony_ci f._CHUNK_SIZE # Just test that it exists 30247db96d56Sopenharmony_ci f._CHUNK_SIZE = 2 30257db96d56Sopenharmony_ci f.readline() 30267db96d56Sopenharmony_ci f.tell() 30277db96d56Sopenharmony_ci 30287db96d56Sopenharmony_ci def test_seek_and_tell(self): 30297db96d56Sopenharmony_ci #Test seek/tell using the StatefulIncrementalDecoder. 30307db96d56Sopenharmony_ci # Make test faster by doing smaller seeks 30317db96d56Sopenharmony_ci CHUNK_SIZE = 128 30327db96d56Sopenharmony_ci 30337db96d56Sopenharmony_ci def test_seek_and_tell_with_data(data, min_pos=0): 30347db96d56Sopenharmony_ci """Tell/seek to various points within a data stream and ensure 30357db96d56Sopenharmony_ci that the decoded data returned by read() is consistent.""" 30367db96d56Sopenharmony_ci f = self.open(os_helper.TESTFN, 'wb') 30377db96d56Sopenharmony_ci f.write(data) 30387db96d56Sopenharmony_ci f.close() 30397db96d56Sopenharmony_ci f = self.open(os_helper.TESTFN, encoding='test_decoder') 30407db96d56Sopenharmony_ci f._CHUNK_SIZE = CHUNK_SIZE 30417db96d56Sopenharmony_ci decoded = f.read() 30427db96d56Sopenharmony_ci f.close() 30437db96d56Sopenharmony_ci 30447db96d56Sopenharmony_ci for i in range(min_pos, len(decoded) + 1): # seek positions 30457db96d56Sopenharmony_ci for j in [1, 5, len(decoded) - i]: # read lengths 30467db96d56Sopenharmony_ci f = self.open(os_helper.TESTFN, encoding='test_decoder') 30477db96d56Sopenharmony_ci self.assertEqual(f.read(i), decoded[:i]) 30487db96d56Sopenharmony_ci cookie = f.tell() 30497db96d56Sopenharmony_ci self.assertEqual(f.read(j), decoded[i:i + j]) 30507db96d56Sopenharmony_ci f.seek(cookie) 30517db96d56Sopenharmony_ci self.assertEqual(f.read(), decoded[i:]) 30527db96d56Sopenharmony_ci f.close() 30537db96d56Sopenharmony_ci 30547db96d56Sopenharmony_ci # Enable the test decoder. 30557db96d56Sopenharmony_ci StatefulIncrementalDecoder.codecEnabled = 1 30567db96d56Sopenharmony_ci 30577db96d56Sopenharmony_ci # Run the tests. 30587db96d56Sopenharmony_ci try: 30597db96d56Sopenharmony_ci # Try each test case. 30607db96d56Sopenharmony_ci for input, _, _ in StatefulIncrementalDecoderTest.test_cases: 30617db96d56Sopenharmony_ci test_seek_and_tell_with_data(input) 30627db96d56Sopenharmony_ci 30637db96d56Sopenharmony_ci # Position each test case so that it crosses a chunk boundary. 30647db96d56Sopenharmony_ci for input, _, _ in StatefulIncrementalDecoderTest.test_cases: 30657db96d56Sopenharmony_ci offset = CHUNK_SIZE - len(input)//2 30667db96d56Sopenharmony_ci prefix = b'.'*offset 30677db96d56Sopenharmony_ci # Don't bother seeking into the prefix (takes too long). 30687db96d56Sopenharmony_ci min_pos = offset*2 30697db96d56Sopenharmony_ci test_seek_and_tell_with_data(prefix + input, min_pos) 30707db96d56Sopenharmony_ci 30717db96d56Sopenharmony_ci # Ensure our test decoder won't interfere with subsequent tests. 30727db96d56Sopenharmony_ci finally: 30737db96d56Sopenharmony_ci StatefulIncrementalDecoder.codecEnabled = 0 30747db96d56Sopenharmony_ci 30757db96d56Sopenharmony_ci def test_multibyte_seek_and_tell(self): 30767db96d56Sopenharmony_ci f = self.open(os_helper.TESTFN, "w", encoding="euc_jp") 30777db96d56Sopenharmony_ci f.write("AB\n\u3046\u3048\n") 30787db96d56Sopenharmony_ci f.close() 30797db96d56Sopenharmony_ci 30807db96d56Sopenharmony_ci f = self.open(os_helper.TESTFN, "r", encoding="euc_jp") 30817db96d56Sopenharmony_ci self.assertEqual(f.readline(), "AB\n") 30827db96d56Sopenharmony_ci p0 = f.tell() 30837db96d56Sopenharmony_ci self.assertEqual(f.readline(), "\u3046\u3048\n") 30847db96d56Sopenharmony_ci p1 = f.tell() 30857db96d56Sopenharmony_ci f.seek(p0) 30867db96d56Sopenharmony_ci self.assertEqual(f.readline(), "\u3046\u3048\n") 30877db96d56Sopenharmony_ci self.assertEqual(f.tell(), p1) 30887db96d56Sopenharmony_ci f.close() 30897db96d56Sopenharmony_ci 30907db96d56Sopenharmony_ci def test_seek_with_encoder_state(self): 30917db96d56Sopenharmony_ci f = self.open(os_helper.TESTFN, "w", encoding="euc_jis_2004") 30927db96d56Sopenharmony_ci f.write("\u00e6\u0300") 30937db96d56Sopenharmony_ci p0 = f.tell() 30947db96d56Sopenharmony_ci f.write("\u00e6") 30957db96d56Sopenharmony_ci f.seek(p0) 30967db96d56Sopenharmony_ci f.write("\u0300") 30977db96d56Sopenharmony_ci f.close() 30987db96d56Sopenharmony_ci 30997db96d56Sopenharmony_ci f = self.open(os_helper.TESTFN, "r", encoding="euc_jis_2004") 31007db96d56Sopenharmony_ci self.assertEqual(f.readline(), "\u00e6\u0300\u0300") 31017db96d56Sopenharmony_ci f.close() 31027db96d56Sopenharmony_ci 31037db96d56Sopenharmony_ci def test_encoded_writes(self): 31047db96d56Sopenharmony_ci data = "1234567890" 31057db96d56Sopenharmony_ci tests = ("utf-16", 31067db96d56Sopenharmony_ci "utf-16-le", 31077db96d56Sopenharmony_ci "utf-16-be", 31087db96d56Sopenharmony_ci "utf-32", 31097db96d56Sopenharmony_ci "utf-32-le", 31107db96d56Sopenharmony_ci "utf-32-be") 31117db96d56Sopenharmony_ci for encoding in tests: 31127db96d56Sopenharmony_ci buf = self.BytesIO() 31137db96d56Sopenharmony_ci f = self.TextIOWrapper(buf, encoding=encoding) 31147db96d56Sopenharmony_ci # Check if the BOM is written only once (see issue1753). 31157db96d56Sopenharmony_ci f.write(data) 31167db96d56Sopenharmony_ci f.write(data) 31177db96d56Sopenharmony_ci f.seek(0) 31187db96d56Sopenharmony_ci self.assertEqual(f.read(), data * 2) 31197db96d56Sopenharmony_ci f.seek(0) 31207db96d56Sopenharmony_ci self.assertEqual(f.read(), data * 2) 31217db96d56Sopenharmony_ci self.assertEqual(buf.getvalue(), (data * 2).encode(encoding)) 31227db96d56Sopenharmony_ci 31237db96d56Sopenharmony_ci def test_unreadable(self): 31247db96d56Sopenharmony_ci class UnReadable(self.BytesIO): 31257db96d56Sopenharmony_ci def readable(self): 31267db96d56Sopenharmony_ci return False 31277db96d56Sopenharmony_ci txt = self.TextIOWrapper(UnReadable(), encoding="utf-8") 31287db96d56Sopenharmony_ci self.assertRaises(OSError, txt.read) 31297db96d56Sopenharmony_ci 31307db96d56Sopenharmony_ci def test_read_one_by_one(self): 31317db96d56Sopenharmony_ci txt = self.TextIOWrapper(self.BytesIO(b"AA\r\nBB"), encoding="utf-8") 31327db96d56Sopenharmony_ci reads = "" 31337db96d56Sopenharmony_ci while True: 31347db96d56Sopenharmony_ci c = txt.read(1) 31357db96d56Sopenharmony_ci if not c: 31367db96d56Sopenharmony_ci break 31377db96d56Sopenharmony_ci reads += c 31387db96d56Sopenharmony_ci self.assertEqual(reads, "AA\nBB") 31397db96d56Sopenharmony_ci 31407db96d56Sopenharmony_ci def test_readlines(self): 31417db96d56Sopenharmony_ci txt = self.TextIOWrapper(self.BytesIO(b"AA\nBB\nCC"), encoding="utf-8") 31427db96d56Sopenharmony_ci self.assertEqual(txt.readlines(), ["AA\n", "BB\n", "CC"]) 31437db96d56Sopenharmony_ci txt.seek(0) 31447db96d56Sopenharmony_ci self.assertEqual(txt.readlines(None), ["AA\n", "BB\n", "CC"]) 31457db96d56Sopenharmony_ci txt.seek(0) 31467db96d56Sopenharmony_ci self.assertEqual(txt.readlines(5), ["AA\n", "BB\n"]) 31477db96d56Sopenharmony_ci 31487db96d56Sopenharmony_ci # read in amounts equal to TextIOWrapper._CHUNK_SIZE which is 128. 31497db96d56Sopenharmony_ci def test_read_by_chunk(self): 31507db96d56Sopenharmony_ci # make sure "\r\n" straddles 128 char boundary. 31517db96d56Sopenharmony_ci txt = self.TextIOWrapper(self.BytesIO(b"A" * 127 + b"\r\nB"), encoding="utf-8") 31527db96d56Sopenharmony_ci reads = "" 31537db96d56Sopenharmony_ci while True: 31547db96d56Sopenharmony_ci c = txt.read(128) 31557db96d56Sopenharmony_ci if not c: 31567db96d56Sopenharmony_ci break 31577db96d56Sopenharmony_ci reads += c 31587db96d56Sopenharmony_ci self.assertEqual(reads, "A"*127+"\nB") 31597db96d56Sopenharmony_ci 31607db96d56Sopenharmony_ci def test_writelines(self): 31617db96d56Sopenharmony_ci l = ['ab', 'cd', 'ef'] 31627db96d56Sopenharmony_ci buf = self.BytesIO() 31637db96d56Sopenharmony_ci txt = self.TextIOWrapper(buf, encoding="utf-8") 31647db96d56Sopenharmony_ci txt.writelines(l) 31657db96d56Sopenharmony_ci txt.flush() 31667db96d56Sopenharmony_ci self.assertEqual(buf.getvalue(), b'abcdef') 31677db96d56Sopenharmony_ci 31687db96d56Sopenharmony_ci def test_writelines_userlist(self): 31697db96d56Sopenharmony_ci l = UserList(['ab', 'cd', 'ef']) 31707db96d56Sopenharmony_ci buf = self.BytesIO() 31717db96d56Sopenharmony_ci txt = self.TextIOWrapper(buf, encoding="utf-8") 31727db96d56Sopenharmony_ci txt.writelines(l) 31737db96d56Sopenharmony_ci txt.flush() 31747db96d56Sopenharmony_ci self.assertEqual(buf.getvalue(), b'abcdef') 31757db96d56Sopenharmony_ci 31767db96d56Sopenharmony_ci def test_writelines_error(self): 31777db96d56Sopenharmony_ci txt = self.TextIOWrapper(self.BytesIO(), encoding="utf-8") 31787db96d56Sopenharmony_ci self.assertRaises(TypeError, txt.writelines, [1, 2, 3]) 31797db96d56Sopenharmony_ci self.assertRaises(TypeError, txt.writelines, None) 31807db96d56Sopenharmony_ci self.assertRaises(TypeError, txt.writelines, b'abc') 31817db96d56Sopenharmony_ci 31827db96d56Sopenharmony_ci def test_issue1395_1(self): 31837db96d56Sopenharmony_ci txt = self.TextIOWrapper(self.BytesIO(self.testdata), encoding="ascii") 31847db96d56Sopenharmony_ci 31857db96d56Sopenharmony_ci # read one char at a time 31867db96d56Sopenharmony_ci reads = "" 31877db96d56Sopenharmony_ci while True: 31887db96d56Sopenharmony_ci c = txt.read(1) 31897db96d56Sopenharmony_ci if not c: 31907db96d56Sopenharmony_ci break 31917db96d56Sopenharmony_ci reads += c 31927db96d56Sopenharmony_ci self.assertEqual(reads, self.normalized) 31937db96d56Sopenharmony_ci 31947db96d56Sopenharmony_ci def test_issue1395_2(self): 31957db96d56Sopenharmony_ci txt = self.TextIOWrapper(self.BytesIO(self.testdata), encoding="ascii") 31967db96d56Sopenharmony_ci txt._CHUNK_SIZE = 4 31977db96d56Sopenharmony_ci 31987db96d56Sopenharmony_ci reads = "" 31997db96d56Sopenharmony_ci while True: 32007db96d56Sopenharmony_ci c = txt.read(4) 32017db96d56Sopenharmony_ci if not c: 32027db96d56Sopenharmony_ci break 32037db96d56Sopenharmony_ci reads += c 32047db96d56Sopenharmony_ci self.assertEqual(reads, self.normalized) 32057db96d56Sopenharmony_ci 32067db96d56Sopenharmony_ci def test_issue1395_3(self): 32077db96d56Sopenharmony_ci txt = self.TextIOWrapper(self.BytesIO(self.testdata), encoding="ascii") 32087db96d56Sopenharmony_ci txt._CHUNK_SIZE = 4 32097db96d56Sopenharmony_ci 32107db96d56Sopenharmony_ci reads = txt.read(4) 32117db96d56Sopenharmony_ci reads += txt.read(4) 32127db96d56Sopenharmony_ci reads += txt.readline() 32137db96d56Sopenharmony_ci reads += txt.readline() 32147db96d56Sopenharmony_ci reads += txt.readline() 32157db96d56Sopenharmony_ci self.assertEqual(reads, self.normalized) 32167db96d56Sopenharmony_ci 32177db96d56Sopenharmony_ci def test_issue1395_4(self): 32187db96d56Sopenharmony_ci txt = self.TextIOWrapper(self.BytesIO(self.testdata), encoding="ascii") 32197db96d56Sopenharmony_ci txt._CHUNK_SIZE = 4 32207db96d56Sopenharmony_ci 32217db96d56Sopenharmony_ci reads = txt.read(4) 32227db96d56Sopenharmony_ci reads += txt.read() 32237db96d56Sopenharmony_ci self.assertEqual(reads, self.normalized) 32247db96d56Sopenharmony_ci 32257db96d56Sopenharmony_ci def test_issue1395_5(self): 32267db96d56Sopenharmony_ci txt = self.TextIOWrapper(self.BytesIO(self.testdata), encoding="ascii") 32277db96d56Sopenharmony_ci txt._CHUNK_SIZE = 4 32287db96d56Sopenharmony_ci 32297db96d56Sopenharmony_ci reads = txt.read(4) 32307db96d56Sopenharmony_ci pos = txt.tell() 32317db96d56Sopenharmony_ci txt.seek(0) 32327db96d56Sopenharmony_ci txt.seek(pos) 32337db96d56Sopenharmony_ci self.assertEqual(txt.read(4), "BBB\n") 32347db96d56Sopenharmony_ci 32357db96d56Sopenharmony_ci def test_issue2282(self): 32367db96d56Sopenharmony_ci buffer = self.BytesIO(self.testdata) 32377db96d56Sopenharmony_ci txt = self.TextIOWrapper(buffer, encoding="ascii") 32387db96d56Sopenharmony_ci 32397db96d56Sopenharmony_ci self.assertEqual(buffer.seekable(), txt.seekable()) 32407db96d56Sopenharmony_ci 32417db96d56Sopenharmony_ci def test_append_bom(self): 32427db96d56Sopenharmony_ci # The BOM is not written again when appending to a non-empty file 32437db96d56Sopenharmony_ci filename = os_helper.TESTFN 32447db96d56Sopenharmony_ci for charset in ('utf-8-sig', 'utf-16', 'utf-32'): 32457db96d56Sopenharmony_ci with self.open(filename, 'w', encoding=charset) as f: 32467db96d56Sopenharmony_ci f.write('aaa') 32477db96d56Sopenharmony_ci pos = f.tell() 32487db96d56Sopenharmony_ci with self.open(filename, 'rb') as f: 32497db96d56Sopenharmony_ci self.assertEqual(f.read(), 'aaa'.encode(charset)) 32507db96d56Sopenharmony_ci 32517db96d56Sopenharmony_ci with self.open(filename, 'a', encoding=charset) as f: 32527db96d56Sopenharmony_ci f.write('xxx') 32537db96d56Sopenharmony_ci with self.open(filename, 'rb') as f: 32547db96d56Sopenharmony_ci self.assertEqual(f.read(), 'aaaxxx'.encode(charset)) 32557db96d56Sopenharmony_ci 32567db96d56Sopenharmony_ci def test_seek_bom(self): 32577db96d56Sopenharmony_ci # Same test, but when seeking manually 32587db96d56Sopenharmony_ci filename = os_helper.TESTFN 32597db96d56Sopenharmony_ci for charset in ('utf-8-sig', 'utf-16', 'utf-32'): 32607db96d56Sopenharmony_ci with self.open(filename, 'w', encoding=charset) as f: 32617db96d56Sopenharmony_ci f.write('aaa') 32627db96d56Sopenharmony_ci pos = f.tell() 32637db96d56Sopenharmony_ci with self.open(filename, 'r+', encoding=charset) as f: 32647db96d56Sopenharmony_ci f.seek(pos) 32657db96d56Sopenharmony_ci f.write('zzz') 32667db96d56Sopenharmony_ci f.seek(0) 32677db96d56Sopenharmony_ci f.write('bbb') 32687db96d56Sopenharmony_ci with self.open(filename, 'rb') as f: 32697db96d56Sopenharmony_ci self.assertEqual(f.read(), 'bbbzzz'.encode(charset)) 32707db96d56Sopenharmony_ci 32717db96d56Sopenharmony_ci def test_seek_append_bom(self): 32727db96d56Sopenharmony_ci # Same test, but first seek to the start and then to the end 32737db96d56Sopenharmony_ci filename = os_helper.TESTFN 32747db96d56Sopenharmony_ci for charset in ('utf-8-sig', 'utf-16', 'utf-32'): 32757db96d56Sopenharmony_ci with self.open(filename, 'w', encoding=charset) as f: 32767db96d56Sopenharmony_ci f.write('aaa') 32777db96d56Sopenharmony_ci with self.open(filename, 'a', encoding=charset) as f: 32787db96d56Sopenharmony_ci f.seek(0) 32797db96d56Sopenharmony_ci f.seek(0, self.SEEK_END) 32807db96d56Sopenharmony_ci f.write('xxx') 32817db96d56Sopenharmony_ci with self.open(filename, 'rb') as f: 32827db96d56Sopenharmony_ci self.assertEqual(f.read(), 'aaaxxx'.encode(charset)) 32837db96d56Sopenharmony_ci 32847db96d56Sopenharmony_ci def test_errors_property(self): 32857db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "w", encoding="utf-8") as f: 32867db96d56Sopenharmony_ci self.assertEqual(f.errors, "strict") 32877db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "w", encoding="utf-8", errors="replace") as f: 32887db96d56Sopenharmony_ci self.assertEqual(f.errors, "replace") 32897db96d56Sopenharmony_ci 32907db96d56Sopenharmony_ci @support.no_tracing 32917db96d56Sopenharmony_ci @threading_helper.requires_working_threading() 32927db96d56Sopenharmony_ci def test_threads_write(self): 32937db96d56Sopenharmony_ci # Issue6750: concurrent writes could duplicate data 32947db96d56Sopenharmony_ci event = threading.Event() 32957db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "w", encoding="utf-8", buffering=1) as f: 32967db96d56Sopenharmony_ci def run(n): 32977db96d56Sopenharmony_ci text = "Thread%03d\n" % n 32987db96d56Sopenharmony_ci event.wait() 32997db96d56Sopenharmony_ci f.write(text) 33007db96d56Sopenharmony_ci threads = [threading.Thread(target=run, args=(x,)) 33017db96d56Sopenharmony_ci for x in range(20)] 33027db96d56Sopenharmony_ci with threading_helper.start_threads(threads, event.set): 33037db96d56Sopenharmony_ci time.sleep(0.02) 33047db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, encoding="utf-8") as f: 33057db96d56Sopenharmony_ci content = f.read() 33067db96d56Sopenharmony_ci for n in range(20): 33077db96d56Sopenharmony_ci self.assertEqual(content.count("Thread%03d\n" % n), 1) 33087db96d56Sopenharmony_ci 33097db96d56Sopenharmony_ci def test_flush_error_on_close(self): 33107db96d56Sopenharmony_ci # Test that text file is closed despite failed flush 33117db96d56Sopenharmony_ci # and that flush() is called before file closed. 33127db96d56Sopenharmony_ci txt = self.TextIOWrapper(self.BytesIO(self.testdata), encoding="ascii") 33137db96d56Sopenharmony_ci closed = [] 33147db96d56Sopenharmony_ci def bad_flush(): 33157db96d56Sopenharmony_ci closed[:] = [txt.closed, txt.buffer.closed] 33167db96d56Sopenharmony_ci raise OSError() 33177db96d56Sopenharmony_ci txt.flush = bad_flush 33187db96d56Sopenharmony_ci self.assertRaises(OSError, txt.close) # exception not swallowed 33197db96d56Sopenharmony_ci self.assertTrue(txt.closed) 33207db96d56Sopenharmony_ci self.assertTrue(txt.buffer.closed) 33217db96d56Sopenharmony_ci self.assertTrue(closed) # flush() called 33227db96d56Sopenharmony_ci self.assertFalse(closed[0]) # flush() called before file closed 33237db96d56Sopenharmony_ci self.assertFalse(closed[1]) 33247db96d56Sopenharmony_ci txt.flush = lambda: None # break reference loop 33257db96d56Sopenharmony_ci 33267db96d56Sopenharmony_ci def test_close_error_on_close(self): 33277db96d56Sopenharmony_ci buffer = self.BytesIO(self.testdata) 33287db96d56Sopenharmony_ci def bad_flush(): 33297db96d56Sopenharmony_ci raise OSError('flush') 33307db96d56Sopenharmony_ci def bad_close(): 33317db96d56Sopenharmony_ci raise OSError('close') 33327db96d56Sopenharmony_ci buffer.close = bad_close 33337db96d56Sopenharmony_ci txt = self.TextIOWrapper(buffer, encoding="ascii") 33347db96d56Sopenharmony_ci txt.flush = bad_flush 33357db96d56Sopenharmony_ci with self.assertRaises(OSError) as err: # exception not swallowed 33367db96d56Sopenharmony_ci txt.close() 33377db96d56Sopenharmony_ci self.assertEqual(err.exception.args, ('close',)) 33387db96d56Sopenharmony_ci self.assertIsInstance(err.exception.__context__, OSError) 33397db96d56Sopenharmony_ci self.assertEqual(err.exception.__context__.args, ('flush',)) 33407db96d56Sopenharmony_ci self.assertFalse(txt.closed) 33417db96d56Sopenharmony_ci 33427db96d56Sopenharmony_ci # Silence destructor error 33437db96d56Sopenharmony_ci buffer.close = lambda: None 33447db96d56Sopenharmony_ci txt.flush = lambda: None 33457db96d56Sopenharmony_ci 33467db96d56Sopenharmony_ci def test_nonnormalized_close_error_on_close(self): 33477db96d56Sopenharmony_ci # Issue #21677 33487db96d56Sopenharmony_ci buffer = self.BytesIO(self.testdata) 33497db96d56Sopenharmony_ci def bad_flush(): 33507db96d56Sopenharmony_ci raise non_existing_flush 33517db96d56Sopenharmony_ci def bad_close(): 33527db96d56Sopenharmony_ci raise non_existing_close 33537db96d56Sopenharmony_ci buffer.close = bad_close 33547db96d56Sopenharmony_ci txt = self.TextIOWrapper(buffer, encoding="ascii") 33557db96d56Sopenharmony_ci txt.flush = bad_flush 33567db96d56Sopenharmony_ci with self.assertRaises(NameError) as err: # exception not swallowed 33577db96d56Sopenharmony_ci txt.close() 33587db96d56Sopenharmony_ci self.assertIn('non_existing_close', str(err.exception)) 33597db96d56Sopenharmony_ci self.assertIsInstance(err.exception.__context__, NameError) 33607db96d56Sopenharmony_ci self.assertIn('non_existing_flush', str(err.exception.__context__)) 33617db96d56Sopenharmony_ci self.assertFalse(txt.closed) 33627db96d56Sopenharmony_ci 33637db96d56Sopenharmony_ci # Silence destructor error 33647db96d56Sopenharmony_ci buffer.close = lambda: None 33657db96d56Sopenharmony_ci txt.flush = lambda: None 33667db96d56Sopenharmony_ci 33677db96d56Sopenharmony_ci def test_multi_close(self): 33687db96d56Sopenharmony_ci txt = self.TextIOWrapper(self.BytesIO(self.testdata), encoding="ascii") 33697db96d56Sopenharmony_ci txt.close() 33707db96d56Sopenharmony_ci txt.close() 33717db96d56Sopenharmony_ci txt.close() 33727db96d56Sopenharmony_ci self.assertRaises(ValueError, txt.flush) 33737db96d56Sopenharmony_ci 33747db96d56Sopenharmony_ci def test_unseekable(self): 33757db96d56Sopenharmony_ci txt = self.TextIOWrapper(self.MockUnseekableIO(self.testdata), encoding="utf-8") 33767db96d56Sopenharmony_ci self.assertRaises(self.UnsupportedOperation, txt.tell) 33777db96d56Sopenharmony_ci self.assertRaises(self.UnsupportedOperation, txt.seek, 0) 33787db96d56Sopenharmony_ci 33797db96d56Sopenharmony_ci def test_readonly_attributes(self): 33807db96d56Sopenharmony_ci txt = self.TextIOWrapper(self.BytesIO(self.testdata), encoding="ascii") 33817db96d56Sopenharmony_ci buf = self.BytesIO(self.testdata) 33827db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 33837db96d56Sopenharmony_ci txt.buffer = buf 33847db96d56Sopenharmony_ci 33857db96d56Sopenharmony_ci def test_rawio(self): 33867db96d56Sopenharmony_ci # Issue #12591: TextIOWrapper must work with raw I/O objects, so 33877db96d56Sopenharmony_ci # that subprocess.Popen() can have the required unbuffered 33887db96d56Sopenharmony_ci # semantics with universal_newlines=True. 33897db96d56Sopenharmony_ci raw = self.MockRawIO([b'abc', b'def', b'ghi\njkl\nopq\n']) 33907db96d56Sopenharmony_ci txt = self.TextIOWrapper(raw, encoding='ascii', newline='\n') 33917db96d56Sopenharmony_ci # Reads 33927db96d56Sopenharmony_ci self.assertEqual(txt.read(4), 'abcd') 33937db96d56Sopenharmony_ci self.assertEqual(txt.readline(), 'efghi\n') 33947db96d56Sopenharmony_ci self.assertEqual(list(txt), ['jkl\n', 'opq\n']) 33957db96d56Sopenharmony_ci 33967db96d56Sopenharmony_ci def test_rawio_write_through(self): 33977db96d56Sopenharmony_ci # Issue #12591: with write_through=True, writes don't need a flush 33987db96d56Sopenharmony_ci raw = self.MockRawIO([b'abc', b'def', b'ghi\njkl\nopq\n']) 33997db96d56Sopenharmony_ci txt = self.TextIOWrapper(raw, encoding='ascii', newline='\n', 34007db96d56Sopenharmony_ci write_through=True) 34017db96d56Sopenharmony_ci txt.write('1') 34027db96d56Sopenharmony_ci txt.write('23\n4') 34037db96d56Sopenharmony_ci txt.write('5') 34047db96d56Sopenharmony_ci self.assertEqual(b''.join(raw._write_stack), b'123\n45') 34057db96d56Sopenharmony_ci 34067db96d56Sopenharmony_ci def test_bufio_write_through(self): 34077db96d56Sopenharmony_ci # Issue #21396: write_through=True doesn't force a flush() 34087db96d56Sopenharmony_ci # on the underlying binary buffered object. 34097db96d56Sopenharmony_ci flush_called, write_called = [], [] 34107db96d56Sopenharmony_ci class BufferedWriter(self.BufferedWriter): 34117db96d56Sopenharmony_ci def flush(self, *args, **kwargs): 34127db96d56Sopenharmony_ci flush_called.append(True) 34137db96d56Sopenharmony_ci return super().flush(*args, **kwargs) 34147db96d56Sopenharmony_ci def write(self, *args, **kwargs): 34157db96d56Sopenharmony_ci write_called.append(True) 34167db96d56Sopenharmony_ci return super().write(*args, **kwargs) 34177db96d56Sopenharmony_ci 34187db96d56Sopenharmony_ci rawio = self.BytesIO() 34197db96d56Sopenharmony_ci data = b"a" 34207db96d56Sopenharmony_ci bufio = BufferedWriter(rawio, len(data)*2) 34217db96d56Sopenharmony_ci textio = self.TextIOWrapper(bufio, encoding='ascii', 34227db96d56Sopenharmony_ci write_through=True) 34237db96d56Sopenharmony_ci # write to the buffered io but don't overflow the buffer 34247db96d56Sopenharmony_ci text = data.decode('ascii') 34257db96d56Sopenharmony_ci textio.write(text) 34267db96d56Sopenharmony_ci 34277db96d56Sopenharmony_ci # buffer.flush is not called with write_through=True 34287db96d56Sopenharmony_ci self.assertFalse(flush_called) 34297db96d56Sopenharmony_ci # buffer.write *is* called with write_through=True 34307db96d56Sopenharmony_ci self.assertTrue(write_called) 34317db96d56Sopenharmony_ci self.assertEqual(rawio.getvalue(), b"") # no flush 34327db96d56Sopenharmony_ci 34337db96d56Sopenharmony_ci write_called = [] # reset 34347db96d56Sopenharmony_ci textio.write(text * 10) # total content is larger than bufio buffer 34357db96d56Sopenharmony_ci self.assertTrue(write_called) 34367db96d56Sopenharmony_ci self.assertEqual(rawio.getvalue(), data * 11) # all flushed 34377db96d56Sopenharmony_ci 34387db96d56Sopenharmony_ci def test_reconfigure_write_through(self): 34397db96d56Sopenharmony_ci raw = self.MockRawIO([]) 34407db96d56Sopenharmony_ci t = self.TextIOWrapper(raw, encoding='ascii', newline='\n') 34417db96d56Sopenharmony_ci t.write('1') 34427db96d56Sopenharmony_ci t.reconfigure(write_through=True) # implied flush 34437db96d56Sopenharmony_ci self.assertEqual(t.write_through, True) 34447db96d56Sopenharmony_ci self.assertEqual(b''.join(raw._write_stack), b'1') 34457db96d56Sopenharmony_ci t.write('23') 34467db96d56Sopenharmony_ci self.assertEqual(b''.join(raw._write_stack), b'123') 34477db96d56Sopenharmony_ci t.reconfigure(write_through=False) 34487db96d56Sopenharmony_ci self.assertEqual(t.write_through, False) 34497db96d56Sopenharmony_ci t.write('45') 34507db96d56Sopenharmony_ci t.flush() 34517db96d56Sopenharmony_ci self.assertEqual(b''.join(raw._write_stack), b'12345') 34527db96d56Sopenharmony_ci # Keeping default value 34537db96d56Sopenharmony_ci t.reconfigure() 34547db96d56Sopenharmony_ci t.reconfigure(write_through=None) 34557db96d56Sopenharmony_ci self.assertEqual(t.write_through, False) 34567db96d56Sopenharmony_ci t.reconfigure(write_through=True) 34577db96d56Sopenharmony_ci t.reconfigure() 34587db96d56Sopenharmony_ci t.reconfigure(write_through=None) 34597db96d56Sopenharmony_ci self.assertEqual(t.write_through, True) 34607db96d56Sopenharmony_ci 34617db96d56Sopenharmony_ci def test_read_nonbytes(self): 34627db96d56Sopenharmony_ci # Issue #17106 34637db96d56Sopenharmony_ci # Crash when underlying read() returns non-bytes 34647db96d56Sopenharmony_ci t = self.TextIOWrapper(self.StringIO('a'), encoding="utf-8") 34657db96d56Sopenharmony_ci self.assertRaises(TypeError, t.read, 1) 34667db96d56Sopenharmony_ci t = self.TextIOWrapper(self.StringIO('a'), encoding="utf-8") 34677db96d56Sopenharmony_ci self.assertRaises(TypeError, t.readline) 34687db96d56Sopenharmony_ci t = self.TextIOWrapper(self.StringIO('a'), encoding="utf-8") 34697db96d56Sopenharmony_ci self.assertRaises(TypeError, t.read) 34707db96d56Sopenharmony_ci 34717db96d56Sopenharmony_ci def test_illegal_encoder(self): 34727db96d56Sopenharmony_ci # Issue 31271: Calling write() while the return value of encoder's 34737db96d56Sopenharmony_ci # encode() is invalid shouldn't cause an assertion failure. 34747db96d56Sopenharmony_ci rot13 = codecs.lookup("rot13") 34757db96d56Sopenharmony_ci with support.swap_attr(rot13, '_is_text_encoding', True): 34767db96d56Sopenharmony_ci t = io.TextIOWrapper(io.BytesIO(b'foo'), encoding="rot13") 34777db96d56Sopenharmony_ci self.assertRaises(TypeError, t.write, 'bar') 34787db96d56Sopenharmony_ci 34797db96d56Sopenharmony_ci def test_illegal_decoder(self): 34807db96d56Sopenharmony_ci # Issue #17106 34817db96d56Sopenharmony_ci # Bypass the early encoding check added in issue 20404 34827db96d56Sopenharmony_ci def _make_illegal_wrapper(): 34837db96d56Sopenharmony_ci quopri = codecs.lookup("quopri") 34847db96d56Sopenharmony_ci quopri._is_text_encoding = True 34857db96d56Sopenharmony_ci try: 34867db96d56Sopenharmony_ci t = self.TextIOWrapper(self.BytesIO(b'aaaaaa'), 34877db96d56Sopenharmony_ci newline='\n', encoding="quopri") 34887db96d56Sopenharmony_ci finally: 34897db96d56Sopenharmony_ci quopri._is_text_encoding = False 34907db96d56Sopenharmony_ci return t 34917db96d56Sopenharmony_ci # Crash when decoder returns non-string 34927db96d56Sopenharmony_ci t = _make_illegal_wrapper() 34937db96d56Sopenharmony_ci self.assertRaises(TypeError, t.read, 1) 34947db96d56Sopenharmony_ci t = _make_illegal_wrapper() 34957db96d56Sopenharmony_ci self.assertRaises(TypeError, t.readline) 34967db96d56Sopenharmony_ci t = _make_illegal_wrapper() 34977db96d56Sopenharmony_ci self.assertRaises(TypeError, t.read) 34987db96d56Sopenharmony_ci 34997db96d56Sopenharmony_ci # Issue 31243: calling read() while the return value of decoder's 35007db96d56Sopenharmony_ci # getstate() is invalid should neither crash the interpreter nor 35017db96d56Sopenharmony_ci # raise a SystemError. 35027db96d56Sopenharmony_ci def _make_very_illegal_wrapper(getstate_ret_val): 35037db96d56Sopenharmony_ci class BadDecoder: 35047db96d56Sopenharmony_ci def getstate(self): 35057db96d56Sopenharmony_ci return getstate_ret_val 35067db96d56Sopenharmony_ci def _get_bad_decoder(dummy): 35077db96d56Sopenharmony_ci return BadDecoder() 35087db96d56Sopenharmony_ci quopri = codecs.lookup("quopri") 35097db96d56Sopenharmony_ci with support.swap_attr(quopri, 'incrementaldecoder', 35107db96d56Sopenharmony_ci _get_bad_decoder): 35117db96d56Sopenharmony_ci return _make_illegal_wrapper() 35127db96d56Sopenharmony_ci t = _make_very_illegal_wrapper(42) 35137db96d56Sopenharmony_ci self.assertRaises(TypeError, t.read, 42) 35147db96d56Sopenharmony_ci t = _make_very_illegal_wrapper(()) 35157db96d56Sopenharmony_ci self.assertRaises(TypeError, t.read, 42) 35167db96d56Sopenharmony_ci t = _make_very_illegal_wrapper((1, 2)) 35177db96d56Sopenharmony_ci self.assertRaises(TypeError, t.read, 42) 35187db96d56Sopenharmony_ci 35197db96d56Sopenharmony_ci def _check_create_at_shutdown(self, **kwargs): 35207db96d56Sopenharmony_ci # Issue #20037: creating a TextIOWrapper at shutdown 35217db96d56Sopenharmony_ci # shouldn't crash the interpreter. 35227db96d56Sopenharmony_ci iomod = self.io.__name__ 35237db96d56Sopenharmony_ci code = """if 1: 35247db96d56Sopenharmony_ci import codecs 35257db96d56Sopenharmony_ci import {iomod} as io 35267db96d56Sopenharmony_ci 35277db96d56Sopenharmony_ci # Avoid looking up codecs at shutdown 35287db96d56Sopenharmony_ci codecs.lookup('utf-8') 35297db96d56Sopenharmony_ci 35307db96d56Sopenharmony_ci class C: 35317db96d56Sopenharmony_ci def __init__(self): 35327db96d56Sopenharmony_ci self.buf = io.BytesIO() 35337db96d56Sopenharmony_ci def __del__(self): 35347db96d56Sopenharmony_ci io.TextIOWrapper(self.buf, **{kwargs}) 35357db96d56Sopenharmony_ci print("ok") 35367db96d56Sopenharmony_ci c = C() 35377db96d56Sopenharmony_ci """.format(iomod=iomod, kwargs=kwargs) 35387db96d56Sopenharmony_ci return assert_python_ok("-c", code) 35397db96d56Sopenharmony_ci 35407db96d56Sopenharmony_ci def test_create_at_shutdown_without_encoding(self): 35417db96d56Sopenharmony_ci rc, out, err = self._check_create_at_shutdown() 35427db96d56Sopenharmony_ci if err: 35437db96d56Sopenharmony_ci # Can error out with a RuntimeError if the module state 35447db96d56Sopenharmony_ci # isn't found. 35457db96d56Sopenharmony_ci self.assertIn(self.shutdown_error, err.decode()) 35467db96d56Sopenharmony_ci else: 35477db96d56Sopenharmony_ci self.assertEqual("ok", out.decode().strip()) 35487db96d56Sopenharmony_ci 35497db96d56Sopenharmony_ci def test_create_at_shutdown_with_encoding(self): 35507db96d56Sopenharmony_ci rc, out, err = self._check_create_at_shutdown(encoding='utf-8', 35517db96d56Sopenharmony_ci errors='strict') 35527db96d56Sopenharmony_ci self.assertFalse(err) 35537db96d56Sopenharmony_ci self.assertEqual("ok", out.decode().strip()) 35547db96d56Sopenharmony_ci 35557db96d56Sopenharmony_ci def test_read_byteslike(self): 35567db96d56Sopenharmony_ci r = MemviewBytesIO(b'Just some random string\n') 35577db96d56Sopenharmony_ci t = self.TextIOWrapper(r, 'utf-8') 35587db96d56Sopenharmony_ci 35597db96d56Sopenharmony_ci # TextIOwrapper will not read the full string, because 35607db96d56Sopenharmony_ci # we truncate it to a multiple of the native int size 35617db96d56Sopenharmony_ci # so that we can construct a more complex memoryview. 35627db96d56Sopenharmony_ci bytes_val = _to_memoryview(r.getvalue()).tobytes() 35637db96d56Sopenharmony_ci 35647db96d56Sopenharmony_ci self.assertEqual(t.read(200), bytes_val.decode('utf-8')) 35657db96d56Sopenharmony_ci 35667db96d56Sopenharmony_ci def test_issue22849(self): 35677db96d56Sopenharmony_ci class F(object): 35687db96d56Sopenharmony_ci def readable(self): return True 35697db96d56Sopenharmony_ci def writable(self): return True 35707db96d56Sopenharmony_ci def seekable(self): return True 35717db96d56Sopenharmony_ci 35727db96d56Sopenharmony_ci for i in range(10): 35737db96d56Sopenharmony_ci try: 35747db96d56Sopenharmony_ci self.TextIOWrapper(F(), encoding='utf-8') 35757db96d56Sopenharmony_ci except Exception: 35767db96d56Sopenharmony_ci pass 35777db96d56Sopenharmony_ci 35787db96d56Sopenharmony_ci F.tell = lambda x: 0 35797db96d56Sopenharmony_ci t = self.TextIOWrapper(F(), encoding='utf-8') 35807db96d56Sopenharmony_ci 35817db96d56Sopenharmony_ci def test_reconfigure_locale(self): 35827db96d56Sopenharmony_ci wrapper = io.TextIOWrapper(io.BytesIO(b"test")) 35837db96d56Sopenharmony_ci wrapper.reconfigure(encoding="locale") 35847db96d56Sopenharmony_ci 35857db96d56Sopenharmony_ci def test_reconfigure_encoding_read(self): 35867db96d56Sopenharmony_ci # latin1 -> utf8 35877db96d56Sopenharmony_ci # (latin1 can decode utf-8 encoded string) 35887db96d56Sopenharmony_ci data = 'abc\xe9\n'.encode('latin1') + 'd\xe9f\n'.encode('utf8') 35897db96d56Sopenharmony_ci raw = self.BytesIO(data) 35907db96d56Sopenharmony_ci txt = self.TextIOWrapper(raw, encoding='latin1', newline='\n') 35917db96d56Sopenharmony_ci self.assertEqual(txt.readline(), 'abc\xe9\n') 35927db96d56Sopenharmony_ci with self.assertRaises(self.UnsupportedOperation): 35937db96d56Sopenharmony_ci txt.reconfigure(encoding='utf-8') 35947db96d56Sopenharmony_ci with self.assertRaises(self.UnsupportedOperation): 35957db96d56Sopenharmony_ci txt.reconfigure(newline=None) 35967db96d56Sopenharmony_ci 35977db96d56Sopenharmony_ci def test_reconfigure_write_fromascii(self): 35987db96d56Sopenharmony_ci # ascii has a specific encodefunc in the C implementation, 35997db96d56Sopenharmony_ci # but utf-8-sig has not. Make sure that we get rid of the 36007db96d56Sopenharmony_ci # cached encodefunc when we switch encoders. 36017db96d56Sopenharmony_ci raw = self.BytesIO() 36027db96d56Sopenharmony_ci txt = self.TextIOWrapper(raw, encoding='ascii', newline='\n') 36037db96d56Sopenharmony_ci txt.write('foo\n') 36047db96d56Sopenharmony_ci txt.reconfigure(encoding='utf-8-sig') 36057db96d56Sopenharmony_ci txt.write('\xe9\n') 36067db96d56Sopenharmony_ci txt.flush() 36077db96d56Sopenharmony_ci self.assertEqual(raw.getvalue(), b'foo\n\xc3\xa9\n') 36087db96d56Sopenharmony_ci 36097db96d56Sopenharmony_ci def test_reconfigure_write(self): 36107db96d56Sopenharmony_ci # latin -> utf8 36117db96d56Sopenharmony_ci raw = self.BytesIO() 36127db96d56Sopenharmony_ci txt = self.TextIOWrapper(raw, encoding='latin1', newline='\n') 36137db96d56Sopenharmony_ci txt.write('abc\xe9\n') 36147db96d56Sopenharmony_ci txt.reconfigure(encoding='utf-8') 36157db96d56Sopenharmony_ci self.assertEqual(raw.getvalue(), b'abc\xe9\n') 36167db96d56Sopenharmony_ci txt.write('d\xe9f\n') 36177db96d56Sopenharmony_ci txt.flush() 36187db96d56Sopenharmony_ci self.assertEqual(raw.getvalue(), b'abc\xe9\nd\xc3\xa9f\n') 36197db96d56Sopenharmony_ci 36207db96d56Sopenharmony_ci # ascii -> utf-8-sig: ensure that no BOM is written in the middle of 36217db96d56Sopenharmony_ci # the file 36227db96d56Sopenharmony_ci raw = self.BytesIO() 36237db96d56Sopenharmony_ci txt = self.TextIOWrapper(raw, encoding='ascii', newline='\n') 36247db96d56Sopenharmony_ci txt.write('abc\n') 36257db96d56Sopenharmony_ci txt.reconfigure(encoding='utf-8-sig') 36267db96d56Sopenharmony_ci txt.write('d\xe9f\n') 36277db96d56Sopenharmony_ci txt.flush() 36287db96d56Sopenharmony_ci self.assertEqual(raw.getvalue(), b'abc\nd\xc3\xa9f\n') 36297db96d56Sopenharmony_ci 36307db96d56Sopenharmony_ci def test_reconfigure_write_non_seekable(self): 36317db96d56Sopenharmony_ci raw = self.BytesIO() 36327db96d56Sopenharmony_ci raw.seekable = lambda: False 36337db96d56Sopenharmony_ci raw.seek = None 36347db96d56Sopenharmony_ci txt = self.TextIOWrapper(raw, encoding='ascii', newline='\n') 36357db96d56Sopenharmony_ci txt.write('abc\n') 36367db96d56Sopenharmony_ci txt.reconfigure(encoding='utf-8-sig') 36377db96d56Sopenharmony_ci txt.write('d\xe9f\n') 36387db96d56Sopenharmony_ci txt.flush() 36397db96d56Sopenharmony_ci 36407db96d56Sopenharmony_ci # If the raw stream is not seekable, there'll be a BOM 36417db96d56Sopenharmony_ci self.assertEqual(raw.getvalue(), b'abc\n\xef\xbb\xbfd\xc3\xa9f\n') 36427db96d56Sopenharmony_ci 36437db96d56Sopenharmony_ci def test_reconfigure_defaults(self): 36447db96d56Sopenharmony_ci txt = self.TextIOWrapper(self.BytesIO(), 'ascii', 'replace', '\n') 36457db96d56Sopenharmony_ci txt.reconfigure(encoding=None) 36467db96d56Sopenharmony_ci self.assertEqual(txt.encoding, 'ascii') 36477db96d56Sopenharmony_ci self.assertEqual(txt.errors, 'replace') 36487db96d56Sopenharmony_ci txt.write('LF\n') 36497db96d56Sopenharmony_ci 36507db96d56Sopenharmony_ci txt.reconfigure(newline='\r\n') 36517db96d56Sopenharmony_ci self.assertEqual(txt.encoding, 'ascii') 36527db96d56Sopenharmony_ci self.assertEqual(txt.errors, 'replace') 36537db96d56Sopenharmony_ci 36547db96d56Sopenharmony_ci txt.reconfigure(errors='ignore') 36557db96d56Sopenharmony_ci self.assertEqual(txt.encoding, 'ascii') 36567db96d56Sopenharmony_ci self.assertEqual(txt.errors, 'ignore') 36577db96d56Sopenharmony_ci txt.write('CRLF\n') 36587db96d56Sopenharmony_ci 36597db96d56Sopenharmony_ci txt.reconfigure(encoding='utf-8', newline=None) 36607db96d56Sopenharmony_ci self.assertEqual(txt.errors, 'strict') 36617db96d56Sopenharmony_ci txt.seek(0) 36627db96d56Sopenharmony_ci self.assertEqual(txt.read(), 'LF\nCRLF\n') 36637db96d56Sopenharmony_ci 36647db96d56Sopenharmony_ci self.assertEqual(txt.detach().getvalue(), b'LF\nCRLF\r\n') 36657db96d56Sopenharmony_ci 36667db96d56Sopenharmony_ci def test_reconfigure_newline(self): 36677db96d56Sopenharmony_ci raw = self.BytesIO(b'CR\rEOF') 36687db96d56Sopenharmony_ci txt = self.TextIOWrapper(raw, 'ascii', newline='\n') 36697db96d56Sopenharmony_ci txt.reconfigure(newline=None) 36707db96d56Sopenharmony_ci self.assertEqual(txt.readline(), 'CR\n') 36717db96d56Sopenharmony_ci raw = self.BytesIO(b'CR\rEOF') 36727db96d56Sopenharmony_ci txt = self.TextIOWrapper(raw, 'ascii', newline='\n') 36737db96d56Sopenharmony_ci txt.reconfigure(newline='') 36747db96d56Sopenharmony_ci self.assertEqual(txt.readline(), 'CR\r') 36757db96d56Sopenharmony_ci raw = self.BytesIO(b'CR\rLF\nEOF') 36767db96d56Sopenharmony_ci txt = self.TextIOWrapper(raw, 'ascii', newline='\r') 36777db96d56Sopenharmony_ci txt.reconfigure(newline='\n') 36787db96d56Sopenharmony_ci self.assertEqual(txt.readline(), 'CR\rLF\n') 36797db96d56Sopenharmony_ci raw = self.BytesIO(b'LF\nCR\rEOF') 36807db96d56Sopenharmony_ci txt = self.TextIOWrapper(raw, 'ascii', newline='\n') 36817db96d56Sopenharmony_ci txt.reconfigure(newline='\r') 36827db96d56Sopenharmony_ci self.assertEqual(txt.readline(), 'LF\nCR\r') 36837db96d56Sopenharmony_ci raw = self.BytesIO(b'CR\rCRLF\r\nEOF') 36847db96d56Sopenharmony_ci txt = self.TextIOWrapper(raw, 'ascii', newline='\r') 36857db96d56Sopenharmony_ci txt.reconfigure(newline='\r\n') 36867db96d56Sopenharmony_ci self.assertEqual(txt.readline(), 'CR\rCRLF\r\n') 36877db96d56Sopenharmony_ci 36887db96d56Sopenharmony_ci txt = self.TextIOWrapper(self.BytesIO(), 'ascii', newline='\r') 36897db96d56Sopenharmony_ci txt.reconfigure(newline=None) 36907db96d56Sopenharmony_ci txt.write('linesep\n') 36917db96d56Sopenharmony_ci txt.reconfigure(newline='') 36927db96d56Sopenharmony_ci txt.write('LF\n') 36937db96d56Sopenharmony_ci txt.reconfigure(newline='\n') 36947db96d56Sopenharmony_ci txt.write('LF\n') 36957db96d56Sopenharmony_ci txt.reconfigure(newline='\r') 36967db96d56Sopenharmony_ci txt.write('CR\n') 36977db96d56Sopenharmony_ci txt.reconfigure(newline='\r\n') 36987db96d56Sopenharmony_ci txt.write('CRLF\n') 36997db96d56Sopenharmony_ci expected = 'linesep' + os.linesep + 'LF\nLF\nCR\rCRLF\r\n' 37007db96d56Sopenharmony_ci self.assertEqual(txt.detach().getvalue().decode('ascii'), expected) 37017db96d56Sopenharmony_ci 37027db96d56Sopenharmony_ci def test_issue25862(self): 37037db96d56Sopenharmony_ci # Assertion failures occurred in tell() after read() and write(). 37047db96d56Sopenharmony_ci t = self.TextIOWrapper(self.BytesIO(b'test'), encoding='ascii') 37057db96d56Sopenharmony_ci t.read(1) 37067db96d56Sopenharmony_ci t.read() 37077db96d56Sopenharmony_ci t.tell() 37087db96d56Sopenharmony_ci t = self.TextIOWrapper(self.BytesIO(b'test'), encoding='ascii') 37097db96d56Sopenharmony_ci t.read(1) 37107db96d56Sopenharmony_ci t.write('x') 37117db96d56Sopenharmony_ci t.tell() 37127db96d56Sopenharmony_ci 37137db96d56Sopenharmony_ci 37147db96d56Sopenharmony_ciclass MemviewBytesIO(io.BytesIO): 37157db96d56Sopenharmony_ci '''A BytesIO object whose read method returns memoryviews 37167db96d56Sopenharmony_ci rather than bytes''' 37177db96d56Sopenharmony_ci 37187db96d56Sopenharmony_ci def read1(self, len_): 37197db96d56Sopenharmony_ci return _to_memoryview(super().read1(len_)) 37207db96d56Sopenharmony_ci 37217db96d56Sopenharmony_ci def read(self, len_): 37227db96d56Sopenharmony_ci return _to_memoryview(super().read(len_)) 37237db96d56Sopenharmony_ci 37247db96d56Sopenharmony_cidef _to_memoryview(buf): 37257db96d56Sopenharmony_ci '''Convert bytes-object *buf* to a non-trivial memoryview''' 37267db96d56Sopenharmony_ci 37277db96d56Sopenharmony_ci arr = array.array('i') 37287db96d56Sopenharmony_ci idx = len(buf) - len(buf) % arr.itemsize 37297db96d56Sopenharmony_ci arr.frombytes(buf[:idx]) 37307db96d56Sopenharmony_ci return memoryview(arr) 37317db96d56Sopenharmony_ci 37327db96d56Sopenharmony_ci 37337db96d56Sopenharmony_ciclass CTextIOWrapperTest(TextIOWrapperTest): 37347db96d56Sopenharmony_ci io = io 37357db96d56Sopenharmony_ci shutdown_error = "LookupError: unknown encoding: ascii" 37367db96d56Sopenharmony_ci 37377db96d56Sopenharmony_ci def test_initialization(self): 37387db96d56Sopenharmony_ci r = self.BytesIO(b"\xc3\xa9\n\n") 37397db96d56Sopenharmony_ci b = self.BufferedReader(r, 1000) 37407db96d56Sopenharmony_ci t = self.TextIOWrapper(b, encoding="utf-8") 37417db96d56Sopenharmony_ci self.assertRaises(ValueError, t.__init__, b, encoding="utf-8", newline='xyzzy') 37427db96d56Sopenharmony_ci self.assertRaises(ValueError, t.read) 37437db96d56Sopenharmony_ci 37447db96d56Sopenharmony_ci t = self.TextIOWrapper.__new__(self.TextIOWrapper) 37457db96d56Sopenharmony_ci self.assertRaises(Exception, repr, t) 37467db96d56Sopenharmony_ci 37477db96d56Sopenharmony_ci def test_garbage_collection(self): 37487db96d56Sopenharmony_ci # C TextIOWrapper objects are collected, and collecting them flushes 37497db96d56Sopenharmony_ci # all data to disk. 37507db96d56Sopenharmony_ci # The Python version has __del__, so it ends in gc.garbage instead. 37517db96d56Sopenharmony_ci with warnings_helper.check_warnings(('', ResourceWarning)): 37527db96d56Sopenharmony_ci rawio = io.FileIO(os_helper.TESTFN, "wb") 37537db96d56Sopenharmony_ci b = self.BufferedWriter(rawio) 37547db96d56Sopenharmony_ci t = self.TextIOWrapper(b, encoding="ascii") 37557db96d56Sopenharmony_ci t.write("456def") 37567db96d56Sopenharmony_ci t.x = t 37577db96d56Sopenharmony_ci wr = weakref.ref(t) 37587db96d56Sopenharmony_ci del t 37597db96d56Sopenharmony_ci support.gc_collect() 37607db96d56Sopenharmony_ci self.assertIsNone(wr(), wr) 37617db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "rb") as f: 37627db96d56Sopenharmony_ci self.assertEqual(f.read(), b"456def") 37637db96d56Sopenharmony_ci 37647db96d56Sopenharmony_ci def test_rwpair_cleared_before_textio(self): 37657db96d56Sopenharmony_ci # Issue 13070: TextIOWrapper's finalization would crash when called 37667db96d56Sopenharmony_ci # after the reference to the underlying BufferedRWPair's writer got 37677db96d56Sopenharmony_ci # cleared by the GC. 37687db96d56Sopenharmony_ci for i in range(1000): 37697db96d56Sopenharmony_ci b1 = self.BufferedRWPair(self.MockRawIO(), self.MockRawIO()) 37707db96d56Sopenharmony_ci t1 = self.TextIOWrapper(b1, encoding="ascii") 37717db96d56Sopenharmony_ci b2 = self.BufferedRWPair(self.MockRawIO(), self.MockRawIO()) 37727db96d56Sopenharmony_ci t2 = self.TextIOWrapper(b2, encoding="ascii") 37737db96d56Sopenharmony_ci # circular references 37747db96d56Sopenharmony_ci t1.buddy = t2 37757db96d56Sopenharmony_ci t2.buddy = t1 37767db96d56Sopenharmony_ci support.gc_collect() 37777db96d56Sopenharmony_ci 37787db96d56Sopenharmony_ci def test_del__CHUNK_SIZE_SystemError(self): 37797db96d56Sopenharmony_ci t = self.TextIOWrapper(self.BytesIO(), encoding='ascii') 37807db96d56Sopenharmony_ci with self.assertRaises(AttributeError): 37817db96d56Sopenharmony_ci del t._CHUNK_SIZE 37827db96d56Sopenharmony_ci 37837db96d56Sopenharmony_ci def test_internal_buffer_size(self): 37847db96d56Sopenharmony_ci # bpo-43260: TextIOWrapper's internal buffer should not store 37857db96d56Sopenharmony_ci # data larger than chunk size. 37867db96d56Sopenharmony_ci chunk_size = 8192 # default chunk size, updated later 37877db96d56Sopenharmony_ci 37887db96d56Sopenharmony_ci class MockIO(self.MockRawIO): 37897db96d56Sopenharmony_ci def write(self, data): 37907db96d56Sopenharmony_ci if len(data) > chunk_size: 37917db96d56Sopenharmony_ci raise RuntimeError 37927db96d56Sopenharmony_ci return super().write(data) 37937db96d56Sopenharmony_ci 37947db96d56Sopenharmony_ci buf = MockIO() 37957db96d56Sopenharmony_ci t = self.TextIOWrapper(buf, encoding="ascii") 37967db96d56Sopenharmony_ci chunk_size = t._CHUNK_SIZE 37977db96d56Sopenharmony_ci t.write("abc") 37987db96d56Sopenharmony_ci t.write("def") 37997db96d56Sopenharmony_ci # default chunk size is 8192 bytes so t don't write data to buf. 38007db96d56Sopenharmony_ci self.assertEqual([], buf._write_stack) 38017db96d56Sopenharmony_ci 38027db96d56Sopenharmony_ci with self.assertRaises(RuntimeError): 38037db96d56Sopenharmony_ci t.write("x"*(chunk_size+1)) 38047db96d56Sopenharmony_ci 38057db96d56Sopenharmony_ci self.assertEqual([b"abcdef"], buf._write_stack) 38067db96d56Sopenharmony_ci t.write("ghi") 38077db96d56Sopenharmony_ci t.write("x"*chunk_size) 38087db96d56Sopenharmony_ci self.assertEqual([b"abcdef", b"ghi", b"x"*chunk_size], buf._write_stack) 38097db96d56Sopenharmony_ci 38107db96d56Sopenharmony_ci 38117db96d56Sopenharmony_ciclass PyTextIOWrapperTest(TextIOWrapperTest): 38127db96d56Sopenharmony_ci io = pyio 38137db96d56Sopenharmony_ci shutdown_error = "LookupError: unknown encoding: ascii" 38147db96d56Sopenharmony_ci 38157db96d56Sopenharmony_ci 38167db96d56Sopenharmony_ciclass IncrementalNewlineDecoderTest(unittest.TestCase): 38177db96d56Sopenharmony_ci 38187db96d56Sopenharmony_ci def check_newline_decoding_utf8(self, decoder): 38197db96d56Sopenharmony_ci # UTF-8 specific tests for a newline decoder 38207db96d56Sopenharmony_ci def _check_decode(b, s, **kwargs): 38217db96d56Sopenharmony_ci # We exercise getstate() / setstate() as well as decode() 38227db96d56Sopenharmony_ci state = decoder.getstate() 38237db96d56Sopenharmony_ci self.assertEqual(decoder.decode(b, **kwargs), s) 38247db96d56Sopenharmony_ci decoder.setstate(state) 38257db96d56Sopenharmony_ci self.assertEqual(decoder.decode(b, **kwargs), s) 38267db96d56Sopenharmony_ci 38277db96d56Sopenharmony_ci _check_decode(b'\xe8\xa2\x88', "\u8888") 38287db96d56Sopenharmony_ci 38297db96d56Sopenharmony_ci _check_decode(b'\xe8', "") 38307db96d56Sopenharmony_ci _check_decode(b'\xa2', "") 38317db96d56Sopenharmony_ci _check_decode(b'\x88', "\u8888") 38327db96d56Sopenharmony_ci 38337db96d56Sopenharmony_ci _check_decode(b'\xe8', "") 38347db96d56Sopenharmony_ci _check_decode(b'\xa2', "") 38357db96d56Sopenharmony_ci _check_decode(b'\x88', "\u8888") 38367db96d56Sopenharmony_ci 38377db96d56Sopenharmony_ci _check_decode(b'\xe8', "") 38387db96d56Sopenharmony_ci self.assertRaises(UnicodeDecodeError, decoder.decode, b'', final=True) 38397db96d56Sopenharmony_ci 38407db96d56Sopenharmony_ci decoder.reset() 38417db96d56Sopenharmony_ci _check_decode(b'\n', "\n") 38427db96d56Sopenharmony_ci _check_decode(b'\r', "") 38437db96d56Sopenharmony_ci _check_decode(b'', "\n", final=True) 38447db96d56Sopenharmony_ci _check_decode(b'\r', "\n", final=True) 38457db96d56Sopenharmony_ci 38467db96d56Sopenharmony_ci _check_decode(b'\r', "") 38477db96d56Sopenharmony_ci _check_decode(b'a', "\na") 38487db96d56Sopenharmony_ci 38497db96d56Sopenharmony_ci _check_decode(b'\r\r\n', "\n\n") 38507db96d56Sopenharmony_ci _check_decode(b'\r', "") 38517db96d56Sopenharmony_ci _check_decode(b'\r', "\n") 38527db96d56Sopenharmony_ci _check_decode(b'\na', "\na") 38537db96d56Sopenharmony_ci 38547db96d56Sopenharmony_ci _check_decode(b'\xe8\xa2\x88\r\n', "\u8888\n") 38557db96d56Sopenharmony_ci _check_decode(b'\xe8\xa2\x88', "\u8888") 38567db96d56Sopenharmony_ci _check_decode(b'\n', "\n") 38577db96d56Sopenharmony_ci _check_decode(b'\xe8\xa2\x88\r', "\u8888") 38587db96d56Sopenharmony_ci _check_decode(b'\n', "\n") 38597db96d56Sopenharmony_ci 38607db96d56Sopenharmony_ci def check_newline_decoding(self, decoder, encoding): 38617db96d56Sopenharmony_ci result = [] 38627db96d56Sopenharmony_ci if encoding is not None: 38637db96d56Sopenharmony_ci encoder = codecs.getincrementalencoder(encoding)() 38647db96d56Sopenharmony_ci def _decode_bytewise(s): 38657db96d56Sopenharmony_ci # Decode one byte at a time 38667db96d56Sopenharmony_ci for b in encoder.encode(s): 38677db96d56Sopenharmony_ci result.append(decoder.decode(bytes([b]))) 38687db96d56Sopenharmony_ci else: 38697db96d56Sopenharmony_ci encoder = None 38707db96d56Sopenharmony_ci def _decode_bytewise(s): 38717db96d56Sopenharmony_ci # Decode one char at a time 38727db96d56Sopenharmony_ci for c in s: 38737db96d56Sopenharmony_ci result.append(decoder.decode(c)) 38747db96d56Sopenharmony_ci self.assertEqual(decoder.newlines, None) 38757db96d56Sopenharmony_ci _decode_bytewise("abc\n\r") 38767db96d56Sopenharmony_ci self.assertEqual(decoder.newlines, '\n') 38777db96d56Sopenharmony_ci _decode_bytewise("\nabc") 38787db96d56Sopenharmony_ci self.assertEqual(decoder.newlines, ('\n', '\r\n')) 38797db96d56Sopenharmony_ci _decode_bytewise("abc\r") 38807db96d56Sopenharmony_ci self.assertEqual(decoder.newlines, ('\n', '\r\n')) 38817db96d56Sopenharmony_ci _decode_bytewise("abc") 38827db96d56Sopenharmony_ci self.assertEqual(decoder.newlines, ('\r', '\n', '\r\n')) 38837db96d56Sopenharmony_ci _decode_bytewise("abc\r") 38847db96d56Sopenharmony_ci self.assertEqual("".join(result), "abc\n\nabcabc\nabcabc") 38857db96d56Sopenharmony_ci decoder.reset() 38867db96d56Sopenharmony_ci input = "abc" 38877db96d56Sopenharmony_ci if encoder is not None: 38887db96d56Sopenharmony_ci encoder.reset() 38897db96d56Sopenharmony_ci input = encoder.encode(input) 38907db96d56Sopenharmony_ci self.assertEqual(decoder.decode(input), "abc") 38917db96d56Sopenharmony_ci self.assertEqual(decoder.newlines, None) 38927db96d56Sopenharmony_ci 38937db96d56Sopenharmony_ci def test_newline_decoder(self): 38947db96d56Sopenharmony_ci encodings = ( 38957db96d56Sopenharmony_ci # None meaning the IncrementalNewlineDecoder takes unicode input 38967db96d56Sopenharmony_ci # rather than bytes input 38977db96d56Sopenharmony_ci None, 'utf-8', 'latin-1', 38987db96d56Sopenharmony_ci 'utf-16', 'utf-16-le', 'utf-16-be', 38997db96d56Sopenharmony_ci 'utf-32', 'utf-32-le', 'utf-32-be', 39007db96d56Sopenharmony_ci ) 39017db96d56Sopenharmony_ci for enc in encodings: 39027db96d56Sopenharmony_ci decoder = enc and codecs.getincrementaldecoder(enc)() 39037db96d56Sopenharmony_ci decoder = self.IncrementalNewlineDecoder(decoder, translate=True) 39047db96d56Sopenharmony_ci self.check_newline_decoding(decoder, enc) 39057db96d56Sopenharmony_ci decoder = codecs.getincrementaldecoder("utf-8")() 39067db96d56Sopenharmony_ci decoder = self.IncrementalNewlineDecoder(decoder, translate=True) 39077db96d56Sopenharmony_ci self.check_newline_decoding_utf8(decoder) 39087db96d56Sopenharmony_ci self.assertRaises(TypeError, decoder.setstate, 42) 39097db96d56Sopenharmony_ci 39107db96d56Sopenharmony_ci def test_newline_bytes(self): 39117db96d56Sopenharmony_ci # Issue 5433: Excessive optimization in IncrementalNewlineDecoder 39127db96d56Sopenharmony_ci def _check(dec): 39137db96d56Sopenharmony_ci self.assertEqual(dec.newlines, None) 39147db96d56Sopenharmony_ci self.assertEqual(dec.decode("\u0D00"), "\u0D00") 39157db96d56Sopenharmony_ci self.assertEqual(dec.newlines, None) 39167db96d56Sopenharmony_ci self.assertEqual(dec.decode("\u0A00"), "\u0A00") 39177db96d56Sopenharmony_ci self.assertEqual(dec.newlines, None) 39187db96d56Sopenharmony_ci dec = self.IncrementalNewlineDecoder(None, translate=False) 39197db96d56Sopenharmony_ci _check(dec) 39207db96d56Sopenharmony_ci dec = self.IncrementalNewlineDecoder(None, translate=True) 39217db96d56Sopenharmony_ci _check(dec) 39227db96d56Sopenharmony_ci 39237db96d56Sopenharmony_ci def test_translate(self): 39247db96d56Sopenharmony_ci # issue 35062 39257db96d56Sopenharmony_ci for translate in (-2, -1, 1, 2): 39267db96d56Sopenharmony_ci decoder = codecs.getincrementaldecoder("utf-8")() 39277db96d56Sopenharmony_ci decoder = self.IncrementalNewlineDecoder(decoder, translate) 39287db96d56Sopenharmony_ci self.check_newline_decoding_utf8(decoder) 39297db96d56Sopenharmony_ci decoder = codecs.getincrementaldecoder("utf-8")() 39307db96d56Sopenharmony_ci decoder = self.IncrementalNewlineDecoder(decoder, translate=0) 39317db96d56Sopenharmony_ci self.assertEqual(decoder.decode(b"\r\r\n"), "\r\r\n") 39327db96d56Sopenharmony_ci 39337db96d56Sopenharmony_ciclass CIncrementalNewlineDecoderTest(IncrementalNewlineDecoderTest): 39347db96d56Sopenharmony_ci @support.cpython_only 39357db96d56Sopenharmony_ci def test_uninitialized(self): 39367db96d56Sopenharmony_ci uninitialized = self.IncrementalNewlineDecoder.__new__( 39377db96d56Sopenharmony_ci self.IncrementalNewlineDecoder) 39387db96d56Sopenharmony_ci self.assertRaises(ValueError, uninitialized.decode, b'bar') 39397db96d56Sopenharmony_ci self.assertRaises(ValueError, uninitialized.getstate) 39407db96d56Sopenharmony_ci self.assertRaises(ValueError, uninitialized.setstate, (b'foo', 0)) 39417db96d56Sopenharmony_ci self.assertRaises(ValueError, uninitialized.reset) 39427db96d56Sopenharmony_ci 39437db96d56Sopenharmony_ci 39447db96d56Sopenharmony_ciclass PyIncrementalNewlineDecoderTest(IncrementalNewlineDecoderTest): 39457db96d56Sopenharmony_ci pass 39467db96d56Sopenharmony_ci 39477db96d56Sopenharmony_ci 39487db96d56Sopenharmony_ci# XXX Tests for open() 39497db96d56Sopenharmony_ci 39507db96d56Sopenharmony_ciclass MiscIOTest(unittest.TestCase): 39517db96d56Sopenharmony_ci 39527db96d56Sopenharmony_ci def tearDown(self): 39537db96d56Sopenharmony_ci os_helper.unlink(os_helper.TESTFN) 39547db96d56Sopenharmony_ci 39557db96d56Sopenharmony_ci def test___all__(self): 39567db96d56Sopenharmony_ci for name in self.io.__all__: 39577db96d56Sopenharmony_ci obj = getattr(self.io, name, None) 39587db96d56Sopenharmony_ci self.assertIsNotNone(obj, name) 39597db96d56Sopenharmony_ci if name in ("open", "open_code"): 39607db96d56Sopenharmony_ci continue 39617db96d56Sopenharmony_ci elif "error" in name.lower() or name == "UnsupportedOperation": 39627db96d56Sopenharmony_ci self.assertTrue(issubclass(obj, Exception), name) 39637db96d56Sopenharmony_ci elif not name.startswith("SEEK_"): 39647db96d56Sopenharmony_ci self.assertTrue(issubclass(obj, self.IOBase)) 39657db96d56Sopenharmony_ci 39667db96d56Sopenharmony_ci def test_attributes(self): 39677db96d56Sopenharmony_ci f = self.open(os_helper.TESTFN, "wb", buffering=0) 39687db96d56Sopenharmony_ci self.assertEqual(f.mode, "wb") 39697db96d56Sopenharmony_ci f.close() 39707db96d56Sopenharmony_ci 39717db96d56Sopenharmony_ci f = self.open(os_helper.TESTFN, "w+", encoding="utf-8") 39727db96d56Sopenharmony_ci self.assertEqual(f.mode, "w+") 39737db96d56Sopenharmony_ci self.assertEqual(f.buffer.mode, "rb+") # Does it really matter? 39747db96d56Sopenharmony_ci self.assertEqual(f.buffer.raw.mode, "rb+") 39757db96d56Sopenharmony_ci 39767db96d56Sopenharmony_ci g = self.open(f.fileno(), "wb", closefd=False) 39777db96d56Sopenharmony_ci self.assertEqual(g.mode, "wb") 39787db96d56Sopenharmony_ci self.assertEqual(g.raw.mode, "wb") 39797db96d56Sopenharmony_ci self.assertEqual(g.name, f.fileno()) 39807db96d56Sopenharmony_ci self.assertEqual(g.raw.name, f.fileno()) 39817db96d56Sopenharmony_ci f.close() 39827db96d56Sopenharmony_ci g.close() 39837db96d56Sopenharmony_ci 39847db96d56Sopenharmony_ci def test_removed_u_mode(self): 39857db96d56Sopenharmony_ci # bpo-37330: The "U" mode has been removed in Python 3.11 39867db96d56Sopenharmony_ci for mode in ("U", "rU", "r+U"): 39877db96d56Sopenharmony_ci with self.assertRaises(ValueError) as cm: 39887db96d56Sopenharmony_ci self.open(os_helper.TESTFN, mode) 39897db96d56Sopenharmony_ci self.assertIn('invalid mode', str(cm.exception)) 39907db96d56Sopenharmony_ci 39917db96d56Sopenharmony_ci @unittest.skipIf( 39927db96d56Sopenharmony_ci support.is_emscripten, "fstat() of a pipe fd is not supported" 39937db96d56Sopenharmony_ci ) 39947db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()") 39957db96d56Sopenharmony_ci def test_open_pipe_with_append(self): 39967db96d56Sopenharmony_ci # bpo-27805: Ignore ESPIPE from lseek() in open(). 39977db96d56Sopenharmony_ci r, w = os.pipe() 39987db96d56Sopenharmony_ci self.addCleanup(os.close, r) 39997db96d56Sopenharmony_ci f = self.open(w, 'a', encoding="utf-8") 40007db96d56Sopenharmony_ci self.addCleanup(f.close) 40017db96d56Sopenharmony_ci # Check that the file is marked non-seekable. On Windows, however, lseek 40027db96d56Sopenharmony_ci # somehow succeeds on pipes. 40037db96d56Sopenharmony_ci if sys.platform != 'win32': 40047db96d56Sopenharmony_ci self.assertFalse(f.seekable()) 40057db96d56Sopenharmony_ci 40067db96d56Sopenharmony_ci def test_io_after_close(self): 40077db96d56Sopenharmony_ci for kwargs in [ 40087db96d56Sopenharmony_ci {"mode": "w"}, 40097db96d56Sopenharmony_ci {"mode": "wb"}, 40107db96d56Sopenharmony_ci {"mode": "w", "buffering": 1}, 40117db96d56Sopenharmony_ci {"mode": "w", "buffering": 2}, 40127db96d56Sopenharmony_ci {"mode": "wb", "buffering": 0}, 40137db96d56Sopenharmony_ci {"mode": "r"}, 40147db96d56Sopenharmony_ci {"mode": "rb"}, 40157db96d56Sopenharmony_ci {"mode": "r", "buffering": 1}, 40167db96d56Sopenharmony_ci {"mode": "r", "buffering": 2}, 40177db96d56Sopenharmony_ci {"mode": "rb", "buffering": 0}, 40187db96d56Sopenharmony_ci {"mode": "w+"}, 40197db96d56Sopenharmony_ci {"mode": "w+b"}, 40207db96d56Sopenharmony_ci {"mode": "w+", "buffering": 1}, 40217db96d56Sopenharmony_ci {"mode": "w+", "buffering": 2}, 40227db96d56Sopenharmony_ci {"mode": "w+b", "buffering": 0}, 40237db96d56Sopenharmony_ci ]: 40247db96d56Sopenharmony_ci if "b" not in kwargs["mode"]: 40257db96d56Sopenharmony_ci kwargs["encoding"] = "utf-8" 40267db96d56Sopenharmony_ci f = self.open(os_helper.TESTFN, **kwargs) 40277db96d56Sopenharmony_ci f.close() 40287db96d56Sopenharmony_ci self.assertRaises(ValueError, f.flush) 40297db96d56Sopenharmony_ci self.assertRaises(ValueError, f.fileno) 40307db96d56Sopenharmony_ci self.assertRaises(ValueError, f.isatty) 40317db96d56Sopenharmony_ci self.assertRaises(ValueError, f.__iter__) 40327db96d56Sopenharmony_ci if hasattr(f, "peek"): 40337db96d56Sopenharmony_ci self.assertRaises(ValueError, f.peek, 1) 40347db96d56Sopenharmony_ci self.assertRaises(ValueError, f.read) 40357db96d56Sopenharmony_ci if hasattr(f, "read1"): 40367db96d56Sopenharmony_ci self.assertRaises(ValueError, f.read1, 1024) 40377db96d56Sopenharmony_ci self.assertRaises(ValueError, f.read1) 40387db96d56Sopenharmony_ci if hasattr(f, "readall"): 40397db96d56Sopenharmony_ci self.assertRaises(ValueError, f.readall) 40407db96d56Sopenharmony_ci if hasattr(f, "readinto"): 40417db96d56Sopenharmony_ci self.assertRaises(ValueError, f.readinto, bytearray(1024)) 40427db96d56Sopenharmony_ci if hasattr(f, "readinto1"): 40437db96d56Sopenharmony_ci self.assertRaises(ValueError, f.readinto1, bytearray(1024)) 40447db96d56Sopenharmony_ci self.assertRaises(ValueError, f.readline) 40457db96d56Sopenharmony_ci self.assertRaises(ValueError, f.readlines) 40467db96d56Sopenharmony_ci self.assertRaises(ValueError, f.readlines, 1) 40477db96d56Sopenharmony_ci self.assertRaises(ValueError, f.seek, 0) 40487db96d56Sopenharmony_ci self.assertRaises(ValueError, f.tell) 40497db96d56Sopenharmony_ci self.assertRaises(ValueError, f.truncate) 40507db96d56Sopenharmony_ci self.assertRaises(ValueError, f.write, 40517db96d56Sopenharmony_ci b"" if "b" in kwargs['mode'] else "") 40527db96d56Sopenharmony_ci self.assertRaises(ValueError, f.writelines, []) 40537db96d56Sopenharmony_ci self.assertRaises(ValueError, next, f) 40547db96d56Sopenharmony_ci 40557db96d56Sopenharmony_ci def test_blockingioerror(self): 40567db96d56Sopenharmony_ci # Various BlockingIOError issues 40577db96d56Sopenharmony_ci class C(str): 40587db96d56Sopenharmony_ci pass 40597db96d56Sopenharmony_ci c = C("") 40607db96d56Sopenharmony_ci b = self.BlockingIOError(1, c) 40617db96d56Sopenharmony_ci c.b = b 40627db96d56Sopenharmony_ci b.c = c 40637db96d56Sopenharmony_ci wr = weakref.ref(c) 40647db96d56Sopenharmony_ci del c, b 40657db96d56Sopenharmony_ci support.gc_collect() 40667db96d56Sopenharmony_ci self.assertIsNone(wr(), wr) 40677db96d56Sopenharmony_ci 40687db96d56Sopenharmony_ci def test_abcs(self): 40697db96d56Sopenharmony_ci # Test the visible base classes are ABCs. 40707db96d56Sopenharmony_ci self.assertIsInstance(self.IOBase, abc.ABCMeta) 40717db96d56Sopenharmony_ci self.assertIsInstance(self.RawIOBase, abc.ABCMeta) 40727db96d56Sopenharmony_ci self.assertIsInstance(self.BufferedIOBase, abc.ABCMeta) 40737db96d56Sopenharmony_ci self.assertIsInstance(self.TextIOBase, abc.ABCMeta) 40747db96d56Sopenharmony_ci 40757db96d56Sopenharmony_ci def _check_abc_inheritance(self, abcmodule): 40767db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "wb", buffering=0) as f: 40777db96d56Sopenharmony_ci self.assertIsInstance(f, abcmodule.IOBase) 40787db96d56Sopenharmony_ci self.assertIsInstance(f, abcmodule.RawIOBase) 40797db96d56Sopenharmony_ci self.assertNotIsInstance(f, abcmodule.BufferedIOBase) 40807db96d56Sopenharmony_ci self.assertNotIsInstance(f, abcmodule.TextIOBase) 40817db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "wb") as f: 40827db96d56Sopenharmony_ci self.assertIsInstance(f, abcmodule.IOBase) 40837db96d56Sopenharmony_ci self.assertNotIsInstance(f, abcmodule.RawIOBase) 40847db96d56Sopenharmony_ci self.assertIsInstance(f, abcmodule.BufferedIOBase) 40857db96d56Sopenharmony_ci self.assertNotIsInstance(f, abcmodule.TextIOBase) 40867db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, "w", encoding="utf-8") as f: 40877db96d56Sopenharmony_ci self.assertIsInstance(f, abcmodule.IOBase) 40887db96d56Sopenharmony_ci self.assertNotIsInstance(f, abcmodule.RawIOBase) 40897db96d56Sopenharmony_ci self.assertNotIsInstance(f, abcmodule.BufferedIOBase) 40907db96d56Sopenharmony_ci self.assertIsInstance(f, abcmodule.TextIOBase) 40917db96d56Sopenharmony_ci 40927db96d56Sopenharmony_ci def test_abc_inheritance(self): 40937db96d56Sopenharmony_ci # Test implementations inherit from their respective ABCs 40947db96d56Sopenharmony_ci self._check_abc_inheritance(self) 40957db96d56Sopenharmony_ci 40967db96d56Sopenharmony_ci def test_abc_inheritance_official(self): 40977db96d56Sopenharmony_ci # Test implementations inherit from the official ABCs of the 40987db96d56Sopenharmony_ci # baseline "io" module. 40997db96d56Sopenharmony_ci self._check_abc_inheritance(io) 41007db96d56Sopenharmony_ci 41017db96d56Sopenharmony_ci def _check_warn_on_dealloc(self, *args, **kwargs): 41027db96d56Sopenharmony_ci f = open(*args, **kwargs) 41037db96d56Sopenharmony_ci r = repr(f) 41047db96d56Sopenharmony_ci with self.assertWarns(ResourceWarning) as cm: 41057db96d56Sopenharmony_ci f = None 41067db96d56Sopenharmony_ci support.gc_collect() 41077db96d56Sopenharmony_ci self.assertIn(r, str(cm.warning.args[0])) 41087db96d56Sopenharmony_ci 41097db96d56Sopenharmony_ci def test_warn_on_dealloc(self): 41107db96d56Sopenharmony_ci self._check_warn_on_dealloc(os_helper.TESTFN, "wb", buffering=0) 41117db96d56Sopenharmony_ci self._check_warn_on_dealloc(os_helper.TESTFN, "wb") 41127db96d56Sopenharmony_ci self._check_warn_on_dealloc(os_helper.TESTFN, "w", encoding="utf-8") 41137db96d56Sopenharmony_ci 41147db96d56Sopenharmony_ci def _check_warn_on_dealloc_fd(self, *args, **kwargs): 41157db96d56Sopenharmony_ci fds = [] 41167db96d56Sopenharmony_ci def cleanup_fds(): 41177db96d56Sopenharmony_ci for fd in fds: 41187db96d56Sopenharmony_ci try: 41197db96d56Sopenharmony_ci os.close(fd) 41207db96d56Sopenharmony_ci except OSError as e: 41217db96d56Sopenharmony_ci if e.errno != errno.EBADF: 41227db96d56Sopenharmony_ci raise 41237db96d56Sopenharmony_ci self.addCleanup(cleanup_fds) 41247db96d56Sopenharmony_ci r, w = os.pipe() 41257db96d56Sopenharmony_ci fds += r, w 41267db96d56Sopenharmony_ci self._check_warn_on_dealloc(r, *args, **kwargs) 41277db96d56Sopenharmony_ci # When using closefd=False, there's no warning 41287db96d56Sopenharmony_ci r, w = os.pipe() 41297db96d56Sopenharmony_ci fds += r, w 41307db96d56Sopenharmony_ci with warnings_helper.check_no_resource_warning(self): 41317db96d56Sopenharmony_ci open(r, *args, closefd=False, **kwargs) 41327db96d56Sopenharmony_ci 41337db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()") 41347db96d56Sopenharmony_ci def test_warn_on_dealloc_fd(self): 41357db96d56Sopenharmony_ci self._check_warn_on_dealloc_fd("rb", buffering=0) 41367db96d56Sopenharmony_ci self._check_warn_on_dealloc_fd("rb") 41377db96d56Sopenharmony_ci self._check_warn_on_dealloc_fd("r", encoding="utf-8") 41387db96d56Sopenharmony_ci 41397db96d56Sopenharmony_ci 41407db96d56Sopenharmony_ci def test_pickling(self): 41417db96d56Sopenharmony_ci # Pickling file objects is forbidden 41427db96d56Sopenharmony_ci for kwargs in [ 41437db96d56Sopenharmony_ci {"mode": "w"}, 41447db96d56Sopenharmony_ci {"mode": "wb"}, 41457db96d56Sopenharmony_ci {"mode": "wb", "buffering": 0}, 41467db96d56Sopenharmony_ci {"mode": "r"}, 41477db96d56Sopenharmony_ci {"mode": "rb"}, 41487db96d56Sopenharmony_ci {"mode": "rb", "buffering": 0}, 41497db96d56Sopenharmony_ci {"mode": "w+"}, 41507db96d56Sopenharmony_ci {"mode": "w+b"}, 41517db96d56Sopenharmony_ci {"mode": "w+b", "buffering": 0}, 41527db96d56Sopenharmony_ci ]: 41537db96d56Sopenharmony_ci if "b" not in kwargs["mode"]: 41547db96d56Sopenharmony_ci kwargs["encoding"] = "utf-8" 41557db96d56Sopenharmony_ci for protocol in range(pickle.HIGHEST_PROTOCOL + 1): 41567db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, **kwargs) as f: 41577db96d56Sopenharmony_ci self.assertRaises(TypeError, pickle.dumps, f, protocol) 41587db96d56Sopenharmony_ci 41597db96d56Sopenharmony_ci @unittest.skipIf( 41607db96d56Sopenharmony_ci support.is_emscripten, "fstat() of a pipe fd is not supported" 41617db96d56Sopenharmony_ci ) 41627db96d56Sopenharmony_ci def test_nonblock_pipe_write_bigbuf(self): 41637db96d56Sopenharmony_ci self._test_nonblock_pipe_write(16*1024) 41647db96d56Sopenharmony_ci 41657db96d56Sopenharmony_ci @unittest.skipIf( 41667db96d56Sopenharmony_ci support.is_emscripten, "fstat() of a pipe fd is not supported" 41677db96d56Sopenharmony_ci ) 41687db96d56Sopenharmony_ci def test_nonblock_pipe_write_smallbuf(self): 41697db96d56Sopenharmony_ci self._test_nonblock_pipe_write(1024) 41707db96d56Sopenharmony_ci 41717db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, 'set_blocking'), 41727db96d56Sopenharmony_ci 'os.set_blocking() required for this test') 41737db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()") 41747db96d56Sopenharmony_ci def _test_nonblock_pipe_write(self, bufsize): 41757db96d56Sopenharmony_ci sent = [] 41767db96d56Sopenharmony_ci received = [] 41777db96d56Sopenharmony_ci r, w = os.pipe() 41787db96d56Sopenharmony_ci os.set_blocking(r, False) 41797db96d56Sopenharmony_ci os.set_blocking(w, False) 41807db96d56Sopenharmony_ci 41817db96d56Sopenharmony_ci # To exercise all code paths in the C implementation we need 41827db96d56Sopenharmony_ci # to play with buffer sizes. For instance, if we choose a 41837db96d56Sopenharmony_ci # buffer size less than or equal to _PIPE_BUF (4096 on Linux) 41847db96d56Sopenharmony_ci # then we will never get a partial write of the buffer. 41857db96d56Sopenharmony_ci rf = self.open(r, mode='rb', closefd=True, buffering=bufsize) 41867db96d56Sopenharmony_ci wf = self.open(w, mode='wb', closefd=True, buffering=bufsize) 41877db96d56Sopenharmony_ci 41887db96d56Sopenharmony_ci with rf, wf: 41897db96d56Sopenharmony_ci for N in 9999, 73, 7574: 41907db96d56Sopenharmony_ci try: 41917db96d56Sopenharmony_ci i = 0 41927db96d56Sopenharmony_ci while True: 41937db96d56Sopenharmony_ci msg = bytes([i % 26 + 97]) * N 41947db96d56Sopenharmony_ci sent.append(msg) 41957db96d56Sopenharmony_ci wf.write(msg) 41967db96d56Sopenharmony_ci i += 1 41977db96d56Sopenharmony_ci 41987db96d56Sopenharmony_ci except self.BlockingIOError as e: 41997db96d56Sopenharmony_ci self.assertEqual(e.args[0], errno.EAGAIN) 42007db96d56Sopenharmony_ci self.assertEqual(e.args[2], e.characters_written) 42017db96d56Sopenharmony_ci sent[-1] = sent[-1][:e.characters_written] 42027db96d56Sopenharmony_ci received.append(rf.read()) 42037db96d56Sopenharmony_ci msg = b'BLOCKED' 42047db96d56Sopenharmony_ci wf.write(msg) 42057db96d56Sopenharmony_ci sent.append(msg) 42067db96d56Sopenharmony_ci 42077db96d56Sopenharmony_ci while True: 42087db96d56Sopenharmony_ci try: 42097db96d56Sopenharmony_ci wf.flush() 42107db96d56Sopenharmony_ci break 42117db96d56Sopenharmony_ci except self.BlockingIOError as e: 42127db96d56Sopenharmony_ci self.assertEqual(e.args[0], errno.EAGAIN) 42137db96d56Sopenharmony_ci self.assertEqual(e.args[2], e.characters_written) 42147db96d56Sopenharmony_ci self.assertEqual(e.characters_written, 0) 42157db96d56Sopenharmony_ci received.append(rf.read()) 42167db96d56Sopenharmony_ci 42177db96d56Sopenharmony_ci received += iter(rf.read, None) 42187db96d56Sopenharmony_ci 42197db96d56Sopenharmony_ci sent, received = b''.join(sent), b''.join(received) 42207db96d56Sopenharmony_ci self.assertEqual(sent, received) 42217db96d56Sopenharmony_ci self.assertTrue(wf.closed) 42227db96d56Sopenharmony_ci self.assertTrue(rf.closed) 42237db96d56Sopenharmony_ci 42247db96d56Sopenharmony_ci def test_create_fail(self): 42257db96d56Sopenharmony_ci # 'x' mode fails if file is existing 42267db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, 'w', encoding="utf-8"): 42277db96d56Sopenharmony_ci pass 42287db96d56Sopenharmony_ci self.assertRaises(FileExistsError, self.open, os_helper.TESTFN, 'x', encoding="utf-8") 42297db96d56Sopenharmony_ci 42307db96d56Sopenharmony_ci def test_create_writes(self): 42317db96d56Sopenharmony_ci # 'x' mode opens for writing 42327db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, 'xb') as f: 42337db96d56Sopenharmony_ci f.write(b"spam") 42347db96d56Sopenharmony_ci with self.open(os_helper.TESTFN, 'rb') as f: 42357db96d56Sopenharmony_ci self.assertEqual(b"spam", f.read()) 42367db96d56Sopenharmony_ci 42377db96d56Sopenharmony_ci def test_open_allargs(self): 42387db96d56Sopenharmony_ci # there used to be a buffer overflow in the parser for rawmode 42397db96d56Sopenharmony_ci self.assertRaises(ValueError, self.open, os_helper.TESTFN, 'rwax+', encoding="utf-8") 42407db96d56Sopenharmony_ci 42417db96d56Sopenharmony_ci def test_check_encoding_errors(self): 42427db96d56Sopenharmony_ci # bpo-37388: open() and TextIOWrapper must check encoding and errors 42437db96d56Sopenharmony_ci # arguments in dev mode 42447db96d56Sopenharmony_ci mod = self.io.__name__ 42457db96d56Sopenharmony_ci filename = __file__ 42467db96d56Sopenharmony_ci invalid = 'Boom, Shaka Laka, Boom!' 42477db96d56Sopenharmony_ci code = textwrap.dedent(f''' 42487db96d56Sopenharmony_ci import sys 42497db96d56Sopenharmony_ci from {mod} import open, TextIOWrapper 42507db96d56Sopenharmony_ci 42517db96d56Sopenharmony_ci try: 42527db96d56Sopenharmony_ci open({filename!r}, encoding={invalid!r}) 42537db96d56Sopenharmony_ci except LookupError: 42547db96d56Sopenharmony_ci pass 42557db96d56Sopenharmony_ci else: 42567db96d56Sopenharmony_ci sys.exit(21) 42577db96d56Sopenharmony_ci 42587db96d56Sopenharmony_ci try: 42597db96d56Sopenharmony_ci open({filename!r}, errors={invalid!r}) 42607db96d56Sopenharmony_ci except LookupError: 42617db96d56Sopenharmony_ci pass 42627db96d56Sopenharmony_ci else: 42637db96d56Sopenharmony_ci sys.exit(22) 42647db96d56Sopenharmony_ci 42657db96d56Sopenharmony_ci fp = open({filename!r}, "rb") 42667db96d56Sopenharmony_ci with fp: 42677db96d56Sopenharmony_ci try: 42687db96d56Sopenharmony_ci TextIOWrapper(fp, encoding={invalid!r}) 42697db96d56Sopenharmony_ci except LookupError: 42707db96d56Sopenharmony_ci pass 42717db96d56Sopenharmony_ci else: 42727db96d56Sopenharmony_ci sys.exit(23) 42737db96d56Sopenharmony_ci 42747db96d56Sopenharmony_ci try: 42757db96d56Sopenharmony_ci TextIOWrapper(fp, errors={invalid!r}) 42767db96d56Sopenharmony_ci except LookupError: 42777db96d56Sopenharmony_ci pass 42787db96d56Sopenharmony_ci else: 42797db96d56Sopenharmony_ci sys.exit(24) 42807db96d56Sopenharmony_ci 42817db96d56Sopenharmony_ci sys.exit(10) 42827db96d56Sopenharmony_ci ''') 42837db96d56Sopenharmony_ci proc = assert_python_failure('-X', 'dev', '-c', code) 42847db96d56Sopenharmony_ci self.assertEqual(proc.rc, 10, proc) 42857db96d56Sopenharmony_ci 42867db96d56Sopenharmony_ci def test_check_encoding_warning(self): 42877db96d56Sopenharmony_ci # PEP 597: Raise warning when encoding is not specified 42887db96d56Sopenharmony_ci # and sys.flags.warn_default_encoding is set. 42897db96d56Sopenharmony_ci mod = self.io.__name__ 42907db96d56Sopenharmony_ci filename = __file__ 42917db96d56Sopenharmony_ci code = textwrap.dedent(f'''\ 42927db96d56Sopenharmony_ci import sys 42937db96d56Sopenharmony_ci from {mod} import open, TextIOWrapper 42947db96d56Sopenharmony_ci import pathlib 42957db96d56Sopenharmony_ci 42967db96d56Sopenharmony_ci with open({filename!r}) as f: # line 5 42977db96d56Sopenharmony_ci pass 42987db96d56Sopenharmony_ci 42997db96d56Sopenharmony_ci pathlib.Path({filename!r}).read_text() # line 8 43007db96d56Sopenharmony_ci ''') 43017db96d56Sopenharmony_ci proc = assert_python_ok('-X', 'warn_default_encoding', '-c', code) 43027db96d56Sopenharmony_ci warnings = proc.err.splitlines() 43037db96d56Sopenharmony_ci self.assertEqual(len(warnings), 2) 43047db96d56Sopenharmony_ci self.assertTrue( 43057db96d56Sopenharmony_ci warnings[0].startswith(b"<string>:5: EncodingWarning: ")) 43067db96d56Sopenharmony_ci self.assertTrue( 43077db96d56Sopenharmony_ci warnings[1].startswith(b"<string>:8: EncodingWarning: ")) 43087db96d56Sopenharmony_ci 43097db96d56Sopenharmony_ci def test_text_encoding(self): 43107db96d56Sopenharmony_ci # PEP 597, bpo-47000. io.text_encoding() returns "locale" or "utf-8" 43117db96d56Sopenharmony_ci # based on sys.flags.utf8_mode 43127db96d56Sopenharmony_ci code = "import io; print(io.text_encoding(None))" 43137db96d56Sopenharmony_ci 43147db96d56Sopenharmony_ci proc = assert_python_ok('-X', 'utf8=0', '-c', code) 43157db96d56Sopenharmony_ci self.assertEqual(b"locale", proc.out.strip()) 43167db96d56Sopenharmony_ci 43177db96d56Sopenharmony_ci proc = assert_python_ok('-X', 'utf8=1', '-c', code) 43187db96d56Sopenharmony_ci self.assertEqual(b"utf-8", proc.out.strip()) 43197db96d56Sopenharmony_ci 43207db96d56Sopenharmony_ci @support.cpython_only 43217db96d56Sopenharmony_ci # Depending if OpenWrapper was already created or not, the warning is 43227db96d56Sopenharmony_ci # emitted or not. For example, the attribute is already created when this 43237db96d56Sopenharmony_ci # test is run multiple times. 43247db96d56Sopenharmony_ci @warnings_helper.ignore_warnings(category=DeprecationWarning) 43257db96d56Sopenharmony_ci def test_openwrapper(self): 43267db96d56Sopenharmony_ci self.assertIs(self.io.OpenWrapper, self.io.open) 43277db96d56Sopenharmony_ci 43287db96d56Sopenharmony_ci 43297db96d56Sopenharmony_ciclass CMiscIOTest(MiscIOTest): 43307db96d56Sopenharmony_ci io = io 43317db96d56Sopenharmony_ci 43327db96d56Sopenharmony_ci def test_readinto_buffer_overflow(self): 43337db96d56Sopenharmony_ci # Issue #18025 43347db96d56Sopenharmony_ci class BadReader(self.io.BufferedIOBase): 43357db96d56Sopenharmony_ci def read(self, n=-1): 43367db96d56Sopenharmony_ci return b'x' * 10**6 43377db96d56Sopenharmony_ci bufio = BadReader() 43387db96d56Sopenharmony_ci b = bytearray(2) 43397db96d56Sopenharmony_ci self.assertRaises(ValueError, bufio.readinto, b) 43407db96d56Sopenharmony_ci 43417db96d56Sopenharmony_ci def check_daemon_threads_shutdown_deadlock(self, stream_name): 43427db96d56Sopenharmony_ci # Issue #23309: deadlocks at shutdown should be avoided when a 43437db96d56Sopenharmony_ci # daemon thread and the main thread both write to a file. 43447db96d56Sopenharmony_ci code = """if 1: 43457db96d56Sopenharmony_ci import sys 43467db96d56Sopenharmony_ci import time 43477db96d56Sopenharmony_ci import threading 43487db96d56Sopenharmony_ci from test.support import SuppressCrashReport 43497db96d56Sopenharmony_ci 43507db96d56Sopenharmony_ci file = sys.{stream_name} 43517db96d56Sopenharmony_ci 43527db96d56Sopenharmony_ci def run(): 43537db96d56Sopenharmony_ci while True: 43547db96d56Sopenharmony_ci file.write('.') 43557db96d56Sopenharmony_ci file.flush() 43567db96d56Sopenharmony_ci 43577db96d56Sopenharmony_ci crash = SuppressCrashReport() 43587db96d56Sopenharmony_ci crash.__enter__() 43597db96d56Sopenharmony_ci # don't call __exit__(): the crash occurs at Python shutdown 43607db96d56Sopenharmony_ci 43617db96d56Sopenharmony_ci thread = threading.Thread(target=run) 43627db96d56Sopenharmony_ci thread.daemon = True 43637db96d56Sopenharmony_ci thread.start() 43647db96d56Sopenharmony_ci 43657db96d56Sopenharmony_ci time.sleep(0.5) 43667db96d56Sopenharmony_ci file.write('!') 43677db96d56Sopenharmony_ci file.flush() 43687db96d56Sopenharmony_ci """.format_map(locals()) 43697db96d56Sopenharmony_ci res, _ = run_python_until_end("-c", code) 43707db96d56Sopenharmony_ci err = res.err.decode() 43717db96d56Sopenharmony_ci if res.rc != 0: 43727db96d56Sopenharmony_ci # Failure: should be a fatal error 43737db96d56Sopenharmony_ci pattern = (r"Fatal Python error: _enter_buffered_busy: " 43747db96d56Sopenharmony_ci r"could not acquire lock " 43757db96d56Sopenharmony_ci r"for <(_io\.)?BufferedWriter name='<{stream_name}>'> " 43767db96d56Sopenharmony_ci r"at interpreter shutdown, possibly due to " 43777db96d56Sopenharmony_ci r"daemon threads".format_map(locals())) 43787db96d56Sopenharmony_ci self.assertRegex(err, pattern) 43797db96d56Sopenharmony_ci else: 43807db96d56Sopenharmony_ci self.assertFalse(err.strip('.!')) 43817db96d56Sopenharmony_ci 43827db96d56Sopenharmony_ci @threading_helper.requires_working_threading() 43837db96d56Sopenharmony_ci def test_daemon_threads_shutdown_stdout_deadlock(self): 43847db96d56Sopenharmony_ci self.check_daemon_threads_shutdown_deadlock('stdout') 43857db96d56Sopenharmony_ci 43867db96d56Sopenharmony_ci @threading_helper.requires_working_threading() 43877db96d56Sopenharmony_ci def test_daemon_threads_shutdown_stderr_deadlock(self): 43887db96d56Sopenharmony_ci self.check_daemon_threads_shutdown_deadlock('stderr') 43897db96d56Sopenharmony_ci 43907db96d56Sopenharmony_ci 43917db96d56Sopenharmony_ciclass PyMiscIOTest(MiscIOTest): 43927db96d56Sopenharmony_ci io = pyio 43937db96d56Sopenharmony_ci 43947db96d56Sopenharmony_ci 43957db96d56Sopenharmony_ci@unittest.skipIf(os.name == 'nt', 'POSIX signals required for this test.') 43967db96d56Sopenharmony_ciclass SignalsTest(unittest.TestCase): 43977db96d56Sopenharmony_ci 43987db96d56Sopenharmony_ci def setUp(self): 43997db96d56Sopenharmony_ci self.oldalrm = signal.signal(signal.SIGALRM, self.alarm_interrupt) 44007db96d56Sopenharmony_ci 44017db96d56Sopenharmony_ci def tearDown(self): 44027db96d56Sopenharmony_ci signal.signal(signal.SIGALRM, self.oldalrm) 44037db96d56Sopenharmony_ci 44047db96d56Sopenharmony_ci def alarm_interrupt(self, sig, frame): 44057db96d56Sopenharmony_ci 1/0 44067db96d56Sopenharmony_ci 44077db96d56Sopenharmony_ci def check_interrupted_write(self, item, bytes, **fdopen_kwargs): 44087db96d56Sopenharmony_ci """Check that a partial write, when it gets interrupted, properly 44097db96d56Sopenharmony_ci invokes the signal handler, and bubbles up the exception raised 44107db96d56Sopenharmony_ci in the latter.""" 44117db96d56Sopenharmony_ci 44127db96d56Sopenharmony_ci # XXX This test has three flaws that appear when objects are 44137db96d56Sopenharmony_ci # XXX not reference counted. 44147db96d56Sopenharmony_ci 44157db96d56Sopenharmony_ci # - if wio.write() happens to trigger a garbage collection, 44167db96d56Sopenharmony_ci # the signal exception may be raised when some __del__ 44177db96d56Sopenharmony_ci # method is running; it will not reach the assertRaises() 44187db96d56Sopenharmony_ci # call. 44197db96d56Sopenharmony_ci 44207db96d56Sopenharmony_ci # - more subtle, if the wio object is not destroyed at once 44217db96d56Sopenharmony_ci # and survives this function, the next opened file is likely 44227db96d56Sopenharmony_ci # to have the same fileno (since the file descriptor was 44237db96d56Sopenharmony_ci # actively closed). When wio.__del__ is finally called, it 44247db96d56Sopenharmony_ci # will close the other's test file... To trigger this with 44257db96d56Sopenharmony_ci # CPython, try adding "global wio" in this function. 44267db96d56Sopenharmony_ci 44277db96d56Sopenharmony_ci # - This happens only for streams created by the _pyio module, 44287db96d56Sopenharmony_ci # because a wio.close() that fails still consider that the 44297db96d56Sopenharmony_ci # file needs to be closed again. You can try adding an 44307db96d56Sopenharmony_ci # "assert wio.closed" at the end of the function. 44317db96d56Sopenharmony_ci 44327db96d56Sopenharmony_ci # Fortunately, a little gc.collect() seems to be enough to 44337db96d56Sopenharmony_ci # work around all these issues. 44347db96d56Sopenharmony_ci support.gc_collect() # For PyPy or other GCs. 44357db96d56Sopenharmony_ci 44367db96d56Sopenharmony_ci read_results = [] 44377db96d56Sopenharmony_ci def _read(): 44387db96d56Sopenharmony_ci s = os.read(r, 1) 44397db96d56Sopenharmony_ci read_results.append(s) 44407db96d56Sopenharmony_ci 44417db96d56Sopenharmony_ci t = threading.Thread(target=_read) 44427db96d56Sopenharmony_ci t.daemon = True 44437db96d56Sopenharmony_ci r, w = os.pipe() 44447db96d56Sopenharmony_ci fdopen_kwargs["closefd"] = False 44457db96d56Sopenharmony_ci large_data = item * (support.PIPE_MAX_SIZE // len(item) + 1) 44467db96d56Sopenharmony_ci try: 44477db96d56Sopenharmony_ci wio = self.io.open(w, **fdopen_kwargs) 44487db96d56Sopenharmony_ci if hasattr(signal, 'pthread_sigmask'): 44497db96d56Sopenharmony_ci # create the thread with SIGALRM signal blocked 44507db96d56Sopenharmony_ci signal.pthread_sigmask(signal.SIG_BLOCK, [signal.SIGALRM]) 44517db96d56Sopenharmony_ci t.start() 44527db96d56Sopenharmony_ci signal.pthread_sigmask(signal.SIG_UNBLOCK, [signal.SIGALRM]) 44537db96d56Sopenharmony_ci else: 44547db96d56Sopenharmony_ci t.start() 44557db96d56Sopenharmony_ci 44567db96d56Sopenharmony_ci # Fill the pipe enough that the write will be blocking. 44577db96d56Sopenharmony_ci # It will be interrupted by the timer armed above. Since the 44587db96d56Sopenharmony_ci # other thread has read one byte, the low-level write will 44597db96d56Sopenharmony_ci # return with a successful (partial) result rather than an EINTR. 44607db96d56Sopenharmony_ci # The buffered IO layer must check for pending signal 44617db96d56Sopenharmony_ci # handlers, which in this case will invoke alarm_interrupt(). 44627db96d56Sopenharmony_ci signal.alarm(1) 44637db96d56Sopenharmony_ci try: 44647db96d56Sopenharmony_ci self.assertRaises(ZeroDivisionError, wio.write, large_data) 44657db96d56Sopenharmony_ci finally: 44667db96d56Sopenharmony_ci signal.alarm(0) 44677db96d56Sopenharmony_ci t.join() 44687db96d56Sopenharmony_ci # We got one byte, get another one and check that it isn't a 44697db96d56Sopenharmony_ci # repeat of the first one. 44707db96d56Sopenharmony_ci read_results.append(os.read(r, 1)) 44717db96d56Sopenharmony_ci self.assertEqual(read_results, [bytes[0:1], bytes[1:2]]) 44727db96d56Sopenharmony_ci finally: 44737db96d56Sopenharmony_ci os.close(w) 44747db96d56Sopenharmony_ci os.close(r) 44757db96d56Sopenharmony_ci # This is deliberate. If we didn't close the file descriptor 44767db96d56Sopenharmony_ci # before closing wio, wio would try to flush its internal 44777db96d56Sopenharmony_ci # buffer, and block again. 44787db96d56Sopenharmony_ci try: 44797db96d56Sopenharmony_ci wio.close() 44807db96d56Sopenharmony_ci except OSError as e: 44817db96d56Sopenharmony_ci if e.errno != errno.EBADF: 44827db96d56Sopenharmony_ci raise 44837db96d56Sopenharmony_ci 44847db96d56Sopenharmony_ci @requires_alarm 44857db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()") 44867db96d56Sopenharmony_ci def test_interrupted_write_unbuffered(self): 44877db96d56Sopenharmony_ci self.check_interrupted_write(b"xy", b"xy", mode="wb", buffering=0) 44887db96d56Sopenharmony_ci 44897db96d56Sopenharmony_ci @requires_alarm 44907db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()") 44917db96d56Sopenharmony_ci def test_interrupted_write_buffered(self): 44927db96d56Sopenharmony_ci self.check_interrupted_write(b"xy", b"xy", mode="wb") 44937db96d56Sopenharmony_ci 44947db96d56Sopenharmony_ci @requires_alarm 44957db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()") 44967db96d56Sopenharmony_ci def test_interrupted_write_text(self): 44977db96d56Sopenharmony_ci self.check_interrupted_write("xy", b"xy", mode="w", encoding="ascii") 44987db96d56Sopenharmony_ci 44997db96d56Sopenharmony_ci @support.no_tracing 45007db96d56Sopenharmony_ci def check_reentrant_write(self, data, **fdopen_kwargs): 45017db96d56Sopenharmony_ci def on_alarm(*args): 45027db96d56Sopenharmony_ci # Will be called reentrantly from the same thread 45037db96d56Sopenharmony_ci wio.write(data) 45047db96d56Sopenharmony_ci 1/0 45057db96d56Sopenharmony_ci signal.signal(signal.SIGALRM, on_alarm) 45067db96d56Sopenharmony_ci r, w = os.pipe() 45077db96d56Sopenharmony_ci wio = self.io.open(w, **fdopen_kwargs) 45087db96d56Sopenharmony_ci try: 45097db96d56Sopenharmony_ci signal.alarm(1) 45107db96d56Sopenharmony_ci # Either the reentrant call to wio.write() fails with RuntimeError, 45117db96d56Sopenharmony_ci # or the signal handler raises ZeroDivisionError. 45127db96d56Sopenharmony_ci with self.assertRaises((ZeroDivisionError, RuntimeError)) as cm: 45137db96d56Sopenharmony_ci while 1: 45147db96d56Sopenharmony_ci for i in range(100): 45157db96d56Sopenharmony_ci wio.write(data) 45167db96d56Sopenharmony_ci wio.flush() 45177db96d56Sopenharmony_ci # Make sure the buffer doesn't fill up and block further writes 45187db96d56Sopenharmony_ci os.read(r, len(data) * 100) 45197db96d56Sopenharmony_ci exc = cm.exception 45207db96d56Sopenharmony_ci if isinstance(exc, RuntimeError): 45217db96d56Sopenharmony_ci self.assertTrue(str(exc).startswith("reentrant call"), str(exc)) 45227db96d56Sopenharmony_ci finally: 45237db96d56Sopenharmony_ci signal.alarm(0) 45247db96d56Sopenharmony_ci wio.close() 45257db96d56Sopenharmony_ci os.close(r) 45267db96d56Sopenharmony_ci 45277db96d56Sopenharmony_ci @requires_alarm 45287db96d56Sopenharmony_ci def test_reentrant_write_buffered(self): 45297db96d56Sopenharmony_ci self.check_reentrant_write(b"xy", mode="wb") 45307db96d56Sopenharmony_ci 45317db96d56Sopenharmony_ci @requires_alarm 45327db96d56Sopenharmony_ci def test_reentrant_write_text(self): 45337db96d56Sopenharmony_ci self.check_reentrant_write("xy", mode="w", encoding="ascii") 45347db96d56Sopenharmony_ci 45357db96d56Sopenharmony_ci def check_interrupted_read_retry(self, decode, **fdopen_kwargs): 45367db96d56Sopenharmony_ci """Check that a buffered read, when it gets interrupted (either 45377db96d56Sopenharmony_ci returning a partial result or EINTR), properly invokes the signal 45387db96d56Sopenharmony_ci handler and retries if the latter returned successfully.""" 45397db96d56Sopenharmony_ci r, w = os.pipe() 45407db96d56Sopenharmony_ci fdopen_kwargs["closefd"] = False 45417db96d56Sopenharmony_ci def alarm_handler(sig, frame): 45427db96d56Sopenharmony_ci os.write(w, b"bar") 45437db96d56Sopenharmony_ci signal.signal(signal.SIGALRM, alarm_handler) 45447db96d56Sopenharmony_ci try: 45457db96d56Sopenharmony_ci rio = self.io.open(r, **fdopen_kwargs) 45467db96d56Sopenharmony_ci os.write(w, b"foo") 45477db96d56Sopenharmony_ci signal.alarm(1) 45487db96d56Sopenharmony_ci # Expected behaviour: 45497db96d56Sopenharmony_ci # - first raw read() returns partial b"foo" 45507db96d56Sopenharmony_ci # - second raw read() returns EINTR 45517db96d56Sopenharmony_ci # - third raw read() returns b"bar" 45527db96d56Sopenharmony_ci self.assertEqual(decode(rio.read(6)), "foobar") 45537db96d56Sopenharmony_ci finally: 45547db96d56Sopenharmony_ci signal.alarm(0) 45557db96d56Sopenharmony_ci rio.close() 45567db96d56Sopenharmony_ci os.close(w) 45577db96d56Sopenharmony_ci os.close(r) 45587db96d56Sopenharmony_ci 45597db96d56Sopenharmony_ci @requires_alarm 45607db96d56Sopenharmony_ci def test_interrupted_read_retry_buffered(self): 45617db96d56Sopenharmony_ci self.check_interrupted_read_retry(lambda x: x.decode('latin1'), 45627db96d56Sopenharmony_ci mode="rb") 45637db96d56Sopenharmony_ci 45647db96d56Sopenharmony_ci @requires_alarm 45657db96d56Sopenharmony_ci def test_interrupted_read_retry_text(self): 45667db96d56Sopenharmony_ci self.check_interrupted_read_retry(lambda x: x, 45677db96d56Sopenharmony_ci mode="r", encoding="latin1") 45687db96d56Sopenharmony_ci 45697db96d56Sopenharmony_ci def check_interrupted_write_retry(self, item, **fdopen_kwargs): 45707db96d56Sopenharmony_ci """Check that a buffered write, when it gets interrupted (either 45717db96d56Sopenharmony_ci returning a partial result or EINTR), properly invokes the signal 45727db96d56Sopenharmony_ci handler and retries if the latter returned successfully.""" 45737db96d56Sopenharmony_ci select = import_helper.import_module("select") 45747db96d56Sopenharmony_ci 45757db96d56Sopenharmony_ci # A quantity that exceeds the buffer size of an anonymous pipe's 45767db96d56Sopenharmony_ci # write end. 45777db96d56Sopenharmony_ci N = support.PIPE_MAX_SIZE 45787db96d56Sopenharmony_ci r, w = os.pipe() 45797db96d56Sopenharmony_ci fdopen_kwargs["closefd"] = False 45807db96d56Sopenharmony_ci 45817db96d56Sopenharmony_ci # We need a separate thread to read from the pipe and allow the 45827db96d56Sopenharmony_ci # write() to finish. This thread is started after the SIGALRM is 45837db96d56Sopenharmony_ci # received (forcing a first EINTR in write()). 45847db96d56Sopenharmony_ci read_results = [] 45857db96d56Sopenharmony_ci write_finished = False 45867db96d56Sopenharmony_ci error = None 45877db96d56Sopenharmony_ci def _read(): 45887db96d56Sopenharmony_ci try: 45897db96d56Sopenharmony_ci while not write_finished: 45907db96d56Sopenharmony_ci while r in select.select([r], [], [], 1.0)[0]: 45917db96d56Sopenharmony_ci s = os.read(r, 1024) 45927db96d56Sopenharmony_ci read_results.append(s) 45937db96d56Sopenharmony_ci except BaseException as exc: 45947db96d56Sopenharmony_ci nonlocal error 45957db96d56Sopenharmony_ci error = exc 45967db96d56Sopenharmony_ci t = threading.Thread(target=_read) 45977db96d56Sopenharmony_ci t.daemon = True 45987db96d56Sopenharmony_ci def alarm1(sig, frame): 45997db96d56Sopenharmony_ci signal.signal(signal.SIGALRM, alarm2) 46007db96d56Sopenharmony_ci signal.alarm(1) 46017db96d56Sopenharmony_ci def alarm2(sig, frame): 46027db96d56Sopenharmony_ci t.start() 46037db96d56Sopenharmony_ci 46047db96d56Sopenharmony_ci large_data = item * N 46057db96d56Sopenharmony_ci signal.signal(signal.SIGALRM, alarm1) 46067db96d56Sopenharmony_ci try: 46077db96d56Sopenharmony_ci wio = self.io.open(w, **fdopen_kwargs) 46087db96d56Sopenharmony_ci signal.alarm(1) 46097db96d56Sopenharmony_ci # Expected behaviour: 46107db96d56Sopenharmony_ci # - first raw write() is partial (because of the limited pipe buffer 46117db96d56Sopenharmony_ci # and the first alarm) 46127db96d56Sopenharmony_ci # - second raw write() returns EINTR (because of the second alarm) 46137db96d56Sopenharmony_ci # - subsequent write()s are successful (either partial or complete) 46147db96d56Sopenharmony_ci written = wio.write(large_data) 46157db96d56Sopenharmony_ci self.assertEqual(N, written) 46167db96d56Sopenharmony_ci 46177db96d56Sopenharmony_ci wio.flush() 46187db96d56Sopenharmony_ci write_finished = True 46197db96d56Sopenharmony_ci t.join() 46207db96d56Sopenharmony_ci 46217db96d56Sopenharmony_ci self.assertIsNone(error) 46227db96d56Sopenharmony_ci self.assertEqual(N, sum(len(x) for x in read_results)) 46237db96d56Sopenharmony_ci finally: 46247db96d56Sopenharmony_ci signal.alarm(0) 46257db96d56Sopenharmony_ci write_finished = True 46267db96d56Sopenharmony_ci os.close(w) 46277db96d56Sopenharmony_ci os.close(r) 46287db96d56Sopenharmony_ci # This is deliberate. If we didn't close the file descriptor 46297db96d56Sopenharmony_ci # before closing wio, wio would try to flush its internal 46307db96d56Sopenharmony_ci # buffer, and could block (in case of failure). 46317db96d56Sopenharmony_ci try: 46327db96d56Sopenharmony_ci wio.close() 46337db96d56Sopenharmony_ci except OSError as e: 46347db96d56Sopenharmony_ci if e.errno != errno.EBADF: 46357db96d56Sopenharmony_ci raise 46367db96d56Sopenharmony_ci 46377db96d56Sopenharmony_ci @requires_alarm 46387db96d56Sopenharmony_ci def test_interrupted_write_retry_buffered(self): 46397db96d56Sopenharmony_ci self.check_interrupted_write_retry(b"x", mode="wb") 46407db96d56Sopenharmony_ci 46417db96d56Sopenharmony_ci @requires_alarm 46427db96d56Sopenharmony_ci def test_interrupted_write_retry_text(self): 46437db96d56Sopenharmony_ci self.check_interrupted_write_retry("x", mode="w", encoding="latin1") 46447db96d56Sopenharmony_ci 46457db96d56Sopenharmony_ci 46467db96d56Sopenharmony_ciclass CSignalsTest(SignalsTest): 46477db96d56Sopenharmony_ci io = io 46487db96d56Sopenharmony_ci 46497db96d56Sopenharmony_ciclass PySignalsTest(SignalsTest): 46507db96d56Sopenharmony_ci io = pyio 46517db96d56Sopenharmony_ci 46527db96d56Sopenharmony_ci # Handling reentrancy issues would slow down _pyio even more, so the 46537db96d56Sopenharmony_ci # tests are disabled. 46547db96d56Sopenharmony_ci test_reentrant_write_buffered = None 46557db96d56Sopenharmony_ci test_reentrant_write_text = None 46567db96d56Sopenharmony_ci 46577db96d56Sopenharmony_ci 46587db96d56Sopenharmony_cidef load_tests(loader, tests, pattern): 46597db96d56Sopenharmony_ci tests = (CIOTest, PyIOTest, APIMismatchTest, 46607db96d56Sopenharmony_ci CBufferedReaderTest, PyBufferedReaderTest, 46617db96d56Sopenharmony_ci CBufferedWriterTest, PyBufferedWriterTest, 46627db96d56Sopenharmony_ci CBufferedRWPairTest, PyBufferedRWPairTest, 46637db96d56Sopenharmony_ci CBufferedRandomTest, PyBufferedRandomTest, 46647db96d56Sopenharmony_ci StatefulIncrementalDecoderTest, 46657db96d56Sopenharmony_ci CIncrementalNewlineDecoderTest, PyIncrementalNewlineDecoderTest, 46667db96d56Sopenharmony_ci CTextIOWrapperTest, PyTextIOWrapperTest, 46677db96d56Sopenharmony_ci CMiscIOTest, PyMiscIOTest, 46687db96d56Sopenharmony_ci CSignalsTest, PySignalsTest, 46697db96d56Sopenharmony_ci ) 46707db96d56Sopenharmony_ci 46717db96d56Sopenharmony_ci # Put the namespaces of the IO module we are testing and some useful mock 46727db96d56Sopenharmony_ci # classes in the __dict__ of each test. 46737db96d56Sopenharmony_ci mocks = (MockRawIO, MisbehavedRawIO, MockFileIO, CloseFailureIO, 46747db96d56Sopenharmony_ci MockNonBlockWriterIO, MockUnseekableIO, MockRawIOWithoutRead, 46757db96d56Sopenharmony_ci SlowFlushRawIO) 46767db96d56Sopenharmony_ci all_members = io.__all__ + ["IncrementalNewlineDecoder"] 46777db96d56Sopenharmony_ci c_io_ns = {name : getattr(io, name) for name in all_members} 46787db96d56Sopenharmony_ci py_io_ns = {name : getattr(pyio, name) for name in all_members} 46797db96d56Sopenharmony_ci globs = globals() 46807db96d56Sopenharmony_ci c_io_ns.update((x.__name__, globs["C" + x.__name__]) for x in mocks) 46817db96d56Sopenharmony_ci py_io_ns.update((x.__name__, globs["Py" + x.__name__]) for x in mocks) 46827db96d56Sopenharmony_ci for test in tests: 46837db96d56Sopenharmony_ci if test.__name__.startswith("C"): 46847db96d56Sopenharmony_ci for name, obj in c_io_ns.items(): 46857db96d56Sopenharmony_ci setattr(test, name, obj) 46867db96d56Sopenharmony_ci elif test.__name__.startswith("Py"): 46877db96d56Sopenharmony_ci for name, obj in py_io_ns.items(): 46887db96d56Sopenharmony_ci setattr(test, name, obj) 46897db96d56Sopenharmony_ci 46907db96d56Sopenharmony_ci suite = loader.suiteClass() 46917db96d56Sopenharmony_ci for test in tests: 46927db96d56Sopenharmony_ci suite.addTest(loader.loadTestsFromTestCase(test)) 46937db96d56Sopenharmony_ci return suite 46947db96d56Sopenharmony_ci 46957db96d56Sopenharmony_ciif __name__ == "__main__": 46967db96d56Sopenharmony_ci unittest.main() 4697