Author: Armin Rigo <[email protected]>
Branch: py3.5
Changeset: r90564:33eb17e3bdc3
Date: 2017-03-05 12:54 +0100
http://bitbucket.org/pypy/pypy/changeset/33eb17e3bdc3/
Log: Implement sendfile() in the posix module. (Not implemented so far:
the extra BSD or OS/X arguments)
diff --git a/pypy/module/posix/__init__.py b/pypy/module/posix/__init__.py
--- a/pypy/module/posix/__init__.py
+++ b/pypy/module/posix/__init__.py
@@ -213,6 +213,9 @@
assert getattr(rposix, _name) is not None, "missing %r" % (_name,)
interpleveldefs[_name] = 'space.wrap(%d)' % getattr(rposix, _name)
+ if hasattr(rposix, 'sendfile'):
+ interpleveldefs['sendfile'] = 'interp_posix.sendfile'
+
for _name in ["O_CLOEXEC"]:
if getattr(rposix, _name) is not None:
interpleveldefs[_name] = 'space.wrap(%d)' % getattr(rposix, _name)
diff --git a/pypy/module/posix/interp_posix.py
b/pypy/module/posix/interp_posix.py
--- a/pypy/module/posix/interp_posix.py
+++ b/pypy/module/posix/interp_posix.py
@@ -24,6 +24,7 @@
_WIN32 = sys.platform == 'win32'
+_LINUX = sys.platform.startswith('linux')
if _WIN32:
from rpython.rlib import rwin32
@@ -2346,3 +2347,30 @@
rposix.set_status_flags(fd, flags)
except OSError as e:
raise wrap_oserror(space, e, eintr_retry=False)
+
+@unwrap_spec(out=c_int, in_=c_int, count=int)
+def sendfile(space, out, in_, w_offset, count):
+ # NB. argument name difference with CPython: "in" versus "in_".
+ # According to a comment in posixmodule.c, the authors are aware that
+ # "in" is a Python keyword and so the argument name is bogus, but don't
+ # do anything about it anyway. PyPy calls it "in_" instead because
+ # "in" would require all sorts of special cases. I hope nobody
+ # relies on the strange name of CPython.
+
+ # XXX only supports the common arguments for now (BSD takes more)
+ if _LINUX and space.is_none(w_offset):
+ while True:
+ try:
+ res = rposix.sendfile_no_offset(out, in_, count)
+ break
+ except OSError as e:
+ wrap_oserror(space, e, eintr_retry=True)
+ else:
+ offset = space.gateway_r_longlong_w(w_offset)
+ while True:
+ try:
+ res = rposix.sendfile(out, in_, offset, count)
+ break
+ except OSError as e:
+ wrap_oserror(space, e, eintr_retry=True)
+ return space.newint(res)
diff --git a/pypy/module/posix/test/test_posix2.py
b/pypy/module/posix/test/test_posix2.py
--- a/pypy/module/posix/test/test_posix2.py
+++ b/pypy/module/posix/test/test_posix2.py
@@ -14,7 +14,7 @@
USEMODULES = ['binascii', 'posix', 'signal', 'struct', 'time']
# py3k os.open uses subprocess, requiring the following per platform
if os.name != 'nt':
- USEMODULES += ['fcntl', 'select', '_posixsubprocess']
+ USEMODULES += ['fcntl', 'select', '_posixsubprocess', '_socket']
else:
USEMODULES += ['_rawffi', 'thread']
@@ -1189,6 +1189,36 @@
raises(OSError, posix.get_blocking, 1234567)
raises(OSError, posix.set_blocking, 1234567, True)
+ if sys.platform != 'win32':
+ def test_sendfile(self):
+ import _socket, posix
+ s1, s2 = _socket.socketpair()
+ fd = posix.open(self.path, posix.O_RDONLY)
+ res = posix.sendfile(s1.fileno(), fd, 3, 5)
+ assert res == 5
+ assert posix.lseek(fd, 0, 1) == 0
+ data = s2.recv(10)
+ expected = b'this is a test'[3:8]
+ assert data == expected
+ posix.close(fd)
+ s2.close()
+ s1.close()
+
+ if sys.platform.startswith('linux'):
+ def test_sendfile_no_offset(self):
+ import _socket, posix
+ s1, s2 = _socket.socketpair()
+ fd = posix.open(self.path, posix.O_RDONLY)
+ posix.lseek(fd, 3, 0)
+ res = posix.sendfile(s1.fileno(), fd, None, 5)
+ assert res == 5
+ assert posix.lseek(fd, 0, 1) == 8
+ data = s2.recv(10)
+ expected = b'this is a test'[3:8]
+ assert data == expected
+ posix.close(fd)
+ s2.close()
+ s1.close()
def test_urandom(self):
os = self.posix
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit