diff options
-rw-r--r-- | Doc/library/socket.rst | 8 | ||||
-rw-r--r-- | Lib/socket.py | 12 | ||||
-rw-r--r-- | Lib/test/test_socket.py | 15 | ||||
-rw-r--r-- | Misc/NEWS | 2 |
4 files changed, 32 insertions, 5 deletions
diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index d778369..2e0c6d6 100644 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -205,7 +205,7 @@ The module :mod:`socket` exports the following constants and functions: .. versionadded:: 2.3 -.. function:: create_connection(address[, timeout]) +.. function:: create_connection(address[, timeout[, source_address]]) Convenience function. Connect to *address* (a 2-tuple ``(host, port)``), and return the socket object. Passing the optional *timeout* parameter will @@ -215,6 +215,12 @@ The module :mod:`socket` exports the following constants and functions: .. versionadded:: 2.6 + If supplied, *source_address* must be a 2-tuple ``(host, port)`` for the + socket to bind to as its source address before connecting. If host or port + are '' or 0 respectively the OS default behavior will be used. + + .. versionadded:: 2.7 + .. function:: getaddrinfo(host, port[, family[, socktype[, proto[, flags]]]]) diff --git a/Lib/socket.py b/Lib/socket.py index b379144..9b4beda 100644 --- a/Lib/socket.py +++ b/Lib/socket.py @@ -24,7 +24,8 @@ inet_ntoa() -- convert 32-bit packed format IP to string (123.45.67.89) ssl() -- secure socket layer support (only available if configured) socket.getdefaulttimeout() -- get the default timeout value socket.setdefaulttimeout() -- set the default timeout value -create_connection() -- connects to an address, with an optional timeout +create_connection() -- connects to an address, with an optional timeout and + optional source address. [*] not available on all platforms! @@ -531,7 +532,8 @@ class _fileobject(object): _GLOBAL_DEFAULT_TIMEOUT = object() -def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT): +def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT, + source_address=None): """Connect to *address* and return the socket object. Convenience function. Connect to *address* (a 2-tuple ``(host, @@ -539,7 +541,9 @@ def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT): *timeout* parameter will set the timeout on the socket instance before attempting to connect. If no *timeout* is supplied, the global default timeout setting returned by :func:`getdefaulttimeout` - is used. + is used. If *source_address* is set it must be a tuple of (host, port) + for the socket to bind as a source address before making the connection. + An host of '' or port 0 tells the OS to use the default. """ msg = "getaddrinfo returns an empty list" @@ -551,6 +555,8 @@ def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT): sock = socket(af, socktype, proto) if timeout is not _GLOBAL_DEFAULT_TIMEOUT: sock.settimeout(timeout) + if source_address: + sock.bind(source_address) sock.connect(sa) return sock diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 472f403..055af67 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -995,7 +995,7 @@ class NetworkConnectionAttributesTest(SocketTCPTest, ThreadableTest): ThreadableTest.__init__(self) def clientSetUp(self): - pass + self.source_port = test_support.find_unused_port() def clientTearDown(self): self.cli.close() @@ -1010,6 +1010,19 @@ class NetworkConnectionAttributesTest(SocketTCPTest, ThreadableTest): self.cli = socket.create_connection((HOST, self.port), timeout=30) self.assertEqual(self.cli.family, 2) + testSourcePort = _justAccept + def _testSourcePort(self): + self.cli = socket.create_connection((HOST, self.port), timeout=30, + source_address=('', self.source_port)) + self.assertEqual(self.cli.getsockname()[1], self.source_port) + + testSourceAddress = _justAccept + def _testSourceAddress(self): + self.cli = socket.create_connection( + (HOST, self.port), 30, ('127.0.0.1', self.source_port)) + self.assertEqual(self.cli.getsockname(), + ('127.0.0.1', self.source_port)) + testTimeoutDefault = _justAccept def _testTimeoutDefault(self): # passing no explicit timeout uses socket's global default @@ -62,6 +62,8 @@ Core and Builtins Library ------- +- socket.create_connection now accepts an optional source_address parameter. + - Issue #5511: now zipfile.ZipFile can be used as a context manager. Initial patch by Brian Curtin. |