예제 #1
0
def extract_license_from_sdist(
    destination: Path,
    sdist: Path,
    license_directories: Dict[str, str],
    license_fallback_urls: Dict[str, str],
) -> None:
    def extract_from_source_tarfile(sdist: Path) -> bool:
        ext = sdist.suffixes[-1][1:]
        with tarfile.open(sdist, mode="r:{}".format(ext)) as tar:
            return find_and_extract_license(destination, tar, tar.getmembers(),
                                            license_directories)

    def extract_from_source_zipfile(sdist: Path) -> bool:
        with zipfile.ZipFile(sdist) as zip:
            return find_and_extract_license(destination, zip, zip.infolist(),
                                            license_directories)

    if sdist.suffixes[-2:-1] == [".tar"]:
        found = extract_from_source_tarfile(sdist)
    elif sdist.suffixes[-1] == ".zip":
        found = extract_from_source_zipfile(sdist)
    else:
        raise NotImplementedError("new sdist type!")

    if found:
        return

    UI.log("License not found in {}".format(sdist.name))
    get_license_fallback(destination, sdist.name, license_directories,
                         license_fallback_urls)
예제 #2
0
파일: update.py 프로젝트: jku/vendoring
def update_requirements(config: Configuration, package: Optional[str]) -> None:
    requirements = config.base_directory / config.requirements

    packages = parse_pinned_packages(requirements)
    for pkg in packages:
        if package is None or pkg.name == package:
            pkg.version = determine_latest_release(pkg.name)

    UI.log(f"Rewriting {requirements}")
    with requirements.open("w", encoding="utf-8") as f:
        f.writelines(f"{p}{linesep}" for p in packages)
예제 #3
0
def determine_latest_release(name: str) -> str:
    UI.log(f"Determining latest version for {name}...")

    try:
        r = requests.get(f"https://pypi.org/pypi/{name}/json")
        retval = str(r.json()["info"]["version"])
    except Exception as e:
        raise VendoringError(
            f"Could not determine latest version for {name}: {e!r}")

    UI.log(f"Got {retval}")
    return retval
예제 #4
0
def run(command: List[str], *, working_directory: Optional[Path]) -> None:
    UI.log("Running {}".format(" ".join(map(shlex.quote, command))))
    p = subprocess.Popen(
        command,
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        encoding="utf-8",
        cwd=working_directory,
    )
    while True:
        retcode = p.poll()
        line = p.stdout.readline().rstrip()

        if line:
            with UI.indent():
                UI.log(line)

        if retcode is not None:
            break
예제 #5
0
def extract_license_member(
    destination: Path,
    tar: SDistArchive,
    member: SDistMember,
    name: str,
    license_directories: Dict[str, str],
) -> None:
    mpath = Path(name)  # relative path inside the sdist

    dirname = list(mpath.parents)[-2].name  # -1 is .
    libname = libname_from_dir(dirname)

    dest = license_destination(destination, libname, mpath.name,
                               license_directories)

    UI.log("Extracting {} into {}".format(name, dest.relative_to(destination)))
    try:
        fileobj = tar.extractfile(member)  # type: ignore
        dest.write_bytes(fileobj.read())  # type: ignore
    except AttributeError:  # zipfile
        dest.write_bytes(tar.read(member))  # type: ignore
예제 #6
0
def find_and_extract_license(
    destination: Path,
    tar: SDistArchive,
    members: Iterable[SDistMember],
    license_directories: Dict[str, str],
) -> bool:
    found = False
    for member in members:
        try:
            license_directories,
            name = member.name  # type: ignore
        except AttributeError:  # zipfile
            name = member.filename  # type: ignore
        if "LICENSE" in name or "COPYING" in name:
            if "/test" in name:
                # some testing licenses in html5lib and distlib
                UI.log("Ignoring {}".format(name))
                continue
            found = True
            extract_license_member(destination, tar, member, name,
                                   license_directories)
    return found
예제 #7
0
def run(command: List[str], *, working_directory: Optional[Path]) -> None:
    cmd = " ".join(map(shlex.quote, command))
    UI.log(f"Running {cmd}")
    p = subprocess.Popen(
        command,
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        encoding="utf-8",
        cwd=working_directory,
    )
    while True:
        retcode = p.poll()
        line = p.stdout.readline().rstrip()

        if line:
            with UI.indent():
                UI.log(line)

        if retcode is not None:
            break
    if retcode:
        raise VendoringError(
            f"Command exited with non-zero exit code: {retcode}")
예제 #8
0
def load_configuration(directory: Path) -> Configuration:
    # Read the contents of the file.
    file = directory / "pyproject.toml"
    UI.log(f"Will attempt to load {file}.")

    try:
        file_contents = file.read_text(encoding="utf8")
    except IOError as read_error:
        raise ConfigurationError(
            "Could not read pyproject.toml.") from read_error
    else:
        UI.log("Read configuration file.")

    try:
        parsed_contents = parse_toml(file_contents)
    except TomlDecodeError as toml_error:
        raise ConfigurationError(
            "Could not parse pyproject.toml.") from toml_error
    else:
        UI.log("Parsed configuration file.")

    if ("tool" not in parsed_contents
            or not isinstance(parsed_contents["tool"], dict)
            or "vendoring" not in parsed_contents["tool"]
            or not isinstance(parsed_contents["tool"]["vendoring"], dict)):
        raise ConfigurationError(
            "Can not load `tool.vendoring` from pyproject.toml")

    tool_config = parsed_contents["tool"]["vendoring"]

    try:
        retval = Configuration.load_from_dict(tool_config, location=directory)
    except ConfigurationError as e:
        raise ConfigurationError(
            "Could not load values from [tool.vendoring] in pyproject.toml.\n"
            f"  REASON: {e}")
    else:
        UI.log("Validated configuration.")
        return retval
예제 #9
0
def download_url(url: str, dest: Path) -> None:
    UI.log("Downloading {}".format(url))
    r = requests.get(url, allow_redirects=True)
    r.raise_for_status()
    dest.write_bytes(r.content)