diff options
-rw-r--r-- | .github/FUNDING.yml | 3 | ||||
-rw-r--r-- | paramiko/sftp_client.py | 17 | ||||
-rw-r--r-- | sites/www/changelog.rst | 3 | ||||
-rw-r--r-- | sites/www/contact.rst | 6 | ||||
-rw-r--r-- | tests/test_sftp.py | 28 |
5 files changed, 51 insertions, 6 deletions
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..30ce38c8 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +tidelift: "pypi/paramiko" diff --git a/paramiko/sftp_client.py b/paramiko/sftp_client.py index 93190d85..6294fb48 100644 --- a/paramiko/sftp_client.py +++ b/paramiko/sftp_client.py @@ -758,7 +758,7 @@ class SFTPClient(BaseSFTP, ClosingContextManager): with open(localpath, "rb") as fl: return self.putfo(fl, remotepath, file_size, callback, confirm) - def getfo(self, remotepath, fl, callback=None): + def getfo(self, remotepath, fl, callback=None, prefetch=True): """ Copy a remote file (``remotepath``) from the SFTP server and write to an open file or file-like object, ``fl``. Any exception raised by @@ -771,18 +771,23 @@ class SFTPClient(BaseSFTP, ClosingContextManager): :param callable callback: optional callback function (form: ``func(int, int)``) that accepts the bytes transferred so far and the total bytes to be transferred + :param bool prefetch: + controls whether prefetching is performed (default: True) :return: the `number <int>` of bytes written to the opened file object .. versionadded:: 1.10 + .. versionchanged:: 2.8 + Added the ``prefetch`` keyword argument. """ file_size = self.stat(remotepath).st_size with self.open(remotepath, "rb") as fr: - fr.prefetch(file_size) + if prefetch: + fr.prefetch(file_size) return self._transfer_with_callback( reader=fr, writer=fl, file_size=file_size, callback=callback ) - def get(self, remotepath, localpath, callback=None): + def get(self, remotepath, localpath, callback=None, prefetch=True): """ Copy a remote file (``remotepath``) from the SFTP server to the local host as ``localpath``. Any exception raised by operations will be @@ -793,13 +798,17 @@ class SFTPClient(BaseSFTP, ClosingContextManager): :param callable callback: optional callback function (form: ``func(int, int)``) that accepts the bytes transferred so far and the total bytes to be transferred + :param bool prefetch: + controls whether prefetching is performed (default: True) .. versionadded:: 1.4 .. versionchanged:: 1.7.4 Added the ``callback`` param + .. versionchanged:: 2.8 + Added the ``prefetch`` keyword argument. """ with open(localpath, "wb") as fl: - size = self.getfo(remotepath, fl, callback) + size = self.getfo(remotepath, fl, callback, prefetch) s = os.stat(localpath) if s.st_size != size: raise IOError( diff --git a/sites/www/changelog.rst b/sites/www/changelog.rst index 3582b775..6dc29569 100644 --- a/sites/www/changelog.rst +++ b/sites/www/changelog.rst @@ -7,6 +7,9 @@ Changelog were incorrectly using SHA1 after all, due to a bug causing them to ignore the ``hash_algo`` class attribute. This has been corrected. Big thanks to Benno Rice for catch & patch. +- :feature:`1846` Add a ``prefetch`` keyword argument to `SFTPClient.get <paramiko.sftp_client.SFTPClient.get>`/`SFTPClient.getfo <paramiko.sftp_client.SFTPClient.getfo>` + so users who need to skip SFTP prefetching are able to conditionally turn it + off. Thanks to Github user ``@h3ll0r`` for the PR. - :release:`2.7.2 <2020-08-30>` - :support:`- backported` Update our CI to catch issues with sdist generation, installation and testing. diff --git a/sites/www/contact.rst b/sites/www/contact.rst index dafc1bd4..202815f8 100644 --- a/sites/www/contact.rst +++ b/sites/www/contact.rst @@ -5,6 +5,8 @@ Contact You can get in touch with the developer & user community in any of the following ways: -* IRC: ``#paramiko`` on Freenode -* This website - a blog section is forthcoming. * Submit contributions on Github - see the :doc:`contributing` page. +* Follow ``@bitprophet`` on Twitter, though it's not a dedicated account and + mostly just retweets funny pictures. +* Subscribe to the ``paramiko`` category on the developer's blog: + http://bitprophet.org/categories/paramiko/ diff --git a/tests/test_sftp.py b/tests/test_sftp.py index e4e18e5a..a98a46c6 100644 --- a/tests/test_sftp.py +++ b/tests/test_sftp.py @@ -554,6 +554,34 @@ class TestSFTP(object): os.unlink(localname) sftp.unlink(sftp.FOLDER + "/bunny.txt") + def test_get_without_prefetch(self, sftp): + """ + Create a 4MB file. Verify that pull works without prefetching + using a lager file. + """ + + sftp_filename = sftp.FOLDER + "/dummy_file" + num_chars = 1024 * 1024 * 4 + + fd, localname = mkstemp() + os.close(fd) + + with open(localname, "wb") as f: + f.write(b"0" * num_chars) + + sftp.put(localname, sftp_filename) + + os.unlink(localname) + fd, localname = mkstemp() + os.close(fd) + + sftp.get(sftp_filename, localname, prefetch=False) + + assert os.stat(localname).st_size == num_chars + + os.unlink(localname) + sftp.unlink(sftp_filename) + def test_check(self, sftp): """ verify that file.check() works against our own server. |