Source code for hfutils.archive.base

import os.path
import warnings
from typing import List, Dict, Tuple, Callable, Optional

_KNOWN_ARCHIVE_TYPES: Dict[str, Tuple[List[str], Callable, Callable]] = {}


[docs]def register_archive_type(name: str, exts: List[str], fn_pack: Callable, fn_unpack: Callable): """ Register a custom archive type with associated file extensions and packing/unpacking functions. :param name: The name of the archive type. :type name: str :param exts: A list of file extensions associated with the archive type. :type exts: List[str] :param fn_pack: The packing function that takes a directory and an archive filename as input and creates an archive. :type fn_pack: Callable :param fn_unpack: The unpacking function that takes an archive filename and a directory as input and extracts the archive. :type fn_unpack: Callable """ if len(exts) == 0: raise ValueError(f'At least one extension name for archive type {name!r} should be provided.') _KNOWN_ARCHIVE_TYPES[name] = (exts, fn_pack, fn_unpack)
[docs]def get_archive_extname(type_name: str) -> str: """ Get the file extension associated with a registered archive type. :param type_name: The name of the archive type. :type type_name: str :return: The file extension associated with the archive type. :rtype: str :raises ValueError: If the archive type is not registered. """ if type_name in _KNOWN_ARCHIVE_TYPES: exts, _, _ = _KNOWN_ARCHIVE_TYPES[type_name] return exts[0] else: raise ValueError(f'Unknown archive type - {type_name!r}.')
[docs]def archive_pack(type_name: str, directory: str, archive_file: str, silent: bool = False): """ Pack a directory into an archive file using the specified archive type. :param type_name: The name of the archive type. :type type_name: str :param directory: The directory to pack. :type directory: str :param archive_file: The filename of the resulting archive. :type archive_file: str :param silent: If True, suppress warnings during the packing process. :type silent: bool :return: The path to the created archive file. :rtype: str """ exts, fn_pack, _ = _KNOWN_ARCHIVE_TYPES[type_name] if not any(os.path.normcase(archive_file).endswith(extname) for extname in exts): warnings.warn(f'The archive type {type_name!r} should be one of the {exts!r}, ' f'but file name {archive_file!r} is assigned. ' f'We strongly recommend using a regular extension name for the archive file.') return fn_pack(directory, archive_file, silent=silent)
[docs]def get_archive_type(archive_file: str) -> str: """ Determine the archive type based on the file extension. :param archive_file: The filename of the archive. :type archive_file: str :return: The name of the archive type. :rtype: str :raises ValueError: If the file extension is not associated with any registered archive type. """ archive_file = os.path.normcase(archive_file) for type_name, (exts, _, _) in _KNOWN_ARCHIVE_TYPES.items(): if any(archive_file.endswith(extname) for extname in exts): return type_name raise ValueError(f'Unknown type of archive file {archive_file!r}.')
[docs]def archive_unpack(archive_file: str, directory: str, silent: bool = False, password: Optional[str] = None): """ Unpack an archive file into a directory using the specified archive type. :param archive_file: The filename of the archive. :type archive_file: str :param directory: The directory to unpack the contents into. :type directory: str :param silent: If True, suppress warnings during the unpacking process. :type silent: bool :param password: The password to extract the archive file. :type password: str, optional :return: The path to the unpacked directory. :rtype: str """ type_name = get_archive_type(archive_file) _, _, fn_unpack = _KNOWN_ARCHIVE_TYPES[type_name] return fn_unpack(archive_file, directory, silent=silent, password=password)