[project @ Arch-1:robey@lag.net--2005-master-shake%paramiko--dev--1--patch-33]
add SFTPClient.put and SFTPClient.get, and make sftp file objects auto-close on del
This commit is contained in:
parent
1f88224239
commit
93f3cae64f
1
README
1
README
|
@ -238,7 +238,6 @@ v0.9 FEAROW
|
|||
|
||||
* ctr forms of ciphers are missing (blowfish-ctr, aes128-ctr, aes256-ctr)
|
||||
|
||||
* would be nice to have an ftp-like interface to sftp (put, get, chdir...)
|
||||
* cool sftp extension: retreive MD5 or SHA1 of section of a file
|
||||
* SFTPClient.from_url('sftp://robey@arch.lag.net/folder/filename', 'r+')
|
||||
keep cache of opened sftp clients by (host, port, username)
|
||||
|
|
|
@ -56,6 +56,9 @@ class BufferedFile (object):
|
|||
# (these may be different because we buffer for line reading)
|
||||
self._pos = self._realpos = 0
|
||||
|
||||
def __del__(self):
|
||||
self.close()
|
||||
|
||||
def __iter__(self):
|
||||
"""
|
||||
Returns an iterator that can be used to iterate over the lines in this
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
Client-mode SFTP support.
|
||||
"""
|
||||
|
||||
import os
|
||||
from sftp import *
|
||||
from sftp_attr import SFTPAttributes
|
||||
from sftp_file import SFTPFile
|
||||
|
@ -429,6 +430,62 @@ class SFTPClient (BaseSFTP):
|
|||
"""
|
||||
return self._cwd
|
||||
|
||||
def put(self, localpath, remotepath):
|
||||
"""
|
||||
Copy a local file (C{localpath}) to the SFTP server as C{remotepath}.
|
||||
Any exception raised by operations will be passed through. This
|
||||
method is primarily provided as a convenience.
|
||||
|
||||
@param localpath: the local file to copy
|
||||
@type localpath: str
|
||||
@param remotepath: the destination path on the SFTP server
|
||||
@type remotepath: str
|
||||
|
||||
@since: 1.4
|
||||
"""
|
||||
fl = file(localpath, 'rb')
|
||||
fr = self.file(remotepath, 'wb')
|
||||
size = 0
|
||||
while True:
|
||||
data = fl.read(16384)
|
||||
if len(data) == 0:
|
||||
break
|
||||
fr.write(data)
|
||||
size += len(data)
|
||||
fl.close()
|
||||
fr.close()
|
||||
s = self.stat(remotepath)
|
||||
if s.st_size != size:
|
||||
raise IOError('size mismatch in put! %d != %d' % (s.st_size, size))
|
||||
|
||||
def get(self, remotepath, localpath):
|
||||
"""
|
||||
Copy a remote file (C{remotepath}) from the SFTP server to the local
|
||||
host as C{localpath}. Any exception raised by operations will be
|
||||
passed through. This method is primarily provided as a convenience.
|
||||
|
||||
@param remotepath: the remote file to copy
|
||||
@type remotepath: str
|
||||
@param localpath: the destination path on the local host
|
||||
@type localpath: str
|
||||
|
||||
@since: 1.4
|
||||
"""
|
||||
fr = self.file(remotepath, 'rb')
|
||||
fl = file(localpath, 'wb')
|
||||
size = 0
|
||||
while True:
|
||||
data = fr.read(16384)
|
||||
if len(data) == 0:
|
||||
break
|
||||
fl.write(data)
|
||||
size += len(data)
|
||||
fl.close()
|
||||
fr.close()
|
||||
s = os.stat(localpath)
|
||||
if s.st_size != size:
|
||||
raise IOError('size mismatch in get! %d != %d' % (s.st_size, size))
|
||||
|
||||
|
||||
### internals...
|
||||
|
||||
|
|
|
@ -43,7 +43,14 @@ class SFTPFile (BufferedFile):
|
|||
|
||||
def close(self):
|
||||
BufferedFile.close(self)
|
||||
try:
|
||||
self.sftp._request(CMD_CLOSE, self.handle)
|
||||
except EOFError:
|
||||
# may have outlived the Transport connection
|
||||
pass
|
||||
except IOError:
|
||||
# may have outlived the Transport connection
|
||||
pass
|
||||
|
||||
def _read(self, size):
|
||||
size = min(size, self.MAX_REQUEST_SIZE)
|
||||
|
|
|
@ -540,3 +540,32 @@ class SFTPTest (unittest.TestCase):
|
|||
except:
|
||||
pass
|
||||
|
||||
def test_J_get_put(self):
|
||||
"""
|
||||
verify that get/put work.
|
||||
"""
|
||||
import os, warnings
|
||||
warnings.filterwarnings('ignore', 'tempnam.*')
|
||||
|
||||
localname = os.tempnam()
|
||||
text = 'All I wanted was a plastic bunny rabbit.\n'
|
||||
f = open(localname, 'w')
|
||||
f.write(text)
|
||||
f.close()
|
||||
sftp.put(localname, FOLDER + '/bunny.txt')
|
||||
|
||||
f = sftp.open(FOLDER + '/bunny.txt', 'r')
|
||||
self.assertEquals(text, f.read(128))
|
||||
f.close()
|
||||
|
||||
os.unlink(localname)
|
||||
localname = os.tempnam()
|
||||
sftp.get(FOLDER + '/bunny.txt', localname)
|
||||
|
||||
f = open(localname, 'r')
|
||||
self.assertEquals(text, f.read(128))
|
||||
f.close()
|
||||
|
||||
os.unlink(localname)
|
||||
sftp.unlink(FOLDER + '/bunny.txt')
|
||||
|
||||
|
|
Loading…
Reference in New Issue