diff options
| -rw-r--r-- | Doc/library/asyncio-eventloop.rst | 14 | ||||
| -rw-r--r-- | Lib/asyncio/base_events.py | 17 | ||||
| -rw-r--r-- | Lib/asyncio/events.py | 10 | ||||
| -rw-r--r-- | Lib/asyncio/unix_events.py | 8 | ||||
| -rw-r--r-- | Lib/test/test_asyncio/test_base_events.py | 5 | ||||
| -rw-r--r-- | Lib/test/test_asyncio/test_unix_events.py | 13 | 
6 files changed, 42 insertions, 25 deletions
diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index e63180b750..6cee171b65 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -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  ------------------- diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index b6a9384d95..00c84a835c 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -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") diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index b06721f3b0..d5365dc480 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -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.""" diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index f40ef12f26..028a0ca8f8 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -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) diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 085124f537..fc3b81096d 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -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)) diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index 4e2b76bb47..8646bf765e 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -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,  | 
