Skip to content

Vendor pip 25.0.1 #6343

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pipenv/patched/patched.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
pip==24.3.1
pip==25.0.1
safety==2.3.2
2 changes: 1 addition & 1 deletion pipenv/patched/pip/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import List, Optional

__version__ = "24.3.1"
__version__ = "25.0.1"


def main(args: Optional[List[str]] = None) -> int:
Expand Down
9 changes: 6 additions & 3 deletions pipenv/patched/pip/_internal/build_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
from types import TracebackType
from typing import TYPE_CHECKING, Iterable, List, Optional, Set, Tuple, Type, Union

from pipenv.patched.pip._vendor.certifi import where
from pipenv.patched.pip._vendor.packaging.version import Version

from pipenv.patched.pip import __file__ as pip_location
Expand Down Expand Up @@ -270,21 +269,25 @@ def _install_requirements(
for link in finder.find_links:
args.extend(["--find-links", link])

if finder.proxy:
args.extend(["--proxy", finder.proxy])
for host in finder.trusted_hosts:
args.extend(["--trusted-host", host])
if finder.custom_cert:
args.extend(["--cert", finder.custom_cert])
if finder.client_cert:
args.extend(["--client-cert", finder.client_cert])
if finder.allow_all_prereleases:
args.append("--pre")
if finder.prefer_binary:
args.append("--prefer-binary")
args.append("--")
args.extend(requirements)
extra_environ = {"_PIP_STANDALONE_CERT": where()}
with open_spinner(f"Installing {kind}") as spinner:
call_subprocess(
args,
command_desc=f"pip subprocess to install {kind}",
spinner=spinner,
extra_environ=extra_environ,
)


Expand Down
9 changes: 9 additions & 0 deletions pipenv/patched/pip/_internal/cli/base_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
NetworkConnectionError,
PreviousBuildDirError,
)
from pipenv.patched.pip._internal.utils.deprecation import deprecated
from pipenv.patched.pip._internal.utils.filesystem import check_path_owner
from pipenv.patched.pip._internal.utils.logging import BrokenStdoutLoggingError, setup_logging
from pipenv.patched.pip._internal.utils.misc import get_prog, normalize_path
Expand Down Expand Up @@ -228,4 +229,12 @@ def _main(self, args: List[str]) -> int:
)
options.cache_dir = None

if options.no_python_version_warning:
deprecated(
reason="--no-python-version-warning is deprecated.",
replacement="to remove the flag as it's a no-op",
gone_in="25.1",
issue=13154,
)

return self._run_wrapper(level_number, options, args)
4 changes: 2 additions & 2 deletions pipenv/patched/pip/_internal/cli/cmdoptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,8 @@ class PipOption(Option):
default="auto",
help=(
"Enable the credential lookup via the keyring library if user input is allowed."
" Specify which mechanism to use [disabled, import, subprocess]."
" (default: disabled)"
" Specify which mechanism to use [auto, disabled, import, subprocess]."
" (default: %default)"
),
)

Expand Down
1 change: 1 addition & 0 deletions pipenv/patched/pip/_internal/cli/index_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ def _build_session(
"https": options.proxy,
}
session.trust_env = False
session.pip_proxy = options.proxy

# Determine if we can prompt the user for authentication or not
session.auth.prompting = not options.no_input
Expand Down
2 changes: 1 addition & 1 deletion pipenv/patched/pip/_internal/cli/progress_bars.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def _raw_progress_bar(
size: Optional[int],
) -> Generator[bytes, None, None]:
def write_progress(current: int, total: int) -> None:
sys.stdout.write("Progress %d of %d\n" % (current, total))
sys.stdout.write(f"Progress {current} of {total}\n")
sys.stdout.flush()

current = 0
Expand Down
5 changes: 4 additions & 1 deletion pipenv/patched/pip/_internal/commands/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from pipenv.patched.pip._internal.exceptions import CommandError, PipError
from pipenv.patched.pip._internal.utils import filesystem
from pipenv.patched.pip._internal.utils.logging import getLogger
from pipenv.patched.pip._internal.utils.misc import format_size

logger = getLogger(__name__)

Expand Down Expand Up @@ -180,10 +181,12 @@ def remove_cache_items(self, options: Values, args: List[Any]) -> None:
if not files:
logger.warning(no_matching_msg)

bytes_removed = 0
for filename in files:
bytes_removed += os.stat(filename).st_size
os.unlink(filename)
logger.verbose("Removed %s", filename)
logger.info("Files removed: %s", len(files))
logger.info("Files removed: %s (%s)", len(files), format_size(bytes_removed))

def purge_cache(self, options: Values, args: List[Any]) -> None:
if args:
Expand Down
15 changes: 8 additions & 7 deletions pipenv/patched/pip/_internal/commands/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@
from pipenv.patched.pip._vendor.packaging.utils import canonicalize_name
from pipenv.patched.pip._vendor.rich import print_json

