[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