Skip to content

Commit 7464e87

Browse files
authored
bpo-32410: Make SendfileNotAvailableError exception public (#5243)
1 parent 2507e29 commit 7464e87

File tree

6 files changed

+42
-25
lines changed

6 files changed

+42
-25
lines changed

Doc/library/asyncio-eventloop.rst

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,7 @@ Low-level socket operations
726726
the file when the platform does not support the sendfile syscall
727727
(e.g. Windows or SSL socket on Unix).
728728

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

732732
.. versionadded:: 3.7
@@ -980,6 +980,18 @@ Handle
980980
.. versionadded:: 3.7
981981

982982

983+
SendfileNotAvailableError
984+
-------------------------
985+
986+
987+
.. exception:: SendfileNotAvailableError
988+
989+
Sendfile syscall is not available, subclass of :exc:`RuntimeError`.
990+
991+
Raised if the OS does not support senfile syscall for
992+
given socket or file type.
993+
994+
983995
Event loop examples
984996
-------------------
985997

Lib/asyncio/base_events.py

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,6 @@ def _run_until_complete_cb(fut):
154154
futures._get_loop(fut).stop()
155155

156156

157-
class _SendfileNotAvailable(RuntimeError):
158-
pass
159-
160-
161157
class Server(events.AbstractServer):
162158

163159
def __init__(self, loop, sockets):
@@ -659,17 +655,16 @@ async def sock_sendfile(self, sock, file, offset=0, count=None,
659655
try:
660656
return await self._sock_sendfile_native(sock, file,
661657
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
658+
except events.SendfileNotAvailableError as exc:
659+
if not fallback:
660+
raise
661+
return await self._sock_sendfile_fallback(sock, file,
662+
offset, count)
668663

669664
async def _sock_sendfile_native(self, sock, file, offset, count):
670665
# NB: sendfile syscall is not supported for SSL sockets and
671666
# non-mmap files even if sendfile is supported by OS
672-
raise _SendfileNotAvailable(
667+
raise events.SendfileNotAvailableError(
673668
f"syscall sendfile is not available for socket {sock!r} "
674669
"and file {file!r} combination")
675670

Lib/asyncio/events.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
__all__ = (
44
'AbstractEventLoopPolicy',
55
'AbstractEventLoop', 'AbstractServer',
6-
'Handle', 'TimerHandle',
6+
'Handle', 'TimerHandle', 'SendfileNotAvailableError',
77
'get_event_loop_policy', 'set_event_loop_policy',
88
'get_event_loop', 'set_event_loop', 'new_event_loop',
99
'get_child_watcher', 'set_child_watcher',
@@ -20,6 +20,14 @@
2020
from . import format_helpers
2121

2222

23+
class SendfileNotAvailableError(RuntimeError):
24+
"""Sendfile syscall is not available.
25+
26+
Raised if OS does not support senfile syscall for given socket or
27+
file type.
28+
"""
29+
30+
2331
class Handle:
2432
"""Object returned by callback registration methods."""
2533

Lib/asyncio/unix_events.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -313,16 +313,16 @@ async def _sock_sendfile_native(self, sock, file, offset, count):
313313
try:
314314
os.sendfile
315315
except AttributeError as exc:
316-
raise base_events._SendfileNotAvailable(
316+
raise events.SendfileNotAvailableError(
317317
"os.sendfile() is not available")
318318
try:
319319
fileno = file.fileno()
320320
except (AttributeError, io.UnsupportedOperation) as err:
321-
raise base_events._SendfileNotAvailable("not a regular file")
321+
raise events.SendfileNotAvailableError("not a regular file")
322322
try:
323323
fsize = os.fstat(fileno).st_size
324324
except OSError as err:
325-
raise base_events._SendfileNotAvailable("not a regular file")
325+
raise events.SendfileNotAvailableError("not a regular file")
326326
blocksize = count if count else fsize
327327
if not blocksize:
328328
return 0 # empty file
@@ -365,7 +365,7 @@ def _sock_sendfile_native_impl(self, fut, registered_fd, sock, fileno,
365365
# one being 'file' is not a regular mmap(2)-like
366366
# file, in which case we'll fall back on using
367367
# plain send().
368-
err = base_events._SendfileNotAvailable(
368+
err = events.SendfileNotAvailableError(
369369
"os.sendfile call failed")
370370
self._sock_sendfile_update_filepos(fileno, offset, total_sent)
371371
fut.set_exception(err)

Lib/test/test_asyncio/test_base_events.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import asyncio
1515
from asyncio import base_events
1616
from asyncio import constants
17+
from asyncio import events
1718
from test.test_asyncio import utils as test_utils
1819
from test import support
1920
from test.support.script_helper import assert_python_ok
@@ -1860,7 +1861,7 @@ def cleanup():
18601861
def test__sock_sendfile_native_failure(self):
18611862
sock, proto = self.prepare()
18621863

1863-
with self.assertRaisesRegex(base_events._SendfileNotAvailable,
1864+
with self.assertRaisesRegex(events.SendfileNotAvailableError,
18641865
"sendfile is not available"):
18651866
self.run_loop(self.loop._sock_sendfile_native(sock, self.file,
18661867
0, None))
@@ -1871,7 +1872,7 @@ def test__sock_sendfile_native_failure(self):
18711872
def test_sock_sendfile_no_fallback(self):
18721873
sock, proto = self.prepare()
18731874

1874-
with self.assertRaisesRegex(RuntimeError,
1875+
with self.assertRaisesRegex(events.SendfileNotAvailableError,
18751876
"sendfile is not available"):
18761877
self.run_loop(self.loop.sock_sendfile(sock, self.file,
18771878
fallback=False))

Lib/test/test_asyncio/test_unix_events.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import asyncio
2424
from asyncio import log
2525
from asyncio import base_events
26+
from asyncio import events
2627
from asyncio import unix_events
2728
from test.test_asyncio import utils as test_utils
2829

@@ -517,7 +518,7 @@ def test_with_offset_and_count(self):
517518
def test_sendfile_not_available(self):
518519
sock, proto = self.prepare()
519520
with mock.patch('asyncio.unix_events.os', spec=[]):
520-
with self.assertRaisesRegex(base_events._SendfileNotAvailable,
521+
with self.assertRaisesRegex(events.SendfileNotAvailableError,
521522
"os[.]sendfile[(][)] is not available"):
522523
self.run_loop(self.loop._sock_sendfile_native(sock, self.file,
523524
0, None))
@@ -526,7 +527,7 @@ def test_sendfile_not_available(self):
526527
def test_sendfile_not_a_file(self):
527528
sock, proto = self.prepare()
528529
f = object()
529-
with self.assertRaisesRegex(base_events._SendfileNotAvailable,
530+
with self.assertRaisesRegex(events.SendfileNotAvailableError,
530531
"not a regular file"):
531532
self.run_loop(self.loop._sock_sendfile_native(sock, f,
532533
0, None))
@@ -535,7 +536,7 @@ def test_sendfile_not_a_file(self):
535536
def test_sendfile_iobuffer(self):
536537
sock, proto = self.prepare()
537538
f = io.BytesIO()
538-
with self.assertRaisesRegex(base_events._SendfileNotAvailable,
539+
with self.assertRaisesRegex(events.SendfileNotAvailableError,
539540
"not a regular file"):
540541
self.run_loop(self.loop._sock_sendfile_native(sock, f,
541542
0, None))
@@ -545,7 +546,7 @@ def test_sendfile_not_regular_file(self):
545546
sock, proto = self.prepare()
546547
f = mock.Mock()
547548
f.fileno.return_value = -1
548-
with self.assertRaisesRegex(base_events._SendfileNotAvailable,
549+
with self.assertRaisesRegex(events.SendfileNotAvailableError,
549550
"not a regular file"):
550551
self.run_loop(self.loop._sock_sendfile_native(sock, f,
551552
0, None))
@@ -631,7 +632,7 @@ def test_os_error_first_call(self):
631632
with self.assertRaises(KeyError):
632633
self.loop._selector.get_key(sock)
633634
exc = fut.exception()
634-
self.assertIsInstance(exc, base_events._SendfileNotAvailable)
635+
self.assertIsInstance(exc, events.SendfileNotAvailableError)
635636
self.assertEqual(0, self.file.tell())
636637

637638
def test_os_error_next_call(self):
@@ -656,7 +657,7 @@ def test_exception(self):
656657

657658
fileno = self.file.fileno()
658659
fut = self.loop.create_future()
659-
err = RuntimeError()
660+
err = events.SendfileNotAvailableError()
660661
with mock.patch('os.sendfile', side_effect=err):
661662
self.loop._sock_sendfile_native_impl(fut, sock.fileno(),
662663
sock, fileno,

0 commit comments

Comments
 (0)