Skip to content

Commit 4d25927

Browse files
committed
Support tribool for fallback
1 parent f7d9bab commit 4d25927

File tree

3 files changed

+35
-14
lines changed

3 files changed

+35
-14
lines changed

Doc/library/asyncio-eventloop.rst

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,7 @@ Low-level socket operations
703703

704704
.. coroutinemethod:: AbstractEventLoop.sock_sendfile(sock, file, \
705705
offset=0, count=None, \
706-
*, fallback=True)
706+
*, fallback=None)
707707
708708
Send a file using high-performance :mod:`os.sendfile` if possible
709709
and return the total number of bytes which were sent.
@@ -722,13 +722,15 @@ Low-level socket operations
722722
<io.IOBase.tell>` can be used to figure out the number of bytes
723723
which were sent.
724724

725-
*fallback* set to ``True`` makes asyncio to manually read and send
726-
the file when the platform does not support the sendfile syscall
727-
(e.g. Windows or SSL socket on Unix).
725+
*fallback* set to ``None`` makes asyncio to manually read and send
726+
the file when the platform does not support the :func:`os.sendfile`
727+
syscall (e.g. Windows or SSL socket on Unix).
728728

729729
Raise :exc:`RuntimeError` if the system does not support
730730
*sendfile* syscall and *fallback* is ``False``.
731731

732+
Never try to use :func:`os.sendfile` if *fallback* is ``True``.
733+
732734
.. versionadded:: 3.7
733735

734736

Lib/asyncio/base_events.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -652,19 +652,23 @@ async def getnameinfo(self, sockaddr, flags=0):
652652
None, socket.getnameinfo, sockaddr, flags)
653653

654654
async def sock_sendfile(self, sock, file, offset=0, count=None,
655-
*, fallback=True):
655+
*, fallback=None):
656656
if self._debug and sock.gettimeout() != 0:
657657
raise ValueError("the socket must be non-blocking")
658658
self._check_sendfile_params(sock, file, offset, count)
659-
try:
660-
return await self._sock_sendfile_native(sock, file,
661-
offset, count)
662-
except _SendfileNotAvailable as exc:
663-
if fallback:
664-
return await self._sock_sendfile_fallback(sock, file,
665-
offset, count)
666-
else:
667-
raise RuntimeError(exc.args[0]) from None
659+
if fallback:
660+
return await self._sock_sendfile_fallback(sock, file,
661+
offset, count)
662+
else:
663+
try:
664+
return await self._sock_sendfile_native(sock, file,
665+
offset, count)
666+
except _SendfileNotAvailable as exc:
667+
if fallback is None:
668+
return await self._sock_sendfile_fallback(sock, file,
669+
offset, count)
670+
else:
671+
raise RuntimeError(exc.args[0]) from None
668672

669673
async def _sock_sendfile_native(self, sock, file, offset, count):
670674
raise _SendfileNotAvailable("Fast sendfile is not available")

Lib/test/test_asyncio/test_base_events.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1868,6 +1868,21 @@ def test__sock_sendfile_native_failure(self):
18681868
self.assertEqual(proto.data, b'')
18691869
self.assertEqual(self.file.tell(), 0)
18701870

1871+
def test__sock_sendfile_always_fallback(self):
1872+
sock, proto = self.prepare()
1873+
1874+
self.loop._sock_sendfile_native = mock.Mock()
1875+
ret = self.run_loop(self.loop.sock_sendfile(sock, self.file,
1876+
0, None, fallback=True))
1877+
1878+
sock.close()
1879+
self.run_loop(proto.wait_closed())
1880+
1881+
self.assertEqual(ret, len(self.DATA))
1882+
self.assertEqual(proto.data, self.DATA)
1883+
self.assertEqual(self.file.tell(), len(self.DATA))
1884+
self.loop._sock_sendfile_native.assert_not_called()
1885+
18711886
def test_sock_sendfile_no_fallback(self):
18721887
sock, proto = self.prepare()
18731888

0 commit comments

Comments
 (0)