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
1 change: 1 addition & 0 deletions news/5979.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Vendor in pip==23.3 which includes updates to certifi, urllib3, and adds truststore among other improvements.
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==23.2.1
pip==23.3
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__ = "23.2.1"
__version__ = "23.3"


def main(args: Optional[List[str]] = None) -> int:
Expand Down
1 change: 0 additions & 1 deletion pipenv/patched/pip/_internal/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from typing import List, Optional

import pipenv.patched.pip._internal.utils.inject_securetransport # noqa
from pipenv.patched.pip._internal.utils import _log

# init_logging() must be called before any call to logging.getLogger()
Expand Down
6 changes: 2 additions & 4 deletions pipenv/patched/pip/_internal/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,10 @@ def _get_candidates(self, link: Link, canonical_package_name: str) -> List[Any]:
if can_not_cache:
return []

candidates = []
path = self.get_path_for_link(link)
if os.path.isdir(path):
for candidate in os.listdir(path):
candidates.append((candidate, path))
return candidates
return [(candidate, path) for candidate in os.listdir(path)]
return []

def get_path_for_link(self, link: Link) -> str:
"""Return a directory to store cached items in for link."""
Expand Down
5 changes: 3 additions & 2 deletions pipenv/patched/pip/_internal/cli/autocompletion.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,9 @@ def autocomplete() -> None:

for opt in subcommand.parser.option_list_all:
if opt.help != optparse.SUPPRESS_HELP:
for opt_str in opt._long_opts + opt._short_opts:
options.append((opt_str, opt.nargs))
options += [
(opt_str, opt.nargs) for opt_str in opt._long_opts + opt._short_opts
]

# filter out previously specified options from available options
prev_opts = [x.split("=")[0] for x in cwords[1 : cword - 1]]
Expand Down
2 changes: 1 addition & 1 deletion pipenv/patched/pip/_internal/cli/base_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ def exc_logging_wrapper(*args: Any) -> int:
assert isinstance(status, int)
return status
except DiagnosticPipError as exc:
logger.error("[present-rich] %s", exc)
logger.error("%s", exc, extra={"rich": True})
logger.debug("Exception information:", exc_info=True)

return ERROR
Expand Down
15 changes: 9 additions & 6 deletions pipenv/patched/pip/_internal/cli/cmdoptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ def check_dist_restriction(options: Values, check_target: bool = False) -> None:
)

if check_target:
if dist_restriction_set and not options.target_dir:
if not options.dry_run and dist_restriction_set and not options.target_dir:
raise CommandError(
"Can not use any platform or abi specific options unless "
"installing via '--target'"
"installing via '--target' or using '--dry-run'"
)


Expand Down Expand Up @@ -670,7 +670,10 @@ def prefer_binary() -> Option:
dest="prefer_binary",
action="store_true",
default=False,
help="Prefer older binary packages over newer source packages.",
help=(
"Prefer binary packages over source packages, even if the "
"source packages are newer."
),
)


