Skip to content

Commit

Permalink
Implement HostnameEndpoint.__repr__
Browse files Browse the repository at this point in the history
Signed-off-by: Gordon Bolt <gbolt@ciena.com>
  • Loading branch information
twm committed Feb 15, 2018
1 parent 3bd48ac commit a661fb2
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 0 deletions.
21 changes: 21 additions & 0 deletions src/twisted/internet/endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,27 @@ def __init__(self, reactor, host, port, timeout=30, bindAddress=None,
self._attemptDelay = attemptDelay


def __repr__(self):
"""
Produce a string representation of the L{HostnameEndpoint}.
@return: A L{str}
"""
if self._badHostname:
# Use the backslash-encoded version of the string passed to the
# constructor, which is already a native string.
host = self._hostStr
elif isIPv6Address(self._hostStr):
host = '[{}]'.format(self._hostStr)
else:
# Convert the bytes representation to a native string to ensure
# that we display the punycoded version of the hostname, which is
# more useful than any IDN version as it can be easily copy-pasted
# into debugging tools.
host = nativeString(self._hostBytes)
return "".join(["<HostnameEndpoint ", host, ":", str(self._port), ">"])


def _getNameResolverAndMaybeWarn(self, reactor):
"""
Retrieve a C{nameResolver} callable and warn the caller's
Expand Down
52 changes: 52 additions & 0 deletions src/twisted/internet/test/test_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -2476,6 +2476,58 @@ def test_deferBadEncodingToConnect(self):
self.assertIn("\\u2ff0-garbage-\\u2ff0", str(err))


class HostnameEndpointReprTests(unittest.SynchronousTestCase):
def test_allASCII(self):
"""
The string representation of L{HostnameEndpoint} includes the host and
port passed to the constructor.
"""
endpoint = endpoints.HostnameEndpoint(
deterministicResolvingReactor(Clock(), []),
'example.com', 80,
)

self.assertEqual("<HostnameEndpoint example.com:80>", repr(endpoint))

def test_idnaHostname(self):
"""
When IDN is passed to the L{HostnameEndpoint} constructor the string
representation includes the punycode version of the host.
"""
endpoint = endpoints.HostnameEndpoint(
deterministicResolvingReactor(Clock(), []),
u'b\xfccher.ch', 443,
)

self.assertEqual("<HostnameEndpoint xn--bcher-kva.ch:443>", repr(endpoint))

def test_hostIPv6Address(self):
"""
When the host passed to L{HostnameEndpoint} is an IPv6 address it is
wrapped in brackets in the string representation, like in a URI. This
prevents the colon separating the host from the port from being
ambiguous.
"""
endpoint = endpoints.HostnameEndpoint(
deterministicResolvingReactor(Clock(), []),
b'::1', 22,
)

self.assertEqual("<HostnameEndpoint [::1]:22>", repr(endpoint))

def test_badEncoding(self):
"""
When a bad hostname is passed to L{HostnameEndpoint}, the string
representation displays invalid characters in backslash-escaped form.
"""
endpoint = endpoints.HostnameEndpoint(
deterministicResolvingReactor(Clock(), []),
b'\xff-garbage-\xff', 80
)

self.assertEqual('<HostnameEndpoint \\xff-garbage-\\xff:80>', repr(endpoint))



class HostnameEndpointsGAIFailureTests(unittest.TestCase):
"""
Expand Down
1 change: 1 addition & 0 deletions src/twisted/newsfragments/9341.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
twisted.internet.endpoints.HostnameEndpoint now has a __repr__ method which includes the host and port to which the endpoint connects.

0 comments on commit a661fb2

Please sign in to comment.