Skip to content
Merged
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.1.2
pip==24.2
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.1.2"
__version__ = "24.2"


def main(args: Optional[List[str]] = None) -> int:
Expand Down
5 changes: 3 additions & 2 deletions pipenv/patched/pip/_internal/build_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@
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.requirements import Requirement
from pipenv.patched.pip._vendor.packaging.version import Version

from pipenv.patched.pip import __file__ as pip_location
from pipenv.patched.pip._internal.cli.spinners import open_spinner
from pipenv.patched.pip._internal.locations import get_platlib, get_purelib, get_scheme
from pipenv.patched.pip._internal.metadata import get_default_environment, get_environment
from pipenv.patched.pip._internal.utils.logging import VERBOSE
from pipenv.patched.pip._internal.utils.packaging import get_requirement
from pipenv.patched.pip._internal.utils.subprocess import call_subprocess
from pipenv.patched.pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds

Expand Down Expand Up @@ -184,7 +184,7 @@ def check_requirements(
else get_default_environment()
)
for req_str in reqs:
req = Requirement(req_str)
req = get_requirement(req_str)
# We're explicitly evaluating with an empty extra value, since build
# environments are not provided any mechanism to select specific extras.
if req.marker is not None and not req.marker.evaluate({"extra": ""}):
Expand Down Expand Up @@ -241,6 +241,7 @@ def _install_requirements(
"--prefix",
prefix.path,
"--no-warn-script-location",
"--disable-pip-version-check",
]
if logger.getEffectiveLevel() <= logging.DEBUG:
args.append("-vv")
Expand Down
125 changes: 61 additions & 64 deletions pipenv/patched/pip/_internal/cli/base_command.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
"""Base Command class, and related routines"""

import functools
import logging
import logging.config
import optparse
import os
import sys
import traceback
from optparse import Values
from typing import Any, Callable, List, Optional, Tuple
from typing import List, Optional, Tuple

from pipenv.patched.pip._vendor.rich import reconfigure
from pipenv.patched.pip._vendor.rich import traceback as rich_traceback

from pipenv.patched.pip._internal.cli import cmdoptions
Expand Down Expand Up @@ -90,6 +90,63 @@ def handle_pip_version_check(self, options: Values) -> None:
def run(self, options: Values, args: List[str]) -> int:
raise NotImplementedError

def _run_wrapper(self, level_number: int, options: Values, args: List[str]) -> int:
def _inner_run() -> int:
try:
return self.run(options, args)
finally:
self.handle_pip_version_check(options)

if options.debug_mode:
rich_traceback.install(show_locals=True)
return _inner_run()

try:
status = _inner_run()
assert isinstance(status, int)
return status
except DiagnosticPipError as exc:
logger.error("%s", exc, extra={"rich": True})
logger.debug("Exception information:", exc_info=True)

return ERROR
except PreviousBuildDirError as exc:
logger.critical(str(exc))
logger.debug("Exception information:", exc_info=True)

return PREVIOUS_BUILD_DIR_ERROR
except (
InstallationError,
BadCommand,
NetworkConnectionError,
) as exc:
logger.critical(str(exc))
logger.debug("Exception information:", exc_info=True)

return ERROR
except CommandError as exc:
logger.critical("%s", exc)
logger.debug("Exception information:", exc_info=True)

return ERROR
except BrokenStdoutLoggingError:
# Bypass our logger and write any remaining messages to
# stderr because stdout no longer works.
print("ERROR: Pipe to stdout was broken", file=sys.stderr)
if level_number <= logging.DEBUG:
traceback.print_exc(file=sys.stderr)

return ERROR
except KeyboardInterrupt:
logger.critical("Operation cancelled by user")
logger.debug("Exception information:", exc_info=True)

return ERROR
except BaseException:
logger.critical("Exception:", exc_info=True)

return UNKNOWN_ERROR

def parse_args(self, args: List[str]) -> Tuple[Values, List[str]]:
# factored out for testability
return self.parser.parse_args(args)
Expand All @@ -115,6 +172,7 @@ def _main(self, args: List[str]) -> int:
# Set verbosity so that it can be used elsewhere.
self.verbosity = options.verbose - options.quiet

