[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