[Python-checkins] CVS: python/dist/src/Modules socketmodule.c,1.188,1.189

Guido van Rossum gvanrossum@users.sourceforge.net
Sat, 27 Oct 2001 15:20:49 -0700


Update of /cvsroot/python/python/dist/src/Modules
In directory usw-pr-cvs1:/tmp/cvs-serv18477

Modified Files:
	socketmodule.c 
Log Message:
Made SocketType and socket the same thing: a subclassable type whose
constructor acts just like socket() before.  All three arguments have
a sensible default now; socket() is equivalent to
socket(AF_INET, SOCK_STREAM).

One minor issue: the socket() function and the SocketType had
different doc strings; socket.__doc__ gave the signature,
SocketType.__doc__ gave the methods.  I've merged these for now, but
maybe the list of methods is no longer necessary since it can easily
be recovered through socket.__dict__.keys().  The problem with keeping
it is that the total doc string is a bit long (34 lines -- it scrolls
of a standard tty screen).

Another general issue with the socket module is that it's a big mess.
There's pages and pages of random platform #ifdefs, and the naming
conventions are totally wrong: it uses Py prefixes and CapWords for
static functions.  That's a cleanup for another day...  (Also I think
the big starting comment that summarizes the API can go -- it's a
repeat of the docstring.)


Index: socketmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/socketmodule.c,v
retrieving revision 1.188
retrieving revision 1.189
diff -C2 -d -r1.188 -r1.189
*** socketmodule.c	2001/10/26 03:25:00	1.188
--- socketmodule.c	2001/10/27 22:20:47	1.189
***************
*** 10,15 ****
  - only AF_INET, AF_INET6 and AF_UNIX address families are supported in a
    portable manner, though AF_PACKET is supported under Linux.
! - no read/write operations (use send/recv or makefile instead)
! - additional restrictions apply on Windows
  
  Module interface:
--- 10,15 ----
  - only AF_INET, AF_INET6 and AF_UNIX address families are supported in a
    portable manner, though AF_PACKET is supported under Linux.
! - no read/write operations (use sendall/recv or makefile instead)
! - additional restrictions apply on Windows (compensated for by socket.py)
  
  Module interface:
***************
*** 78,81 ****
--- 78,84 ----
  #include "Python.h"
  
+ /* XXX This is a terrible mess of of platform-dependent preprocessor hacks.
+    I hope some day someone can clean this up please... */
+ 
  /* Hacks for gethostbyname_r().  On some non-Linux platforms, the configure
     script doesn't get this right, so we hardcode some platform checks below.
***************
*** 268,271 ****
--- 271,278 ----
  #endif
  
+ 
+ /* XXX There's a problem here: *static* functions are not supposed to have
+    a Py prefix (or use CapitalizedWords).  Later... */
+ 
  /* Global variable holding the exception type for errors detected
     by this module (but not argument type or memory errors, etc.). */
