4545except ImportError :
4646 threading = None
4747
48+ try :
49+ import ctypes
50+ except ImportError :
51+ def byteslike (* pos , ** kw ):
52+ return array .array ("b" , bytes (* pos , ** kw ))
53+ else :
54+ def byteslike (* pos , ** kw ):
55+ """Create a bytes-like object having no string or sequence methods"""
56+ data = bytes (* pos , ** kw )
57+ obj = EmptyStruct ()
58+ ctypes .resize (obj , len (data ))
59+ memoryview (obj ).cast ("B" )[:] = data
60+ return obj
61+ class EmptyStruct (ctypes .Structure ):
62+ pass
63+
4864def _default_chunk_size ():
4965 """Get the default TextIOWrapper chunk size"""
5066 with open (__file__ , "r" , encoding = "latin-1" ) as f :
@@ -284,7 +300,9 @@ def write_ops(self, f):
284300 self .assertEqual (f .tell (), 6 )
285301 self .assertEqual (f .seek (- 1 , 1 ), 5 )
286302 self .assertEqual (f .tell (), 5 )
287- self .assertEqual (f .write (bytearray (b" world\n \n \n " )), 9 )
303+ buffer = bytearray (b" world\n \n \n " )
304+ self .assertEqual (f .write (buffer ), 9 )
305+ buffer [:] = b"*" * 9 # Overwrite our copy of the data
288306 self .assertEqual (f .seek (0 ), 0 )
289307 self .assertEqual (f .write (b"h" ), 1 )
290308 self .assertEqual (f .seek (- 1 , 2 ), 13 )
@@ -297,20 +315,21 @@ def write_ops(self, f):
297315 def read_ops (self , f , buffered = False ):
298316 data = f .read (5 )
299317 self .assertEqual (data , b"hello" )
300- data = bytearray (data )
318+ data = byteslike (data )
301319 self .assertEqual (f .readinto (data ), 5 )
302- self .assertEqual (data , b" worl" )
320+ self .assertEqual (bytes (data ), b" worl" )
321+ data = bytearray (5 )
303322 self .assertEqual (f .readinto (data ), 2 )
304323 self .assertEqual (len (data ), 5 )
305324 self .assertEqual (data [:2 ], b"d\n " )
306325 self .assertEqual (f .seek (0 ), 0 )
307326 self .assertEqual (f .read (20 ), b"hello world\n " )
308327 self .assertEqual (f .read (1 ), b"" )
309- self .assertEqual (f .readinto (bytearray (b"x" )), 0 )
328+ self .assertEqual (f .readinto (byteslike (b"x" )), 0 )
310329 self .assertEqual (f .seek (- 6 , 2 ), 6 )
311330 self .assertEqual (f .read (5 ), b"world" )
312331 self .assertEqual (f .read (0 ), b"" )
313- self .assertEqual (f .readinto (bytearray ()), 0 )
332+ self .assertEqual (f .readinto (byteslike ()), 0 )
314333 self .assertEqual (f .seek (- 6 , 1 ), 5 )
315334 self .assertEqual (f .read (5 ), b" worl" )
316335 self .assertEqual (f .tell (), 10 )
@@ -321,6 +340,10 @@ def read_ops(self, f, buffered=False):
321340 f .seek (6 )
322341 self .assertEqual (f .read (), b"world\n " )
323342 self .assertEqual (f .read (), b"" )
343+ f .seek (0 )
344+ data = byteslike (5 )
345+ self .assertEqual (f .readinto1 (data ), 5 )
346+ self .assertEqual (bytes (data ), b"hello" )
324347
325348 LARGE = 2 ** 31
326349
@@ -641,10 +664,15 @@ def test_close_flushes(self):
641664 def test_array_writes (self ):
642665 a = array .array ('i' , range (10 ))
643666 n = len (a .tobytes ())
644- with self .open (support .TESTFN , "wb" , 0 ) as f :
645- self .assertEqual (f .write (a ), n )
646- with self .open (support .TESTFN , "wb" ) as f :
647- self .assertEqual (f .write (a ), n )
667+ def check (f ):
668+ with f :
669+ self .assertEqual (f .write (a ), n )
670+ f .writelines ((a ,))
671+ check (self .BytesIO ())
672+ check (self .FileIO (support .TESTFN , "w" ))
673+ check (self .BufferedWriter (self .MockRawIO ()))
674+ check (self .BufferedRandom (self .MockRawIO ()))
675+ check (self .BufferedRWPair (self .MockRawIO (), self .MockRawIO ()))
648676
649677 def test_closefd (self ):
650678 self .assertRaises (ValueError , self .open , support .TESTFN , 'w' ,
@@ -803,6 +831,19 @@ def test_invalid_newline(self):
803831 with self .assertRaises (ValueError ):
804832 self .open (support .TESTFN , 'w' , newline = 'invalid' )
805833
834+ def test_buffered_readinto_mixin (self ):
835+ # Test the implementation provided by BufferedIOBase
836+ class Stream (self .BufferedIOBase ):
837+ def read (self , size ):
838+ return b"12345"
839+ read1 = read
840+ stream = Stream ()
841+ for method in ("readinto" , "readinto1" ):
842+ with self .subTest (method ):
843+ buffer = byteslike (5 )
844+ self .assertEqual (getattr (stream , method )(buffer ), 5 )
845+ self .assertEqual (bytes (buffer ), b"12345" )
846+
806847
807848class CIOTest (IOTest ):
808849
@@ -1394,6 +1435,11 @@ def test_write(self):
13941435 bufio = self .tp (writer , 8 )
13951436 bufio .write (b"abc" )
13961437 self .assertFalse (writer ._write_stack )
1438+ buffer = bytearray (b"def" )
1439+ bufio .write (buffer )
1440+ buffer [:] = b"***" # Overwrite our copy of the data
1441+ bufio .flush ()
1442+ self .assertEqual (b"" .join (writer ._write_stack ), b"abcdef" )
13971443
13981444 def test_write_overflow (self ):
13991445 writer = self .MockRawIO ()
@@ -1720,19 +1766,23 @@ def test_read1(self):
17201766 self .assertEqual (pair .read1 (3 ), b"abc" )
17211767
17221768 def test_readinto (self ):
1723- pair = self .tp (self .BytesIO (b"abcdef" ), self .MockRawIO ())
1769+ for method in ("readinto" , "readinto1" ):
1770+ with self .subTest (method ):
1771+ pair = self .tp (self .BytesIO (b"abcdef" ), self .MockRawIO ())
17241772
1725- data = bytearray (5 )
1726- self .assertEqual (pair . readinto (data ), 5 )
1727- self .assertEqual (data , b"abcde" )
1773+ data = byteslike (5 )
1774+ self .assertEqual (getattr ( pair , method ) (data ), 5 )
1775+ self .assertEqual (bytes ( data ) , b"abcde" )
17281776
17291777 def test_write (self ):
17301778 w = self .MockRawIO ()
17311779 pair = self .tp (self .MockRawIO (), w )
17321780
17331781 pair .write (b"abc" )
17341782 pair .flush ()
1735- pair .write (b"def" )
1783+ buffer = bytearray (b"def" )
1784+ pair .write (buffer )
1785+ buffer [:] = b"***" # Overwrite our copy of the data
17361786 pair .flush ()
17371787 self .assertEqual (w ._write_stack , [b"abc" , b"def" ])
17381788
0 commit comments