1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
#!/usr/bin/env python # ######################### # # $Id: sendfile.py,v 1.4 2008/03/19 11:59:52 dhylton Exp $ # # $Log: $ # ######################### import time import os import sys #import paramiko #import ftplib #import pycurl class SftpSClient (object): def __init__(self, protocol, hostname, hostport, username, password, source_path, dest_path): self.protocol = protocol self.hostname = hostname self.hostport = hostport self.username = username self.password = password self.source_path = source_path self.dest_path = dest_path if self.protocol == "sftp": import paramiko self.client = paramiko.SSHClient() self.client.load_system_host_keys() elif self.protocol == "ftps": import pycurl self.client = pycurl.Curl() else: #self.protocol == "ftp": import ftplib self.client = ftplib.FTP() def xfer(self, source_file, dest_file=None): if not dest_file: dest_file = source_file source = os.path.join(self.source_path, source_file) dest = os.path.join(self.dest_path, dest_file) if self.protocol == "sftp": if not self.hostport: self.hostport = 22 self.client.connect(self.hostname, self.hostport, self.username, self.password) sftp_client = self.client.open_sftp() sftp_client.put(source, dest) sftp_client.close() elif self.protocol == "ftps": if not self.hostport: self.hostport = 990 userpwd = '%s:%s' % (self.username, self.password) infile = open(source, 'rb') self.client.setopt(pycurl.URL, 'ftp://%s:%d/%s' % (self.hostname, self.hostport, dest)) self.client.setopt(pycurl.FTP_SSL, 1) self.client.setopt(pycurl.FTPSSLAUTH, 1) self.client.setopt(pycurl.SSL_VERIFYHOST, 1) self.client.setopt(pycurl.SSL_VERIFYPEER, 1) self.client.setopt(pycurl.USERPWD, userpwd) self.client.setopt(pycurl.READDATA, infile) self.client.setopt(pycurl.UPLOAD, 1) self.client.perform() infile.close() else: #self.protocol == "ftp": if not self.hostport: self.hostport = 21 self.client.connect(self.hostname, self.hostport) self.client.login(user=self.username, passwd=self.password) self.client.set_pasv(False) infile = open(source, 'rb') self.client.storbinary('STOR ' + dest, infile) infile.close() def main(): hostname = 'localhost' username = 'snark' password = 'Bgt54rfv' source_path = 'lo cal' source_file = "test file'132" dest_file = "remote test file'133" print 'testing ftp' protocol = 'ftp' hostport = None start = time.time() dest_path = '%s/re mote' % (protocol) p = SftpSClient(protocol, hostname, hostport, username, password, source_path, dest_path) p.xfer(source_file, dest_file) elapsedtime = time.time() - start print 'elapsed time:', elapsedtime print 'testing ftps' protocol = 'ftps' hostport = 990 start = time.time() dest_path = '%s/re mote' % (protocol) p = SftpSClient(protocol, hostname, hostport, username, password, source_path, dest_path) p.xfer(source_file, dest_file) elapsedtime = time.time() - start print 'elapsed time:', elapsedtime print 'testing sftp' protocol = 'sftp' hostport = 22 start = time.time() dest_path = '%s/re mote' % (protocol) p = SftpSClient(protocol, hostname, hostport, username, password, source_path, dest_path) p.xfer(source_file, dest_file) elapsedtime = time.time() - start print 'elapsed time:', elapsedtime if __name__ == '__main__': main()
Refactorings
No refactoring yet !
Simon Law
March 19, 2008, March 19, 2008 17:06, permalink
That's because pycurl is only defined in SftpSClient.__init__().
Here, it makes more sense for you to use a factory make SftpSClient.__init__() construct a good delegate object, that knows how to configure itself, instead of trying to keep state in SftpSClient.protocol.
dhylton.myopenid.com
March 19, 2008, March 19, 2008 17:13, permalink
why does this not apply to paramiko and ftplib?
could you (please) show an example of your recommendation?
Simon Law
March 20, 2008, March 20, 2008 00:02, permalink
You use pycurl outside of its imported scope.
Here is an example implementation that uses a delegate.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
import time import os import sys class SftpSClient(object): def __init__(self, protocol, hostname, hostport, username, password, source_path, dest_path): if protocol == "sftp": self.delegate = ParamikoClient(protocol, hostname, hostport, username, password, source_path, dest_path) elif protocol == "ftps": self.delegate = PycurlClient(protocol, hostname, hostport, username, password, source_path, dest_path) else: #self.protocol == "ftp": self.delegate = FtpClient(protocol, hostname, hostport, username, password, source_path, dest_path) def _setup(self, protocol, hostname, hostport, username, password, source_path, dest_path): self.protocol = protocol self.hostname = hostname self.hostport = hostport self.username = username self.password = password self.source_path = source_path self.dest_path = dest_path def _xfer(self, source_file, dest_file): if not dest_file: dest_file = source_file source = os.path.join(self.source_path, source_file) dest = os.path.join(self.dest_path, dest_file) return (source, dest) def xfer(self, source_file, dest_file): self.delegate.xfer(*args, **kwargs) class ParamikoClient(SftpSClient): def __init__(self, *args, **kwargs): self._setup(*args, **kwargs) self.paramiko = __import__("paramiko") self.client = self.paramiko.SSHClient() self.client.load_system_host_keys() def xfer(self, source_file, dest_file): source, dest = self._xfer(source_file, dest_file) if not self.hostport: self.hostport = 22 self.client.connect(self.hostname, self.hostport, self.username, self.password) sftp_client = self.client.open_sftp() sftp_client.put(source, dest) sftp_client.close() class PycurlClient(SftpSClient): def __init__(self, *args, **kwargs): self._setup(*args, **kwargs) self.pycurl = __import__("pycurl") self.client = self.pycurl.Curl() def xfer(self, source_file, dest_file): source, dest = self._xfer(source_file, dest_file) if not self.hostport: self.hostport = 990 userpwd = '%s:%s' % (self.username, self.password) infile = open(source, 'rb') self.client.setopt(self.pycurl.URL, 'ftp://%s:%d/%s' % (self.hostname, self.hostport, dest)) self.client.setopt(self.pycurl.FTP_SSL, 1) self.client.setopt(self.pycurl.FTPSSLAUTH, 1) self.client.setopt(self.pycurl.SSL_VERIFYHOST, 1) self.client.setopt(self.pycurl.SSL_VERIFYPEER, 1) self.client.setopt(self.pycurl.USERPWD, userpwd) self.client.setopt(self.pycurl.READDATA, infile) self.client.setopt(self.pycurl.UPLOAD, 1) self.client.perform() infile.close() class FtpClient(SftpSClient): def __init__(self, *args, **kwargs): self._setup(*args, **kwargs) self.ftplib = __import__("ftplib") self.client = self.ftplib.FTP() def xfer(self, source_file, dest_file): source, dest = self._xfer(source_file, dest_file) if not self.hostport: self.hostport = 21 self.client.connect(self.hostname, self.hostport) self.client.login(user=self.username, passwd=self.password) self.client.set_pasv(False) infile = open(source, 'rb') self.client.storbinary('STOR ' + dest, infile) infile.close() def main(): hostname = 'localhost' username = 'snark' password = 'Bgt54rfv' source_path = 'lo cal' source_file = "test file'132" dest_file = "remote test file'133" print 'testing ftp' protocol = 'ftp' hostport = None start = time.time() dest_path = '%s/re mote' % (protocol) p = SftpSClient(protocol, hostname, hostport, username, password, source_path, dest_path) p.xfer(source_file, dest_file) elapsedtime = time.time() - start print 'elapsed time:', elapsedtime print 'testing ftps' protocol = 'ftps' hostport = 990 start = time.time() dest_path = '%s/re mote' % (protocol) p = SftpSClient(protocol, hostname, hostport, username, password, source_path, dest_path) p.xfer(source_file, dest_file) elapsedtime = time.time() - start print 'elapsed time:', elapsedtime print 'testing sftp' protocol = 'sftp' hostport = 22 start = time.time() dest_path = '%s/re mote' % (protocol) p = SftpSClient(protocol, hostname, hostport, username, password, source_path, dest_path) p.xfer(source_file, dest_file) elapsedtime = time.time() - start print 'elapsed time:', elapsedtime if __name__ == '__main__': main()
the goal is to be able to export the SftpSClient class ('from sendfile import SftpSClient') from another script that uses ConfigParser to define the actual variables (hostname, protocol, etc.) currently i get a name (scope) error with pycurl, but both ftplib and paramiko work just fine.