[Python-checkins] cpython: Issue #18643: Add socket.socketpair() on Windows.

charles-francois.natali python-checkins at python.org
Tue Oct 14 22:23:30 CEST 2014


https://hg.python.org/cpython/rev/6098141155f9
changeset:   93053:6098141155f9
parent:      93051:424fbf011176
user:        Charles-François Natali <cf.natali at gmail.com>
date:        Tue Oct 14 21:22:44 2014 +0100
summary:
  Issue #18643: Add socket.socketpair() on Windows.

files:
  Doc/library/socket.rst  |   4 +-
  Lib/socket.py           |  51 +++++++++++++++++++++++++++++
  Lib/test/test_socket.py |   2 -
  Misc/NEWS               |   2 +
  4 files changed, 56 insertions(+), 3 deletions(-)


diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst
--- a/Doc/library/socket.rst
+++ b/Doc/library/socket.rst
@@ -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 --git a/Lib/socket.py b/Lib/socket.py
--- a/Lib/socket.py
+++ b/Lib/socket.py
@@ -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("Only 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
+                csock.setblocking(True)
+                ssock, _ = lsock.accept()
+            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 --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -3728,8 +3728,6 @@
         self.cli.connect((HOST, self.port))
         time.sleep(1.0)
 
- at unittest.skipUnless(hasattr(socket, 'socketpair'),
-                     'test needs socket.socketpair()')
 @unittest.skipUnless(thread, 'Threading required for this test.')
 class BasicSocketPairTest(SocketPairTest):
 
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -177,6 +177,8 @@
 Library
 -------
 
+- Issue #18643: Add socket.socketpair() on Windows.
+
 - Issue #22435: Fix a file descriptor leak when SocketServer bind fails.
 
 - Issue #13096: Fixed segfault in CTypes POINTER handling of large

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list