Commit 7464e87a authored by Andrew Svetlov's avatar Andrew Svetlov Committed by GitHub

bpo-32410: Make SendfileNotAvailableError exception public (#5243)

parent 2507e29a
......@@ -726,7 +726,7 @@ Low-level socket operations
the file when the platform does not support the sendfile syscall
(e.g. Windows or SSL socket on Unix).
Raise :exc:`RuntimeError` if the system does not support
Raise :exc:`SendfileNotAvailableError` if the system does not support
*sendfile* syscall and *fallback* is ``False``.
.. versionadded:: 3.7
......@@ -980,6 +980,18 @@ Handle
.. versionadded:: 3.7
SendfileNotAvailableError
-------------------------
.. exception:: SendfileNotAvailableError
Sendfile syscall is not available, subclass of :exc:`RuntimeError`.
Raised if the OS does not support senfile syscall for
given socket or file type.
Event loop examples
-------------------
......
......@@ -154,10 +154,6 @@ def _run_until_complete_cb(fut):
futures._get_loop(fut).stop()
class _SendfileNotAvailable(RuntimeError):
pass
class Server(events.AbstractServer):
def __init__(self, loop, sockets):
......@@ -659,17 +655,16 @@ class BaseEventLoop(events.AbstractEventLoop):
try:
return await self._sock_sendfile_native(sock, file,
offset, count)
except _SendfileNotAvailable as exc:
if fallback:
return await self._sock_sendfile_fallback(sock, file,
offset, count)
else:
raise RuntimeError(exc.args[0]) from None
except events.SendfileNotAvailableError as exc:
if not fallback:
raise
return await self._sock_sendfile_fallback(sock, file,
offset, count)
async def _sock_sendfile_native(self, sock, file, offset, count):
# NB: sendfile syscall is not supported for SSL sockets and
# non-mmap files even if sendfile is supported by OS
raise _SendfileNotAvailable(
raise events.SendfileNotAvailableError(
f"syscall sendfile is not available for socket {sock!r} "
"and file {file!r} combination")
......
......@@ -3,7 +3,7 @@
__all__ = (
'AbstractEventLoopPolicy',
'AbstractEventLoop', 'AbstractServer',
'Handle', 'TimerHandle',
'Handle', 'TimerHandle', 'SendfileNotAvailableError',
'get_event_loop_policy', 'set_event_loop_policy',
'get_event_loop', 'set_event_loop', 'new_event_loop',
'get_child_watcher', 'set_child_watcher',
......@@ -20,6 +20,14 @@ import threading
from . import format_helpers
class SendfileNotAvailableError(RuntimeError):
"""Sendfile syscall is not available.
Raised if OS does not support senfile syscall for given socket or
file type.
"""
class Handle:
"""Object returned by callback registration methods."""
......
......@@ -313,16 +313,16 @@ class _UnixSelectorEventLoop(selector_events.BaseSelectorEventLoop):
try:
os.sendfile
except AttributeError as exc:
raise base_events._SendfileNotAvailable(
raise events.SendfileNotAvailableError(
"os.sendfile() is not available")
try:
fileno = file.fileno()
except (AttributeError, io.UnsupportedOperation) as err:
raise base_events._SendfileNotAvailable("not a regular file")
raise events.SendfileNotAvailableError("not a regular file")
try:
fsize = os.fstat(fileno).st_size
except OSError as err:
raise base_events._SendfileNotAvailable("not a regular file")
raise events.SendfileNotAvailableError("not a regular file")
blocksize = count if count else fsize
if not blocksize:
return 0 # empty file
......@@ -365,7 +365,7 @@ class _UnixSelectorEventLoop(selector_events.BaseSelectorEventLoop):
# one being 'file' is not a regular mmap(2)-like
# file, in which case we'll fall back on using
# plain send().
err = base_events._SendfileNotAvailable(
err = events.SendfileNotAvailableError(
"os.sendfile call failed")
self._sock_sendfile_update_filepos(fileno, offset, total_sent)
fut.set_exception(err)
......
......@@ -14,6 +14,7 @@ from unittest import mock
import asyncio
from asyncio import base_events
from asyncio import constants
from asyncio import events
from test.test_asyncio import utils as test_utils
from test import support
from test.support.script_helper import assert_python_ok
......@@ -1860,7 +1861,7 @@ class BaseLoopSendfileTests(test_utils.TestCase):
def test__sock_sendfile_native_failure(self):
sock, proto = self.prepare()
with self.assertRaisesRegex(base_events._SendfileNotAvailable,
with self.assertRaisesRegex(events.SendfileNotAvailableError,
"sendfile is not available"):
self.run_loop(self.loop._sock_sendfile_native(sock, self.file,
0, None))
......@@ -1871,7 +1872,7 @@ class BaseLoopSendfileTests(test_utils.TestCase):
def test_sock_sendfile_no_fallback(self):
sock, proto = self.prepare()
with self.assertRaisesRegex(RuntimeError,
with self.assertRaisesRegex(events.SendfileNotAvailableError,
"sendfile is not available"):
self.run_loop(self.loop.sock_sendfile(sock, self.file,
fallback=False))
......
......@@ -23,6 +23,7 @@ if sys.platform == 'win32':
import asyncio
from asyncio import log
from asyncio import base_events
from asyncio import events
from asyncio import unix_events
from test.test_asyncio import utils as test_utils
......@@ -517,7 +518,7 @@ class SelectorEventLoopUnixSockSendfileTests(test_utils.TestCase):
def test_sendfile_not_available(self):
sock, proto = self.prepare()
with mock.patch('asyncio.unix_events.os', spec=[]):
with self.assertRaisesRegex(base_events._SendfileNotAvailable,
with self.assertRaisesRegex(events.SendfileNotAvailableError,
"os[.]sendfile[(][)] is not available"):
self.run_loop(self.loop._sock_sendfile_native(sock, self.file,
0, None))
......@@ -526,7 +527,7 @@ class SelectorEventLoopUnixSockSendfileTests(test_utils.TestCase):
def test_sendfile_not_a_file(self):
sock, proto = self.prepare()
f = object()
with self.assertRaisesRegex(base_events._SendfileNotAvailable,
with self.assertRaisesRegex(events.SendfileNotAvailableError,
"not a regular file"):
self.run_loop(self.loop._sock_sendfile_native(sock, f,
0, None))
......@@ -535,7 +536,7 @@ class SelectorEventLoopUnixSockSendfileTests(test_utils.TestCase):
def test_sendfile_iobuffer(self):
sock, proto = self.prepare()
f = io.BytesIO()
with self.assertRaisesRegex(base_events._SendfileNotAvailable,
with self.assertRaisesRegex(events.SendfileNotAvailableError,
"not a regular file"):
self.run_loop(self.loop._sock_sendfile_native(sock, f,
0, None))
......@@ -545,7 +546,7 @@ class SelectorEventLoopUnixSockSendfileTests(test_utils.TestCase):
sock, proto = self.prepare()
f = mock.Mock()
f.fileno.return_value = -1
with self.assertRaisesRegex(base_events._SendfileNotAvailable,
with self.assertRaisesRegex(events.SendfileNotAvailableError,
"not a regular file"):
self.run_loop(self.loop._sock_sendfile_native(sock, f,
0, None))
......@@ -631,7 +632,7 @@ class SelectorEventLoopUnixSockSendfileTests(test_utils.TestCase):
with self.assertRaises(KeyError):
self.loop._selector.get_key(sock)
exc = fut.exception()
self.assertIsInstance(exc, base_events._SendfileNotAvailable)
self.assertIsInstance(exc, events.SendfileNotAvailableError)
self.assertEqual(0, self.file.tell())
def test_os_error_next_call(self):
......@@ -656,7 +657,7 @@ class SelectorEventLoopUnixSockSendfileTests(test_utils.TestCase):
fileno = self.file.fileno()
fut = self.loop.create_future()
err = RuntimeError()
err = events.SendfileNotAvailableError()
with mock.patch('os.sendfile', side_effect=err):
self.loop._sock_sendfile_native_impl(fut, sock.fileno(),
sock, fileno,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment