[pypy-svn] r18634 - in pypy/dist/pypy/module/_socket: . test

afa at codespeak.net afa at codespeak.net
Sat Oct 15 16:55:52 CEST 2005


Author: afa
Date: Sat Oct 15 16:55:48 2005
New Revision: 18634

Modified:
   pypy/dist/pypy/module/_socket/__init__.py
   pypy/dist/pypy/module/_socket/app_socket.py
   pypy/dist/pypy/module/_socket/interp_socket.py
   pypy/dist/pypy/module/_socket/test/test_socket2.py
Log:
valentino, afa: more socket.
The socket type does not work yet.


Modified: pypy/dist/pypy/module/_socket/__init__.py
==============================================================================
--- pypy/dist/pypy/module/_socket/__init__.py	(original)
+++ pypy/dist/pypy/module/_socket/__init__.py	Sat Oct 15 16:55:48 2005
@@ -9,11 +9,11 @@
         'herror'     : 'app_socket.herror',
         'gaierror'   : 'app_socket.gaierror',
         'timeout'    : 'app_socket.timeout',
-        'setdefaulttimeout'    : 'app_socket.setdefaulttimeout',
-        'getdefaulttimeout'    : 'app_socket.getdefaulttimeout',
     }
 
     interpleveldefs = {
+        'SocketType':  'interp_socket.getsockettype(space)',
+        'socket'    :  'interp_socket.getsockettype(space)',
     }
 
 for name in """
@@ -22,6 +22,7 @@
     fromfd socketpair
     ntohs ntohl htons htonl inet_aton inet_ntoa inet_pton inet_ntop
     getaddrinfo getnameinfo
+    getdefaulttimeout setdefaulttimeout 
     """.split():
     
     if hasattr(_socket, name):

Modified: pypy/dist/pypy/module/_socket/app_socket.py
==============================================================================
--- pypy/dist/pypy/module/_socket/app_socket.py	(original)
+++ pypy/dist/pypy/module/_socket/app_socket.py	Sat Oct 15 16:55:48 2005
@@ -1,10 +1,7 @@
 """Implementation module for socket operations.
-NOT_RPYTHON
 
 See the socket module for documentation."""
 
-defaulttimeout = -1 # Default timeout for new sockets
-
 class error(Exception):
     pass
 
@@ -22,20 +19,3 @@
 
 socket = SocketType
 
-def setdefaulttimeout(timeout):
-    if timeout is None:
-        timeout = -1.0
-    else:
-        if timeout < 0.0:
-            raise ValueError, "Timeout value out of range"
-
-    global defaulttimeout
-    defaulttimeout = timeout
-
-def getdefaulttimeout():
-    timeout = defaulttimeout
-
-    if timeout < 0.0:
-        return None
-    else:
-        return timeout

Modified: pypy/dist/pypy/module/_socket/interp_socket.py
==============================================================================
--- pypy/dist/pypy/module/_socket/interp_socket.py	(original)
+++ pypy/dist/pypy/module/_socket/interp_socket.py	Sat Oct 15 16:55:48 2005
@@ -1,8 +1,10 @@
 
 import socket, errno, sys
+from pypy.interpreter.typedef import TypeDef
+from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.error import OperationError
-from pypy.interpreter.gateway import W_Root
-from pypy.interpreter.gateway import ObjSpace, NoneNotWrapped
+from pypy.interpreter.gateway import W_Root, NoneNotWrapped
+from pypy.interpreter.gateway import ObjSpace, interp2app
 
 if sys.platform == 'win32':
     WIN32_ERROR_MESSAGES = {
@@ -77,15 +79,23 @@
     
     w_module = space.getbuiltinmodule('_socket')
     if isinstance(e, socket.gaierror):
-        w_error = space.getattr(w_module, space.wrap('gaierror'))
+        w_errortype = space.getattr(w_module, space.wrap('gaierror'))
     elif isinstance(e, socket.herror):
-        w_error = space.getattr(w_module, space.wrap('gaierror'))
+        w_errortype = space.getattr(w_module, space.wrap('herror'))
     else:
-        w_error = space.getattr(w_module, space.wrap('error'))
+        w_errortype = space.getattr(w_module, space.wrap('error'))
+        
+    return OperationError(w_errortype,
+                          space.wrap(errno),
+                          space.wrap(msg))
+
+def wrap_timeouterror(space):
+    
+    w_module = space.getbuiltinmodule('_socket')
+    w_error = space.getattr(w_module, space.wrap('timeout'))
         
     w_error = space.call_function(w_error,
-                                  space.wrap(errno),
-                                  space.wrap(msg))
+                                  space.wrap("timed out"))
     return w_error
 
 def gethostname(space):
@@ -338,3 +348,417 @@
         raise wrap_socketerror(space, e)
 getnameinfo.unwrap_spec = [ObjSpace, W_Root, int]
 
+# _____________________________________________________________
+#
+# Timeout management
+
+class State: 
+    def __init__(self, space):
+        self.space = space
+        
+        self.defaulttimeout = -1 # Default timeout for new sockets
+        
+def getstate(space): 
+    return space.fromcache(State)
+
+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"))
+
+    getstate(space).defaulttimeout = timeout
+setdefaulttimeout.unwrap_spec = [ObjSpace, W_Root]
+
+def getdefaulttimeout(space):
+    timeout = getstate(space).defaulttimeout
+
+    if timeout < 0.0:
+        return space.wrap(None)
+    else:
+        return space.wrap(timeout)
+getdefaulttimeout.unwrap_spec = [ObjSpace]
+
+# _____________________________________________________________
+#
+# The socket type
+
+def getsockettype(space):
+    return space.gettypeobject(Socket.typedef)
+
+def newsocket(space, family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0):
+    try:
+        socket.setdefaulttimeout(getstate(space).defaulttimeout)
+        fd = socket.socket(family, type, proto)
+    except socket.error, e:
+        raise wrap_socketerror(space, e)
+    return Socket(fd, family, type, proto)
+descr_socket_init = interp2app(newsocket,
+                               unwrap_spec=[ObjSpace, int, int, int])
+    
+class Socket(Wrappable):
+    "A wrappable box around an interp-level socket object."
+
+    def __init__(self, fd, family, type, proto):
+        self.fd = fd
+        self.family = family
+        self.type = type
+        self.proto = proto
+        self.timeout = getstate(space).defaulttimeout
+
+    def accept(self, space):
+        """accept() -> (socket object, address info)
+
+        Wait for an incoming connection.  Return a new socket representing the
+        connection, and the address of the client.  For IP sockets, the address
+        info is a pair (hostaddr, port).
+        """
+        try:
+            newfd, address = self.fd.accept()
+        except socket.error, e:
+            raise wrap_socketerror(space, e)
+        newsock = Socket(newfd, self.family, self.type, self.proto)
+        return space.wrap((newsock, address))
+    accept.unwrap_spec = ['self', ObjSpace]
+        
+    def bind(self, space, w_addr):
+        """bind(address)
+        
+        Bind the socket to a local address.  For IP sockets, the address is a
+        pair (host, port); the host must refer to the local host. For raw packet
+        sockets the address is a tuple (ifname, proto [,pkttype [,hatype]])
+        """
+        addr = space.unwrap(w_addr)
+        try:
+            self.fd.bind(adrr)
+        except socket.error, e:
+            raise wrap_socketerror(space, e)
+    bind.unwrap_spec = ['self', ObjSpace, W_Root]
+        
+    def close(self, space):
+        """close()
+
+        Close the socket.  It cannot be used after this call.
+        """
+        if self.fd is not None:
+            fd = self.fd
+            self.fd = None
+            fd.close()
+    close.unwrap_spec = ['self', ObjSpace]
+
+    def connect(self, space, w_addr):
+        """connect(address)
+
+        Connect the socket to a remote address.  For IP sockets, the address
+        is a pair (host, port).
+        """
+        addr = space.unwrap(w_addr)
+        try:
+            self.fd.connect(addr)
+        except timeout:
+            raise wrap_timeout(space)
+        except socket.error, e:
+            raise wrap_socketerror(space, e)
+    connect.unwrap_spec = ['self', ObjSpace, W_Root]
+        
+    def connect_ex(self, space, w_addr):
+        """connect_ex(address) -> errno
+        
+        This is like connect(address), but returns an error code (the errno value)
+        instead of raising an exception when an error occurs.
+        """
+        addr = space.unwrap(w_addr)
+        try:
+            self.fd.connect(addr)
+        except socket.error, e:
+            return space.wrap(e.errno)
+    connect_ex.unwrap_spec = ['self', ObjSpace, W_Root]
+        
+    def dup(self, space):
+        """dup() -> socket object
+
+        Return a new socket object connected to the same system resource.
+        """
+        try:
+            newfd = self.fd.dup()
+        except socket.error, e:
+            raise wrap_socketerror(space, e)
+        newsock = Socket(newfd, self.family, self.type, self.proto)
+        return space.wrap(newsock)
+    dup.unwrap_spec = ['self', ObjSpace]
+
+    def fileno(self, space):
+        """fileno() -> integer
+
+        Return the integer file descriptor of the socket.
+        """
+        return space.wrap(self.fd.fileno())
+    fileno.unwrap_spec = ['self', ObjSpace]
+
+    def getpeername(self, space):
+        """getpeername() -> address info
+
+        Return the address of the remote endpoint.  For IP sockets, the address
+        info is a pair (hostaddr, port).
+        """
+        try:
+            return space.wrap(self.fd.getpeername())
+        except socket.error, e:
+            raise wrap_socketerror(space, e)
+    getpeername.unwrap_spec = ['self', ObjSpace]
+
+    def getsockname(self, space):
+        """getsockname() -> address info
+
+        Return the address of the local endpoint.  For IP sockets, the address
+        info is a pair (hostaddr, port).
+        """
+        try:
+            return space.wrap(self.fd.getsockname())
+        except socket.error, e:
+            raise wrap_socketerror(space, e)
+    getsockname.unwrap_spec = ['self', ObjSpace]
+        
+    def getsockopt(self, space, level, option, w_buffersize=NoneNotWrapped):
+        """getsockopt(level, option[, buffersize]) -> value
+
+        Get a socket option.  See the Unix manual for level and option.
+        If a nonzero buffersize argument is given, the return value is a
+        string of that length; otherwise it is an integer.
+        """
+        try:
+            if w_buffersize is None:
+                return space.wrap(self.fd.getsockopt(level, option))
+            else:
+                buffersize = space.int_w(w_buffersize)
+                return space.wrap(self.fd.getsockopt(level, option, buffersize))
+        except socket.error, e:
+            raise wrap_socketerror(space, e)
+    getsockopt.unwrap_spec = ['self', ObjSpace, int, int, W_Root]
+        
+    def listen(self, space, backlog):
+        """listen(backlog)
+
+        Enable a server to accept connections.  The backlog argument must be at
+        least 1; it specifies the number of unaccepted connection that the system
+        will allow before refusing new connections.
+        """
+        try:
+            self.fd.listen(backlog)
+        except socket.error, e:
+            raise wrap_socketerror(space, e)
+    listen.unwrap_spec = ['self', ObjSpace, int]
+        
+    def makefile(self, space, mode="r", buffersize=-1):
+        """makefile([mode[, buffersize]]) -> file object
+
+        Return a regular file object corresponding to the socket.
+        The mode and buffersize arguments are as for the built-in open() function.
+        """
+        try:
+            f = self.fd.makefile(mode, buffersize)
+        except socket.error, e:
+            raise wrap_socketerror(space, e)
+        return f
+    makefile.unwrap_spec = ['self', ObjSpace, str, int]
+
+    def recv(self, space, buffersize, flags=0):
+        """recv(buffersize[, flags]) -> data
+
+        Receive up to buffersize bytes from the socket.  For the optional flags
+        argument, see the Unix manual.  When no data is available, block 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.
+        """
+        try:
+            return space.wrap(self.fd.recv(buffersize, flags))
+        except socket.error, e:
+            raise wrap_socketerror(space, e)
+    recv.unwrap_spec = ['self', ObjSpace, int, int]
+
+    def recvfrom(self, space, buffersize, flags=0):
+        """recvfrom(buffersize[, flags]) -> (data, address info)
+
+        Like recv(buffersize, flags) but also return the sender's address info.
+        """
+        try:
+            return space.wrap(self.fd.recvfrom(buffersize, flags))
+        except socket.error, e:
+            raise wrap_socketerror(space, e)
+    recvfrom.unwrap_spec = ['self', ObjSpace, int, int]
+
+    def send(self, space, data, flags=0):
+        """send(data[, flags]) -> count
+
+        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.
+        """
+        try:
+            return space.wrap(self.fd.send(data, flags))
+        except socket.error, e:
+            raise wrap_socketerror(space, e)
+    send.unwrap_spec = ['self', ObjSpace, str, int]
+        
+    def sendall(self, space, data, flags=0):
+        """sendall(data[, flags])
+
+        Send a data string to the socket.  For the optional flags
+        argument, see the Unix manual.  This calls send() repeatedly
+        until all data is sent.  If an error occurs, it's impossible
+        to tell how much data has been sent.
+        """
+        try:
+            self.fd.sendall(data, flags)
+        except socket.error, e:
+            raise wrap_socketerror(space, e)
+    sendall.unwrap_spec = ['self', ObjSpace, str, int]
+    
+    def sendto(self, space, data, w_param2, w_param3=NoneNotWrapped):
+        """sendto(data[, flags], address) -> count
+
+        Like send(data, flags) but allows specifying the destination address.
+        For IP sockets, the address is a pair (hostaddr, port).
+        """
+        if w_param3 is None:
+            # 2 args version
+            flags = 0
+            addr = space.str_w(w_param2)
+        else:
+            # 3 args version
+            flags = space.int_w(w_param2)
+            addr = space.str_w(w_param3)
+        try:
+            self.fd.sendto(data, flags, addr)
+        except socket.error, e:
+            raise wrap_socketerror(space, e)
+    sendto.unwrap_spec = ['self', ObjSpace, str, W_Root, W_Root]
+    
+    def setblocking(self, space, flag):
+        """setblocking(flag)
+
+        Set the socket to blocking (flag is true) or non-blocking (false).
+        setblocking(True) is equivalent to settimeout(None);
+        setblocking(False) is equivalent to settimeout(0.0).
+        """
+        if flag:
+            self.settimeout(space, None)
+        else:
+            self.settimeout(space, 0.0)
+    setblocking.unwrap_spec = ['self', ObjSpace, int]
+
+    def setsockopt(self, space, level, option, w_value):
+        """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.
+        """
+        
+        if space.isinstance(w_value, space.w_string):
+            strvalue = space.str_w(w_value)
+            self.fd.setsockopt(level, option, strvalue)
+        else:
+            intvalue = space.int_w(w_value)
+            self.fd.setsockopt(level, option, intvalue)
+    setsockopt.unwrap_spec = ['self', ObjSpace, int, int, W_Root]
+
+    def gettimeout(self, space):
+        """gettimeout() -> timeout
+
+        Returns the timeout in floating seconds associated with socket
+        operations. A timeout of None indicates that timeouts on socket
+        operations are disabled.
+        """
+        if self.timeout < 0.0:
+            return space.w_None
+        else:
+            return space.wrap(self.timeout)
+    gettimeout.unwrap_spec = ['self', ObjSpace]
+
+    def settimeout(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.timeout = timeout
+        self.fd.settimeout(timeout)
+    settimeout.unwrap_spec = ['self', ObjSpace, W_Root]
+
+    def shutdown(self, space, how):
+        """shutdown(flag)
+
+        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).
+        """
+        self.fd.shutdown(how)
+    shutdown.unwrap_spec = ['self', ObjSpace, int]
+
+socketmethods = {}
+for methodname in dir(Socket):
+    if methodname in dir(Wrappable):
+        continue
+    if methodname.startswith('_'):
+        continue
+    method = getattr(Socket, methodname)
+    if not callable(method):
+        continue
+    assert hasattr(method,'unwrap_spec'), methodname
+    assert method.im_func.func_code.co_argcount == len(method.unwrap_spec), methodname
+    socketmethods[methodname] = interp2app(method, method.unwrap_spec)
+
+Socket.typedef = TypeDef("_socket.socket",
+    __doc__ = """\
+socket([family[, type[, proto]]]) -> socket object
+
+Open a socket of the given type.  The family argument specifies the
+address family; it defaults to AF_INET.  The type argument specifies
+whether this is a stream (SOCK_STREAM, this is the default)
+or datagram (SOCK_DGRAM) socket.  The protocol argument defaults to 0,
+specifying the default protocol.  Keyword arguments are accepted.
+
+A socket object represents one endpoint of a network connection.
+
+Methods of socket objects (keyword arguments not allowed):
+
+accept() -- accept a connection, returning new socket and client address
+bind(addr) -- bind the socket to a local address
+close() -- close the socket
+connect(addr) -- connect the socket to a remote address
+connect_ex(addr) -- connect, return an error code instead of an exception
+dup() -- return a new socket object identical to the current one [*]
+fileno() -- return underlying file descriptor
+getpeername() -- return remote address [*]
+getsockname() -- return local address
+getsockopt(level, optname[, buflen]) -- get socket options
+gettimeout() -- return timeout or None
+listen(n) -- start listening for incoming connections
+makefile([mode, [bufsize]]) -- return a file object for the socket [*]
+recv(buflen[, flags]) -- receive data
+recvfrom(buflen[, flags]) -- receive data and sender's address
+sendall(data[, flags]) -- send all data
+send(data[, flags]) -- send data, may not send all of it
+sendto(data[, flags], addr) -- send data to a given address
+setblocking(0 | 1) -- set or clear the blocking I/O flag
+setsockopt(level, optname, value) -- set socket options
+settimeout(None | float) -- set or clear the timeout
+shutdown(how) -- shut down traffic in one or both directions
+
+ [*] not available on all platforms!""",
+    __init__ = descr_socket_init,
+    **socketmethods
+    )

Modified: pypy/dist/pypy/module/_socket/test/test_socket2.py
==============================================================================
--- pypy/dist/pypy/module/_socket/test/test_socket2.py	(original)
+++ pypy/dist/pypy/module/_socket/test/test_socket2.py	Sat Oct 15 16:55:48 2005
@@ -173,7 +173,11 @@
     w_t = space.appexec([w_socket],
                   "(_socket): return _socket.getdefaulttimeout()")
     assert space.unwrap(w_t) is None
-    
-    
-    
-    
+
+class AppTestSocket:
+    def setup_class(cls):
+        cls.space = space
+
+    def INPROGRESStest_newsocket(self):
+        import _socket
+        s = _socket.socket()



More information about the Pypy-commit mailing list