# Eagerly import self_outdated_check to avoid crashes. Otherwise,
# this module would be imported *after* pip was replaced, resulting
# in crashes if the new self_outdated_check module was incompatible
# with the rest of pip that's already imported, or allowing a
# wheel to execute arbitrary code on install by replacing
# self_outdated_check.
import pipenv.patched.pip._internal.self_outdated_check # noqa: F401
from pipenv.patched.pip._internal.cache import WheelCache
from pipenv.patched.pip._internal.cli import cmdoptions
from pipenv.patched.pip._internal.cli.cmdoptions import make_target_python
Expand Down Expand Up @@ -408,12 +415,6 @@ def run(self, options: Values, args: List[str]) -> int:
# If we're not replacing an already installed pip,
# we're not modifying it.
modifying_pip = pip_req.satisfied_by is None
if modifying_pip:
# Eagerly import this module to avoid crashes. Otherwise, this
# module would be imported *after* pip was replaced, resulting in
# crashes if the new self_outdated_check module was incompatible
# with the rest of pip that's already imported.
import pipenv.patched.pip._internal.self_outdated_check # noqa: F401
protect_pip_from_modification_on_windows(modifying_pip=modifying_pip)

reqs_to_build = [
Expand All @@ -432,7 +433,7 @@ def run(self, options: Values, args: List[str]) -> int:

if build_failures:
raise InstallationError(
"ERROR: Failed to build installable wheels for some "
"Failed to build installable wheels for some "
"pyproject.toml based projects ({})".format(
", ".join(r.name for r in build_failures) # type: ignore
)
Expand Down
9 changes: 8 additions & 1 deletion pipenv/patched/pip/_internal/commands/show.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class _PackageInfo(NamedTuple):
author: str
author_email: str
license: str
license_expression: str
entry_points: List[str]
files: Optional[List[str]]

Expand Down Expand Up @@ -161,6 +162,7 @@ def _get_requiring_packages(current_dist: BaseDistribution) -> Iterator[str]:
author=metadata.get("Author", ""),
author_email=metadata.get("Author-email", ""),
license=metadata.get("License", ""),
license_expression=metadata.get("License-Expression", ""),
entry_points=entry_points,
files=files,
)
Expand All @@ -180,13 +182,18 @@ def print_results(
if i > 0:
write_output("---")

metadata_version_tuple = tuple(map(int, dist.metadata_version.split(".")))

write_output("Name: %s", dist.name)
write_output("Version: %s", dist.version)
write_output("Summary: %s", dist.summary)
write_output("Home-page: %s", dist.homepage)
write_output("Author: %s", dist.author)
write_output("Author-email: %s", dist.author_email)
write_output("License: %s", dist.license)
if metadata_version_tuple >= (2, 4) and dist.license_expression:
write_output("License-Expression: %s", dist.license_expression)
else:
write_output("License: %s", dist.license)
write_output("Location: %s", dist.location)
if dist.editable_project_location is not None:
write_output(
Expand Down
2 changes: 1 addition & 1 deletion pipenv/patched/pip/_internal/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ def iter_config_files(self) -> Iterable[Tuple[Kind, List[str]]]:
This should be treated like items of a dictionary. The order
here doesn't affect what gets overridden. That is controlled
by OVERRIDE_ORDER. However this does control the order they are
displayed to the user. It's probably most ergononmic to display
displayed to the user. It's probably most ergonomic to display
things in the same order as OVERRIDE_ORDER
"""
# SMELL: Move the conditions out of this function
Expand Down
73 changes: 41 additions & 32 deletions pipenv/patched/pip/_internal/index/package_finder.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,44 +338,30 @@ class CandidatePreferences:
allow_all_prereleases: bool = False


@dataclass(frozen=True)
class BestCandidateResult:
"""A collection of candidates, returned by `PackageFinder.find_best_candidate`.

This class is only intended to be instantiated by CandidateEvaluator's
`compute_best_candidate()` method.
"""

def __init__(
self,
candidates: List[InstallationCandidate],
applicable_candidates: List[InstallationCandidate],
best_candidate: Optional[InstallationCandidate],
) -> None:
"""
:param candidates: A sequence of all available candidates found.
:param applicable_candidates: The applicable candidates.
:param best_candidate: The most preferred candidate found, or None
if no applicable candidates were found.
"""
assert set(applicable_candidates) <= set(candidates)

if best_candidate is None:
assert not applicable_candidates
else:
assert best_candidate in applicable_candidates

self._applicable_candidates = applicable_candidates
self._candidates = candidates
:param all_candidates: A sequence of all available candidates found.
:param applicable_candidates: The applicable candidates.
:param best_candidate: The most preferred candidate found, or None
if no applicable candidates were found.
"""

self.best_candidate = best_candidate
all_candidates: List[InstallationCandidate]
applicable_candidates: List[InstallationCandidate]
best_candidate: Optional[InstallationCandidate]

def iter_all(self) -> Iterable[InstallationCandidate]:
"""Iterate through all candidates."""
return iter(self._candidates)
def __post_init__(self) -> None:
assert set(self.applicable_candidates) <= set(self.all_candidates)

def iter_applicable(self) -> Iterable[InstallationCandidate]:
"""Iterate through the applicable candidates."""
return iter(self._applicable_candidates)
if self.best_candidate is None:
assert not self.applicable_candidates
else:
assert self.best_candidate in self.applicable_candidates


class CandidateEvaluator:
Expand Down Expand Up @@ -687,11 +673,29 @@ def find_links(self) -> List[str]:
def index_urls(self) -> List[str]:
return self.search_scope.index_urls

@property
def proxy(self) -> Optional[str]:
return self._link_collector.session.pip_proxy

@property
def trusted_hosts(self) -> Iterable[str]:
for host_port in self._link_collector.session.pip_trusted_origins:
yield build_netloc(*host_port)

@property
def custom_cert(self) -> Optional[str]:
# session.verify is either a boolean (use default bundle/no SSL
# verification) or a string path to a custom CA bundle to use. We only
# care about the latter.
verify = self._link_collector.session.verify
return verify if isinstance(verify, str) else None

@property
def client_cert(self) -> Optional[str]:
cert = self._link_collector.session.cert
assert not isinstance(cert, tuple), "pip only supports PEM client certs"
return cert

@property
def allow_all_prereleases(self) -> bool:
return self._candidate_prefs.allow_all_prereleases
Expand Down Expand Up @@ -745,6 +749,11 @@ def _sort_links(self, links: Iterable[Link]) -> List[Link]:
return no_eggs + eggs

def _log_skipped_link(self, link: Link, result: LinkType, detail: str) -> None:
# This is a hot method so don't waste time hashing links unless we're
# actually going to log 'em.
if not logger.isEnabledFor(logging.DEBUG):
return

entry = (link, result, detail)
if entry not in self._logged_links:
# Put the link at the end so the reason is more visible and because
Expand Down Expand Up @@ -942,7 +951,7 @@ def _format_versions(cand_iter: Iterable[InstallationCandidate]) -> str:
"Could not find a version that satisfies the requirement %s "
"(from versions: %s)",
req,
_format_versions(best_candidate_result.iter_all()),
_format_versions(best_candidate_result.all_candidates),
)

raise DistributionNotFound(f"No matching distribution found for {req}")
Expand Down Expand Up @@ -976,15 +985,15 @@ def _should_install_candidate(
logger.debug(
"Using version %s (newest of versions: %s)",
best_candidate.version,
_format_versions(best_candidate_result.iter_applicable()),
_format_versions(best_candidate_result.applicable_candidates),
)
return best_candidate

# We have an existing version, and its the best version
logger.debug(
"Installed version (%s) is most up-to-date (past versions: %s)",
installed_version,
_format_versions(best_candidate_result.iter_applicable()),
_format_versions(best_candidate_result.applicable_candidates),
)
raise BestVersionAlreadyInstalled

Expand Down
4 changes: 2 additions & 2 deletions pipenv/patched/pip/_internal/metadata/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def _should_use_importlib_metadata() -> bool:
"""Whether to use the ``importlib.metadata`` or ``pkg_resources`` backend.

By default, pip uses ``importlib.metadata`` on Python 3.11+, and
``pkg_resourcess`` otherwise. This can be overridden by a couple of ways:
``pkg_resources`` otherwise. This can be overridden by a couple of ways:

* If environment variable ``_PIP_USE_IMPORTLIB_METADATA`` is set, it
dictates whether ``importlib.metadata`` is used, regardless of Python
Expand Down Expand Up @@ -71,7 +71,7 @@ def get_default_environment() -> BaseEnvironment:

This returns an Environment instance from the chosen backend. The default
Environment instance should be built from ``sys.path`` and may use caching
to share instance state accorss calls.
to share instance state across calls.
"""
return select_backend().Environment.default()

Expand Down
2 changes: 2 additions & 0 deletions pipenv/patched/pip/_internal/metadata/_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
("Maintainer", False),
("Maintainer-email", False),
("License", False),
("License-Expression", False),
("License-File", True),
("Classifier", True),
("Requires-Dist", True),
("Requires-Python", False),
Expand Down
9 changes: 8 additions & 1 deletion pipenv/patched/pip/_internal/metadata/importlib/_dists.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import importlib.metadata
import pathlib
import zipfile
from os import PathLike
from typing import (
Collection,
Dict,
Expand All @@ -10,6 +11,7 @@
Mapping,
Optional,
Sequence,
Union,
cast,
)

Expand Down Expand Up @@ -95,6 +97,11 @@ def read_text(self, filename: str) -> Optional[str]:
raise UnsupportedWheel(error)
return text

def locate_file(self, path: Union[str, "PathLike[str]"]) -> pathlib.Path:
# This method doesn't make sense for our in-memory wheel, but the API
# requires us to define it.
raise NotImplementedError


class Distribution(BaseDistribution):
def __init__(
Expand Down Expand Up @@ -190,7 +197,7 @@ def read_text(self, path: InfoPath) -> str:
return content

def iter_entry_points(self) -> Iterable[BaseEntryPoint]:
# importlib.metadata's EntryPoint structure sasitfies BaseEntryPoint.
# importlib.metadata's EntryPoint structure satisfies BaseEntryPoint.
return self._dist.entry_points

def _metadata_impl(self) -> email.message.Message:
Expand Down
Loading
Loading