***************
*** 461,465 ****
  typedef struct {
  	PyObject_HEAD
! 	SOCKET_T sock_fd;		/* Socket file descriptor */
  	int sock_family;	/* Address family, e.g., AF_INET */
  	int sock_type;		/* Socket type, e.g., SOCK_STREAM */
--- 468,472 ----
  typedef struct {
  	PyObject_HEAD
! 	SOCKET_T sock_fd;	/* Socket file descriptor */
  	int sock_family;	/* Address family, e.g., AF_INET */
  	int sock_type;		/* Socket type, e.g., SOCK_STREAM */
***************
*** 512,515 ****
--- 519,543 ----
  
  
+ /* Initialize a new socket object. */
+ 
+ static void
+ init_sockobject(PySocketSockObject *s,
+ 		SOCKET_T fd, int family, int type, int proto)
+ {
+ #ifdef RISCOS
+ 	int block = 1;
+ #endif
+ 	s->sock_fd = fd;
+ 	s->sock_family = family;
+ 	s->sock_type = type;
+ 	s->sock_proto = proto;
+ #ifdef RISCOS
+ 	if(taskwindow) {
+ 		socketioctl(s->sock_fd, 0x80046679, (u_long*)&block);
+ 	}
+ #endif
+ }
+ 
+ 
  /* Create a new socket object.
     This just creates the object and initializes it.
***************
*** 520,540 ****
  PySocketSock_New(SOCKET_T fd, int family, int type, int proto)
  {
- #ifdef RISCOS
- 	int block = 1;
- #endif
  	PySocketSockObject *s;
! 	PySocketSock_Type.ob_type = &PyType_Type;
! 	s = PyObject_New(PySocketSockObject, &PySocketSock_Type);
! 	if (s != NULL) {
! 		s->sock_fd = fd;
! 		s->sock_family = family;
! 		s->sock_type = type;
! 		s->sock_proto = proto;
! #ifdef RISCOS
! 		if(taskwindow) {
! 			socketioctl(s->sock_fd, 0x80046679, (u_long*)&block);
! 		}
! #endif
! 	}
  	return s;
  }
--- 548,556 ----
  PySocketSock_New(SOCKET_T fd, int family, int type, int proto)
  {
  	PySocketSockObject *s;
! 	s = (PySocketSockObject *)
! 		PyType_GenericNew(&PySocketSock_Type, NULL, NULL);
! 	if (s != NULL)
! 		init_sockobject(s, fd, family, type, proto);
  	return s;
  }
***************
*** 1721,1734 ****
  	if (s->sock_fd != -1)
  		(void) SOCKETCLOSE(s->sock_fd);
! 	PyObject_Del(s);
! }
! 
! 
! /* Return a socket object's named attribute. */
! 
! static PyObject *
! PySocketSock_getattr(PySocketSockObject *s, char *name)
! {
! 	return Py_FindMethod(PySocketSock_methods, (PyObject *) s, name);
  }
  
--- 1737,1741 ----
  	if (s->sock_fd != -1)
  		(void) SOCKETCLOSE(s->sock_fd);
! 	s->ob_type->tp_free((PyObject *)s);
  }
  
***************
*** 1755,1775 ****
  
  
  /* Type object for socket objects. */
  
  static PyTypeObject PySocketSock_Type = {
  	PyObject_HEAD_INIT(0)	/* Must fill in type value later */
! 	0,
! 	"socket",
! 	sizeof(PySocketSockObject),
! 	0,
! 	(destructor)PySocketSock_dealloc, /*tp_dealloc*/
! 	0,		/*tp_print*/
! 	(getattrfunc)PySocketSock_getattr, /*tp_getattr*/
! 	0,		/*tp_setattr*/
! 	0,		/*tp_compare*/
! 	(reprfunc)PySocketSock_repr, /*tp_repr*/
! 	0,		/*tp_as_number*/
! 	0,		/*tp_as_sequence*/
! 	0,		/*tp_as_mapping*/
  };
  
--- 1762,1895 ----
  
  
+ /* Create a new, uninitialized socket object. */
+ 
+ static PyObject *
+ PySocketSock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+ {
+ 	PyObject *new;
+ 
+ 	new = type->tp_alloc(type, 0);
+ 	if (new != NULL)
+ 		((PySocketSockObject *)new)->sock_fd = -1;
+ 	return new;
+ }
+ 
+ 
+ /* Initialize a new socket object. */
+ 
+ /*ARGSUSED*/
+ static int
+ PySocketSock_init(PyObject *self, PyObject *args, PyObject *kwds)
+ {
+ 	PySocketSockObject *s = (PySocketSockObject *)self;
+ 	SOCKET_T fd;
+ 	int family = AF_INET, type = SOCK_STREAM, proto = 0;
+ 	static char *keywords[] = {"family", "type", "proto", 0};
+ 
+ 	if (!PyArg_ParseTupleAndKeywords(args, kwds,
+ 					 "|iii:socket", keywords,
+ 					 &family, &type, &proto))
+ 		return -1;
+ 	Py_BEGIN_ALLOW_THREADS
+ 	fd = socket(family, type, proto);
+ 	Py_END_ALLOW_THREADS
+ #ifdef MS_WINDOWS
+ 	if (fd == INVALID_SOCKET)
+ #else
+ 	if (fd < 0)
+ #endif
+ 	{
+ 		PySocket_Err();
+ 		return -1;
+ 	}
+ 	init_sockobject(s, fd, family, type, proto);
+ 	/* From now on, ignore SIGPIPE and let the error checking
+ 	   do the work. */
+ #ifdef SIGPIPE
+ 	(void) signal(SIGPIPE, SIG_IGN);
+ #endif
+ 	return 0;
+ }
+ 
+ 
  /* Type object for socket objects. */
  
+ static char socket_doc[] =
+ "socket([family[, type[, proto]]]) -> socket object\n\
+ \n\
+ Open a socket of the given type.  The family argument specifies the\n\
+ address family; it defaults to AF_INET.  The type argument specifies\n\
+ whether this is a stream (SOCK_STREAM, this is the default)\n\
+ or datagram (SOCK_DGRAM) socket.  The protocol argument defaults to 0,\n\
+ specifying the default protocol.\n\
+ \n\
+ A socket represents one endpoint of a network connection.\n\
+ \n\
+ Methods:\n\
+ \n\
+ accept() -- accept a connection, returning new socket and client address\n\
+ bind() -- bind the socket to a local address\n\
+ close() -- close the socket\n\
+ connect() -- connect the socket to a remote address\n\
+ connect_ex() -- connect, return an error code instead of an exception \n\
+ dup() -- return a new socket object identical to the current one (*)\n\
+ fileno() -- return underlying file descriptor\n\
+ getpeername() -- return remote address (*)\n\
+ getsockname() -- return local address\n\
+ getsockopt() -- get socket options\n\
+ listen() -- start listening for incoming connections\n\
+ makefile() -- return a file object corresponding tot the socket (*)\n\
+ recv() -- receive data\n\
+ recvfrom() -- receive data and sender's address\n\
+ send() -- send data, may not send all of it\n\
+ sendall() -- send all data\n\
+ sendto() -- send data to a given address\n\
+ setblocking() -- set or clear the blocking I/O flag\n\
+ setsockopt() -- set socket options\n\
+ shutdown() -- shut down traffic in one or both directions\n\
+ \n\
+ (*) not available on all platforms!)";
+ 
  static PyTypeObject PySocketSock_Type = {
  	PyObject_HEAD_INIT(0)	/* Must fill in type value later */
! 	0,					/* ob_size */
! 	"socket.socket",			/* tp_name */
! 	sizeof(PySocketSockObject),		/* tp_basicsize */
! 	0,					/* tp_itemsize */
! 	(destructor)PySocketSock_dealloc,	/* tp_dealloc */
! 	0,					/* tp_print */
! 	0,					/* tp_getattr */
! 	0,					/* tp_setattr */
! 	0,					/* tp_compare */
! 	(reprfunc)PySocketSock_repr,		/* tp_repr */
! 	0,					/* tp_as_number */
! 	0,					/* tp_as_sequence */
! 	0,					/* tp_as_mapping */
! 	0,					/* tp_hash */
! 	0,					/* tp_call */
! 	0,					/* tp_str */
! 	PyObject_GenericGetAttr,		/* tp_getattro */
! 	0,					/* tp_setattro */
! 	0,					/* tp_as_buffer */
! 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
! 	socket_doc,				/* tp_doc */
! 	0,					/* tp_traverse */
! 	0,					/* tp_clear */
! 	0,					/* tp_richcompare */
! 	0,					/* tp_weaklistoffset */
! 	0,					/* tp_iter */
! 	0,					/* tp_iternext */
! 	PySocketSock_methods,			/* tp_methods */
! 	0,					/* tp_members */
! 	0,					/* tp_getset */
! 	0,					/* tp_base */
! 	0,					/* tp_dict */
! 	0,					/* tp_descr_get */
! 	0,					/* tp_descr_set */
! 	0,					/* tp_dictoffset */
! 	PySocketSock_init,			/* tp_init */
! 	PyType_GenericAlloc,			/* tp_alloc */
! 	PySocketSock_new,			/* tp_new */
! 	_PyObject_Del,				/* tp_free */
  };
  
***************
*** 2150,2198 ****
  
  
- /* Python interface to socket(family, type, proto).
-    The third (protocol) argument is optional.
-    Return a new socket object. */
- 
- /*ARGSUSED*/
- static PyObject *
- PySocket_socket(PyObject *self, PyObject *args)
- {
- 	PySocketSockObject *s;
- 	SOCKET_T fd;
- 	int family, type, proto = 0;
- 	if (!PyArg_ParseTuple(args, "ii|i:socket", &family, &type, &proto))
- 		return NULL;
- 	Py_BEGIN_ALLOW_THREADS
- 	fd = socket(family, type, proto);
- 	Py_END_ALLOW_THREADS
- #ifdef MS_WINDOWS
- 	if (fd == INVALID_SOCKET)
- #else
- 	if (fd < 0)
- #endif
- 		return PySocket_Err();
- 	s = PySocketSock_New(fd, family, type, proto);
- 	/* If the object can't be created, don't forget to close the
- 	   file descriptor again! */
- 	if (s == NULL)
- 		(void) SOCKETCLOSE(fd);
- 	/* From now on, ignore SIGPIPE and let the error checking
- 	   do the work. */
- #ifdef SIGPIPE
- 	(void) signal(SIGPIPE, SIG_IGN);
- #endif
- 	return (PyObject *) s;
- }
- 
- static char socket_doc[] =
- "socket(family, type[, proto]) -> socket object\n\
- \n\
- Open a socket of the given type.  The family argument specifies the\n\
- address family; it is normally AF_INET, sometimes AF_UNIX.\n\
- The type argument specifies whether this is a stream (SOCK_STREAM)\n\
- or datagram (SOCK_DGRAM) socket.  The protocol argument defaults to 0,\n\
- specifying the default protocol.";
- 
- 
  #ifndef NO_DUP
  /* Create a socket object from a numeric file description.
--- 2270,2273 ----
***************
*** 2793,2797 ****
  	PyObject_HEAD_INIT(NULL)
  	0,				/*ob_size*/
! 	"SSL",			/*tp_name*/
  	sizeof(PySSLObject),		/*tp_basicsize*/
  	0,				/*tp_itemsize*/
--- 2868,2872 ----
  	PyObject_HEAD_INIT(NULL)
  	0,				/*ob_size*/
! 	"SSL",				/*tp_name*/
  	sizeof(PySSLObject),		/*tp_basicsize*/
  	0,				/*tp_itemsize*/
***************
*** 2887,2892 ****
  	{"getprotobyname",	PySocket_getprotobyname,
  	 METH_VARARGS,getprotobyname_doc},
- 	{"socket",		PySocket_socket,
- 	 METH_VARARGS, socket_doc},
  #ifndef NO_DUP
  	{"fromfd",		PySocket_fromfd,
--- 2962,2965 ----
***************
*** 3030,3060 ****
  for documentation.";
  
- static char sockettype_doc[] =
- "A socket represents one endpoint of a network connection.\n\
- \n\
- Methods:\n\
- \n\
- accept() -- accept a connection, returning new socket and client address\n\
- bind() -- bind the socket to a local address\n\
- close() -- close the socket\n\
- connect() -- connect the socket to a remote address\n\
- connect_ex() -- connect, return an error code instead of an exception \n\
- dup() -- return a new socket object identical to the current one (*)\n\
- fileno() -- return underlying file descriptor\n\
- getpeername() -- return remote address (*)\n\
- getsockname() -- return local address\n\
- getsockopt() -- get socket options\n\
- listen() -- start listening for incoming connections\n\
- makefile() -- return a file object corresponding tot the socket (*)\n\
- recv() -- receive data\n\
- recvfrom() -- receive data and sender's address\n\
- send() -- send data\n\
- sendto() -- send data to a given address\n\
- setblocking() -- set or clear the blocking I/O flag\n\
- setsockopt() -- set socket options\n\
- shutdown() -- shut down traffic in one or both directions\n\
- \n\
- (*) not available on all platforms!)";
- 
  DL_EXPORT(void)
  init_socket(void)
--- 3103,3106 ----
***************
*** 3077,3080 ****
--- 3123,3127 ----
  #endif /* MS_WINDOWS */
  #endif /* RISCOS */
+ 	PySocketSock_Type.ob_type = &PyType_Type;
  #ifdef USE_SSL
  	PySSL_Type.ob_type = &PyType_Type;
***************
*** 3118,3124 ****
  				SSL_ERROR_SSL);
  #endif /* USE_SSL */
- 	PySocketSock_Type.ob_type = &PyType_Type;
- 	PySocketSock_Type.tp_doc = sockettype_doc;
  	if (PyDict_SetItemString(d, "SocketType",
  				 (PyObject *)&PySocketSock_Type) != 0)
  		return;
--- 3165,3172 ----
  				SSL_ERROR_SSL);
  #endif /* USE_SSL */
  	if (PyDict_SetItemString(d, "SocketType",
+ 				 (PyObject *)&PySocketSock_Type) != 0)
+ 		return;
+ 	if (PyDict_SetItemString(d, "socket",
  				 (PyObject *)&PySocketSock_Type) != 0)
  		return;