reconfigure(no_color=options.no_color)
level_number = setup_logging(
verbosity=self.verbosity,
no_color=options.no_color,
Expand Down Expand Up @@ -170,65 +228,4 @@ def _main(self, args: List[str]) -> int:
)
options.cache_dir = None

def intercepts_unhandled_exc(
run_func: Callable[..., int]
) -> Callable[..., int]:
@functools.wraps(run_func)
def exc_logging_wrapper(*args: Any) -> int:
try:
status = run_func(*args)
assert isinstance(status, int)
return status
except DiagnosticPipError as exc:
logger.error("%s", exc, extra={"rich": True})
logger.debug("Exception information:", exc_info=True)

return ERROR
except PreviousBuildDirError as exc:
logger.critical(str(exc))
logger.debug("Exception information:", exc_info=True)

return PREVIOUS_BUILD_DIR_ERROR
except (
InstallationError,
BadCommand,
NetworkConnectionError,
) as exc:
logger.critical(str(exc))
logger.debug("Exception information:", exc_info=True)

return ERROR
except CommandError as exc:
logger.critical("%s", exc)
logger.debug("Exception information:", exc_info=True)

return ERROR
except BrokenStdoutLoggingError:
# Bypass our logger and write any remaining messages to
# stderr because stdout no longer works.
print("ERROR: Pipe to stdout was broken", file=sys.stderr)
if level_number <= logging.DEBUG:
traceback.print_exc(file=sys.stderr)

return ERROR
except KeyboardInterrupt:
logger.critical("Operation cancelled by user")
logger.debug("Exception information:", exc_info=True)

return ERROR
except BaseException:
logger.critical("Exception:", exc_info=True)

return UNKNOWN_ERROR

return exc_logging_wrapper

try:
if not options.debug_mode:
run = intercepts_unhandled_exc(self.run)
else:
run = self.run
rich_traceback.install(show_locals=True)
return run(options, args)
finally:
self.handle_pip_version_check(options)
return self._run_wrapper(level_number, options, args)
3 changes: 2 additions & 1 deletion pipenv/patched/pip/_internal/cli/cmdoptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -996,6 +996,7 @@ def check_list_path_option(options: Values) -> None:

# Features that are now always on. A warning is printed if they are used.
ALWAYS_ENABLED_FEATURES = [
"truststore", # always on since 24.2
"no-binary-enable-wheel-cache", # always on since 23.1
]

Expand All @@ -1008,7 +1009,6 @@ def check_list_path_option(options: Values) -> None:
default=[],
choices=[
"fast-deps",
"truststore",
]
+ ALWAYS_ENABLED_FEATURES,
help="Enable new functionality, that may be backward incompatible.",
Expand All @@ -1023,6 +1023,7 @@ def check_list_path_option(options: Values) -> None:
default=[],
choices=[
"legacy-resolver",
"legacy-certs",
],
help=("Enable deprecated functionality, that will be removed in the future."),
)
Expand Down
50 changes: 24 additions & 26 deletions pipenv/patched/pip/_internal/cli/index_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
from optparse import Values
from typing import TYPE_CHECKING, List, Optional

from pipenv.patched.pip._vendor import certifi

from pipenv.patched.pip._internal.cli.base_command import Command
from pipenv.patched.pip._internal.cli.command_context import CommandContextMixIn
from pipenv.patched.pip._internal.exceptions import CommandError

if TYPE_CHECKING:
from ssl import SSLContext
Expand All @@ -26,7 +27,8 @@

def _create_truststore_ssl_context() -> Optional["SSLContext"]:
if sys.version_info < (3, 10):
raise CommandError("The truststore feature is only available for Python 3.10+")
logger.debug("Disabling truststore because Python version isn't 3.10+")
return None

try:
import ssl
Expand All @@ -36,10 +38,13 @@ def _create_truststore_ssl_context() -> Optional["SSLContext"]:

try:
from pipenv.patched.pip._vendor import truststore
except ImportError as e:
raise CommandError(f"The truststore feature is unavailable: {e}")
except ImportError:
logger.warning("Disabling truststore because platform isn't supported")
return None

return truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx = truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.load_verify_locations(certifi.where())
return ctx


class SessionCommandMixin(CommandContextMixIn):
Expand Down Expand Up @@ -80,20 +85,14 @@ def _build_session(
options: Values,
retries: Optional[int] = None,
timeout: Optional[int] = None,
fallback_to_certifi: bool = False,
) -> "PipSession":
from pipenv.patched.pip._internal.network.session import PipSession

cache_dir = options.cache_dir
assert not cache_dir or os.path.isabs(cache_dir)

if "truststore" in options.features_enabled:
try:
ssl_context = _create_truststore_ssl_context()
except Exception:
if not fallback_to_certifi:
raise
ssl_context = None
if "legacy-certs" not in options.deprecated_features_enabled:
ssl_context = _create_truststore_ssl_context()
else:
ssl_context = None

Expand Down Expand Up @@ -157,16 +156,15 @@ def handle_pip_version_check(self, options: Values) -> None:
if options.disable_pip_version_check or options.no_index:
return

# Otherwise, check if we're using the latest version of pip available.
session = self._build_session(
options,
retries=0,
timeout=min(5, options.timeout),
# This is set to ensure the function does not fail when truststore is
# specified in use-feature but cannot be loaded. This usually raises a
# CommandError and shows a nice user-facing error, but this function is not
# called in that try-except block.
fallback_to_certifi=True,
)
with session:
_pip_self_version_check(session, options)
try:
# Otherwise, check if we're using the latest version of pip available.
session = self._build_session(
options,
retries=0,
timeout=min(5, options.timeout),
)
with session:
_pip_self_version_check(session, options)
except Exception:
logger.warning("There was an error checking the latest version of pip.")
logger.debug("See below for error", exc_info=True)
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 @@ -49,7 +49,7 @@ def _rich_progress_bar(
TimeRemainingColumn(),
)

progress = Progress(*columns, refresh_per_second=30)
progress = Progress(*columns, refresh_per_second=5)
task_id = progress.add_task(" " * (get_indentation() + 2), total=total)
with progress:
for chunk in iterable:
Expand Down
19 changes: 17 additions & 2 deletions pipenv/patched/pip/_internal/commands/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@

from pipenv.patched.pip._internal.cli.base_command import Command
from pipenv.patched.pip._internal.cli.status_codes import ERROR, SUCCESS
from pipenv.patched.pip._internal.metadata import get_default_environment
from pipenv.patched.pip._internal.operations.check import (
check_package_set,
check_unsupported,
create_package_set_from_installed,
)
from pipenv.patched.pip._internal.utils.compatibility_tags import get_supported
from pipenv.patched.pip._internal.utils.misc import write_output

logger = logging.getLogger(__name__)
Expand All @@ -16,12 +19,19 @@
class CheckCommand(Command):
"""Verify installed packages have compatible dependencies."""

ignore_require_venv = True
usage = """
%prog [options]"""

def run(self, options: Values, args: List[str]) -> int:
package_set, parsing_probs = create_package_set_from_installed()
missing, conflicting = check_package_set(package_set)
unsupported = list(
check_unsupported(
get_default_environment().iter_installed_distributions(),
get_supported(),
)
)

for project_name in missing:
version = package_set[project_name].version
Expand All @@ -44,8 +54,13 @@ def run(self, options: Values, args: List[str]) -> int:
dep_name,
dep_version,
)

if missing or conflicting or parsing_probs:
for package in unsupported:
write_output(
"%s %s is not supported on this platform",
package.raw_name,
package.version,
)
if missing or conflicting or parsing_probs or unsupported:
return ERROR
else:
write_output("No broken requirements found.")
Expand Down
1 change: 1 addition & 0 deletions pipenv/patched/pip/_internal/commands/freeze.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class FreezeCommand(Command):
packages are listed in a case-insensitive sorted order.
"""

ignore_require_venv = True
usage = """
%prog [options]"""
log_streams = ("ext://sys.stderr", "ext://sys.stderr")
Expand Down
Loading
Loading