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
@@ -637,10 +660,15 @@ def test_close_flushes(self):
637660 def test_array_writes (self ):
638661 a = array .array ('i' , range (10 ))
639662 n = len (a .tobytes ())
640- with self .open (support .TESTFN , "wb" , 0 ) as f :
641- self .assertEqual (f .write (a ), n )
642- with self .open (support .TESTFN , "wb" ) as f :
643- self .assertEqual (f .write (a ), n )
663+ def check (f ):
664+ with f :
665+ self .assertEqual (f .write (a ), n )
666+ f .writelines ((a ,))
667+ check (self .BytesIO ())
668+ check (self .FileIO (support .TESTFN , "w" ))
669+ check (self .BufferedWriter (self .MockRawIO ()))
670+ check (self .BufferedRandom (self .MockRawIO ()))
671+ check (self .BufferedRWPair (self .MockRawIO (), self .MockRawIO ()))
644672
645673 def test_closefd (self ):
646674 self .assertRaises (ValueError , self .open , support .TESTFN , 'w' ,
@@ -799,6 +827,19 @@ def test_invalid_newline(self):
799827 with self .assertRaises (ValueError ):
800828 self .open (support .TESTFN , 'w' , newline = 'invalid' )
801829
830+ def test_buffered_readinto_mixin (self ):
831+ # Test the implementation provided by BufferedIOBase
832+ class Stream (self .BufferedIOBase ):
833+ def read (self , size ):
834+ return b"12345"
835+ read1 = read
836+ stream = Stream ()
837+ for method in ("readinto" , "readinto1" ):
838+ with self .subTest (method ):
839+ buffer = byteslike (5 )
840+ self .assertEqual (getattr (stream , method )(buffer ), 5 )
841+ self .assertEqual (bytes (buffer ), b"12345" )
842+
802843
803844class CIOTest (IOTest ):
804845
@@ -1390,6 +1431,11 @@ def test_write(self):
13901431 bufio = self .tp (writer , 8 )
13911432 bufio .write (b"abc" )
13921433 self .assertFalse (writer ._write_stack )
1434+ buffer = bytearray (b"def" )
1435+ bufio .write (buffer )
1436+ buffer [:] = b"***" # Overwrite our copy of the data
1437+ bufio .flush ()
1438+ self .assertEqual (b"" .join (writer ._write_stack ), b"abcdef" )
13931439
13941440 def test_write_overflow (self ):
13951441 writer = self .MockRawIO ()
@@ -1716,19 +1762,23 @@ def test_read1(self):
17161762 self .assertEqual (pair .read1 (3 ), b"abc" )
17171763
17181764 def test_readinto (self ):
1719- pair = self .tp (self .BytesIO (b"abcdef" ), self .MockRawIO ())
1765+ for method in ("readinto" , "readinto1" ):
1766+ with self .subTest (method ):
1767+ pair = self .tp (self .BytesIO (b"abcdef" ), self .MockRawIO ())
17201768
1721- data = bytearray (5 )
1722- self .assertEqual (pair . readinto (data ), 5 )
1723- self .assertEqual (data , b"abcde" )
1769+ data = byteslike (5 )
1770+ self .assertEqual (getattr ( pair , method ) (data ), 5 )
1771+ self .assertEqual (bytes ( data ) , b"abcde" )
17241772
17251773 def test_write (self ):
17261774 w = self .MockRawIO ()
17271775 pair = self .tp (self .MockRawIO (), w )
17281776
17291777 pair .write (b"abc" )
17301778 pair .flush ()
1731- pair .write (b"def" )
1779+ buffer = bytearray (b"def" )
1780+ pair .write (buffer )
1781+ buffer [:] = b"***" # Overwrite our copy of the data
17321782 pair .flush ()
17331783 self .assertEqual (w ._write_stack , [b"abc" , b"def" ])
17341784
0 commit comments