def unpack_if_needed(destination_path, fpath):
    '''
    fpath is the fully qualified path to a single file that
    might be a ZIP / TGZ archive.

    The function moves the file, or the content if it is an
    archive, to the directory given by destination_path.

    The function returns two values. The first one is a 
    directory name if:

    - fpath is an archive.
    - The archive contains only one this single directory with
      arbitrary content.

    Otherwise, it is zero.

    This is helpful in catching the typical "right-click to compress"
    cases for single ZIP files in Explorer / Finder.

    The second return value is a boolean indicating if 
    fpath was an archive.

    '''
    single_dir = None
    did_unpack = False

    dircontent = os.listdir(destination_path)
    logger.debug("Content of %s before unarchiving: %s" %
                 (destination_path, str(dircontent)))

    # Perform un-archiving, in case
    if zipfile.is_zipfile(fpath):
        logger.debug("Detected ZIP file at %s, unpacking it." % (fpath))
        did_unpack = True
        with zipfile.ZipFile(fpath, "r") as zip:
            infolist = zip.infolist()
            directories = [
                entry.filename for entry in infolist if entry.filename.endswith('/')]
            logger.debug("List of directory entries: " + str(directories))

            # Consider this case: ['subdir1/', 'subdir1/subdir2/']
            if len(directories) > 1:
                redundant = []
                for current in directories:
                    starts_with_this = [
                        el for el in directories if el.startswith(current)]
                    if len(starts_with_this) == len(directories):
                        # current is a partial directory name that is contained
                        # in all others
                        redundant.append(current)
                logger.debug("Redundant directory entries: " + str(redundant))
                directories = [
                    entry for entry in directories if entry not in redundant]
                logger.debug(
                    "Updated list of directory entries: " + str(directories))

            files = [
                entry.filename for entry in infolist if not entry.filename.endswith('/')]
            logger.debug("List of files: " + str(files))
            if len(directories) == 1:
                d = directories[0]
                in_this_dir = [entry for entry in files if entry.startswith(d)]
                if len(files) == len(in_this_dir):
                    logger.debug("ZIP archive contains only one subdirectory")
                    single_dir = d
            zip.extractall(destination_path)
    elif tarfile.is_tarfile(fpath):
        logger.debug("Detected TAR file at %s, unpacking it." % (fpath))
        did_unpack = True
        with tarfile.open(fpath) as tar:
            infolist = tar.getmembers()
            # A TGZ file of one subdirectory with arbitrary files
            # has one infolist entry per directory and file
            directories = [entry.name for entry in infolist if entry.isdir()]
            files = [entry.name for entry in infolist if entry.isfile()]
            logger.debug(directories)
            logger.debug(files)
            if len(directories) == 1:
                d = directories[0]
                in_this_dir = [entry for entry in files if entry.startswith(d)]
                if len(files) == len(in_this_dir):
                    logger.debug("TGZ archive contains only one subdirectory")
                    single_dir = d
            tar.extractall(destination_path)
    else:
        if not fpath.startswith(destination_path):
            logger.debug(
                "File at %s is a single non-archive file, copying it to %s" % (fpath, destination_path))
            shutil.copy(fpath, destination_path)

    dircontent = os.listdir(destination_path)
    logger.debug("Content of %s after unarchiving: %s" %
                 (destination_path, str(dircontent)))
    return single_dir, did_unpack
def unpack_if_needed ( destination_path , fpath ) : single_dir = None did_unpack = False dircontent = os . listdir ( destination_path ) logger . debug ( "Content of %s before unarchiving: %s" % ( destination_path , str ( dircontent ) ) ) if zipfile . is_zipfile ( fpath ) : logger . debug ( "Detected ZIP file at %s, unpacking it." % ( fpath ) ) did_unpack = True with zipfile . ZipFile ( fpath , "r" ) as zip : infolist = zip . infolist ( ) directories = [ entry . filename for entry in infolist if entry . filename . endswith ( '/' ) ] logger . debug ( "List of directory entries: " + str ( directories ) ) if len ( directories ) > 1 : redundant = [ ] for current in directories : starts_with_this = [ el for el in directories if el . startswith ( current ) ] if len ( starts_with_this ) == len ( directories ) : redundant . append ( current ) logger . debug ( "Redundant directory entries: " + str ( redundant ) ) directories = [ entry for entry in directories if entry not in redundant ] logger . debug ( "Updated list of directory entries: " + str ( directories ) ) files = [ entry . filename for entry in infolist if not entry . filename . endswith ( '/' ) ] logger . debug ( "List of files: " + str ( files ) ) if len ( directories ) == 1 : d = directories [ 0 ] in_this_dir = [ entry for entry in files if entry . startswith ( d ) ] if len ( files ) == len ( in_this_dir ) : logger . debug ( "ZIP archive contains only one subdirectory" ) single_dir = d zip . extractall ( destination_path ) elif tarfile . is_tarfile ( fpath ) : logger . debug ( "Detected TAR file at %s, unpacking it." % ( fpath ) ) did_unpack = True with tarfile . open ( fpath ) as tar : infolist = tar . getmembers ( ) directories = [ entry . name for entry in infolist if entry . isdir ( ) ] files = [ entry . name for entry in infolist if entry . isfile ( ) ] logger . debug ( directories ) logger . debug ( files ) if len ( directories ) == 1 : d = directories [ 0 ] in_this_dir = [ entry for entry in files if entry . startswith ( d ) ] if len ( files ) == len ( in_this_dir ) : logger . debug ( "TGZ archive contains only one subdirectory" ) single_dir = d tar . extractall ( destination_path ) else : if not fpath . startswith ( destination_path ) : logger . debug ( "File at %s is a single non-archive file, copying it to %s" % ( fpath , destination_path ) ) shutil . copy ( fpath , destination_path ) dircontent = os . listdir ( destination_path ) logger . debug ( "Content of %s after unarchiving: %s" % ( destination_path , str ( dircontent ) ) ) return single_dir , did_unpack
fpath is the fully qualified path to a single file that
    might be a ZIP / TGZ archive.

    The function moves the file, or the content if it is an
    archive, to the directory given by destination_path.

    The function returns two values. The first one is a 
    directory name if:

    - fpath is an archive.
    - The archive contains only one this single directory with
      arbitrary content.

    Otherwise, it is zero.

    This is helpful in catching the typical "right-click to compress"
    cases for single ZIP files in Explorer / Finder.

    The second return value is a boolean indicating if 
    fpath was an archive.