'Method for extracting an archive file (e.g. zip, tar, tar.gz, 7z)
:param archive_path: absolute path to file to extract
:type archive_path: str
:param output_dir: **optional** absolute path to directory to extract to
:type output_dir: str
:param cls_name: name of Extractor/Compressor class to use
:type cls_name: str
:param password: **optional** password to use
:type password: str
:param kwargs: keyword arguments (e.g for special flags)
:returns True if successful, otherwise False'

def extract(self, archive_path, output_dir=None, cls_name=None, password=None, **kwargs):

    if (not os.path.isfile(archive_path)):
        self.err = 'invalid    archive_path    (file    does    not    exist):    {}'.format(archive_path)
        log.error(self.err)
        return False
    if output_dir:
        if (not os.path.exists(output_dir)):
            os.makedirs(output_dir)
            log.debug('creating    output    directory:    {}'.format(output_dir))
    else:
        output_dir = tempfile.mkdtemp(prefix='viper_tmp_')
        log.debug('created    output    directory:    {}'.format(output_dir))
    if cls_name:
        log.debug('Extractor    specified    by    caller')
        try:
            sub = self.extractors[cls_name]
        except KeyError:
            self.err = 'invalid    Extractor:    {}.    Check    for    missing    dependencies.'.format(cls_name)
            log.error(self.err)
            return False
    else:
        (_, ext) = self.auto_discover_ext(archive_path)
        if (not ext):
            self.err = 'unable    to    discover    extension'
            log.error(self.err)
            return False
        try:
            sub = self.extractors_by_extension[ext][0]
            if password:
                for item in self.extractors_by_extension[ext]:
                    if item.supports_password:
                        sub = item
                        break
                    else:
                        sub = self.extractors_by_extension[ext][0]
        except KeyError:
            self.err = 'no    available    Extractor    supports    extension:    {}.    Check    for    missing    dependencies.'.format(cls_name)
            log.error(self.err)
            return False
    sub.input_path = archive_path
    sub.output_path = output_dir
    if sub.supports_password:
        ret = sub.run(password=password, **kwargs)
    else:
        ret = sub.run(**kwargs)
    if ret:
        self.output_path = sub.output_path
        log.debug(self.output_path)
        return True
    else:
        self.err = sub.err
        log.error(self.err)
        return False
