[pypy-svn] r33649 - in pypy/dist/pypy/module/rsocket: . test
ac at codespeak.net
ac at codespeak.net
Tue Oct 24 14:38:52 CEST 2006
Author: ac
Date: Tue Oct 24 14:38:49 2006
New Revision: 33649
Modified:
pypy/dist/pypy/module/rsocket/__init__.py
pypy/dist/pypy/module/rsocket/ctypes_socket.py
pypy/dist/pypy/module/rsocket/interp_socket.py
pypy/dist/pypy/module/rsocket/rsocket.py
pypy/dist/pypy/module/rsocket/test/test_rsocket.py
pypy/dist/pypy/module/rsocket/test/test_sock_app.py
Log:
Add support for timeouts on sockets. You can now import socket at app-level :-)
Allso, sort methods by name.
Modified: pypy/dist/pypy/module/rsocket/__init__.py
==============================================================================
--- pypy/dist/pypy/module/rsocket/__init__.py (original)
+++ pypy/dist/pypy/module/rsocket/__init__.py Tue Oct 24 14:38:49 2006
@@ -25,10 +25,12 @@
fromfd socketpair
ntohs ntohl htons htonl inet_aton inet_ntoa inet_pton inet_ntop
getaddrinfo getnameinfo
- getdefaulttimeout setdefaulttimeout
""".split():
Module.interpleveldefs[name] = 'interp_func.%s' % (name, )
+ for name in """getdefaulttimeout setdefaulttimeout""".split():
+ Module.interpleveldefs[name] = 'interp_socket.%s' % (name, )
+
for constant, value in _c.constants.iteritems():
Module.interpleveldefs[constant] = "space.wrap(%r)" % value
Modified: pypy/dist/pypy/module/rsocket/ctypes_socket.py
==============================================================================
--- pypy/dist/pypy/module/rsocket/ctypes_socket.py (original)
+++ pypy/dist/pypy/module/rsocket/ctypes_socket.py Tue Oct 24 14:38:49 2006
@@ -7,7 +7,7 @@
from pypy.rpython.rctypes.aerrno import geterrno
from ctypes import c_ushort, c_int, c_uint, c_char_p, c_void_p, c_char, c_ubyte
-from ctypes import POINTER, ARRAY, cdll, sizeof, SetPointerType
+from ctypes import c_short, POINTER, ARRAY, cdll, sizeof, SetPointerType
# Also not used here, but exported for other code.
from ctypes import cast, pointer, create_string_buffer
@@ -15,6 +15,7 @@
includes = ('sys/types.h',
'sys/socket.h',
'sys/un.h',
+ 'sys/poll.h',
'netinet/in.h',
'netinet/tcp.h',
'unistd.h',
@@ -39,7 +40,11 @@
INVALID_SOCKET = ctypes_platform.DefinedConstantInteger('INVALID_SOCKET')
INET_ADDRSTRLEN = ctypes_platform.DefinedConstantInteger('INET_ADDRSTRLEN')
INET6_ADDRSTRLEN= ctypes_platform.DefinedConstantInteger('INET6_ADDRSTRLEN')
-
+ POLLIN = ctypes_platform.DefinedConstantInteger('POLLIN')
+ POLLOUT = ctypes_platform.DefinedConstantInteger('POLLOUT')
+ EINPROGRESS = ctypes_platform.DefinedConstantInteger('EINPROGRESS')
+ EWOULDBLOCK = ctypes_platform.DefinedConstantInteger('EWOULDBLOCK')
+
constant_names = ['AF_APPLETALK', 'AF_ASH', 'AF_ATMPVC', 'AF_ATMSVC', 'AF_AX25',
'AF_BLUETOOTH', 'AF_BRIDGE', 'AF_ECONET', 'AF_INET', 'AF_INET6',
'AF_IPX', 'AF_IRDA', 'AF_KEY', 'AF_NETBEUI', 'AF_NETLINK',
@@ -163,6 +168,12 @@
[('p_proto', c_int),
])
+CConfig.nfds_t = ctypes_platform.SimpleType('nfds_t')
+CConfig.pollfd = ctypes_platform.Struct('struct pollfd',
+ [('fd', c_int),
+ ('events', c_short),
+ ('revents', c_short)])
+
class cConfig:
pass
cConfig.__dict__.update(ctypes_platform.configure(CConfig))
@@ -192,6 +203,10 @@
F_SETFL = cConfig.F_SETFL
INET_ADDRSTRLEN = cConfig.INET_ADDRSTRLEN
INET6_ADDRSTRLEN = cConfig.INET6_ADDRSTRLEN
+POLLIN = cConfig.POLLIN
+POLLOUT = cConfig.POLLOUT
+EINPROGRESS = cConfig.EINPROGRESS
+EWOULDBLOCK = cConfig.EWOULDBLOCK
linux = cConfig.linux
MS_WINDOWS = cConfig.MS_WINDOWS
@@ -218,11 +233,14 @@
in_addr_size = sizeof(in_addr)
in6_addr = cConfig.in6_addr
addrinfo = cConfig.addrinfo
+nfds_t = cConfig.nfds_t
+pollfd = cConfig.pollfd
c_int_size = sizeof(c_int)
SetPointerType(addrinfo_ptr, addrinfo)
SetPointerType(sockaddr_ptr, sockaddr)
+
# functions
dllname = util.find_library('c')
assert dllname is not None
@@ -412,6 +430,9 @@
shutdown.argtypes = [c_int, c_int]
shutdown.restype = c_int
+poll = socketdll.poll
+poll.argtypes = [POINTER(pollfd), nfds_t, c_int]
+poll.restype = c_int
if MS_WINDOWS:
WIN32_ERROR_MESSAGES = {
Modified: pypy/dist/pypy/module/rsocket/interp_socket.py
==============================================================================
--- pypy/dist/pypy/module/rsocket/interp_socket.py (original)
+++ pypy/dist/pypy/module/rsocket/interp_socket.py Tue Oct 24 14:38:49 2006
@@ -8,7 +8,10 @@
class W_RSocket(Wrappable, RSocket):
-
+ def __init__(self, space, family, type, proto):
+ RSocket.__init__(self, family, type, proto)
+ self.settimeout(space.fromcache(State).defaulttimeout)
+
def accept_w(self, space):
"""accept() -> (socket object, address info)
@@ -125,28 +128,18 @@
buflen = space.int_w(w_buflen)
return space.wrap(self.getsockopt(level, optname, buflen))
getsockopt_w.unwrap_spec = ['self', ObjSpace, int, int, W_Root]
-
- def setsockopt_w(self, space, level, optname, w_optval):
- """setsockopt(level, option, value)
- Set a socket option. See the Unix manual for level and option.
- The value argument can either be an integer or a string.
+ def gettimeout_w(self, space):
+ """gettimeout() -> timeout
+
+ Returns the timeout in floating seconds associated with socket
+ operations. A timeout of None indicates that timeouts on socket
"""
- try:
- optval = space.int_w(w_optval)
- except:
- optval = space.str_w(w_optval)
- try:
- self.setsockopt(level, optname, optval)
- except SocketError, e:
- raise converted_error(space, e)
- return
- try:
- self.setsockopt_int(level, optname, optval)
- except SocketError, e:
- raise converted_error(space, e)
-
- setsockopt_w.unwrap_spec = ['self', ObjSpace, int, int, W_Root]
+ timeout = self.gettimeout()
+ if timeout < 0.0:
+ return space.w_None
+ return space.wrap(timeout)
+ gettimeout_w.unwrap_spec = ['self', ObjSpace]
def listen_w(self, space, backlog):
"""listen(backlog)
@@ -248,6 +241,46 @@
self.setblocking(bool(flag))
setblocking_w.unwrap_spec = ['self', ObjSpace, int]
+ def setsockopt_w(self, space, level, optname, w_optval):
+ """setsockopt(level, option, value)
+
+ Set a socket option. See the Unix manual for level and option.
+ The value argument can either be an integer or a string.
+ """
+ try:
+ optval = space.int_w(w_optval)
+ except:
+ optval = space.str_w(w_optval)
+ try:
+ self.setsockopt(level, optname, optval)
+ except SocketError, e:
+ raise converted_error(space, e)
+ return
+ try:
+ self.setsockopt_int(level, optname, optval)
+ except SocketError, e:
+ raise converted_error(space, e)
+
+ setsockopt_w.unwrap_spec = ['self', ObjSpace, int, int, W_Root]
+
+ def settimeout_w(self, space, w_timeout):
+ """settimeout(timeout)
+
+ Set a timeout on socket operations. 'timeout' can be a float,
+ giving in seconds, or None. Setting a timeout of None disables
+ the timeout feature and is equivalent to setblocking(1).
+ Setting a timeout of zero is the same as setblocking(0).
+ """
+ if space.is_w(w_timeout, space.w_None):
+ timeout = -1.0
+ else:
+ timeout = space.float_w(w_timeout)
+ if timeout < 0.0:
+ raise OperationError(space.w_ValueError,
+ space.wrap('Timeout value out of range'))
+ self.settimeout(timeout)
+ settimeout_w.unwrap_spec = ['self', ObjSpace, W_Root]
+
def shutdown_w(self, space, how):
"""shutdown(flag)
@@ -261,7 +294,34 @@
raise converted_error(space, e)
shutdown_w.unwrap_spec = ['self', ObjSpace, int]
+class State:
+ defaulttimeout = -1.0 # Default is blocking
+ def __init__(self, space):
+ pass
+
+def getdefaulttimeout(space):
+ """getdefaulttimeout() -> timeout
+ Returns the default timeout in floating seconds for new socket objects.
+ A value of None indicates that new socket objects have no timeout.
+ When the socket module is first imported, the default is None.
+ """
+ timeout = space.fromcache(State).defaulttimeout
+ if timeout < 0.0:
+ return space.w_None
+ return space.wrap(timeout)
+getdefaulttimeout.unwrap_spec = [ObjSpace]
+
+def setdefaulttimeout(space, w_timeout):
+ if space.is_w(w_timeout, space.w_None):
+ timeout = -1.0
+ else:
+ timeout = space.float_w(w_timeout)
+ if timeout < 0.0:
+ raise OperationError(space.w_ValueError,
+ space.wrap('Timeout value out of range'))
+ space.fromcache(State).defaulttimeout = timeout
+
def newsocket(space, w_subtype, family=_c.AF_INET,
type=_c.SOCK_STREAM, proto=0):
# XXX If we want to support subclassing the socket type we will need
@@ -270,7 +330,7 @@
#sock = space.allocate_instance(W_RSocket, w_subtype)
#Socket.__init__(sock, space, fd, family, type, proto)
try:
- sock = W_RSocket(family, type, proto)
+ sock = W_RSocket(space, family, type, proto)
except SocketError, e:
raise converted_error(space, e)
return space.wrap(sock)
@@ -293,9 +353,9 @@
socketmethodnames = """
accept bind close connect connect_ex fileno
-getpeername getsockname getsockopt listen recv
+getpeername getsockname getsockopt gettimeout listen recv
recvfrom send sendall sendto setblocking
-setsockopt shutdown
+setsockopt settimeout shutdown
""".split() # dup makefile gettimeout settimeout
socketmethods = {}
for methodname in socketmethodnames:
Modified: pypy/dist/pypy/module/rsocket/rsocket.py
==============================================================================
--- pypy/dist/pypy/module/rsocket/rsocket.py (original)
+++ pypy/dist/pypy/module/rsocket/rsocket.py Tue Oct 24 14:38:49 2006
@@ -8,9 +8,8 @@
#
# - support for non-Linux platforms
# - address families other than AF_INET, AF_INET6, AF_UNIX
-# - methods dup(), getsockopt(), setsockopt(), makefile(),
-# gettimeout(), settimeout()
-# - functions getnameinfo(), getdefaulttimeout(), setdefaulttimeout()
+# - methods dup(), makefile(),
+# - functions getnameinfo()
# - SSL
from pypy.rpython.objectmodel import instantiate
@@ -411,7 +410,7 @@
"""
_mixin_ = True # for interp_socket.py
fd = _c.INVALID_SOCKET
-
+ timeout = -1.0 # Default is blocking
def __init__(self, family=_c.AF_INET, type=_c.SOCK_STREAM, proto=0):
"""Create a new socket."""
fd = _c.socket(family, type, proto)
@@ -422,10 +421,40 @@
self.family = family
self.type = type
self.proto = proto
-
+
def __del__(self):
self.close()
+ def _setblocking(self, block):
+ # PLAT various methods on other platforms
+ # XXX Windows missing
+ delay_flag = _c.fcntl(self.fd, _c.F_GETFL, 0)
+ if block:
+ delay_flag &= ~_c.O_NONBLOCK
+ else:
+ delay_flag |= _c.O_NONBLOCK
+ _c.fcntl(self.fd, _c.F_SETFL, delay_flag)
+
+ def _select(self, for_writing):
+ """Returns 0 when reading/writing is possible,
+ 1 when timing out and -1 on error."""
+ if self.timeout <= 0.0 or self.fd < 0:
+ # blocking I/O or no socket.
+ return 0
+ pollfd = _c.pollfd()
+ pollfd.fd = self.fd
+ if for_writing:
+ pollfd.events = _c.POLLOUT
+ else:
+ pollfd.events = _c.POLLIN
+ timeout = int(self.timeout * 1000.0 + 0.5)
+ n = _c.poll(byref(pollfd), 1, timeout)
+ if n < 0:
+ return -1
+ if n == 0:
+ return 1
+ return 0
+
def error_handler(self):
return last_error()
@@ -445,6 +474,8 @@
def accept(self):
"""Wait for an incoming connection.
Return (new socket object, client address)."""
+ if self._select(False) == 1:
+ raise SocketTimeout
address, addrlen = self._addrbuf()
newfd = _c.socketaccept(self.fd, byref(address.addr), byref(addrlen))
if _c.invalid_socket(newfd):
@@ -472,6 +503,18 @@
def connect(self, address):
"""Connect the socket to a remote address."""
res = _c.socketconnect(self.fd, byref(address.addr), address.addrlen)
+ if self.timeout > 0.0:
+ errno = _c.geterrno()
+ if res < 0 and errno == _c.EINPROGRESS:
+ timeout = self._select(True)
+ if timeout == 0:
+ res = _c.socketconnect(self.fd, byref(address.addr),
+ address.addrlen)
+ elif timeout == -1:
+ raise self.error_handler()
+ else:
+ raise SocketTimeout
+
if res != 0:
raise self.error_handler()
@@ -479,8 +522,20 @@
"""This is like connect(address), but returns an error code (the errno
value) instead of raising an exception when an error occurs."""
res = _c.socketconnect(self.fd, byref(address.addr), address.addrlen)
+ if self.timeout > 0.0:
+ errno = _c.geterrno()
+ if res < 0 and errno == _c.EINPROGRESS:
+ timeout = self._select(True)
+ if timeout == 0:
+ res = _c.socketconnect(self.fd, byref(address.addr),
+ address.addrlen)
+ elif timeout == -1:
+ return _c.geterrno()
+ else:
+ return _c.EWOULDBLOCK
+
if res != 0:
- res = _c.geterrno()
+ return _c.geterrno()
return res
def fileno(self):
@@ -509,6 +564,30 @@
address.addrlen = addrlen.value
return address
+ def getsockopt(self, level, option, maxlen):
+ buf = _c.create_string_buffer(maxlen)
+ bufsize = _c.socklen_t()
+ bufsize.value = maxlen
+ res = _c.socketgetsockopt(self.fd, level, option, byref(buf), byref(bufsize))
+ if res < 0:
+ raise self.error_handler()
+ return buf.raw[:bufsize.value]
+
+ def getsockopt_int(self, level, option):
+ flag = _c.c_int()
+ flagsize = _c.socklen_t()
+ flagsize.value = _c.sizeof(flag)
+ res = _c.socketgetsockopt(self.fd, level, option,
+ byref(flag), byref(flagsize))
+ if res < 0:
+ raise self.error_handler()
+ return flag.value
+
+ def gettimeout(self):
+ """Return the timeout of the socket. A timeout < 0 means that
+ timeouts are dissabled in the socket."""
+ return self.timeout
+
def listen(self, backlog):
"""Enable a server to accept connections. The backlog argument
must be at least 1; it specifies the number of unaccepted connections
@@ -525,8 +604,13 @@
until at least one byte is available or until the remote end is closed.
When the remote end is closed and all data is read, return the empty
string."""
- buf = create_string_buffer(buffersize)
- read_bytes = _c.socketrecv(self.fd, buf, buffersize, flags)
+ read_bytes = -1
+ timeout = self._select(False)
+ if timeout == 1:
+ raise SocketTimeout
+ elif timeout == 0:
+ buf = create_string_buffer(buffersize)
+ read_bytes = _c.socketrecv(self.fd, buf, buffersize, flags)
if read_bytes < 0:
raise self.error_handler()
return buf[:read_bytes]
@@ -534,10 +618,15 @@
def recvfrom(self, buffersize, flags=0):
"""Like recv(buffersize, flags) but also return the sender's
address."""
- buf = create_string_buffer(buffersize)
- address, addrlen = self._addrbuf()
- read_bytes = _c.recvfrom(self.fd, buf, buffersize, flags,
- byref(address.addr), byref(addrlen))
+ read_bytes = -1
+ timeout = self._select(False)
+ if timeout == 1:
+ raise SocketTimeout
+ elif timeout == 0:
+ buf = create_string_buffer(buffersize)
+ address, addrlen = self._addrbuf()
+ read_bytes = _c.recvfrom(self.fd, buf, buffersize, flags,
+ byref(address.addr), byref(addrlen))
if read_bytes < 0:
raise self.error_handler()
address.addrlen = addrlen.value
@@ -547,7 +636,12 @@
"""Send a data string to the socket. For the optional flags
argument, see the Unix manual. Return the number of bytes
sent; this may be less than len(data) if the network is busy."""
- res = _c.send(self.fd, data, len(data), flags)
+ res = -1
+ timeout = self._select(False)
+ if timeout == 1:
+ raise SocketTimeout
+ elif timeout == 0:
+ res = _c.send(self.fd, data, len(data), flags)
if res < 0:
raise self.error_handler()
return res
@@ -564,48 +658,28 @@
def sendto(self, data, flags, address):
"""Like send(data, flags) but allows specifying the destination
address. (Note that 'flags' is mandatory here.)"""
- res = _c.sendto(self.fd, data, len(data), flags,
- byref(address.addr), address.addrlen)
+ res = -1
+ timeout = self._select(False)
+ if timeout == 1:
+ raise SocketTimeout
+ elif timeout == 0:
+ res = _c.sendto(self.fd, data, len(data), flags,
+ byref(address.addr), address.addrlen)
if res < 0:
raise self.error_handler()
return res
def setblocking(self, block):
- # PLAT various methods on other platforms
- # XXX Windows missing
- delay_flag = _c.fcntl(self.fd, _c.F_GETFL, 0)
if block:
- delay_flag &= ~_c.O_NONBLOCK
+ timeout = -1.0
else:
- delay_flag |= _c.O_NONBLOCK
- _c.fcntl(self.fd, _c.F_SETFL, delay_flag)
-
- def shutdown(self, how):
- """Shut down the reading side of the socket (flag == SHUT_RD), the
- writing side of the socket (flag == SHUT_WR), or both ends
- (flag == SHUT_RDWR)."""
- res = _c.socketshutdown(self.fd, how)
- if res < 0:
- raise self.error_handler()
-
- def getsockopt_int(self, level, option):
- flag = _c.c_int()
- flagsize = _c.socklen_t()
- flagsize.value = _c.sizeof(flag)
- res = _c.socketgetsockopt(self.fd, level, option,
- byref(flag), byref(flagsize))
- if res < 0:
- raise self.error_handler()
- return flag.value
+ timeout = 0.0
+ self.settimeout(timeout)
- def getsockopt(self, level, option, maxlen):
- buf = _c.create_string_buffer(maxlen)
- bufsize = _c.socklen_t()
- bufsize.value = maxlen
- res = _c.socketgetsockopt(self.fd, level, option, byref(buf), byref(bufsize))
+ def setsockopt(self, level, option, value):
+ res = _c.socketsetsockopt(self.fd, level, option, value, len(value))
if res < 0:
raise self.error_handler()
- return buf.raw[:bufsize.value]
def setsockopt_int(self, level, option, value):
flag = _c.c_int(value)
@@ -614,10 +688,23 @@
if res < 0:
raise self.error_handler()
- def setsockopt(self, level, option, value):
- res = _c.socketsetsockopt(self.fd, level, option, value, len(value))
+ def settimeout(self, timeout):
+ """Set the timeout of the socket. A timeout < 0 means that
+ timeouts are dissabled in the socket."""
+ if timeout < 0.0:
+ self.timeout = -1.0
+ else:
+ self.timeout = timeout
+ self._setblocking(self.timeout < 0.0)
+
+ def shutdown(self, how):
+ """Shut down the reading side of the socket (flag == SHUT_RD), the
+ writing side of the socket (flag == SHUT_WR), or both ends
+ (flag == SHUT_RDWR)."""
+ res = _c.socketshutdown(self.fd, how)
if res < 0:
raise self.error_handler()
+
# ____________________________________________________________
def make_socket(fd, family, type, proto, SocketClass=RSocket):
@@ -664,6 +751,10 @@
def __str__(self):
return "host lookup failed: '%s'" % (self.host,)
+class SocketTimeout(SocketError):
+ applevelerrcls = 'timeout'
+ def __str__(self):
+ return 'timed out'
# ____________________________________________________________
if _c.AF_UNIX is None:
Modified: pypy/dist/pypy/module/rsocket/test/test_rsocket.py
==============================================================================
--- pypy/dist/pypy/module/rsocket/test/test_rsocket.py (original)
+++ pypy/dist/pypy/module/rsocket/test/test_rsocket.py Tue Oct 24 14:38:49 2006
@@ -204,3 +204,30 @@
reusestr = s.getsockopt(_c.SOL_SOCKET, _c.SO_REUSEADDR, sizeof(_c.c_int))
reuseptr = _c.cast(_c.c_char_p(reusestr), _c.POINTER(_c.c_int))
assert reuseptr[0] != 0
+
+class TestTCP:
+ PORT = 50007
+ HOST = 'localhost'
+
+ def setup_method(self, method):
+ self.serv = RSocket(_c.AF_INET, _c.SOCK_STREAM)
+ self.serv.setsockopt_int(_c.SOL_SOCKET, _c.SO_REUSEADDR, 1)
+ self.serv.bind(INETAddress(self.HOST, self.PORT))
+ self.serv.listen(1)
+
+ def teardown_method(self, method):
+ self.serv.close()
+ self.serv = None
+
+ def test_timeout(self):
+ def raise_timeout():
+ self.serv.settimeout(1.0)
+ self.serv.accept()
+ py.test.raises(SocketTimeout, raise_timeout)
+
+ def test_timeout_zero(self):
+ def raise_error():
+ self.serv.settimeout(0.0)
+ foo = self.serv.accept()
+ py.test.raises(SocketError, raise_error)
+
Modified: pypy/dist/pypy/module/rsocket/test/test_sock_app.py
==============================================================================
--- pypy/dist/pypy/module/rsocket/test/test_sock_app.py (original)
+++ pypy/dist/pypy/module/rsocket/test/test_sock_app.py Tue Oct 24 14:38:49 2006
@@ -214,7 +214,6 @@
assert space.unwrap(w_l) == info
def test_timeout():
- skip("not implemented yet")
space.appexec([w_socket, space.wrap(25.4)],
"(_socket, timeout): _socket.setdefaulttimeout(timeout)")
w_t = space.appexec([w_socket],
@@ -349,7 +348,6 @@
assert False
def test_newsocket(self):
- skip("in progress - importing socket doesn't work so far")
import socket
s = socket.socket()
@@ -377,3 +375,42 @@
intsize)
(reuse,) = struct.unpack('i', reusestr)
assert reuse != 0
+
+
+class AppTestSocketTCP:
+ def setup_class(cls):
+ cls.space = space
+
+ PORT = 50007
+ HOST = 'localhost'
+
+ def setup_method(self, method):
+ w_HOST = space.wrap(self.HOST)
+ w_PORT = space.wrap(self.PORT)
+ self.w_serv = space.appexec([w_socket, w_HOST, w_PORT],
+ '''(_socket, HOST, PORT):
+ serv = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM)
+ serv.setsockopt(_socket.SOL_SOCKET, _socket.SO_REUSEADDR, 1)
+ serv.bind((HOST, PORT))
+ serv.listen(1)
+ return serv
+ ''')
+ def teardown_method(self, method):
+ space.appexec([self.w_serv], '(serv): serv.close()')
+ self.w_serv = None
+
+
+ def test_timeout(self):
+ from _socket import timeout
+ def raise_timeout():
+ self.serv.settimeout(1.0)
+ self.serv.accept()
+ raises(timeout, raise_timeout)
+
+ def test_timeout_zero(self):
+ from _socket import error
+ def raise_error():
+ self.serv.settimeout(0.0)
+ foo = self.serv.accept()
+ raises(error, raise_error)
+
More information about the Pypy-commit
mailing list