Unverified Kaydet (Commit) 7464e87a authored tarafından Andrew Svetlov's avatar Andrew Svetlov Kaydeden (comit) GitHub

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

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