6.13.1.5. FTP input

This object fetches a file by ftp on construction. The file is then read from the local copy. The host name and remote filename arguments are mandatory. Optional arguments given by keywords are:
port
The port number of the host to use for FTP. Defaults to 21.
user
User name. Defaults to 'anonymous'.
account
User's account name.
password
User's password. If user is anonymous, the default password is `realuser@host' where realuser is the real user name (glanced from the `LOGNAME' or `USER' environment variable) and host is the hostname as returned by socket.gethostname().
remote_directory
The directory to 'cd' to to get the nominated file. If not specified, no 'cd' is done and the file is expected in the FTP root. This filename must obey the conventions of the remote host.
local_filename
The name of the file to which the download should be written. Defaults to 'remote_filename'. This name must obey the unix conventions for a relative filename.
local_directory
The name of the directory into which the download should be written; this name must obey the unix conventions for a relative filename and include a trailing '/'. Defaults to 'remote_directory' with a trailing '/' added.
local_prefix
The name of the file to which the download should be written. Thsi filename must obey the conventions of the local operating system, and include a trailing directory separator. Defaults to the current directory (with a trailing separator).
refresh_interval
The is the number of days old the local file can be before ftp is done. The default is 28. If this value is set to 0, a download is always done. If the value is set to -1, a download is done only if the local file does not exist; delete the file to force another download.
An exception is thrown if there is no local file, and the attempt to ftp the remote file fails. No exception is thrown if the local file exists, even if it is out of date.

It is recommended the following convention be used: the local_prefix should be set to interscript.directory, the interscript module directory, and the local directory should be set to 'ftp/' plus the hostname plus '/' plus the remote directory plus '/'. For example:

  ftp_file_source(get_pass_frame(),
    'ftp.python.org',
    'interscript_1_0a9.tar.gz',
    remote_directory='contrib/misc/',
    local_prefix=interscript.directory,
    local_directory='ftp/ftp.python.org/contrib/misc/'
    )
because this will cache the file in a fixed, shared, location, which also identifies its origin.

Start python section to interscript/drivers/sources/ftp.py[1 /1 ]
     1: #line 381 "source_drivers.ipk"
     2: #---------------------------------------------------------
     3: # gets input by FTP
     4: import ftplib
     5: import time
     6: import os
     7: import stat
     8: from interscript.drivers.sources.base import file_source
     9: from interscript.drivers.sources.base import eof
    10: import string
    11: import tempfile
    12: import traceback
    13: from interscript.drivers.sinks.disk import simple_named_file_sink
    14: 
    15: class dummy: pass
    16: 
    17: class ftp_file_source(file_source):
    18:   def __init__(self, pass_frame,
    19:     host, remote_filename,
    20:     encoding='utf8', **kwds):
    21:     self.pass_frame = pass_frame
    22:     self.master = pass_frame.master
    23:     self.process = pass_frame.process
    24:     self.site = self.process.site
    25:     self.platform = self.process.site.platform
    26:     self.global_frame = pass_frame.master.process.global_frame
    27:     if 'sources' in self.process.trace:
    28:       self.process.acquire_object(self, 'FTP SOURCE '+remote_filename)
    29: 
    30:     apply(file_source.__init__, (self,encoding), kwds)
    31: 
    32:     self.name = remote_filename
    33:     self.remote_filename = remote_filename
    34:     self.host = host
    35: 
    36:     for k in kwds.keys():
    37:       self.__dict__[k]=kwds[k]
    38:     if not hasattr(self,'local_filename'):
    39:       self.local_filename = self.remote_filename
    40:     if not hasattr(self,'local_prefix'):
    41:       self.local_prefix = ''
    42:     if not hasattr(self,'local_directory'):
    43:       self.local_directory = ''
    44: 
    45:     if not hasattr(self,'port'):
    46:       self.port = ''
    47:     if not hasattr(self,'remote_directory'):
    48:       self.remote_directory = ''
    49: 
    50:     self.iflist_index = len(pass_frame.iflist)
    51:     pass_frame.iflist.append([self.local_filename,0])
    52:     pass_frame.ftp_list.append([self.host, self.remote_directory, self.remote_filename, self.local_filename])
    53: 
    54: 
    55:     self.os = os
    56:     pathname = self.fetch()
    57:     self.file = open(pathname,'r')
    58:     self.closed = 0
    59: 
    60:   def transfer(self,data):
    61:     self.file.write(data+'\n')
    62: 
    63:   def fetch(self):
    64:     if not hasattr(self,'refresh_interval'):
    65:       self.refresh_interval = 28
    66:     if self.refresh_interval < 0: self.refresh_interval = 100000
    67:     pathname = self.platform.mk_dir(self.local_prefix,
    68:       string.split(self.local_directory+self.local_filename, '/'))
    69:     self.local_file_exists = self.platform.file_exists(pathname)
    70: 
    71:     if self.local_file_exists:
    72:       #print 'Local file exists'
    73:       self.local_file_modify_time = os.stat(pathname)[stat.ST_MTIME]
    74:       now = time.time()
    75:       age = (now - self.local_file_modify_time)/ (24 * 60 * 60)
    76:       download = age > self.refresh_interval
    77:     else:
    78:       print 'Local file does not exist'
    79:       download = 1
    80: 
    81:     if hasattr(self.global_frame,'download'):
    82:       if self.global_frame.download == 'always': download = 1
    83:       if self.global_frame.download == 'never': download = 0
    84: 
    85:     if download:
    86:       try:
    87:         if 'sources' in self.process.trace:
    88:           print 'downloading',self.remote_filename
    89:         # create FTP object
    90:         ftp = ftplib.FTP()
    91: 
    92:         # connect to server
    93:         if self.port:
    94:           ftp.connect(self.host,self.port)
    95:         else:
    96:           ftp.connect(self.host)
    97:         print 'connected to',self.host
    98: 
    99:         # login to server
   100:         if hasattr(self,'user'):
   101:           if hasattr(self,'password'):
   102:             if hasattr(self,'account'):
   103:               ftp.login(self.user,self.password,self.account)
   104:             else: ftp.login(self.user,self.password)
   105:           else: ftp.login(self.user)
   106:         else: ftp.login()
   107:         if 'sources' in self.process.trace:
   108:           print 'logged in'
   109: 
   110:         # set remote directory
   111:         if self.remote_directory:
   112:           ftp.cwd(self.remote_directory)
   113:           print 'changed to remote directory',self.remote_directory
   114: 
   115:         # get file to a temporary
   116:         try:
   117:           tmp_filename = tempfile.mktemp()
   118:           self.file= open(tmp_filename,'w')
   119:           print 'opened',tmp_filename,'for download'
   120:           ftp.retrlines('RETR '+self.remote_filename, self.transfer)
   121:           self.file.close()
   122:           ftp.quit()
   123:           if 'sources' in self.process.trace:
   124:             print 'download complete'
   125: 
   126:           file = open(tmp_filename,'r')
   127:           newlines = file.readlines()
   128:           file.close()
   129: 
   130:           if self.local_file_exists:
   131:             file = open(pathname,'r')
   132:             oldlines = file.readlines()
   133:             file.close()
   134: 
   135:             if newlines != oldlines:
   136:               if 'sources' in self.process.trace:
   137:                 print 'Local file',self.local_filename,'UPDATED from',self.remote_filename
   138:             else:
   139:               if 'sources' in self.process.trace:
   140:                 print 'Local file',self.local_filename,'unchanged'
   141:           else:
   142:             if 'sources' in self.process.trace:
   143:               print 'Writing new local file',self.local_filename
   144: 
   145:           # note that the local file is written even if it isn't changed
   146:           # to update the time stamp
   147:           try:
   148:             file = simple_named_file_sink(self.pass_frame,
   149:               self.local_directory+self.local_filename, prefix=self.local_prefix)
   150:             file.writelines(newlines)
   151:             del file
   152:           except:
   153:             print 'Error writing file', self.local_directory+self.local_filename,'in',self.local_prefix
   154:             traceback.print_exc()
   155:             raise
   156: 
   157:         except:
   158:           print 'ftp error: Cannot download',self.remote_filename,
   159:           if hasattr(self,'remote_directory'):
   160:             print 'from directory',self.remote_directory,
   161:           print 'of',self.host
   162:           file.close()
   163:           self.os.remove(tmp_filename)
   164:           ftp.quit()
   165:           traceback.print_exc()
   166:           raise
   167: 
   168:       except:
   169:         pass # ignore errors from ftp attempt
   170:     else:
   171:       if 'sources' in self.process.trace:
   172:         print 'Skipping ftp download ftp://'+self.host+'/'+self.remote_directory+'/'+self.remote_filename
   173:     return pathname
   174:   def __del__(self):
   175:     if 'sources' in self.process.trace:
   176:       self.process.release_object(self)
   177: 
End python section to interscript/drivers/sources/ftp.py[1]