Expand Down Expand Up @@ -823,7 +826,7 @@ def _handle_config_settings(
) -> None:
key, sep, val = value.partition("=")
if sep != "=":
parser.error(f"Arguments to {opt_str} must be of the form KEY=VAL") # noqa
parser.error(f"Arguments to {opt_str} must be of the form KEY=VAL")
dest = getattr(parser.values, option.dest)
if dest is None:
dest = {}
Expand Down Expand Up @@ -918,13 +921,13 @@ def _handle_merge_hash(
algo, digest = value.split(":", 1)
except ValueError:
parser.error(
"Arguments to {} must be a hash name " # noqa
"Arguments to {} must be a hash name "
"followed by a value, like --hash=sha256:"
"abcde...".format(opt_str)
)
if algo not in STRONG_HASHES:
parser.error(
"Allowed hash algorithms for {} are {}.".format( # noqa
"Allowed hash algorithms for {} are {}.".format(
opt_str, ", ".join(STRONG_HASHES)
)
)
Expand Down
4 changes: 2 additions & 2 deletions pipenv/patched/pip/_internal/cli/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ def _update_defaults(self, defaults: Dict[str, Any]) -> Dict[str, Any]:
val = strtobool(val)
except ValueError:
self.error(
"{} is not a valid value for {} option, " # noqa
"{} is not a valid value for {} option, "
"please specify a boolean value like yes/no, "
"true/false or 1/0 instead.".format(val, key)
)
Expand All @@ -240,7 +240,7 @@ def _update_defaults(self, defaults: Dict[str, Any]) -> Dict[str, Any]:
val = int(val)
if not isinstance(val, int) or val < 0:
self.error(
"{} is not a valid value for {} option, " # noqa
"{} is not a valid value for {} option, "
"please instead specify either a non-negative integer "
"or a boolean value like yes/no or false/true "
"which is equivalent to 1/0.".format(val, key)
Expand Down
17 changes: 7 additions & 10 deletions pipenv/patched/pip/_internal/cli/req_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,9 @@ def _create_truststore_ssl_context() -> Optional["SSLContext"]:
return None

try:
import truststore
except ImportError:
raise CommandError(
"To use the truststore feature, 'truststore' must be installed into "
"pip's current environment."
)
from pipenv.patched.pip._vendor import truststore
except ImportError as e:
raise CommandError(f"The truststore feature is unavailable: {e}")

return truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)

Expand Down Expand Up @@ -123,7 +120,7 @@ def _build_session(
ssl_context = None

session = PipSession(
cache=os.path.join(cache_dir, "http") if cache_dir else None,
cache=os.path.join(cache_dir, "http-v2") if cache_dir else None,
retries=retries if retries is not None else options.retries,
trusted_hosts=options.trusted_hosts,
index_urls=self._get_index_urls(options),
Expand Down Expand Up @@ -268,7 +265,7 @@ def determine_resolver_variant(options: Values) -> str:
if "legacy-resolver" in options.deprecated_features_enabled:
return "legacy"

return "2020-resolver"
return "resolvelib"

@classmethod
def make_requirement_preparer(
Expand All @@ -290,7 +287,7 @@ def make_requirement_preparer(
legacy_resolver = False

resolver_variant = cls.determine_resolver_variant(options)
if resolver_variant == "2020-resolver":
if resolver_variant == "resolvelib":
lazy_wheel = "fast-deps" in options.features_enabled
if lazy_wheel:
logger.warning(
Expand Down Expand Up @@ -352,7 +349,7 @@ def make_resolver(
# The long import name and duplicated invocation is needed to convince
# Mypy into correctly typechecking. Otherwise it would complain the
# "Resolver" class being redefined.
if resolver_variant == "2020-resolver":
if resolver_variant == "resolvelib":
import pipenv.patched.pip._internal.resolution.resolvelib.resolver

return pipenv.patched.pip._internal.resolution.resolvelib.resolver.Resolver(
Expand Down
33 changes: 18 additions & 15 deletions pipenv/patched/pip/_internal/commands/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
from optparse import Values
from typing import Any, List

import pipenv.patched.pip._internal.utils.filesystem as filesystem
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.exceptions import CommandError, PipError
from pipenv.patched.pip._internal.utils import filesystem
from pipenv.patched.pip._internal.utils.logging import getLogger

logger = getLogger(__name__)
Expand Down Expand Up @@ -93,24 +93,30 @@ def get_cache_info(self, options: Values, args: List[Any]) -> None:
num_http_files = len(self._find_http_files(options))
num_packages = len(self._find_wheels(options, "*"))

http_cache_location = self._cache_dir(options, "http")
http_cache_location = self._cache_dir(options, "http-v2")
old_http_cache_location = self._cache_dir(options, "http")
wheels_cache_location = self._cache_dir(options, "wheels")
http_cache_size = filesystem.format_directory_size(http_cache_location)
http_cache_size = filesystem.format_size(
filesystem.directory_size(http_cache_location)
+ filesystem.directory_size(old_http_cache_location)
)
wheels_cache_size = filesystem.format_directory_size(wheels_cache_location)

message = (
textwrap.dedent(
"""
Package index page cache location: {http_cache_location}
Package index page cache location (pip v23.3+): {http_cache_location}
Package index page cache location (older pips): {old_http_cache_location}
Package index page cache size: {http_cache_size}
Number of HTTP files: {num_http_files}
Locally built wheels location: {wheels_cache_location}
Locally built wheels size: {wheels_cache_size}
Number of locally built wheels: {package_count}
"""
""" # noqa: E501
)
.format(
http_cache_location=http_cache_location,
old_http_cache_location=old_http_cache_location,
http_cache_size=http_cache_size,
num_http_files=num_http_files,
wheels_cache_location=wheels_cache_location,
Expand Down Expand Up @@ -151,14 +157,8 @@ def format_for_human(self, files: List[str]) -> None:
logger.info("\n".join(sorted(results)))

def format_for_abspath(self, files: List[str]) -> None:
if not files:
return

results = []
for filename in files:
results.append(filename)

logger.info("\n".join(sorted(results)))
if files:
logger.info("\n".join(sorted(files)))

def remove_cache_items(self, options: Values, args: List[Any]) -> None:
if len(args) > 1:
Expand Down Expand Up @@ -195,8 +195,11 @@ def _cache_dir(self, options: Values, subdir: str) -> str:
return os.path.join(options.cache_dir, subdir)

def _find_http_files(self, options: Values) -> List[str]:
http_dir = self._cache_dir(options, "http")
return filesystem.find_files(http_dir, "*")
old_http_dir = self._cache_dir(options, "http")
new_http_dir = self._cache_dir(options, "http-v2")
return filesystem.find_files(old_http_dir, "*") + filesystem.find_files(
new_http_dir, "*"
)

def _find_wheels(self, options: Values, pattern: str) -> List[str]:
wheel_dir = self._cache_dir(options, "wheels")
Expand Down
15 changes: 12 additions & 3 deletions pipenv/patched/pip/_internal/commands/completion.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,18 @@
""",
"zsh": """
#compdef -P pip[0-9.]#
compadd $( COMP_WORDS="$words[*]" \\
COMP_CWORD=$((CURRENT-1)) \\
PIP_AUTO_COMPLETE=1 $words[1] 2>/dev/null )
__pip() {{
compadd $( COMP_WORDS="$words[*]" \\
COMP_CWORD=$((CURRENT-1)) \\
PIP_AUTO_COMPLETE=1 $words[1] 2>/dev/null )
}}
if [[ $zsh_eval_context[-1] == loadautofunc ]]; then
# autoload from fpath, call function directly
__pip "$@"
else
# eval/source/. command, register function for later
compdef __pip -P 'pip[0-9.]#'
fi
""",
"fish": """
function __fish_complete_pip
Expand Down
22 changes: 13 additions & 9 deletions pipenv/patched/pip/_internal/commands/debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,22 +46,29 @@ def create_vendor_txt_map() -> Dict[str, str]:
return dict(line.split("==", 1) for line in lines)


def get_module_from_module_name(module_name: str) -> ModuleType:
def get_module_from_module_name(module_name: str) -> Optional[ModuleType]:
# Module name can be uppercase in vendor.txt for some reason...
module_name = module_name.lower().replace("-", "_")
# PATCH: setuptools is actually only pkg_resources.
if module_name == "setuptools":
module_name = "pkg_resources"

__import__(f"pipenv.patched.pip._vendor.{module_name}", globals(), locals(), level=0)
return getattr(pipenv.patched.pip._vendor, module_name)
try:
__import__(f"pipenv.patched.pip._vendor.{module_name}", globals(), locals(), level=0)
return getattr(pipenv.patched.pip._vendor, module_name)
except ImportError:
# We allow 'truststore' to fail to import due
# to being unavailable on Python 3.9 and earlier.
if module_name == "truststore" and sys.version_info < (3, 10):
return None
raise


def get_vendor_version_from_module(module_name: str) -> Optional[str]:
module = get_module_from_module_name(module_name)
version = getattr(module, "__version__", None)

if not version:
if module and not version:
# Try to find version in debundled module info.
assert module.__file__ is not None
env = get_environment([os.path.dirname(module.__file__)])
Expand Down Expand Up @@ -105,7 +112,7 @@ def show_tags(options: Values) -> None:
tag_limit = 10

target_python = make_target_python(options)
tags = target_python.get_tags()
tags = target_python.get_sorted_tags()

# Display the target options that were explicitly provided.
formatted_target = target_python.format_given()
Expand Down Expand Up @@ -134,10 +141,7 @@ def show_tags(options: Values) -> None:


def ca_bundle_info(config: Configuration) -> str:
levels = set()
for key, _ in config.items():
levels.add(key.split(".")[0])

levels = {key.split(".", 1)[0] for key, _ in config.items()}
if not levels:
return "Not specified"

Expand Down
6 changes: 3 additions & 3 deletions pipenv/patched/pip/_internal/commands/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@ def run(self, options: Values, args: List[str]) -> int:
show_traceback,
options.use_user_site,
)
logger.error(message, exc_info=show_traceback) # noqa
logger.error(message, exc_info=show_traceback)

return ERROR

Expand Down Expand Up @@ -595,7 +595,7 @@ def _warn_about_conflicts(
"source of the following dependency conflicts."
)
else:
assert resolver_variant == "2020-resolver"
assert resolver_variant == "resolvelib"
parts.append(
"pip's dependency resolver does not currently take into account "
"all the packages that are installed. This behaviour is the "
Expand Down Expand Up @@ -628,7 +628,7 @@ def _warn_about_conflicts(
requirement=req,
dep_name=dep_name,
dep_version=dep_version,
you=("you" if resolver_variant == "2020-resolver" else "you'll"),
you=("you" if resolver_variant == "resolvelib" else "you'll"),
)
parts.append(message)

Expand Down
2 changes: 1 addition & 1 deletion pipenv/patched/pip/_internal/commands/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ def output_package_listing_columns(

# Create and add a separator.
if len(data) > 0:
pkg_strings.insert(1, " ".join(map(lambda x: "-" * x, sizes)))
pkg_strings.insert(1, " ".join("-" * x for x in sizes))

for val in pkg_strings:
write_output(val)
Expand Down
12 changes: 12 additions & 0 deletions pipenv/patched/pip/_internal/distributions/base.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import abc
from typing import Optional

from pipenv.patched.pip._internal.index.package_finder import PackageFinder
from pipenv.patched.pip._internal.metadata.base import BaseDistribution
Expand All @@ -19,12 +20,23 @@ class AbstractDistribution(metaclass=abc.ABCMeta):

- we must be able to create a Distribution object exposing the
above metadata.

- if we need to do work in the build tracker, we must be able to generate a unique
string to identify the requirement in the build tracker.
"""

def __init__(self, req: InstallRequirement) -> None:
super().__init__()
self.req = req

@abc.abstractproperty
def build_tracker_id(self) -> Optional[str]:
"""A string that uniquely identifies this requirement to the build tracker.

If None, then this dist has no work to do in the build tracker, and
``.prepare_distribution_metadata()`` will not be called."""
raise NotImplementedError()

@abc.abstractmethod
def get_metadata_distribution(self) -> BaseDistribution:
raise NotImplementedError()
Expand Down
Loading