def chdir(self, path): """Change the directory on the host.""" # Fail early if we get a unicode path which can't be encoded. path = str(path) ftp_error._try_with_oserror(self._session.cwd, path) # The path given as the argument is relative to the old current # directory, therefore join them. self._cached_current_dir = \ self.path.normpath(self.path.join(self._cached_current_dir, path))
def _FTPHost_dir_command(self, path): """Callback function.""" lines = [] def callback(line): """Callback function.""" lines.append(line) if self._accepts_list_a_option: args = (self._session.dir, u"-a", path, callback) else: args = (self._session.dir, path, callback) ftp_error._try_with_oserror(*args) return lines
def keep_alive(self): """ Try to keep the connection alive in order to avoid server timeouts. Note that this won't help if the connection has already timed out! In this case, `keep_alive` will raise an `TemporaryError`. (Actually, if you get a server timeout, the error - for a specific connection - will be permanent.) """ # Warning: Don't call this method on `FTPHost` instances which # represent file transfers. This may fail in confusing ways. ftp_error._try_with_oserror(self._session.pwd)
def __init__(self, *args, **kwargs): """Abstract initialization of `FTPHost` object.""" # Store arguments for later operations. self._args = args self._kwargs = kwargs #XXX Maybe put the following in a `reset` method. # The time shift setting shouldn't be reset though. # Make a session according to these arguments. self._session = self._make_session() # Simulate `os.path`. self.path = ftp_path._Path(self) # lstat, stat, listdir services. self._stat = ftp_stat._Stat(self) self.stat_cache = self._stat._lstat_cache self.stat_cache.enable() self._cached_current_dir = \ ftp_error._try_with_oserror(self._session.pwd) # Associated `FTPHost` objects for data transfer. self._children = [] # This is only set to something else than `None` if this # instance represents an `_FTPFile`. self._file = None # Now opened. self.closed = False # Set curdir, pardir etc. for the remote host. RFC 959 states # that this is, strictly speaking, dependent on the server OS # but it seems to work at least with Unix and Windows servers. self.curdir, self.pardir, self.sep = '.', '..', '/' # Set default time shift (used in `upload_if_newer` and # `download_if_newer`). self.set_time_shift(0.0) # Use `LIST -a` option by default. If this causes problems, # the user can set the attribute to `False`. self.use_list_a_option = True
def _check_list_a_option(self): """Check for support of the `-a` option for the `LIST` command. If the option is available, use it for all further directory listing requests. """ def callback(line): """Directory listing callback.""" pass # It seems that most servers just ignore unknown `LIST` # options instead of reacting with an error status. # In such a case, ftputil will subsequently use the `-a` # option even if it doesn't have any apparent effect. try: ftp_error._try_with_oserror(self._session.dir, u"-a", self.curdir, callback) except ftp_error.PermanentError: self._accepts_list_a_option = False else: self._accepts_list_a_option = True
def close(self): """Close host connection.""" if self.closed: return # Close associated children. for host in self._children: # Children have a `_file` attribute which is an `_FTPFile` object. host._file.close() host.close() # Now deal with ourself. try: ftp_error._try_with_oserror(self._session.close) finally: # If something went wrong before, the host/session is # probably defunct and subsequent calls to `close` won't # help either, so we consider the host/session closed for # practical purposes. self.stat_cache.clear() self._children = [] self.closed = True
def _make_session(self): """ Return a new session object according to the current state of this `FTPHost` instance. """ # Use copies of the arguments. args = self._args[:] kwargs = self._kwargs.copy() # If a session factory had been given on the instantiation of # this `FTPHost` object, use the same factory for this # `FTPHost` object's child sessions. factory = kwargs.pop('session_factory', ftplib.FTP) return ftp_error._try_with_oserror(factory, *args, **kwargs)
def rename(self, source, target): """Rename the source on the FTP host to target.""" # Fail early if we get a unicode path which can't be encoded. source = str(source) target = str(target) # The following code is in spirit similar to the code in the # method `_robust_ftp_command`, though we do _not_ do # _everything_ imaginable. self._check_inaccessible_login_directory() source_head, source_tail = self.path.split(source) target_head, target_tail = self.path.split(target) paths_contain_whitespace = (" " in source_head) or (" " in target_head) if paths_contain_whitespace and source_head == target_head: # Both items are in the same directory. old_dir = self.getcwd() try: self.chdir(source_head) ftp_error._try_with_oserror(self._session.rename, source_tail, target_tail) finally: self.chdir(old_dir) else: # Use straightforward command. ftp_error._try_with_oserror(self._session.rename, source, target)
def command(self, path): """Callback function.""" ftp_error._try_with_oserror(self._session.voidcmd, "SITE CHMOD %s %s" % (oct(mode), path))
def command(self, path): """Callback function.""" ftp_error._try_with_oserror(self._session.delete, path)
def command(self, path): """Callback function.""" return ftp_error._try_with_oserror(self._session.mkd, path)