Changeset 491:bbb12d16377f

Show
Ignore:
Timestamp:
2006-02-18 21:32:10 (4 years ago)
Author:
Stefan Schwarzer <sschwarzer@…>
Branch:
default
convert_revision:
svn:778c30c8-61e0-0310-89d4-fe2f97a467b2/trunk@510
Message:
Reworked keep-alive functionality regarding writable files. If you read
the code, you will see that it's potentially brittle, and I may remove
the keep-alive code completely before the final 2.1 release.

In `ftp_file.py`, renamed `_binmode` and `_readmode` to `_bin_mode` and
`_read_mode`, respectively.
Files:
4 modified

Legend:

Unmodified
Added
Removed
  • _test_real_ftp.py

    r489 r491  
    337337                print "Keeping host alive (%d of %d) " % (i+1, intervals) 
    338338                host.keep_alive(ignore_errors=True) 
     339                self.assertRaises(ftp_error.KeepAliveError, host.keep_alive) 
     340                # open written files can't be "kept alive", 
     341                #  so cause some activity 
     342                written_file.write("x") 
     343                written_file.flush() 
    339344                time.sleep(interval_length) 
    340345            # do some tests; order of statements is important 
     
    342347            #   files get reused) 
    343348            self.assertEqual(read_file.read(2), "Te") 
    344             written_file.write("xyz") 
    345349            # - try to reuse the stale files 
    346350            written_file2 = host.file("_test_file3_", "w") 
     
    354358        finally: 
    355359            # clean up 
    356             print 2, host.listdir(".") 
    357 #             host.remove("_test_file_") 
    358 #             host.remove("_test_file2_") 
    359 #             host.remove("_test_file3_") 
     360            host.remove("_test_file_") 
     361            host.remove("_test_file2_") 
     362            host.remove("_test_file3_") 
    360363 
    361364 
  • ftp_error.py

    r471 r491  
    6161class TimeShiftError(InternalError): pass 
    6262class ParserError(InternalError): pass 
     63class KeepAliveError(InternalError): pass 
    6364 
    6465class FTPOSError(FTPError, OSError): pass 
  • ftp_file.py

    r484 r491  
    9999            raise ftp_error.FTPIOError("invalid mode '%s'" % mode) 
    100100        # remember convenience variables instead of mode 
    101         self._binmode = 'b' in mode 
    102         self._readmode = 'r' in mode 
     101        self._bin_mode = 'b' in mode 
     102        self._read_mode = 'r' in mode 
    103103        # select ASCII or binary mode 
    104         transfer_type = ('A', 'I')[self._binmode] 
     104        transfer_type = ('A', 'I')[self._bin_mode] 
    105105        command = 'TYPE %s' % transfer_type 
    106106        ftp_error._try_with_ioerror(self._session.voidcmd, command) 
    107107        # make transfer command 
    108         command_type = ('STOR', 'RETR')[self._readmode] 
     108        command_type = ('STOR', 'RETR')[self._read_mode] 
    109109        command = '%s %s' % (command_type, path) 
    110110        # ensure we can process the raw line separators; 
     
    131131        """Return read bytes, normalized if in text transfer mode.""" 
    132132        data = self._fo.read(*args) 
    133         if self._binmode: 
     133        if self._bin_mode: 
    134134            return data 
    135135        data = _crlf_to_python_linesep(data) 
     
    164164        """Return one read line, normalized if in text transfer mode.""" 
    165165        data = self._fo.readline(*args) 
    166         if self._binmode: 
     166        if self._bin_mode: 
    167167            return data 
    168168        # if necessary, complete begun newline 
     
    174174        """Return read lines, normalized if in text transfer mode.""" 
    175175        lines = self._fo.readlines(*args) 
    176         if self._binmode: 
     176        if self._bin_mode: 
    177177            return lines 
    178178        # more memory-friendly than `return [... for line in lines]` 
     
    186186        separator conversion support. 
    187187        """ 
    188         if self._binmode: 
     188        if self._bin_mode: 
    189189            return self._fo.xreadlines() 
    190190        return _XReadlines(self) 
     
    192192    def write(self, data): 
    193193        """Write data to file. Do linesep conversion for text mode.""" 
    194         if not self._binmode: 
     194        if not self._bin_mode: 
    195195            data = _python_to_crlf_linesep(data) 
    196196        self._fo.write(data) 
     
    198198    def writelines(self, lines): 
    199199        """Write lines to file. Do linesep conversion for text mode.""" 
    200         if self._binmode: 
     200        if self._bin_mode: 
    201201            self._fo.writelines(lines) 
    202202            return 
     
    221221              "'FTPFile' object has no attribute '%s'" % attr_name) 
    222222 
    223     def keep_alive(self): 
     223    def keep_alive(self, ignore_errors=False): 
    224224        """ 
    225225        Keep the connection busy to prevent lost connections 
    226226        because of server timeouts. 
    227         """ 
    228         if self._readmode: 
     227 
     228        Since this doesn't seem to work for writable files, 
     229        `ignore_errors` must be set to a true value to avoid that a 
     230        `KeepAliveError` is raised. By default, `ignore_errors` is a 
     231        false value, so errors can't pass silently. 
     232        """ 
     233        if self.closed: 
     234            self._host.getcwd() 
     235        elif self._read_mode: 
    229236            self.read(0) 
    230237        else: 
    231             self.write("") 
     238            # I thought about putting `self.flush()` here; this will 
     239            #  work if the client wrote at least a byte in the file 
     240            #  since the last flush. However, using `flush()` here 
     241            #  could lead to subtle failures in ftputil client code. 
     242            #  Post on the ftputil mailing list if you think the 
     243            #  `flush` call is appropriate here. 
     244            if not ignore_errors: 
     245                raise ftp_error.KeepAliveError( 
     246                      "keep-alive doesn't work for writable files") 
    232247 
    233248    def close(self): 
  • ftputil.py

    r487 r491  
    249249        return self.file(path, mode) 
    250250 
    251     def keep_alive(self, also_files=True): 
     251    def keep_alive(self, also_files=True, ignore_errors=False): 
    252252        """ 
    253253        Do something without side effects to keep the connection to 
     
    260260        may want to set `also_files` to `False` and call the 
    261261        `keep_alive` method of the file-like objects individually. 
    262         """ 
    263         # just prevent loss of the connection, so discard the result 
     262 
     263        If `ignore_errors` is set to a false value (the default), 
     264        keep-alive attempts on writable files will raise a 
     265        `KeepAliveError` (because there doesn't seem to be a way to 
     266        implement this functionality). Set `ignore_errors` to a true 
     267        value to mask such errors. 
     268        """ 
     269        # discard result 
    264270        self.getcwd() 
    265271        # refresh also connections of associated file-like objects 
    266272        if also_files: 
    267273            for host in self._children: 
    268                 host._file.keep_alive() 
     274                host._file.keep_alive(ignore_errors=ignore_errors) 
    269275 
    270276    def close(self):