summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--paramiko/ssh_exception.py10
-rw-r--r--sites/www/changelog.rst5
-rwxr-xr-xtest.py4
-rw-r--r--tests/test_ssh_exception.py31
4 files changed, 47 insertions, 3 deletions
diff --git a/paramiko/ssh_exception.py b/paramiko/ssh_exception.py
index 016a411e..ed36a952 100644
--- a/paramiko/ssh_exception.py
+++ b/paramiko/ssh_exception.py
@@ -164,12 +164,18 @@ class NoValidConnectionsError(socket.error):
:param dict errors:
The errors dict to store, as described by class docstring.
"""
- addrs = errors.keys()
+ addrs = sorted(errors.keys())
body = ', '.join([x[0] for x in addrs[:-1]])
tail = addrs[-1][0]
- msg = "Unable to connect to port {0} on {1} or {2}"
+ if body:
+ msg = "Unable to connect to port {0} on {1} or {2}"
+ else:
+ msg = "Unable to connect to port {0} on {2}"
super(NoValidConnectionsError, self).__init__(
None, # stand-in for errno
msg.format(addrs[0][1], body, tail)
)
self.errors = errors
+
+ def __reduce__(self):
+ return (self.__class__, (self.errors, ))
diff --git a/sites/www/changelog.rst b/sites/www/changelog.rst
index 9ec970c7..340379fc 100644
--- a/sites/www/changelog.rst
+++ b/sites/www/changelog.rst
@@ -2,6 +2,11 @@
Changelog
=========
+* :bug:`617` (aka `fabric/fabric#1429
+ <https://github.com/fabric/fabric/issues/1429>`_; via :issue:`679`; related:
+ :issue:`678`, :issue:`685`) Fix up
+ `~paramiko.ssh_exception.NoValidConnectionsError` so it pickles correctly.
+ Thanks to Rebecca Schlussel for the report & Marius Gedminas for the patch.
* :bug:`613` (via :issue:`619`) Update to ``jaraco.windows`` 3.4.1 to fix some
errors related to ``ctypes`` on Windows platforms. Credit to Jason R. Coombs.
* :support:`621 backported` Annotate some public attributes on
diff --git a/test.py b/test.py
index 37fc5a6f..a1f13d85 100755
--- a/test.py
+++ b/test.py
@@ -43,8 +43,9 @@ from tests.test_kex import KexTest
from tests.test_packetizer import PacketizerTest
from tests.test_auth import AuthTest
from tests.test_transport import TransportTest
+from tests.test_ssh_exception import NoValidConnectionsErrorTest
from tests.test_client import SSHClientTest
-from test_client import SSHClientTest
+from test_client import SSHClientTest # XXX why shadow the above import?
from test_gssapi import GSSAPITest
from test_ssh_gss import GSSAuthTest
from test_kex_gss import GSSKexTest
@@ -156,6 +157,7 @@ def main():
if options.use_transport:
suite.addTest(unittest.makeSuite(AuthTest))
suite.addTest(unittest.makeSuite(TransportTest))
+ suite.addTest(unittest.makeSuite(NoValidConnectionsErrorTest))
suite.addTest(unittest.makeSuite(SSHClientTest))
if options.use_sftp:
suite.addTest(unittest.makeSuite(SFTPTest))
diff --git a/tests/test_ssh_exception.py b/tests/test_ssh_exception.py
new file mode 100644
index 00000000..18f2a97d
--- /dev/null
+++ b/tests/test_ssh_exception.py
@@ -0,0 +1,31 @@
+import pickle
+import unittest
+
+from paramiko.ssh_exception import NoValidConnectionsError
+
+
+class NoValidConnectionsErrorTest (unittest.TestCase):
+
+ def test_pickling(self):
+ # Regression test for https://github.com/paramiko/paramiko/issues/617
+ exc = NoValidConnectionsError({('127.0.0.1', '22'): Exception()})
+ new_exc = pickle.loads(pickle.dumps(exc))
+ self.assertEqual(type(exc), type(new_exc))
+ self.assertEqual(str(exc), str(new_exc))
+ self.assertEqual(exc.args, new_exc.args)
+
+ def test_error_message_for_single_host(self):
+ exc = NoValidConnectionsError({('127.0.0.1', '22'): Exception()})
+ assert "Unable to connect to port 22 on 127.0.0.1" in str(exc)
+
+ def test_error_message_for_two_hosts(self):
+ exc = NoValidConnectionsError({('127.0.0.1', '22'): Exception(),
+ ('::1', '22'): Exception()})
+ assert "Unable to connect to port 22 on 127.0.0.1 or ::1" in str(exc)
+
+ def test_error_message_for_multiple_hosts(self):
+ exc = NoValidConnectionsError({('127.0.0.1', '22'): Exception(),
+ ('::1', '22'): Exception(),
+ ('10.0.0.42', '22'): Exception()})
+ exp = "Unable to connect to port 22 on 10.0.0.42, 127.0.0.1 or ::1"
+ assert exp in str(exc)