]> granicus.if.org Git - python/commitdiff
Issue #18643: Add socket.socketpair() on Windows.
authorCharles-François Natali <cf.natali@gmail.com>
Tue, 14 Oct 2014 20:22:44 +0000 (21:22 +0100)
committerCharles-François Natali <cf.natali@gmail.com>
Tue, 14 Oct 2014 20:22:44 +0000 (21:22 +0100)
Doc/library/socket.rst
Lib/socket.py
Lib/test/test_socket.py
Misc/NEWS

index ceeb7767951fbcca8e4a5e6ff04cae6c407c1579..1c333f447b0b6a6813a0c543e40fd0e66de176e1 100644 (file)
@@ -350,7 +350,6 @@ The following functions all create :ref:`socket objects <socket-objects>`.
    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 @@ The following functions all create :ref:`socket objects <socket-objects>`.
    .. versionchanged:: 3.4
       The returned sockets are now non-inheritable.
 
+   .. versionchanged:: 3.5
+      Windows support added.
+
 
 .. function:: create_connection(address[, timeout[, source_address]])
 
index 72aa220e6c15da5e17a4d1ac684855b3093f93b8..ca3d21cb653a74bb4c0470f5790295cb2fabfac9 100644 (file)
@@ -76,6 +76,11 @@ SocketType = IntEnum('SocketType',
                       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 @@ if hasattr(_socket, "socketpair"):
         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 }
 
index 3f2057bc9e55e01a4e075a5afe4b31ef85f59840..ca79532b419bd6422607d96f52b83e7fa48779f2 100644 (file)
@@ -3728,8 +3728,6 @@ class TCPCloserTest(ThreadedTCPSocketTest):
         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):
 
index 2691fc6ea08ec62b0f4c3bbbc0df486b5cc395f9..224b68eddeb64b425bba1ac71b392f65956aa3b6 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -177,6 +177,8 @@ Core and Builtins
 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