@@ -26,32 +26,34 @@ def __init__(
2626 self .mode = mode
2727 self .max_requests = max_requests or _MAX_SFTP_REQUESTS
2828
29- if block_size is None :
30- # "The OpenSSH SFTP server will close the connection
31- # if it receives a message larger than 256 KB, and
32- # limits read requests to returning no more than
33- # 64 KB."
34- #
35- # We are going to use the maximum block_size possible
36- # with a 16KB margin (so instead of sending 256 KB data,
37- # we'll send 240 KB + headers for write requests)
38-
39- if self .readable ():
40- block_size = READ_BLOCK_SIZE
41- else :
42- block_size = WRITE_BLOCK_SIZE
43-
4429 # The blocksize is often used with constructs like
4530 # shutil.copyfileobj(src, dst, length=file.blocksize) and since we are
4631 # using pipelining, we are going to reflect the total size rather than
4732 # a size of chunk to our limits.
48- self .blocksize = block_size * self .max_requests
33+ self .blocksize = None if block_size is None else block_size * self .max_requests
4934
5035 self .kwargs = kwargs
5136
5237 self ._file = sync (self .loop , self ._open_file )
5338 self ._closed = False
5439
40+ def _determine_block_size (self , channel ):
41+ # Use the asyncssh block sizes to ensure the best performance.
42+ limits = getattr (channel , "limits" , None )
43+ if limits :
44+ return limits .max_read_len if self .readable () else limits .max_write_len
45+
46+ # "The OpenSSH SFTP server will close the connection
47+ # if it receives a message larger than 256 KB, and
48+ # limits read requests to returning no more than
49+ # 64 KB."
50+ #
51+ # We are going to use the maximum block_size possible
52+ # with a 16KB margin (so instead of sending 256 KB data,
53+ # we'll send 240 KB + headers for write requests)
54+ return READ_BLOCK_SIZE if self .readable () else WRITE_BLOCK_SIZE
55+
56+
5557 @wrap_exceptions
5658 async def _open_file (self ):
5759 # TODO: this needs to keep a reference to the
@@ -61,6 +63,8 @@ async def _open_file(self):
6163 # it's operations but the pool it thinking this
6264 # channel is freed.
6365 async with self .fs ._pool .get () as channel :
66+ if self .blocksize is None :
67+ self .blocksize = self ._determine_block_size (channel ) * self .max_requests
6468 return await channel .open (
6569 self .path ,
6670 self .mode ,
0 commit comments