changeset: 93053:6098141155f9 parent: 93051:424fbf011176 user: Charles-François Natali date: Tue Oct 14 21:22:44 2014 +0100 files: Doc/library/socket.rst Lib/socket.py Lib/test/test_socket.py Misc/NEWS description: Issue #18643: Add socket.socketpair() on Windows. diff -r 424fbf011176 -r 6098141155f9 Doc/library/socket.rst --- a/Doc/library/socket.rst Tue Oct 14 08:59:14 2014 -0700 +++ b/Doc/library/socket.rst Tue Oct 14 21:22:44 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 `. @@ -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 424fbf011176 -r 6098141155f9 Lib/socket.py --- a/Lib/socket.py Tue Oct 14 08:59:14 2014 -0700 +++ b/Lib/socket.py Tue Oct 14 21:22:44 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("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 -r 424fbf011176 -r 6098141155f9 Lib/test/test_socket.py --- a/Lib/test/test_socket.py Tue Oct 14 08:59:14 2014 -0700 +++ b/Lib/test/test_socket.py Tue Oct 14 21:22:44 2014 +0100 @@ -3728,8 +3728,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): diff -r 424fbf011176 -r 6098141155f9 Misc/NEWS --- a/Misc/NEWS Tue Oct 14 08:59:14 2014 -0700 +++ b/Misc/NEWS Tue Oct 14 21:22:44 2014 +0100 @@ -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