diff --git a/storages/backends/sftpstorage.py b/storages/backends/sftpstorage.py index f07e8cf5d..4b4194828 100644 --- a/storages/backends/sftpstorage.py +++ b/storages/backends/sftpstorage.py @@ -49,6 +49,7 @@ def __init__(self, host=None, params=None, interactive=None, file_mode=None, # for now it's all posix paths. Maybe someday we'll support figuring # out if the remote host is windows. self._pathmod = posixpath + self._sftp = None def _connect(self): self._ssh = paramiko.SSHClient() @@ -79,13 +80,13 @@ def _connect(self): except Exception as e: print(e) - if not hasattr(self, '_sftp'): + if self._ssh.get_transport(): self._sftp = self._ssh.open_sftp() @property def sftp(self): """Lazy SFTP connection""" - if not hasattr(self, '_sftp'): + if not self._sftp or not self._ssh.get_transport().is_active(): self._connect() return self._sftp diff --git a/tests/test_sftp.py b/tests/test_sftp.py index 754e98703..5b9c01c75 100644 --- a/tests/test_sftp.py +++ b/tests/test_sftp.py @@ -2,6 +2,7 @@ import stat from datetime import datetime +import paramiko from django.core.files.base import File from django.test import TestCase from django.utils.six import BytesIO @@ -133,6 +134,24 @@ def test_url(self): self.storage._base_url = None self.storage.url('foo') + @patch('paramiko.transport.Transport', **{ + 'is_active.side_effect': (True, False) + }) + @patch('storages.backends.sftpstorage.SFTPStorage._connect') + def test_sftp(self, connect, transport): + self.assertIsNone(self.storage.sftp) + self.assertTrue(connect.called) + connect.reset_mock() + self.storage._ssh = paramiko.SSHClient() + self.storage._ssh._transport = transport + + self.storage._sftp = True + self.assertTrue(self.storage.sftp) + self.assertFalse(connect.called) + + self.assertTrue(self.storage.sftp) + self.assertTrue(connect.called) + class SFTPStorageFileTest(TestCase): def setUp(self):