def __construct_remote_paths(self, source, root_dest, remote_directories, 
                                local_remote_files):
        """Computes the directories and files that are to uploaded to remote 
        system.
        
        Arguments:
            source (str) - absolute path to the local source directory
            root_dest (str) - absolute path to the remote destination directory
            remote_directories (list) - list reference where the directories
                                        which has to created will be added
            local_remote_files (list) - list reference where a tuples of
                                        (localfile_path, remotefile_path)
                                        will be added
            root_dest_exists (boolean) - defaults to False; Set to True if dest
                                         exists at remote side

        Returns:
            The return values are append to the reference variables 
            i.e remote_directories and local_remote_files list
        """
        if local_isfile(source):
            root_dest = joinpath(root_dest, local_basename(source))
            local_remote_files.append((source, root_dest))
            return
        
        parent_dest_exists = root_dest_exists = False
        parent_path = root_dest
        
        if self.sftp.isdir(root_dest):
            parent_dest_exists = root_dest_exists = True
        
        for base_dir, _, files in local_walk(source):
            
            dest_dir = local_normpath(joinpath(root_dest,
                              base_dir.replace(source, '').strip(pathsep)))
            
            if root_dest_exists:
                new_parent_path = local_dirname(base_dir)
                if new_parent_path == parent_path and not parent_dest_exists:
                    remote_directories.append(dest_dir)
                else: 
                    parent_path = new_parent_path
                    if not self.sftp.exists(dest_dir):
                        parent_dest_exists = False
                        remote_directories.append(dest_dir)
                    elif not self.sftp.isdir(dest_dir):
                        msg = ''.join(["Copy aborted. Mismatch in file type ",
                                       "Local: '%s' Remote: '%s'" % (base_dir,
                                       dest_dir)])
                        raise RemoteDispatcherException(msg)
                    else:
                        parent_dest_exists = True
            else:
                remote_directories.append(local_normpath(dest_dir))
                
            local_remote_files.extend(\
                [(joinpath(base_dir, fname), \
                  joinpath(dest_dir, fname)) \
                 for fname in files])
    def __get_paths_source_pattern(self, source, dest):
        """Costructs the the remote directories and files to be created

        Arguments:
            source - local source pattern
            dest - remote destionation path
        
        Returns:
            Tuple ([dir1, dir2, ...], 
                   [(local_file_path1, remote_file_path1), 
                    (local_file_path1, remote_file_path2), ...])
        
        """
        
        remote_directories = deque()
        local_remote_files = deque()
        root_dest = dest
        
        # Get pattern matching files and directories
        source_list = glob.glob(source)

        if not source_list:
            raise RemoteDispatcherException("File or Directory not found: %s" 
                                            % (source))

        if not self.sftp.isdir(root_dest):
            remote_directories.append(root_dest)
        
        for lfile in source_list:
            # IF lfile is a directory then concatenated the dir-name with
            # remote path.
            if local_isdir(lfile):
                dest = joinpath(root_dest, local_basename(lfile))
            else:
                dest = root_dest

            self.__construct_remote_paths(lfile, dest, remote_directories,
                                         local_remote_files)

        return (remote_directories, local_remote_files)
    def __get_paths_source_dir(self, source, dest):
        """Costructs the the remote directories and files to be created

        Arguments:
            source - local source directory path
            dest - remote destionation path
        
        Returns:
            Tuple ([dir1, dir2, ...], 
                   [(local_file_path1, remote_file_path1), 
                    (local_file_path1, remote_file_path2), ...])
        
        """
        remote_directories = deque()
        local_remote_files = deque()
        
        if self.sftp.isdir(dest):
            dest = joinpath(dest, local_basename(source))
        
        self.__construct_remote_paths(source, dest, remote_directories,
                                      local_remote_files)
        return (remote_directories, local_remote_files)
 def scp(self, source, dest, recursive=False):
     """Copies a file[s] or directories between the local and remote host
     
     Arguments:
         source (str) -  absolute path to the source file or directory 
                         or a pattern
         dest (str) - remote absolute path
         recursive (boolean) - for copying recursively; should be enabled
                               in case of directory or more than 2 files
                               i.e pattern matched to be copied
     
     Actions:
         * Get list of directories and files need to uploaded to remote 
           system
         * Create remote directory skeleton
         * Upload the files to respective directories
     
     Returns:
         Exception if errors encountered
     """
     source = local_normpath(source)
     dest = local_normpath(dest)
     
     if local_isdir(source) or len(glob.glob(source)) > 1:
         if not recursive:
             # For copying more than one file recursive flag should be 
             # enabled.
             msg = "Please enable recursive argument to copy recursively"
             LOG.error(msg)
             raise RemoteDispatcherException(msg)
     
     # Establish the secure connection.
     self.connect()
     
     if local_isfile(source):
         (rdirs, lrfiles) = self.__get_paths_source_file(source, dest)
     elif local_isdir(source):
         (rdirs, lrfiles) = self.__get_paths_source_dir(source, dest)
     else:
         # else local_ispattern
         (rdirs, lrfiles) = self.__get_paths_source_pattern(source, dest)
     
     # Create directory skeleton
     for rdir in rdirs:
         try:
             LOG.debug(rdir)
             self.sftp.mkdir(rdir)
         except IOError:
             msg = "Couldn't create dest directory: '%s'" % (rdir)
             LOG.error(msg)
             raise RemoteDispatcherException(msg)
     
     # Upload the files
     for lfile, rfile in lrfiles:
         try:
             LOG.info("%s [%0.3f KB]" % \
                     (local_basename(lfile), 
                      local_getsize(lfile)/float(1024)))
             self.sftp.put(lfile, rfile)
         except IOError:
             msg = "Couldn't copy from local: '%s' to remote: '%s'" \
                   % (lfile, rfile)
             LOG.error(msg)
             raise RemoteDispatcherException(msg)