imanhodjaev/pycran

View on GitHub
pycran/util.py

Summary

Maintainability
A
25 mins
Test Coverage
import tarfile
from os import path

from pycran.errors import DescriptionNotFound, NotTarFile
from pycran.typings import BytesOrString, PathOrTarFile


def as_string(meta_line: BytesOrString) -> str:
    """Convert bytes to string
    Args:
        meta_line (BytesOrString): raw metadata
    Returns:
        (str): string version of `meta_line`
    """
    if isinstance(meta_line, bytes):
        return meta_line.decode("utf-8")

    return meta_line


def read_description(archive: PathOrTarFile) -> str:
    """Convert bytes to string
    Args:
        archive (PathOrTarFile): path to archive or `TarFile` instance

    Returns:
        (str): contents of description file
    """
    if isinstance(archive, str):
        if not path.exists(archive):
            raise FileNotFoundError(f"File {archive} does not exist.")

        if not tarfile.is_tarfile(archive):
            raise NotTarFile(f"File {archive} is not a tar archive.")

        tar: tarfile.TarFile = tarfile.open(archive)
    else:
        tar = archive

    with tar:
        description: tarfile.TarInfo = tar.getmember(get_description_path(tar))
        with tar.fileobject(tar, description) as metadata:  # type: ignore
            return metadata.read()


def get_description_path(tar: tarfile.TarFile) -> str:
    """Lookup description file
    Args:
        tar (tarfile.TarFile): `tarfile.TarFile` instance

    Returns:
        (str): path to description file
    """
    for info in tar.getmembers():
        if "DESCRIPTION" in info.name:
            return info.name

    raise DescriptionNotFound("Description file not found.")