Changeset 876:dc80d10de7eb

Show
Ignore:
Timestamp:
2010-06-17 12:57:38 (3 months ago)
Author:
Stefan Schwarzer <sschwarzer@…>
Branch:
default
Message:
Added timeout logic for servers which don't send a response for
incomplete transfers. See ticket #51.
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • _mock_ftplib.py

    r869 r876  
    6060        self.file_path = path 
    6161        self.mock_file_content = mock_file_content 
     62        self._timeout = 60 
    6263 
    6364    def makefile(self, mode): 
     
    6667    def close(self): 
    6768        pass 
     69 
     70    def gettimeout(self): 
     71        return self._timeout 
     72 
     73    def settimeout(self, timeout): 
     74        self._timeout = timeout 
    6875 
    6976 
     
    136143        #  each has a corresponding `voidresp` 
    137144        self._transfercmds = 0 
     145        # dummy, only for getting/setting timeout in `_FTPFile.close` 
     146        self.sock = MockSocket("", "") 
    138147 
    139148    def voidcmd(self, cmd): 
  • ftp_file.py

    r874 r876  
    4141    requested. 
    4242    """ 
     43 
     44    # set timeout in seconds when closing file connections, see ticket #51 
     45    _close_timeout = 5 
    4346 
    4447    def __init__(self, host): 
     
    210213        if self.closed: 
    211214            return 
     215        # timeout value to restore, see below 
     216        #  statement works only before the try/finally statement, 
     217        #  otherwise Python raises an `UnboundLocalError` 
     218        old_timeout = self._session.sock.gettimeout() 
    212219        try: 
    213220            self._fo.close() 
    214221            ftp_error._try_with_ioerror(self._conn.close) 
     222            # set a timeout to prevent waiting until server timeout 
     223            #  if we have a server blocking here like in ticket #51 
     224            self._session.sock.settimeout(self._close_timeout) 
    215225            try: 
    216226                ftp_error._try_with_ioerror(self._session.voidresp) 
     
    220230                #  http://ftputil.sschwarzer.net/trac/ticket/17, 
    221231                #  respectively 
    222                 error_code = str(exception)[:3] 
    223                 if error_code not in ("150", "426", "450", "451"): 
     232                exception = str(exception) 
     233                error_code = exception[:3] 
     234                if exception.splitlines()[0] != "timed out" and \ 
     235                  error_code not in ("150", "426", "450", "451"): 
    224236                    raise 
    225237        finally: 
     238            # restore timeout for socket of `_FTPFile`'s `ftplib.FTP` 
     239            #  object in case the connection is reused later 
     240            self._session.sock.settimeout(old_timeout) 
    226241            # if something went wrong before, the file is probably 
    227242            #  defunct and subsequent calls to `close` won't help