pip 25.3__py3-none-any.whl → 26.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pip/__init__.py +1 -1
- pip/_internal/build_env.py +194 -5
- pip/_internal/cli/base_command.py +11 -0
- pip/_internal/cli/cmdoptions.py +157 -0
- pip/_internal/cli/index_command.py +20 -0
- pip/_internal/cli/main.py +11 -6
- pip/_internal/cli/main_parser.py +3 -1
- pip/_internal/cli/parser.py +93 -33
- pip/_internal/cli/progress_bars.py +4 -2
- pip/_internal/cli/req_command.py +99 -23
- pip/_internal/commands/cache.py +24 -0
- pip/_internal/commands/completion.py +2 -1
- pip/_internal/commands/download.py +8 -4
- pip/_internal/commands/index.py +13 -6
- pip/_internal/commands/install.py +36 -29
- pip/_internal/commands/list.py +14 -16
- pip/_internal/commands/lock.py +16 -8
- pip/_internal/commands/wheel.py +8 -13
- pip/_internal/exceptions.py +76 -3
- pip/_internal/index/collector.py +2 -3
- pip/_internal/index/package_finder.py +84 -18
- pip/_internal/locations/__init__.py +1 -2
- pip/_internal/locations/_sysconfig.py +4 -1
- pip/_internal/models/link.py +18 -14
- pip/_internal/models/release_control.py +92 -0
- pip/_internal/models/selection_prefs.py +6 -3
- pip/_internal/network/auth.py +6 -2
- pip/_internal/network/download.py +4 -5
- pip/_internal/network/session.py +14 -10
- pip/_internal/operations/install/wheel.py +1 -2
- pip/_internal/operations/prepare.py +2 -3
- pip/_internal/req/constructors.py +3 -1
- pip/_internal/req/pep723.py +41 -0
- pip/_internal/req/req_file.py +10 -1
- pip/_internal/resolution/resolvelib/factory.py +12 -1
- pip/_internal/resolution/resolvelib/requirements.py +7 -3
- pip/_internal/self_outdated_check.py +6 -13
- pip/_internal/utils/datetime.py +18 -0
- pip/_internal/utils/filesystem.py +40 -1
- pip/_internal/utils/logging.py +34 -2
- pip/_internal/utils/misc.py +18 -12
- pip/_internal/utils/pylock.py +116 -0
- pip/_internal/utils/unpacking.py +1 -1
- pip/_internal/vcs/versioncontrol.py +3 -1
- pip/_vendor/cachecontrol/__init__.py +6 -3
- pip/_vendor/cachecontrol/adapter.py +0 -1
- pip/_vendor/cachecontrol/controller.py +1 -1
- pip/_vendor/cachecontrol/filewrapper.py +3 -1
- pip/_vendor/certifi/__init__.py +1 -1
- pip/_vendor/certifi/cacert.pem +0 -332
- pip/_vendor/idna/LICENSE.md +1 -1
- pip/_vendor/idna/codec.py +1 -1
- pip/_vendor/idna/core.py +1 -1
- pip/_vendor/idna/idnadata.py +72 -6
- pip/_vendor/idna/package_data.py +1 -1
- pip/_vendor/idna/uts46data.py +891 -731
- pip/_vendor/packaging/__init__.py +1 -1
- pip/_vendor/packaging/_elffile.py +0 -1
- pip/_vendor/packaging/_manylinux.py +36 -36
- pip/_vendor/packaging/_musllinux.py +1 -1
- pip/_vendor/packaging/_parser.py +22 -10
- pip/_vendor/packaging/_structures.py +8 -0
- pip/_vendor/packaging/_tokenizer.py +23 -25
- pip/_vendor/packaging/licenses/__init__.py +13 -11
- pip/_vendor/packaging/licenses/_spdx.py +41 -1
- pip/_vendor/packaging/markers.py +64 -38
- pip/_vendor/packaging/metadata.py +143 -27
- pip/_vendor/packaging/pylock.py +635 -0
- pip/_vendor/packaging/requirements.py +5 -10
- pip/_vendor/packaging/specifiers.py +219 -170
- pip/_vendor/packaging/tags.py +15 -20
- pip/_vendor/packaging/utils.py +19 -24
- pip/_vendor/packaging/version.py +315 -105
- pip/_vendor/platformdirs/version.py +2 -2
- pip/_vendor/platformdirs/windows.py +7 -1
- pip/_vendor/vendor.txt +5 -5
- {pip-25.3.dist-info → pip-26.0.dist-info}/METADATA +2 -2
- {pip-25.3.dist-info → pip-26.0.dist-info}/RECORD +103 -100
- {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/AUTHORS.txt +18 -0
- {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/idna/LICENSE.md +1 -1
- pip/_internal/models/pylock.py +0 -188
- {pip-25.3.dist-info → pip-26.0.dist-info}/WHEEL +0 -0
- {pip-25.3.dist-info → pip-26.0.dist-info}/entry_points.txt +0 -0
- {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/LICENSE.txt +0 -0
- {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/cachecontrol/LICENSE.txt +0 -0
- {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/certifi/LICENSE +0 -0
- {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/dependency_groups/LICENSE.txt +0 -0
- {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/distlib/LICENSE.txt +0 -0
- {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/distro/LICENSE +0 -0
- {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/msgpack/COPYING +0 -0
- {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE +0 -0
- {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE.APACHE +0 -0
- {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE.BSD +0 -0
- {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/pkg_resources/LICENSE +0 -0
- {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/platformdirs/LICENSE +0 -0
- {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/pygments/LICENSE +0 -0
- {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/pyproject_hooks/LICENSE +0 -0
- {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/requests/LICENSE +0 -0
- {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/resolvelib/LICENSE +0 -0
- {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/rich/LICENSE +0 -0
- {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/tomli/LICENSE +0 -0
- {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/tomli_w/LICENSE +0 -0
- {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/truststore/LICENSE +0 -0
- {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/urllib3/LICENSE.txt +0 -0
pip/_internal/cli/parser.py
CHANGED
|
@@ -4,6 +4,8 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import logging
|
|
6
6
|
import optparse
|
|
7
|
+
import os
|
|
8
|
+
import re
|
|
7
9
|
import shutil
|
|
8
10
|
import sys
|
|
9
11
|
import textwrap
|
|
@@ -11,8 +13,12 @@ from collections.abc import Generator
|
|
|
11
13
|
from contextlib import suppress
|
|
12
14
|
from typing import Any, NoReturn
|
|
13
15
|
|
|
16
|
+
from pip._vendor.rich.markup import escape
|
|
17
|
+
from pip._vendor.rich.theme import Theme
|
|
18
|
+
|
|
14
19
|
from pip._internal.cli.status_codes import UNKNOWN_ERROR
|
|
15
20
|
from pip._internal.configuration import Configuration, ConfigurationError
|
|
21
|
+
from pip._internal.utils.logging import PipConsole
|
|
16
22
|
from pip._internal.utils.misc import redact_auth_from_url, strtobool
|
|
17
23
|
|
|
18
24
|
logger = logging.getLogger(__name__)
|
|
@@ -21,6 +27,17 @@ logger = logging.getLogger(__name__)
|
|
|
21
27
|
class PrettyHelpFormatter(optparse.IndentedHelpFormatter):
|
|
22
28
|
"""A prettier/less verbose help formatter for optparse."""
|
|
23
29
|
|
|
30
|
+
styles = {
|
|
31
|
+
"optparse.shortargs": "green",
|
|
32
|
+
"optparse.longargs": "cyan",
|
|
33
|
+
"optparse.groups": "bold blue",
|
|
34
|
+
"optparse.metavar": "yellow",
|
|
35
|
+
}
|
|
36
|
+
highlights = {
|
|
37
|
+
r"\s(-{1}[\w]+[\w-]*)": "shortargs", # highlight -letter as short args
|
|
38
|
+
r"\s(-{2}[\w]+[\w-]*)": "longargs", # highlight --words as long args
|
|
39
|
+
}
|
|
40
|
+
|
|
24
41
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
25
42
|
# help position must be aligned with __init__.parseopts.description
|
|
26
43
|
kwargs["max_help_position"] = 30
|
|
@@ -29,61 +46,82 @@ class PrettyHelpFormatter(optparse.IndentedHelpFormatter):
|
|
|
29
46
|
super().__init__(*args, **kwargs)
|
|
30
47
|
|
|
31
48
|
def format_option_strings(self, option: optparse.Option) -> str:
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def _format_option_strings(
|
|
35
|
-
self, option: optparse.Option, mvarfmt: str = " <{}>", optsep: str = ", "
|
|
36
|
-
) -> str:
|
|
37
|
-
"""
|
|
38
|
-
Return a comma-separated list of option strings and metavars.
|
|
39
|
-
|
|
40
|
-
:param option: tuple of (short opt, long opt), e.g: ('-f', '--format')
|
|
41
|
-
:param mvarfmt: metavar format string
|
|
42
|
-
:param optsep: separator
|
|
43
|
-
"""
|
|
49
|
+
"""Return a comma-separated list of option strings and metavars."""
|
|
44
50
|
opts = []
|
|
45
51
|
|
|
46
52
|
if option._short_opts:
|
|
47
|
-
opts.append(option._short_opts[0])
|
|
53
|
+
opts.append(f"[optparse.shortargs]{option._short_opts[0]}[/]")
|
|
48
54
|
if option._long_opts:
|
|
49
|
-
opts.append(option._long_opts[0])
|
|
55
|
+
opts.append(f"[optparse.longargs]{option._long_opts[0]}[/]")
|
|
50
56
|
if len(opts) > 1:
|
|
51
|
-
opts.insert(1,
|
|
57
|
+
opts.insert(1, ", ")
|
|
52
58
|
|
|
53
59
|
if option.takes_value():
|
|
54
60
|
assert option.dest is not None
|
|
55
61
|
metavar = option.metavar or option.dest.lower()
|
|
56
|
-
opts.append(
|
|
62
|
+
opts.append(f" [optparse.metavar]<{escape(metavar.lower())}>[/]")
|
|
57
63
|
|
|
58
64
|
return "".join(opts)
|
|
59
65
|
|
|
66
|
+
def format_option(self, option: optparse.Option) -> str:
|
|
67
|
+
"""Overridden method with Rich support."""
|
|
68
|
+
# fmt: off
|
|
69
|
+
result = []
|
|
70
|
+
opts = self.option_strings[option]
|
|
71
|
+
opt_width = self.help_position - self.current_indent - 2
|
|
72
|
+
# Remove the rich style tags before calculating width during
|
|
73
|
+
# text wrap calculations. Also store the length removed to adjust
|
|
74
|
+
# the padding in the else branch.
|
|
75
|
+
stripped = re.sub(r"(\[[a-z.]+\])|(\[\/\])", "", opts)
|
|
76
|
+
style_tag_length = len(opts) - len(stripped)
|
|
77
|
+
if len(stripped) > opt_width:
|
|
78
|
+
opts = "%*s%s\n" % (self.current_indent, "", opts) # noqa: UP031
|
|
79
|
+
indent_first = self.help_position
|
|
80
|
+
else: # start help on same line as opts
|
|
81
|
+
opts = "%*s%-*s " % (self.current_indent, "", # noqa: UP031
|
|
82
|
+
opt_width + style_tag_length, opts)
|
|
83
|
+
indent_first = 0
|
|
84
|
+
result.append(opts)
|
|
85
|
+
if option.help:
|
|
86
|
+
help_text = self.expand_default(option)
|
|
87
|
+
help_lines = textwrap.wrap(help_text, self.help_width)
|
|
88
|
+
result.append("%*s%s\n" % (indent_first, "", help_lines[0])) # noqa: UP031
|
|
89
|
+
result.extend(["%*s%s\n" % (self.help_position, "", line) # noqa: UP031
|
|
90
|
+
for line in help_lines[1:]])
|
|
91
|
+
elif opts[-1] != "\n":
|
|
92
|
+
result.append("\n")
|
|
93
|
+
return "".join(result)
|
|
94
|
+
# fmt: on
|
|
95
|
+
|
|
60
96
|
def format_heading(self, heading: str) -> str:
|
|
61
97
|
if heading == "Options":
|
|
62
98
|
return ""
|
|
63
|
-
return heading + "
|
|
99
|
+
return "[optparse.groups]" + escape(heading) + ":[/]\n"
|
|
64
100
|
|
|
65
101
|
def format_usage(self, usage: str) -> str:
|
|
66
102
|
"""
|
|
67
103
|
Ensure there is only one newline between usage and the first heading
|
|
68
104
|
if there is no description.
|
|
69
105
|
"""
|
|
70
|
-
|
|
106
|
+
contents = self.indent_lines(textwrap.dedent(usage), " ")
|
|
107
|
+
msg = f"\n[optparse.groups]Usage:[/] {escape(contents)}\n"
|
|
71
108
|
return msg
|
|
72
109
|
|
|
73
110
|
def format_description(self, description: str | None) -> str:
|
|
74
111
|
# leave full control over description to us
|
|
75
112
|
if description:
|
|
76
113
|
if hasattr(self.parser, "main"):
|
|
77
|
-
label = "Commands"
|
|
114
|
+
label = "[optparse.groups]Commands:[/]"
|
|
78
115
|
else:
|
|
79
|
-
label = "Description"
|
|
116
|
+
label = "[optparse.groups]Description:[/]"
|
|
117
|
+
|
|
80
118
|
# some doc strings have initial newlines, some don't
|
|
81
119
|
description = description.lstrip("\n")
|
|
82
120
|
# some doc strings have final newlines and spaces, some don't
|
|
83
121
|
description = description.rstrip()
|
|
84
122
|
# dedent, then reindent
|
|
85
123
|
description = self.indent_lines(textwrap.dedent(description), " ")
|
|
86
|
-
description = f"{label}
|
|
124
|
+
description = f"{label}\n{description}\n"
|
|
87
125
|
return description
|
|
88
126
|
else:
|
|
89
127
|
return ""
|
|
@@ -91,10 +129,17 @@ class PrettyHelpFormatter(optparse.IndentedHelpFormatter):
|
|
|
91
129
|
def format_epilog(self, epilog: str | None) -> str:
|
|
92
130
|
# leave full control over epilog to us
|
|
93
131
|
if epilog:
|
|
94
|
-
return epilog
|
|
132
|
+
return escape(epilog)
|
|
95
133
|
else:
|
|
96
134
|
return ""
|
|
97
135
|
|
|
136
|
+
def expand_default(self, option: optparse.Option) -> str:
|
|
137
|
+
"""Overridden HelpFormatter.expand_default() which colorizes flags."""
|
|
138
|
+
help = escape(super().expand_default(option))
|
|
139
|
+
for regex, style in self.highlights.items():
|
|
140
|
+
help = re.sub(regex, rf"[optparse.{style}] \1[/]", help)
|
|
141
|
+
return help
|
|
142
|
+
|
|
98
143
|
def indent_lines(self, text: str, indent: str) -> str:
|
|
99
144
|
new_lines = [indent + line for line in text.split("\n")]
|
|
100
145
|
return "\n".join(new_lines)
|
|
@@ -185,23 +230,25 @@ class ConfigOptionParser(CustomOptionParser):
|
|
|
185
230
|
override_order = ["global", self.name, ":env:"]
|
|
186
231
|
|
|
187
232
|
# Pool the options into different groups
|
|
188
|
-
|
|
189
|
-
|
|
233
|
+
# Use a dict because we need to implement the fallthrough logic after PR 12201
|
|
234
|
+
# was merged which removed the fallthrough logic for options
|
|
235
|
+
section_items_dict: dict[str, dict[str, Any]] = {
|
|
236
|
+
name: {} for name in override_order
|
|
190
237
|
}
|
|
191
238
|
|
|
192
|
-
for _, value in self.config.items():
|
|
239
|
+
for _, value in self.config.items():
|
|
193
240
|
for section_key, val in value.items():
|
|
194
|
-
# ignore empty values
|
|
195
|
-
if not val:
|
|
196
|
-
logger.debug(
|
|
197
|
-
"Ignoring configuration key '%s' as its value is empty.",
|
|
198
|
-
section_key,
|
|
199
|
-
)
|
|
200
|
-
continue
|
|
201
241
|
|
|
202
242
|
section, key = section_key.split(".", 1)
|
|
203
243
|
if section in override_order:
|
|
204
|
-
|
|
244
|
+
section_items_dict[section][key] = val
|
|
245
|
+
|
|
246
|
+
# Now that we a dict of items per section, convert to list of tuples
|
|
247
|
+
# Make sure we completely remove empty values again
|
|
248
|
+
section_items = {
|
|
249
|
+
name: [(k, v) for k, v in section_items_dict[name].items() if v]
|
|
250
|
+
for name in override_order
|
|
251
|
+
}
|
|
205
252
|
|
|
206
253
|
# Yield each group in their override order
|
|
207
254
|
for section in override_order:
|
|
@@ -296,3 +343,16 @@ class ConfigOptionParser(CustomOptionParser):
|
|
|
296
343
|
def error(self, msg: str) -> NoReturn:
|
|
297
344
|
self.print_usage(sys.stderr)
|
|
298
345
|
self.exit(UNKNOWN_ERROR, f"{msg}\n")
|
|
346
|
+
|
|
347
|
+
def print_help(self, file: Any = None) -> None:
|
|
348
|
+
# This is unfortunate but necessary since arguments may have not been
|
|
349
|
+
# parsed yet at this point, so detect --no-color manually.
|
|
350
|
+
no_color = (
|
|
351
|
+
"--no-color" in sys.argv
|
|
352
|
+
or bool(strtobool(os.environ.get("PIP_NO_COLOR", "no") or "no"))
|
|
353
|
+
or "NO_COLOR" in os.environ
|
|
354
|
+
)
|
|
355
|
+
console = PipConsole(
|
|
356
|
+
theme=Theme(PrettyHelpFormatter.styles), no_color=no_color, file=file
|
|
357
|
+
)
|
|
358
|
+
console.print(self.format_help().rstrip(), highlight=False)
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import functools
|
|
4
4
|
import sys
|
|
5
5
|
from collections.abc import Generator, Iterable, Iterator
|
|
6
|
-
from typing import Callable, Literal, TypeVar
|
|
6
|
+
from typing import TYPE_CHECKING, Callable, Literal, TypeVar
|
|
7
7
|
|
|
8
8
|
from pip._vendor.rich.progress import (
|
|
9
9
|
BarColumn,
|
|
@@ -20,9 +20,11 @@ from pip._vendor.rich.progress import (
|
|
|
20
20
|
)
|
|
21
21
|
|
|
22
22
|
from pip._internal.cli.spinners import RateLimiter
|
|
23
|
-
from pip._internal.req.req_install import InstallRequirement
|
|
24
23
|
from pip._internal.utils.logging import get_console, get_indentation
|
|
25
24
|
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from pip._internal.req.req_install import InstallRequirement
|
|
27
|
+
|
|
26
28
|
T = TypeVar("T")
|
|
27
29
|
ProgressRenderer = Callable[[Iterable[T]], Iterator[T]]
|
|
28
30
|
BarType = Literal["on", "off", "raw"]
|
pip/_internal/cli/req_command.py
CHANGED
|
@@ -13,12 +13,21 @@ from functools import partial
|
|
|
13
13
|
from optparse import Values
|
|
14
14
|
from typing import Any, Callable, TypeVar
|
|
15
15
|
|
|
16
|
-
from pip._internal.build_env import
|
|
16
|
+
from pip._internal.build_env import (
|
|
17
|
+
BuildEnvironmentInstaller,
|
|
18
|
+
InprocessBuildEnvironmentInstaller,
|
|
19
|
+
SubprocessBuildEnvironmentInstaller,
|
|
20
|
+
)
|
|
17
21
|
from pip._internal.cache import WheelCache
|
|
18
22
|
from pip._internal.cli import cmdoptions
|
|
23
|
+
from pip._internal.cli.cmdoptions import make_target_python
|
|
19
24
|
from pip._internal.cli.index_command import IndexGroupCommand
|
|
20
25
|
from pip._internal.cli.index_command import SessionCommandMixin as SessionCommandMixin
|
|
21
|
-
from pip._internal.exceptions import
|
|
26
|
+
from pip._internal.exceptions import (
|
|
27
|
+
CommandError,
|
|
28
|
+
PreviousBuildDirError,
|
|
29
|
+
UnsupportedPythonVersion,
|
|
30
|
+
)
|
|
22
31
|
from pip._internal.index.collector import LinkCollector
|
|
23
32
|
from pip._internal.index.package_finder import PackageFinder
|
|
24
33
|
from pip._internal.models.selection_prefs import SelectionPreferences
|
|
@@ -32,10 +41,12 @@ from pip._internal.req.constructors import (
|
|
|
32
41
|
install_req_from_parsed_requirement,
|
|
33
42
|
install_req_from_req_string,
|
|
34
43
|
)
|
|
44
|
+
from pip._internal.req.pep723 import PEP723Exception, pep723_metadata
|
|
35
45
|
from pip._internal.req.req_dependency_group import parse_dependency_groups
|
|
36
46
|
from pip._internal.req.req_file import parse_requirements
|
|
37
47
|
from pip._internal.req.req_install import InstallRequirement
|
|
38
48
|
from pip._internal.resolution.base import BaseResolver
|
|
49
|
+
from pip._internal.utils.packaging import check_requires_python
|
|
39
50
|
from pip._internal.utils.temp_dir import (
|
|
40
51
|
TempDirectory,
|
|
41
52
|
TempDirectoryTypeRegistry,
|
|
@@ -93,6 +104,31 @@ def with_cleanup(
|
|
|
93
104
|
return wrapper
|
|
94
105
|
|
|
95
106
|
|
|
107
|
+
def parse_constraint_files(
|
|
108
|
+
constraint_files: list[str],
|
|
109
|
+
finder: PackageFinder,
|
|
110
|
+
options: Values,
|
|
111
|
+
session: PipSession,
|
|
112
|
+
) -> list[InstallRequirement]:
|
|
113
|
+
requirements = []
|
|
114
|
+
for filename in constraint_files:
|
|
115
|
+
for parsed_req in parse_requirements(
|
|
116
|
+
filename,
|
|
117
|
+
constraint=True,
|
|
118
|
+
finder=finder,
|
|
119
|
+
options=options,
|
|
120
|
+
session=session,
|
|
121
|
+
):
|
|
122
|
+
req_to_add = install_req_from_parsed_requirement(
|
|
123
|
+
parsed_req,
|
|
124
|
+
isolated=options.isolated_mode,
|
|
125
|
+
user_supplied=False,
|
|
126
|
+
)
|
|
127
|
+
requirements.append(req_to_add)
|
|
128
|
+
|
|
129
|
+
return requirements
|
|
130
|
+
|
|
131
|
+
|
|
96
132
|
class RequirementCommand(IndexGroupCommand):
|
|
97
133
|
def __init__(self, *args: Any, **kw: Any) -> None:
|
|
98
134
|
super().__init__(*args, **kw)
|
|
@@ -152,16 +188,31 @@ class RequirementCommand(IndexGroupCommand):
|
|
|
152
188
|
"build-constraint" in options.features_enabled
|
|
153
189
|
)
|
|
154
190
|
|
|
191
|
+
env_installer: BuildEnvironmentInstaller
|
|
192
|
+
if "inprocess-build-deps" in options.features_enabled:
|
|
193
|
+
build_constraint_reqs = parse_constraint_files(
|
|
194
|
+
build_constraints, finder, options, session
|
|
195
|
+
)
|
|
196
|
+
env_installer = InprocessBuildEnvironmentInstaller(
|
|
197
|
+
finder=finder,
|
|
198
|
+
build_tracker=build_tracker,
|
|
199
|
+
build_constraints=build_constraint_reqs,
|
|
200
|
+
verbosity=verbosity,
|
|
201
|
+
wheel_cache=WheelCache(options.cache_dir),
|
|
202
|
+
)
|
|
203
|
+
else:
|
|
204
|
+
env_installer = SubprocessBuildEnvironmentInstaller(
|
|
205
|
+
finder,
|
|
206
|
+
build_constraints=build_constraints,
|
|
207
|
+
build_constraint_feature_enabled=build_constraint_feature_enabled,
|
|
208
|
+
)
|
|
209
|
+
|
|
155
210
|
return RequirementPreparer(
|
|
156
211
|
build_dir=temp_build_dir_path,
|
|
157
212
|
src_dir=options.src_dir,
|
|
158
213
|
download_dir=download_dir,
|
|
159
214
|
build_isolation=options.build_isolation,
|
|
160
|
-
build_isolation_installer=
|
|
161
|
-
finder,
|
|
162
|
-
build_constraints=build_constraints,
|
|
163
|
-
build_constraint_feature_enabled=build_constraint_feature_enabled,
|
|
164
|
-
),
|
|
215
|
+
build_isolation_installer=env_installer,
|
|
165
216
|
check_build_deps=options.check_build_deps,
|
|
166
217
|
build_tracker=build_tracker,
|
|
167
218
|
session=session,
|
|
@@ -172,7 +223,6 @@ class RequirementCommand(IndexGroupCommand):
|
|
|
172
223
|
lazy_wheel=lazy_wheel,
|
|
173
224
|
verbosity=verbosity,
|
|
174
225
|
legacy_resolver=legacy_resolver,
|
|
175
|
-
resume_retries=options.resume_retries,
|
|
176
226
|
)
|
|
177
227
|
|
|
178
228
|
@classmethod
|
|
@@ -245,22 +295,14 @@ class RequirementCommand(IndexGroupCommand):
|
|
|
245
295
|
requirements: list[InstallRequirement] = []
|
|
246
296
|
|
|
247
297
|
if not should_ignore_regular_constraints(options):
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
finder=finder,
|
|
253
|
-
options=options,
|
|
254
|
-
session=session,
|
|
255
|
-
):
|
|
256
|
-
req_to_add = install_req_from_parsed_requirement(
|
|
257
|
-
parsed_req,
|
|
258
|
-
isolated=options.isolated_mode,
|
|
259
|
-
user_supplied=False,
|
|
260
|
-
)
|
|
261
|
-
requirements.append(req_to_add)
|
|
298
|
+
constraints = parse_constraint_files(
|
|
299
|
+
options.constraints, finder, options, session
|
|
300
|
+
)
|
|
301
|
+
requirements.extend(constraints)
|
|
262
302
|
|
|
263
303
|
for req in args:
|
|
304
|
+
if not req.strip():
|
|
305
|
+
continue
|
|
264
306
|
req_to_add = install_req_from_line(
|
|
265
307
|
req,
|
|
266
308
|
comes_from=None,
|
|
@@ -305,6 +347,38 @@ class RequirementCommand(IndexGroupCommand):
|
|
|
305
347
|
)
|
|
306
348
|
requirements.append(req_to_add)
|
|
307
349
|
|
|
350
|
+
if options.requirements_from_scripts:
|
|
351
|
+
if len(options.requirements_from_scripts) > 1:
|
|
352
|
+
raise CommandError("--requirements-from-script can only be given once")
|
|
353
|
+
|
|
354
|
+
script = options.requirements_from_scripts[0]
|
|
355
|
+
try:
|
|
356
|
+
script_metadata = pep723_metadata(script)
|
|
357
|
+
except PEP723Exception as exc:
|
|
358
|
+
raise CommandError(exc.msg)
|
|
359
|
+
|
|
360
|
+
script_requires_python = script_metadata.get("requires-python", "")
|
|
361
|
+
|
|
362
|
+
if script_requires_python and not options.ignore_requires_python:
|
|
363
|
+
target_python = make_target_python(options)
|
|
364
|
+
|
|
365
|
+
if not check_requires_python(
|
|
366
|
+
requires_python=script_requires_python,
|
|
367
|
+
version_info=target_python.py_version_info,
|
|
368
|
+
):
|
|
369
|
+
raise UnsupportedPythonVersion(
|
|
370
|
+
f"Script {script!r} requires a different Python: "
|
|
371
|
+
f"{target_python.py_version} not in {script_requires_python!r}"
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
for req in script_metadata.get("dependencies", []):
|
|
375
|
+
req_to_add = install_req_from_req_string(
|
|
376
|
+
req,
|
|
377
|
+
isolated=options.isolated_mode,
|
|
378
|
+
user_supplied=True,
|
|
379
|
+
)
|
|
380
|
+
requirements.append(req_to_add)
|
|
381
|
+
|
|
308
382
|
# If any requirement has hash options, enable hash checking.
|
|
309
383
|
if any(req.has_hash_options for req in requirements):
|
|
310
384
|
options.require_hashes = True
|
|
@@ -314,6 +388,7 @@ class RequirementCommand(IndexGroupCommand):
|
|
|
314
388
|
or options.editables
|
|
315
389
|
or options.requirements
|
|
316
390
|
or options.dependency_groups
|
|
391
|
+
or options.requirements_from_scripts
|
|
317
392
|
):
|
|
318
393
|
opts = {"name": self.name}
|
|
319
394
|
if options.find_links:
|
|
@@ -359,7 +434,7 @@ class RequirementCommand(IndexGroupCommand):
|
|
|
359
434
|
selection_prefs = SelectionPreferences(
|
|
360
435
|
allow_yanked=True,
|
|
361
436
|
format_control=options.format_control,
|
|
362
|
-
|
|
437
|
+
release_control=options.release_control,
|
|
363
438
|
prefer_binary=options.prefer_binary,
|
|
364
439
|
ignore_requires_python=ignore_requires_python,
|
|
365
440
|
)
|
|
@@ -368,4 +443,5 @@ class RequirementCommand(IndexGroupCommand):
|
|
|
368
443
|
link_collector=link_collector,
|
|
369
444
|
selection_prefs=selection_prefs,
|
|
370
445
|
target_python=target_python,
|
|
446
|
+
uploaded_prior_to=options.uploaded_prior_to,
|
|
371
447
|
)
|
pip/_internal/commands/cache.py
CHANGED
|
@@ -189,7 +189,31 @@ class CacheCommand(Command):
|
|
|
189
189
|
bytes_removed += os.stat(filename).st_size
|
|
190
190
|
os.unlink(filename)
|
|
191
191
|
logger.verbose("Removed %s", filename)
|
|
192
|
+
|
|
193
|
+
http_dirs = filesystem.subdirs_without_files(self._cache_dir(options, "http"))
|
|
194
|
+
wheel_dirs = filesystem.subdirs_without_wheels(
|
|
195
|
+
self._cache_dir(options, "wheels")
|
|
196
|
+
)
|
|
197
|
+
dirs = [*http_dirs, *wheel_dirs]
|
|
198
|
+
|
|
199
|
+
for subdir in dirs:
|
|
200
|
+
try:
|
|
201
|
+
for file in subdir.iterdir():
|
|
202
|
+
file.unlink(missing_ok=True)
|
|
203
|
+
subdir.rmdir()
|
|
204
|
+
except FileNotFoundError:
|
|
205
|
+
# If the directory is already gone, that's fine.
|
|
206
|
+
pass
|
|
207
|
+
logger.verbose("Removed %s", subdir)
|
|
208
|
+
|
|
209
|
+
# selfcheck.json is no longer used by pip.
|
|
210
|
+
selfcheck_json = self._cache_dir(options, "selfcheck.json")
|
|
211
|
+
if os.path.isfile(selfcheck_json):
|
|
212
|
+
os.remove(selfcheck_json)
|
|
213
|
+
logger.verbose("Removed legacy selfcheck.json file")
|
|
214
|
+
|
|
192
215
|
logger.info("Files removed: %s (%s)", len(files), format_size(bytes_removed))
|
|
216
|
+
logger.info("Directories removed: %s", len(dirs))
|
|
193
217
|
|
|
194
218
|
def purge_cache(self, options: Values, args: list[str]) -> None:
|
|
195
219
|
if args:
|
|
@@ -14,9 +14,10 @@ COMPLETION_SCRIPTS = {
|
|
|
14
14
|
"bash": """
|
|
15
15
|
_pip_completion()
|
|
16
16
|
{{
|
|
17
|
+
local IFS=$' \\t\\n'
|
|
17
18
|
COMPREPLY=( $( COMP_WORDS="${{COMP_WORDS[*]}}" \\
|
|
18
19
|
COMP_CWORD=$COMP_CWORD \\
|
|
19
|
-
PIP_AUTO_COMPLETE=1 $1 2>/dev/null ) )
|
|
20
|
+
PIP_AUTO_COMPLETE=1 "$1" 2>/dev/null ) )
|
|
20
21
|
}}
|
|
21
22
|
complete -o default -F _pip_completion {prog}
|
|
22
23
|
""",
|
|
@@ -37,12 +37,9 @@ class DownloadCommand(RequirementCommand):
|
|
|
37
37
|
self.cmd_opts.add_option(cmdoptions.constraints())
|
|
38
38
|
self.cmd_opts.add_option(cmdoptions.build_constraints())
|
|
39
39
|
self.cmd_opts.add_option(cmdoptions.requirements())
|
|
40
|
+
self.cmd_opts.add_option(cmdoptions.requirements_from_scripts())
|
|
40
41
|
self.cmd_opts.add_option(cmdoptions.no_deps())
|
|
41
|
-
self.cmd_opts.add_option(cmdoptions.no_binary())
|
|
42
|
-
self.cmd_opts.add_option(cmdoptions.only_binary())
|
|
43
|
-
self.cmd_opts.add_option(cmdoptions.prefer_binary())
|
|
44
42
|
self.cmd_opts.add_option(cmdoptions.src())
|
|
45
|
-
self.cmd_opts.add_option(cmdoptions.pre())
|
|
46
43
|
self.cmd_opts.add_option(cmdoptions.require_hashes())
|
|
47
44
|
self.cmd_opts.add_option(cmdoptions.progress_bar())
|
|
48
45
|
self.cmd_opts.add_option(cmdoptions.no_build_isolation())
|
|
@@ -68,7 +65,13 @@ class DownloadCommand(RequirementCommand):
|
|
|
68
65
|
self.parser,
|
|
69
66
|
)
|
|
70
67
|
|
|
68
|
+
selection_opts = cmdoptions.make_option_group(
|
|
69
|
+
cmdoptions.package_selection_group,
|
|
70
|
+
self.parser,
|
|
71
|
+
)
|
|
72
|
+
|
|
71
73
|
self.parser.insert_option_group(0, index_opts)
|
|
74
|
+
self.parser.insert_option_group(0, selection_opts)
|
|
72
75
|
self.parser.insert_option_group(0, self.cmd_opts)
|
|
73
76
|
|
|
74
77
|
@with_cleanup
|
|
@@ -80,6 +83,7 @@ class DownloadCommand(RequirementCommand):
|
|
|
80
83
|
|
|
81
84
|
cmdoptions.check_dist_restriction(options)
|
|
82
85
|
cmdoptions.check_build_constraints(options)
|
|
86
|
+
cmdoptions.check_release_control_exclusive(options)
|
|
83
87
|
|
|
84
88
|
options.download_dir = normalize_path(options.download_dir)
|
|
85
89
|
ensure_dir(options.download_dir)
|
pip/_internal/commands/index.py
CHANGED
|
@@ -6,6 +6,7 @@ from collections.abc import Iterable
|
|
|
6
6
|
from optparse import Values
|
|
7
7
|
from typing import Any, Callable
|
|
8
8
|
|
|
9
|
+
from pip._vendor.packaging.utils import canonicalize_name
|
|
9
10
|
from pip._vendor.packaging.version import Version
|
|
10
11
|
|
|
11
12
|
from pip._internal.cli import cmdoptions
|
|
@@ -40,17 +41,20 @@ class IndexCommand(IndexGroupCommand):
|
|
|
40
41
|
cmdoptions.add_target_python_options(self.cmd_opts)
|
|
41
42
|
|
|
42
43
|
self.cmd_opts.add_option(cmdoptions.ignore_requires_python())
|
|
43
|
-
self.cmd_opts.add_option(cmdoptions.pre())
|
|
44
44
|
self.cmd_opts.add_option(cmdoptions.json())
|
|
45
|
-
self.cmd_opts.add_option(cmdoptions.no_binary())
|
|
46
|
-
self.cmd_opts.add_option(cmdoptions.only_binary())
|
|
47
45
|
|
|
48
46
|
index_opts = cmdoptions.make_option_group(
|
|
49
47
|
cmdoptions.index_group,
|
|
50
48
|
self.parser,
|
|
51
49
|
)
|
|
52
50
|
|
|
51
|
+
selection_opts = cmdoptions.make_option_group(
|
|
52
|
+
cmdoptions.package_selection_group,
|
|
53
|
+
self.parser,
|
|
54
|
+
)
|
|
55
|
+
|
|
53
56
|
self.parser.insert_option_group(0, index_opts)
|
|
57
|
+
self.parser.insert_option_group(0, selection_opts)
|
|
54
58
|
self.parser.insert_option_group(0, self.cmd_opts)
|
|
55
59
|
|
|
56
60
|
def handler_map(self) -> dict[str, Callable[[Values, list[str]], None]]:
|
|
@@ -59,6 +63,8 @@ class IndexCommand(IndexGroupCommand):
|
|
|
59
63
|
}
|
|
60
64
|
|
|
61
65
|
def run(self, options: Values, args: list[str]) -> int:
|
|
66
|
+
cmdoptions.check_release_control_exclusive(options)
|
|
67
|
+
|
|
62
68
|
handler_map = self.handler_map()
|
|
63
69
|
|
|
64
70
|
# Determine action
|
|
@@ -95,7 +101,8 @@ class IndexCommand(IndexGroupCommand):
|
|
|
95
101
|
# Pass allow_yanked=False to ignore yanked versions.
|
|
96
102
|
selection_prefs = SelectionPreferences(
|
|
97
103
|
allow_yanked=False,
|
|
98
|
-
|
|
104
|
+
release_control=options.release_control,
|
|
105
|
+
format_control=options.format_control,
|
|
99
106
|
ignore_requires_python=ignore_requires_python,
|
|
100
107
|
)
|
|
101
108
|
|
|
@@ -103,6 +110,7 @@ class IndexCommand(IndexGroupCommand):
|
|
|
103
110
|
link_collector=link_collector,
|
|
104
111
|
selection_prefs=selection_prefs,
|
|
105
112
|
target_python=target_python,
|
|
113
|
+
uploaded_prior_to=options.uploaded_prior_to,
|
|
106
114
|
)
|
|
107
115
|
|
|
108
116
|
def get_available_package_versions(self, options: Values, args: list[Any]) -> None:
|
|
@@ -124,8 +132,7 @@ class IndexCommand(IndexGroupCommand):
|
|
|
124
132
|
candidate.version for candidate in finder.find_all_candidates(query)
|
|
125
133
|
)
|
|
126
134
|
|
|
127
|
-
if
|
|
128
|
-
# Remove prereleases
|
|
135
|
+
if self.should_exclude_prerelease(options, canonicalize_name(query)):
|
|
129
136
|
versions = (
|
|
130
137
|
version for version in versions if not version.is_prerelease
|
|
131
138
|
)
|