This topic has been addressed in limited detail in other threads: [1] "sockets don't play nice with new style classes :(" May 14 2005. http://groups.google.com/group/comp.lang.python/browse_thread/thread/76d27388b0d286fa/c9849013e37c995b
[2] "Subclassing socket" Dec 20 2005 - Jan 14 2006. http://groups.google.com/group/comp.lang.python/browse_thread/thread/391728cd442339c8/c0581b9ee5e7ceaf Briefly, the socket module ("socket.py") provides a wrapper for python extension code ("_socket.so","Modules/socketmodule.*" in the source) that is built on top of the system socket library ("socket.h",etc). This wrapper attempts to provide a SocketType we can instantiate and treat as a typical Python object. It does this by forwarding some of its function calls (send, recv, etc.) to an object that it references as self._sock. This "delegation" pattern has been used in the past to allow built-in types to be treated like normal types. The problem is that, in this instance, delegation fails to maintain the inheritance behavior that we expect from normal types. (See [1] and [2] for examples.) My question is: What can be done about this? The issue is somewhat complicated. It seems to me that the crux of the problem is that sockets can spawn other sockets via the .dup and .accept methods. These calls pass right down to the system level and return references to objects of the built-in type (ie, _socket.socket) to interpreted code. All the interpreted code can do it try to "cast" (in the sense of Java) the object to a non-built-in type. If "newsock" is a reference to a _socket.socket object, the socket module does this by calling (notionally) "SocketType(_sock=newsock)". The new object of type SocketType delegates to the object of type _socket.socket via self._sock. Please see the source code for a clearer picture. Now I'll have a little chat with myself. Q1) Can't we just have _socket.socket.dup and _socket.socket.accept return something of type(self) rather than type _socket.socket? A1) I don't think you can "tell" the compiled code about what "type" of PyObject to return. Maybe the Python gods will bless us with a complete answer here. Q2) Ok, so it looks like we are stuck with delegation at some level or another then, huh? A2) Well, yeah, but in some sense Python is all about delegating data and operations to compiled code. It's just a matter of how and where. We want to maintain a clear object model in the interpreted code and push the dirty work down to compiled code. The problem is that in the case of the socket module, the "how and where" are not obvious because of the way the accept and dup system calls work. Q3) Are you saying that the way that sockets work is fundamentally different than the way other built-in objects work? A3) Yeah, I guess I am. There aren't really any other built-ins that can reach down to compiled code and spawn themselves like that. When stuff like that happens in Python, it is usually handled with a copy, deepcopy, or some kind of factory function. Sockets just do some things that are hard to shoe-horn into a standard Python idiom. The easiest solution to this problem is probably to fix the delegation mechanism so that it transparently supports inheritance. The .accept and .dup methods would pass a _socket.socket object into type(self).__init__. Some __getattribute__ magic would likely be involved. It's not immediately obvious to me how to do this, but my intuition is that it can be done fairly painlessly. The ideal solution is to redesign both the _socket and socket modules so that we don't have to resort to delegation. However, due to the argument that I have given, this will likely result in an interface change. Interface changes are painful, yes, but at least things become more pythonic. What does the peanut gallery think? How should we go about fixing this problem? -- http://mail.python.org/mailman/listinfo/python-list