
--boundary_.oOo._Rx9OhzP9R2kL7JjQ74D1irDIsu1evu/J
Content-Length: 3227
Content-Type: application/octet-stream
X-File-MD5: b488f4095cd70842483dc8d9cf8982e9
X-File-Mtime: 1722745340
X-File-Path: /@software_development/apps/python/flappy_bird/venv/lib/python3.9/site-packages/pip/_internal/operations/build/wheel_legacy.py

import logging
import os.path
from typing import List, Optional

from pip._internal.cli.spinners import open_spinner
from pip._internal.utils.setuptools_build import make_setuptools_bdist_wheel_args
from pip._internal.utils.subprocess import (
    LOG_DIVIDER,
    call_subprocess,
    format_command_args,
)

logger = logging.getLogger(__name__)


def format_command_result(
    command_args,  # type: List[str]
    command_output,  # type: str
):
    # type: (...) -> str
    """Format command information for logging."""
    command_desc = format_command_args(command_args)
    text = f'Command arguments: {command_desc}\n'

    if not command_output:
        text += 'Command output: None'
    elif logger.getEffectiveLevel() > logging.DEBUG:
        text += 'Command output: [use --verbose to show]'
    else:
        if not command_output.endswith('\n'):
            command_output += '\n'
        text += f'Command output:\n{command_output}{LOG_DIVIDER}'

    return text


def get_legacy_build_wheel_path(
    names,  # type: List[str]
    temp_dir,  # type: str
    name,  # type: str
    command_args,  # type: List[str]
    command_output,  # type: str
):
    # type: (...) -> Optional[str]
    """Return the path to the wheel in the temporary build directory."""
    # Sort for determinism.
    names = sorted(names)
    if not names:
        msg = (
            'Legacy build of wheel for {!r} created no files.\n'
        ).format(name)
        msg += format_command_result(command_args, command_output)
        logger.warning(msg)
        return None

    if len(names) > 1:
        msg = (
            'Legacy build of wheel for {!r} created more than one file.\n'
            'Filenames (choosing first): {}\n'
        ).format(name, names)
        msg += format_command_result(command_args, command_output)
        logger.warning(msg)

    return os.path.join(temp_dir, names[0])


def build_wheel_legacy(
    name,  # type: str
    setup_py_path,  # type: str
    source_dir,  # type: str
    global_options,  # type: List[str]
    build_options,  # type: List[str]
    tempd,  # type: str
):
    # type: (...) -> Optional[str]
    """Build one unpacked package using the "legacy" build process.

    Returns path to wheel if successfully built. Otherwise, returns None.
    """
    wheel_args = make_setuptools_bdist_wheel_args(
        setup_py_path,
        global_options=global_options,
        build_options=build_options,
        destination_dir=tempd,
    )

    spin_message = f'Building wheel for {name} (setup.py)'
    with open_spinner(spin_message) as spinner:
        logger.debug('Destination directory: %s', tempd)

        try:
            output = call_subprocess(
                wheel_args,
                cwd=source_dir,
                spinner=spinner,
            )
        except Exception:
            spinner.finish("error")
            logger.error('Failed building wheel for %s', name)
            return None

        names = os.listdir(tempd)
        wheel_path = get_legacy_build_wheel_path(
            names=names,
            temp_dir=tempd,
            name=name,
            command_args=wheel_args,
            command_output=output,
        )
        return wheel_path

--boundary_.oOo._Rx9OhzP9R2kL7JjQ74D1irDIsu1evu/J
Content-Length: 5295
Content-Type: application/octet-stream
X-File-MD5: cf10d164386ef711d2628a07b759e15c
X-File-Mtime: 1722745340
X-File-Path: /@software_development/apps/python/flappy_bird/venv/lib/python3.9/site-packages/pip/_internal/operations/check.py

"""Validation of dependencies of packages
"""

import logging
from typing import TYPE_CHECKING, Callable, Dict, List, NamedTuple, Optional, Set, Tuple

from pip._vendor.packaging.requirements import Requirement
from pip._vendor.packaging.utils import canonicalize_name

from pip._internal.distributions import make_distribution_for_install_requirement
from pip._internal.metadata import get_default_environment
from pip._internal.metadata.base import DistributionVersion
from pip._internal.req.req_install import InstallRequirement

if TYPE_CHECKING:
    from pip._vendor.packaging.utils import NormalizedName

logger = logging.getLogger(__name__)


class PackageDetails(NamedTuple):
    version: DistributionVersion
    dependencies: List[Requirement]


# Shorthands
PackageSet = Dict['NormalizedName', PackageDetails]
Missing = Tuple['NormalizedName', Requirement]
Conflicting = Tuple['NormalizedName', DistributionVersion, Requirement]

MissingDict = Dict['NormalizedName', List[Missing]]
ConflictingDict = Dict['NormalizedName', List[Conflicting]]
CheckResult = Tuple[MissingDict, ConflictingDict]
ConflictDetails = Tuple[PackageSet, CheckResult]


def create_package_set_from_installed() -> Tuple[PackageSet, bool]:
    """Converts a list of distributions into a PackageSet."""
    package_set = {}
    problems = False
    env = get_default_environment()
    for dist in env.iter_installed_distributions(local_only=False, skip=()):
        name = dist.canonical_name
        try:
            dependencies = list(dist.iter_dependencies())
            package_set[name] = PackageDetails(dist.version, dependencies)
        except (OSError, ValueError) as e:
            # Don't crash on unreadable or broken metadata.
            logger.warning("Error parsing requirements for %s: %s", name, e)
            problems = True
    return package_set, problems


def check_package_set(package_set, should_ignore=None):
    # type: (PackageSet, Optional[Callable[[str], bool]]) -> CheckResult
    """Check if a package set is consistent

    If should_ignore is passed, it should be a callable that takes a
    package name and returns a boolean.
    """

    missing = {}
    conflicting = {}

    for package_name, package_detail in package_set.items():
        # Info about dependencies of package_name
        missing_deps = set()  # type: Set[Missing]
        conflicting_deps = set()  # type: Set[Conflicting]

        if should_ignore and should_ignore(package_name):
            continue

        for req in package_detail.dependencies:
            name = canonicalize_name(req.name)

            # Check if it's missing
            if name not in package_set:
                missed = True
                if req.marker is not None:
                    missed = req.marker.evaluate()
                if missed:
                    missing_deps.add((name, req))
                continue

            # Check if there's a conflict
            version = package_set[name].version
            if not req.specifier.contains(version, prereleases=True):
                conflicting_deps.add((name, version, req))

        if missing_deps:
            missing[package_name] = sorted(missing_deps, key=str)
        if conflicting_deps:
            conflicting[package_name] = sorted(conflicting_deps, key=str)

    return missing, conflicting


def check_install_conflicts(to_install):
    # type: (List[InstallRequirement]) -> ConflictDetails
    """For checking if the dependency graph would be consistent after \
    installing given requirements
    """
    # Start from the current state
    package_set, _ = create_package_set_from_installed()
    # Install packages
    would_be_installed = _simulate_installation_of(to_install, package_set)

    # Only warn about directly-dependent packages; create a whitelist of them
    whitelist = _create_whitelist(would_be_installed, package_set)

    return (
        package_set,
        check_package_set(
            package_set, should_ignore=lambda name: name not in whitelist
        )
    )


def _simulate_installation_of(to_install, package_set):
    # type: (List[InstallRequirement], PackageSet) -> Set[NormalizedName]
    """Computes the version of packages after installing to_install.
    """
    # Keep track of packages that were installed
    installed =