Charles-François Natali added the comment:

> You should copy the code from asyncio.windows_utils.socketpair(). It checks 
> also type and proto parameter: raise a ValueError for unsupported values 
> (only SOCK_STREAM and proto=0 are supported). It also supports IPv6. It 
> handles BlockingIOError and InterruptedError on connect (I never understood 
> why these exceptions are simply ignored).

I could use it then, although all those checks are unnecessary since
the underlying socket() call will check it for us.

> You patch checks the address received by accept() and retry. It's a little 
> bit surprising. If you get an unexpected connection, maybe an exception 
> should be raised, instead of just ignoring it. Maybe we should modify the 
> code in asyncio to check also the address?

Why?
If you have an unexpected connection, it should be dropped, and we
should wait until the client we're expecting connects, there's no
reason to raise an error.
But I'll just reuse asyncio's version.

> Finally, please add socketpair() directly to the socket module. It is useful 
> for applications, not only for tests.

Well, that's what I suggested initially, but never got any reply, so I
went for the least intrusive. I personally think too it should belong
to socket module.

So here it is.

----------
Added file: http://bugs.python.org/file36055/socketpair-4.diff

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue18643>
_______________________________________
diff -r f7643c893587 Doc/library/socket.rst
--- a/Doc/library/socket.rst    Wed Jul 23 19:28:13 2014 +0100
+++ b/Doc/library/socket.rst    Wed Jul 23 23:20:09 2014 +0100
@@ -350,7 +350,6 @@
    type, and protocol number.  Address family, socket type, and protocol 
number are
    as for the :func:`.socket` function above. The default family is 
:const:`AF_UNIX`
    if defined on the platform; otherwise, the default is :const:`AF_INET`.
-   Availability: Unix.
 
    The newly created sockets are :ref:`non-inheritable <fd_inheritance>`.
 
@@ -361,6 +360,9 @@
    .. versionchanged:: 3.4
       The returned sockets are now non-inheritable.
 
+   .. versionchanged:: 3.5
+      Windows support added
+
 
 .. function:: create_connection(address[, timeout[, source_address]])
 
diff -r f7643c893587 Lib/socket.py
--- a/Lib/socket.py     Wed Jul 23 19:28:13 2014 +0100
+++ b/Lib/socket.py     Wed Jul 23 23:20:09 2014 +0100
@@ -76,6 +76,11 @@
                       if name.isupper() and name.startswith('SOCK_')})
 globals().update(SocketType.__members__)
 
+
+_LOCALHOST    = '127.0.0.1'
+_LOCALHOST_V6 = '::1'
+
+
 def _intenum_converter(value, enum_klass):
     """Convert a numeric family value to an IntEnum member.
 
@@ -468,6 +473,52 @@
         b = socket(family, type, proto, b.detach())
         return a, b
 
+else:
+
+    # Origin: https://gist.github.com/4325783, by Geert Jansen.  Public domain.
+    def socketpair(family=AF_INET, type=SOCK_STREAM, proto=0):
+        if family == AF_INET:
+            host = _LOCALHOST
+        elif family == AF_INET6:
+            host = _LOCALHOST_V6
+        else:
+            raise ValueError("Ony AF_INET and AF_INET6 socket address families 
"
+                             "are supported")
+        if type != SOCK_STREAM:
+            raise ValueError("Only SOCK_STREAM socket type is supported")
+        if proto != 0:
+            raise ValueError("Only protocol zero is supported")
+
+        # We create a connected TCP socket. Note the trick with
+        # setblocking(False) that prevents us from having to create a thread.
+        lsock = socket(family, type, proto)
+        try:
+            lsock.bind((host, 0))
+            lsock.listen()
+            # On IPv6, ignore flow_info and scope_id
+            addr, port = lsock.getsockname()[:2]
+            csock = socket(family, type, proto)
+            try:
+                csock.setblocking(False)
+                try:
+                    csock.connect((addr, port))
+                except (BlockingIOError, InterruptedError):
+                    pass
+                ssock, _ = lsock.accept()
+                csock.setblocking(True)
+            except:
+                csock.close()
+                raise
+        finally:
+            lsock.close()
+        return (ssock, csock)
+
+socketpair.__doc__ = """socketpair([family[, type[, proto]]]) -> (socket 
object, socket object)
+Create a pair of socket objects from the sockets returned by the platform
+socketpair() function.
+The arguments are the same as for socket() except the default family is AF_UNIX
+if defined on the platform; otherwise, the default is AF_INET.
+"""
 
 _blocking_errnos = { EAGAIN, EWOULDBLOCK }
 
diff -r f7643c893587 Lib/test/test_socket.py
--- a/Lib/test/test_socket.py   Wed Jul 23 19:28:13 2014 +0100
+++ b/Lib/test/test_socket.py   Wed Jul 23 23:20:09 2014 +0100
@@ -3702,8 +3702,6 @@
         self.cli.connect((HOST, self.port))
         time.sleep(1.0)
 
-@unittest.skipUnless(hasattr(socket, 'socketpair'),
-                     'test needs socket.socketpair()')
 @unittest.skipUnless(thread, 'Threading required for this test.')
 class BasicSocketPairTest(SocketPairTest):
 
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to