03402885f5a969d18fa2ac4b56348196

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.

#!/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 !

6869f98aa6911b0f9f13468ccca24813

Simon Law

March 19, 2008, March 19, 2008 17:06, permalink

No rating. Login to rate!

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.

03402885f5a969d18fa2ac4b56348196

dhylton.myopenid.com

March 19, 2008, March 19, 2008 17:13, permalink

No rating. Login to rate!

why does this not apply to paramiko and ftplib?

could you (please) show an example of your recommendation?

6869f98aa6911b0f9f13468ccca24813

Simon Law

March 20, 2008, March 20, 2008 00:02, permalink

No rating. Login to rate!

You use pycurl outside of its imported scope.

Here is an example implementation that uses a delegate.

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()

Your refactoring





Format Copy from initial code

or Cancel