44from __future__ import print_function
55from __future__ import unicode_literals
66
7+ import array
78import calendar
89import io
910import itertools
3637from . import _ftp_parse as ftp_parse
3738
3839if typing .TYPE_CHECKING :
40+ import mmap
3941 import ftplib
4042 from typing import (
4143 Any ,
@@ -236,14 +238,17 @@ def read(self, size=-1):
236238 return b"" .join (chunks )
237239
238240 def readinto (self , buffer ):
239- # type: (bytearray) -> int
241+ # type: (Union[ bytearray, memoryview, array.array[Any], mmap.mmap] ) -> int
240242 data = self .read (len (buffer ))
241243 bytes_read = len (data )
242- buffer [:bytes_read ] = data
244+ if isinstance (buffer , array .array ):
245+ buffer [:bytes_read ] = array .array (buffer .typecode , data )
246+ else :
247+ buffer [:bytes_read ] = data # type: ignore
243248 return bytes_read
244249
245- def readline (self , size = - 1 ):
246- # type: (int) -> bytes
250+ def readline (self , size = None ):
251+ # type: (Optional[ int] ) -> bytes
247252 return next (line_iterator (self , size )) # type: ignore
248253
249254 def readlines (self , hint = - 1 ):
@@ -262,10 +267,13 @@ def writable(self):
262267 return self .mode .writing
263268
264269 def write (self , data ):
265- # type: (bytes) -> int
270+ # type: (Union[ bytes, bytearray, memoryview, array.array[Any], mmap.mmap] ) -> int
266271 if not self .mode .writing :
267272 raise IOError ("File not open for writing" )
268273
274+ if isinstance (data , array .array ):
275+ data = data .tobytes ()
276+
269277 with self ._lock :
270278 conn = self .write_conn
271279 data_pos = 0
@@ -281,8 +289,9 @@ def write(self, data):
281289 return data_pos
282290
283291 def writelines (self , lines ):
284- # type: (Iterable[bytes]) -> None
285- self .write (b"" .join (lines ))
292+ # type: (Iterable[Union[bytes, bytearray, memoryview, array.array[Any], mmap.mmap]]) -> None
293+ for line in lines :
294+ self .write (line )
286295
287296 def truncate (self , size = None ):
288297 # type: (Optional[int]) -> int
0 commit comments