pip 25.1.1__py3-none-any.whl → 25.2__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 +3 -3
- pip/_internal/__init__.py +2 -2
- pip/_internal/build_env.py +118 -94
- pip/_internal/cache.py +16 -14
- pip/_internal/cli/autocompletion.py +13 -4
- pip/_internal/cli/base_command.py +18 -7
- pip/_internal/cli/cmdoptions.py +14 -9
- pip/_internal/cli/command_context.py +4 -3
- pip/_internal/cli/index_command.py +11 -9
- pip/_internal/cli/main.py +3 -2
- pip/_internal/cli/main_parser.py +4 -3
- pip/_internal/cli/parser.py +26 -22
- pip/_internal/cli/progress_bars.py +19 -12
- pip/_internal/cli/req_command.py +16 -12
- pip/_internal/cli/spinners.py +81 -5
- pip/_internal/commands/__init__.py +5 -3
- pip/_internal/commands/cache.py +18 -15
- pip/_internal/commands/check.py +1 -2
- pip/_internal/commands/completion.py +1 -2
- pip/_internal/commands/configuration.py +26 -18
- pip/_internal/commands/debug.py +8 -6
- pip/_internal/commands/download.py +2 -3
- pip/_internal/commands/freeze.py +2 -3
- pip/_internal/commands/hash.py +1 -2
- pip/_internal/commands/help.py +1 -2
- pip/_internal/commands/index.py +15 -9
- pip/_internal/commands/inspect.py +4 -4
- pip/_internal/commands/install.py +44 -39
- pip/_internal/commands/list.py +35 -26
- pip/_internal/commands/lock.py +1 -2
- pip/_internal/commands/search.py +14 -12
- pip/_internal/commands/show.py +14 -11
- pip/_internal/commands/uninstall.py +1 -2
- pip/_internal/commands/wheel.py +2 -3
- pip/_internal/configuration.py +39 -25
- pip/_internal/distributions/base.py +6 -4
- pip/_internal/distributions/installed.py +8 -4
- pip/_internal/distributions/sdist.py +20 -13
- pip/_internal/distributions/wheel.py +6 -4
- pip/_internal/exceptions.py +58 -39
- pip/_internal/index/collector.py +24 -29
- pip/_internal/index/package_finder.py +70 -61
- pip/_internal/index/sources.py +17 -14
- pip/_internal/locations/__init__.py +18 -16
- pip/_internal/locations/_distutils.py +12 -11
- pip/_internal/locations/_sysconfig.py +5 -4
- pip/_internal/locations/base.py +4 -3
- pip/_internal/main.py +2 -2
- pip/_internal/metadata/__init__.py +8 -6
- pip/_internal/metadata/_json.py +5 -4
- pip/_internal/metadata/base.py +22 -27
- pip/_internal/metadata/importlib/_compat.py +6 -4
- pip/_internal/metadata/importlib/_dists.py +12 -17
- pip/_internal/metadata/importlib/_envs.py +9 -6
- pip/_internal/metadata/pkg_resources.py +11 -14
- pip/_internal/models/direct_url.py +24 -21
- pip/_internal/models/format_control.py +5 -5
- pip/_internal/models/installation_report.py +4 -3
- pip/_internal/models/link.py +39 -34
- pip/_internal/models/pylock.py +27 -22
- pip/_internal/models/search_scope.py +6 -7
- pip/_internal/models/selection_prefs.py +3 -3
- pip/_internal/models/target_python.py +10 -9
- pip/_internal/models/wheel.py +7 -5
- pip/_internal/network/auth.py +20 -22
- pip/_internal/network/cache.py +22 -6
- pip/_internal/network/download.py +169 -141
- pip/_internal/network/lazy_wheel.py +10 -7
- pip/_internal/network/session.py +32 -27
- pip/_internal/network/utils.py +2 -2
- pip/_internal/network/xmlrpc.py +2 -2
- pip/_internal/operations/build/build_tracker.py +10 -8
- pip/_internal/operations/build/wheel.py +3 -2
- pip/_internal/operations/build/wheel_editable.py +3 -2
- pip/_internal/operations/build/wheel_legacy.py +9 -8
- pip/_internal/operations/check.py +21 -26
- pip/_internal/operations/freeze.py +12 -9
- pip/_internal/operations/install/editable_legacy.py +5 -3
- pip/_internal/operations/install/wheel.py +49 -41
- pip/_internal/operations/prepare.py +35 -30
- pip/_internal/pyproject.py +7 -10
- pip/_internal/req/__init__.py +12 -10
- pip/_internal/req/constructors.py +33 -31
- pip/_internal/req/req_dependency_group.py +7 -11
- pip/_internal/req/req_file.py +32 -35
- pip/_internal/req/req_install.py +37 -34
- pip/_internal/req/req_set.py +4 -5
- pip/_internal/req/req_uninstall.py +20 -17
- pip/_internal/resolution/base.py +3 -3
- pip/_internal/resolution/legacy/resolver.py +21 -20
- pip/_internal/resolution/resolvelib/base.py +16 -13
- pip/_internal/resolution/resolvelib/candidates.py +29 -26
- pip/_internal/resolution/resolvelib/factory.py +41 -50
- pip/_internal/resolution/resolvelib/found_candidates.py +11 -9
- pip/_internal/resolution/resolvelib/provider.py +15 -20
- pip/_internal/resolution/resolvelib/reporter.py +5 -3
- pip/_internal/resolution/resolvelib/requirements.py +8 -6
- pip/_internal/resolution/resolvelib/resolver.py +39 -23
- pip/_internal/self_outdated_check.py +8 -6
- pip/_internal/utils/appdirs.py +1 -2
- pip/_internal/utils/compat.py +7 -1
- pip/_internal/utils/compatibility_tags.py +17 -16
- pip/_internal/utils/deprecation.py +11 -9
- pip/_internal/utils/direct_url_helpers.py +2 -2
- pip/_internal/utils/egg_link.py +6 -5
- pip/_internal/utils/entrypoints.py +3 -2
- pip/_internal/utils/filesystem.py +8 -5
- pip/_internal/utils/filetypes.py +4 -6
- pip/_internal/utils/glibc.py +6 -5
- pip/_internal/utils/hashes.py +9 -6
- pip/_internal/utils/logging.py +8 -5
- pip/_internal/utils/misc.py +37 -45
- pip/_internal/utils/packaging.py +3 -2
- pip/_internal/utils/retry.py +7 -4
- pip/_internal/utils/setuptools_build.py +12 -10
- pip/_internal/utils/subprocess.py +20 -17
- pip/_internal/utils/temp_dir.py +10 -12
- pip/_internal/utils/unpacking.py +6 -4
- pip/_internal/utils/urls.py +1 -1
- pip/_internal/utils/virtualenv.py +3 -2
- pip/_internal/utils/wheel.py +3 -4
- pip/_internal/vcs/bazaar.py +26 -8
- pip/_internal/vcs/git.py +59 -24
- pip/_internal/vcs/mercurial.py +34 -11
- pip/_internal/vcs/subversion.py +27 -16
- pip/_internal/vcs/versioncontrol.py +56 -51
- pip/_internal/wheel_builder.py +14 -12
- pip/_vendor/cachecontrol/__init__.py +1 -1
- pip/_vendor/certifi/__init__.py +1 -1
- pip/_vendor/certifi/cacert.pem +102 -221
- pip/_vendor/certifi/core.py +1 -32
- pip/_vendor/distlib/__init__.py +2 -2
- pip/_vendor/distlib/scripts.py +1 -1
- pip/_vendor/msgpack/__init__.py +2 -2
- pip/_vendor/pkg_resources/__init__.py +1 -1
- pip/_vendor/platformdirs/version.py +2 -2
- pip/_vendor/pygments/__init__.py +1 -1
- pip/_vendor/requests/__version__.py +2 -2
- pip/_vendor/requests/compat.py +12 -0
- pip/_vendor/requests/models.py +3 -1
- pip/_vendor/requests/utils.py +6 -16
- pip/_vendor/resolvelib/__init__.py +3 -3
- pip/_vendor/resolvelib/reporters.py +1 -1
- pip/_vendor/resolvelib/resolvers/__init__.py +4 -4
- pip/_vendor/resolvelib/resolvers/resolution.py +91 -10
- pip/_vendor/rich/__main__.py +12 -40
- pip/_vendor/rich/_inspect.py +1 -1
- pip/_vendor/rich/_ratio.py +1 -7
- pip/_vendor/rich/align.py +1 -7
- pip/_vendor/rich/box.py +1 -7
- pip/_vendor/rich/console.py +25 -20
- pip/_vendor/rich/control.py +1 -7
- pip/_vendor/rich/diagnose.py +1 -0
- pip/_vendor/rich/emoji.py +1 -6
- pip/_vendor/rich/live.py +32 -7
- pip/_vendor/rich/live_render.py +1 -7
- pip/_vendor/rich/logging.py +1 -1
- pip/_vendor/rich/panel.py +3 -4
- pip/_vendor/rich/progress.py +15 -15
- pip/_vendor/rich/spinner.py +7 -13
- pip/_vendor/rich/syntax.py +24 -5
- pip/_vendor/rich/traceback.py +32 -17
- pip/_vendor/truststore/_api.py +1 -1
- pip/_vendor/vendor.txt +9 -10
- {pip-25.1.1.dist-info → pip-25.2.dist-info}/METADATA +26 -4
- {pip-25.1.1.dist-info → pip-25.2.dist-info}/RECORD +193 -180
- {pip-25.1.1.dist-info → pip-25.2.dist-info}/WHEEL +1 -1
- {pip-25.1.1.dist-info → pip-25.2.dist-info}/licenses/AUTHORS.txt +12 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/cachecontrol/LICENSE.txt +13 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/certifi/LICENSE +20 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/dependency_groups/LICENSE.txt +9 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/distlib/LICENSE.txt +284 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/distro/LICENSE +202 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/idna/LICENSE.md +31 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/msgpack/COPYING +14 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/packaging/LICENSE +3 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.APACHE +177 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.BSD +23 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/pkg_resources/LICENSE +17 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/platformdirs/LICENSE +21 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/pygments/LICENSE +25 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/pyproject_hooks/LICENSE +21 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/requests/LICENSE +175 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/resolvelib/LICENSE +13 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/rich/LICENSE +19 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/tomli/LICENSE +21 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/tomli/LICENSE-HEADER +3 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/tomli_w/LICENSE +21 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/truststore/LICENSE +21 -0
- pip-25.2.dist-info/licenses/src/pip/_vendor/urllib3/LICENSE.txt +21 -0
- pip/_vendor/distlib/database.py +0 -1329
- pip/_vendor/distlib/index.py +0 -508
- pip/_vendor/distlib/locators.py +0 -1295
- pip/_vendor/distlib/manifest.py +0 -384
- pip/_vendor/distlib/markers.py +0 -162
- pip/_vendor/distlib/metadata.py +0 -1031
- pip/_vendor/distlib/version.py +0 -750
- pip/_vendor/distlib/wheel.py +0 -1100
- pip/_vendor/typing_extensions.py +0 -4584
- {pip-25.1.1.dist-info → pip-25.2.dist-info}/entry_points.txt +0 -0
- {pip-25.1.1.dist-info → pip-25.2.dist-info}/licenses/LICENSE.txt +0 -0
- {pip-25.1.1.dist-info → pip-25.2.dist-info}/top_level.txt +0 -0
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""Support for installing and building the "wheel" binary package format."""
|
|
2
2
|
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
3
5
|
import collections
|
|
4
6
|
import compileall
|
|
5
7
|
import contextlib
|
|
@@ -10,8 +12,10 @@ import os.path
|
|
|
10
12
|
import re
|
|
11
13
|
import shutil
|
|
12
14
|
import sys
|
|
15
|
+
import textwrap
|
|
13
16
|
import warnings
|
|
14
17
|
from base64 import urlsafe_b64encode
|
|
18
|
+
from collections.abc import Generator, Iterable, Iterator, Sequence
|
|
15
19
|
from email.message import Message
|
|
16
20
|
from itertools import chain, filterfalse, starmap
|
|
17
21
|
from typing import (
|
|
@@ -19,17 +23,8 @@ from typing import (
|
|
|
19
23
|
Any,
|
|
20
24
|
BinaryIO,
|
|
21
25
|
Callable,
|
|
22
|
-
Dict,
|
|
23
|
-
Generator,
|
|
24
|
-
Iterable,
|
|
25
|
-
Iterator,
|
|
26
|
-
List,
|
|
27
26
|
NewType,
|
|
28
|
-
Optional,
|
|
29
27
|
Protocol,
|
|
30
|
-
Sequence,
|
|
31
|
-
Set,
|
|
32
|
-
Tuple,
|
|
33
28
|
Union,
|
|
34
29
|
cast,
|
|
35
30
|
)
|
|
@@ -60,7 +55,7 @@ from pip._internal.utils.wheel import parse_wheel
|
|
|
60
55
|
|
|
61
56
|
|
|
62
57
|
class File(Protocol):
|
|
63
|
-
src_record_path:
|
|
58
|
+
src_record_path: RecordPath
|
|
64
59
|
dest_path: str
|
|
65
60
|
changed: bool
|
|
66
61
|
|
|
@@ -71,17 +66,17 @@ class File(Protocol):
|
|
|
71
66
|
logger = logging.getLogger(__name__)
|
|
72
67
|
|
|
73
68
|
RecordPath = NewType("RecordPath", str)
|
|
74
|
-
InstalledCSVRow =
|
|
69
|
+
InstalledCSVRow = tuple[RecordPath, str, Union[int, str]]
|
|
75
70
|
|
|
76
71
|
|
|
77
|
-
def rehash(path: str, blocksize: int = 1 << 20) ->
|
|
72
|
+
def rehash(path: str, blocksize: int = 1 << 20) -> tuple[str, str]:
|
|
78
73
|
"""Return (encoded_digest, length) for path using hashlib.sha256()"""
|
|
79
74
|
h, length = hash_file(path, blocksize)
|
|
80
75
|
digest = "sha256=" + urlsafe_b64encode(h.digest()).decode("latin1").rstrip("=")
|
|
81
76
|
return (digest, str(length))
|
|
82
77
|
|
|
83
78
|
|
|
84
|
-
def csv_io_kwargs(mode: str) ->
|
|
79
|
+
def csv_io_kwargs(mode: str) -> dict[str, Any]:
|
|
85
80
|
"""Return keyword arguments to properly open a CSV file
|
|
86
81
|
in the given mode.
|
|
87
82
|
"""
|
|
@@ -112,7 +107,7 @@ def wheel_root_is_purelib(metadata: Message) -> bool:
|
|
|
112
107
|
return metadata.get("Root-Is-Purelib", "").lower() == "true"
|
|
113
108
|
|
|
114
109
|
|
|
115
|
-
def get_entrypoints(dist: BaseDistribution) ->
|
|
110
|
+
def get_entrypoints(dist: BaseDistribution) -> tuple[dict[str, str], dict[str, str]]:
|
|
116
111
|
console_scripts = {}
|
|
117
112
|
gui_scripts = {}
|
|
118
113
|
for entry_point in dist.iter_entry_points():
|
|
@@ -123,7 +118,7 @@ def get_entrypoints(dist: BaseDistribution) -> Tuple[Dict[str, str], Dict[str, s
|
|
|
123
118
|
return console_scripts, gui_scripts
|
|
124
119
|
|
|
125
120
|
|
|
126
|
-
def message_about_scripts_not_on_PATH(scripts: Sequence[str]) ->
|
|
121
|
+
def message_about_scripts_not_on_PATH(scripts: Sequence[str]) -> str | None:
|
|
127
122
|
"""Determine if any scripts are not on PATH and format a warning.
|
|
128
123
|
Returns a warning message if one or more scripts are not on PATH,
|
|
129
124
|
otherwise None.
|
|
@@ -132,7 +127,7 @@ def message_about_scripts_not_on_PATH(scripts: Sequence[str]) -> Optional[str]:
|
|
|
132
127
|
return None
|
|
133
128
|
|
|
134
129
|
# Group scripts by the path they were installed in
|
|
135
|
-
grouped_by_dir:
|
|
130
|
+
grouped_by_dir: dict[str, set[str]] = collections.defaultdict(set)
|
|
136
131
|
for destfile in scripts:
|
|
137
132
|
parent_dir = os.path.dirname(destfile)
|
|
138
133
|
script_name = os.path.basename(destfile)
|
|
@@ -148,7 +143,7 @@ def message_about_scripts_not_on_PATH(scripts: Sequence[str]) -> Optional[str]:
|
|
|
148
143
|
not_warn_dirs.append(
|
|
149
144
|
os.path.normcase(os.path.normpath(os.path.dirname(sys.executable)))
|
|
150
145
|
)
|
|
151
|
-
warn_for:
|
|
146
|
+
warn_for: dict[str, set[str]] = {
|
|
152
147
|
parent_dir: scripts
|
|
153
148
|
for parent_dir, scripts in grouped_by_dir.items()
|
|
154
149
|
if os.path.normcase(os.path.normpath(parent_dir)) not in not_warn_dirs
|
|
@@ -159,7 +154,7 @@ def message_about_scripts_not_on_PATH(scripts: Sequence[str]) -> Optional[str]:
|
|
|
159
154
|
# Format a message
|
|
160
155
|
msg_lines = []
|
|
161
156
|
for parent_dir, dir_scripts in warn_for.items():
|
|
162
|
-
sorted_scripts:
|
|
157
|
+
sorted_scripts: list[str] = sorted(dir_scripts)
|
|
163
158
|
if len(sorted_scripts) == 1:
|
|
164
159
|
start_text = f"script {sorted_scripts[0]} is"
|
|
165
160
|
else:
|
|
@@ -197,7 +192,7 @@ def message_about_scripts_not_on_PATH(scripts: Sequence[str]) -> Optional[str]:
|
|
|
197
192
|
|
|
198
193
|
def _normalized_outrows(
|
|
199
194
|
outrows: Iterable[InstalledCSVRow],
|
|
200
|
-
) ->
|
|
195
|
+
) -> list[tuple[str, str, str]]:
|
|
201
196
|
"""Normalize the given rows of a RECORD file.
|
|
202
197
|
|
|
203
198
|
Items in each row are converted into str. Rows are then sorted to make
|
|
@@ -236,17 +231,17 @@ def _fs_to_record_path(path: str, lib_dir: str) -> RecordPath:
|
|
|
236
231
|
|
|
237
232
|
|
|
238
233
|
def get_csv_rows_for_installed(
|
|
239
|
-
old_csv_rows:
|
|
240
|
-
installed:
|
|
241
|
-
changed:
|
|
242
|
-
generated:
|
|
234
|
+
old_csv_rows: list[list[str]],
|
|
235
|
+
installed: dict[RecordPath, RecordPath],
|
|
236
|
+
changed: set[RecordPath],
|
|
237
|
+
generated: list[str],
|
|
243
238
|
lib_dir: str,
|
|
244
|
-
) ->
|
|
239
|
+
) -> list[InstalledCSVRow]:
|
|
245
240
|
"""
|
|
246
241
|
:param installed: A map from archive RECORD path to installation RECORD
|
|
247
242
|
path.
|
|
248
243
|
"""
|
|
249
|
-
installed_rows:
|
|
244
|
+
installed_rows: list[InstalledCSVRow] = []
|
|
250
245
|
for row in old_csv_rows:
|
|
251
246
|
if len(row) > 3:
|
|
252
247
|
logger.warning("RECORD line has more than three elements: %s", row)
|
|
@@ -267,7 +262,7 @@ def get_csv_rows_for_installed(
|
|
|
267
262
|
]
|
|
268
263
|
|
|
269
264
|
|
|
270
|
-
def get_console_script_specs(console:
|
|
265
|
+
def get_console_script_specs(console: dict[str, str]) -> list[str]:
|
|
271
266
|
"""
|
|
272
267
|
Given the mapping from entrypoint name to callable, return the relevant
|
|
273
268
|
console script specs.
|
|
@@ -381,7 +376,7 @@ class ZipBackedFile:
|
|
|
381
376
|
|
|
382
377
|
|
|
383
378
|
class ScriptFile:
|
|
384
|
-
def __init__(self, file:
|
|
379
|
+
def __init__(self, file: File) -> None:
|
|
385
380
|
self._file = file
|
|
386
381
|
self.src_record_path = self._file.src_record_path
|
|
387
382
|
self.dest_path = self._file.dest_path
|
|
@@ -396,7 +391,7 @@ class MissingCallableSuffix(InstallationError):
|
|
|
396
391
|
def __init__(self, entry_point: str) -> None:
|
|
397
392
|
super().__init__(
|
|
398
393
|
f"Invalid script entry point: {entry_point} - A callable "
|
|
399
|
-
"suffix is required.
|
|
394
|
+
"suffix is required. See https://packaging.python.org/"
|
|
400
395
|
"specifications/entry-points/#use-for-scripts for more "
|
|
401
396
|
"information."
|
|
402
397
|
)
|
|
@@ -409,9 +404,22 @@ def _raise_for_invalid_entrypoint(specification: str) -> None:
|
|
|
409
404
|
|
|
410
405
|
|
|
411
406
|
class PipScriptMaker(ScriptMaker):
|
|
407
|
+
# Override distlib's default script template with one that
|
|
408
|
+
# doesn't import `re` module, allowing scripts to load faster.
|
|
409
|
+
script_template = textwrap.dedent(
|
|
410
|
+
"""\
|
|
411
|
+
import sys
|
|
412
|
+
from %(module)s import %(import_name)s
|
|
413
|
+
if __name__ == '__main__':
|
|
414
|
+
if sys.argv[0].endswith('.exe'):
|
|
415
|
+
sys.argv[0] = sys.argv[0][:-4]
|
|
416
|
+
sys.exit(%(func)s())
|
|
417
|
+
"""
|
|
418
|
+
)
|
|
419
|
+
|
|
412
420
|
def make(
|
|
413
|
-
self, specification: str, options:
|
|
414
|
-
) ->
|
|
421
|
+
self, specification: str, options: dict[str, Any] | None = None
|
|
422
|
+
) -> list[str]:
|
|
415
423
|
_raise_for_invalid_entrypoint(specification)
|
|
416
424
|
return super().make(specification, options)
|
|
417
425
|
|
|
@@ -423,7 +431,7 @@ def _install_wheel( # noqa: C901, PLR0915 function is too long
|
|
|
423
431
|
scheme: Scheme,
|
|
424
432
|
pycompile: bool = True,
|
|
425
433
|
warn_script_location: bool = True,
|
|
426
|
-
direct_url:
|
|
434
|
+
direct_url: DirectUrl | None = None,
|
|
427
435
|
requested: bool = False,
|
|
428
436
|
) -> None:
|
|
429
437
|
"""Install a wheel.
|
|
@@ -452,9 +460,9 @@ def _install_wheel( # noqa: C901, PLR0915 function is too long
|
|
|
452
460
|
# installed = files copied from the wheel to the destination
|
|
453
461
|
# changed = files changed while installing (scripts #! line typically)
|
|
454
462
|
# generated = files newly generated during the install (script wrappers)
|
|
455
|
-
installed:
|
|
456
|
-
changed:
|
|
457
|
-
generated:
|
|
463
|
+
installed: dict[RecordPath, RecordPath] = {}
|
|
464
|
+
changed: set[RecordPath] = set()
|
|
465
|
+
generated: list[str] = []
|
|
458
466
|
|
|
459
467
|
def record_installed(
|
|
460
468
|
srcfile: RecordPath, destfile: str, modified: bool = False
|
|
@@ -480,8 +488,8 @@ def _install_wheel( # noqa: C901, PLR0915 function is too long
|
|
|
480
488
|
|
|
481
489
|
def root_scheme_file_maker(
|
|
482
490
|
zip_file: ZipFile, dest: str
|
|
483
|
-
) -> Callable[[RecordPath],
|
|
484
|
-
def make_root_scheme_file(record_path: RecordPath) ->
|
|
491
|
+
) -> Callable[[RecordPath], File]:
|
|
492
|
+
def make_root_scheme_file(record_path: RecordPath) -> File:
|
|
485
493
|
normed_path = os.path.normpath(record_path)
|
|
486
494
|
dest_path = os.path.join(dest, normed_path)
|
|
487
495
|
assert_no_path_traversal(dest, dest_path)
|
|
@@ -491,10 +499,10 @@ def _install_wheel( # noqa: C901, PLR0915 function is too long
|
|
|
491
499
|
|
|
492
500
|
def data_scheme_file_maker(
|
|
493
501
|
zip_file: ZipFile, scheme: Scheme
|
|
494
|
-
) -> Callable[[RecordPath],
|
|
502
|
+
) -> Callable[[RecordPath], File]:
|
|
495
503
|
scheme_paths = {key: getattr(scheme, key) for key in SCHEME_KEYS}
|
|
496
504
|
|
|
497
|
-
def make_data_scheme_file(record_path: RecordPath) ->
|
|
505
|
+
def make_data_scheme_file(record_path: RecordPath) -> File:
|
|
498
506
|
normed_path = os.path.normpath(record_path)
|
|
499
507
|
try:
|
|
500
508
|
_, scheme_key, dest_subpath = normed_path.split(os.path.sep, 2)
|
|
@@ -526,7 +534,7 @@ def _install_wheel( # noqa: C901, PLR0915 function is too long
|
|
|
526
534
|
def is_data_scheme_path(path: RecordPath) -> bool:
|
|
527
535
|
return path.split("/", 1)[0].endswith(".data")
|
|
528
536
|
|
|
529
|
-
paths = cast(
|
|
537
|
+
paths = cast(list[RecordPath], wheel_zip.namelist())
|
|
530
538
|
file_paths = filterfalse(is_dir_path, paths)
|
|
531
539
|
root_scheme_paths, data_scheme_paths = partition(is_data_scheme_path, file_paths)
|
|
532
540
|
|
|
@@ -552,7 +560,7 @@ def _install_wheel( # noqa: C901, PLR0915 function is too long
|
|
|
552
560
|
)
|
|
553
561
|
console, gui = get_entrypoints(distribution)
|
|
554
562
|
|
|
555
|
-
def is_entrypoint_wrapper(file:
|
|
563
|
+
def is_entrypoint_wrapper(file: File) -> bool:
|
|
556
564
|
# EP, EP.exe and EP-script.py are scripts generated for
|
|
557
565
|
# entry point EP by setuptools
|
|
558
566
|
path = file.dest_path
|
|
@@ -721,7 +729,7 @@ def install_wheel(
|
|
|
721
729
|
req_description: str,
|
|
722
730
|
pycompile: bool = True,
|
|
723
731
|
warn_script_location: bool = True,
|
|
724
|
-
direct_url:
|
|
732
|
+
direct_url: DirectUrl | None = None,
|
|
725
733
|
requested: bool = False,
|
|
726
734
|
) -> None:
|
|
727
735
|
with ZipFile(wheel_path, allowZip64=True) as z:
|
|
@@ -2,16 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
# The following comment should be removed at some point in the future.
|
|
4
4
|
# mypy: strict-optional=False
|
|
5
|
+
from __future__ import annotations
|
|
5
6
|
|
|
6
7
|
import mimetypes
|
|
7
8
|
import os
|
|
8
9
|
import shutil
|
|
10
|
+
from collections.abc import Iterable
|
|
9
11
|
from dataclasses import dataclass
|
|
10
12
|
from pathlib import Path
|
|
11
|
-
from typing import
|
|
13
|
+
from typing import TYPE_CHECKING
|
|
12
14
|
|
|
13
15
|
from pip._vendor.packaging.utils import canonicalize_name
|
|
14
16
|
|
|
17
|
+
from pip._internal.build_env import BuildEnvironmentInstaller
|
|
15
18
|
from pip._internal.distributions import make_distribution_for_install_requirement
|
|
16
19
|
from pip._internal.distributions.installed import InstalledDistribution
|
|
17
20
|
from pip._internal.exceptions import (
|
|
@@ -28,7 +31,7 @@ from pip._internal.metadata import BaseDistribution, get_metadata_distribution
|
|
|
28
31
|
from pip._internal.models.direct_url import ArchiveInfo
|
|
29
32
|
from pip._internal.models.link import Link
|
|
30
33
|
from pip._internal.models.wheel import Wheel
|
|
31
|
-
from pip._internal.network.download import
|
|
34
|
+
from pip._internal.network.download import Downloader
|
|
32
35
|
from pip._internal.network.lazy_wheel import (
|
|
33
36
|
HTTPRangeRequestUnsupported,
|
|
34
37
|
dist_from_wheel_url,
|
|
@@ -53,13 +56,16 @@ from pip._internal.utils.temp_dir import TempDirectory
|
|
|
53
56
|
from pip._internal.utils.unpacking import unpack_file
|
|
54
57
|
from pip._internal.vcs import vcs
|
|
55
58
|
|
|
59
|
+
if TYPE_CHECKING:
|
|
60
|
+
from pip._internal.cli.progress_bars import BarType
|
|
61
|
+
|
|
56
62
|
logger = getLogger(__name__)
|
|
57
63
|
|
|
58
64
|
|
|
59
65
|
def _get_prepared_distribution(
|
|
60
66
|
req: InstallRequirement,
|
|
61
67
|
build_tracker: BuildTracker,
|
|
62
|
-
|
|
68
|
+
build_env_installer: BuildEnvironmentInstaller,
|
|
63
69
|
build_isolation: bool,
|
|
64
70
|
check_build_deps: bool,
|
|
65
71
|
) -> BaseDistribution:
|
|
@@ -69,7 +75,7 @@ def _get_prepared_distribution(
|
|
|
69
75
|
if tracker_id is not None:
|
|
70
76
|
with build_tracker.track(req, tracker_id):
|
|
71
77
|
abstract_dist.prepare_distribution_metadata(
|
|
72
|
-
|
|
78
|
+
build_env_installer, build_isolation, check_build_deps
|
|
73
79
|
)
|
|
74
80
|
return abstract_dist.get_metadata_distribution()
|
|
75
81
|
|
|
@@ -83,7 +89,7 @@ def unpack_vcs_link(link: Link, location: str, verbosity: int) -> None:
|
|
|
83
89
|
@dataclass
|
|
84
90
|
class File:
|
|
85
91
|
path: str
|
|
86
|
-
content_type:
|
|
92
|
+
content_type: str | None = None
|
|
87
93
|
|
|
88
94
|
def __post_init__(self) -> None:
|
|
89
95
|
if self.content_type is None:
|
|
@@ -98,8 +104,8 @@ class File:
|
|
|
98
104
|
def get_http_url(
|
|
99
105
|
link: Link,
|
|
100
106
|
download: Downloader,
|
|
101
|
-
download_dir:
|
|
102
|
-
hashes:
|
|
107
|
+
download_dir: str | None = None,
|
|
108
|
+
hashes: Hashes | None = None,
|
|
103
109
|
) -> File:
|
|
104
110
|
temp_dir = TempDirectory(kind="unpack", globally_managed=True)
|
|
105
111
|
# If a download dir is specified, is the file already downloaded there?
|
|
@@ -120,7 +126,7 @@ def get_http_url(
|
|
|
120
126
|
|
|
121
127
|
|
|
122
128
|
def get_file_url(
|
|
123
|
-
link: Link, download_dir:
|
|
129
|
+
link: Link, download_dir: str | None = None, hashes: Hashes | None = None
|
|
124
130
|
) -> File:
|
|
125
131
|
"""Get file and optionally check its hash."""
|
|
126
132
|
# If a download dir is specified, is the file already there and valid?
|
|
@@ -148,9 +154,9 @@ def unpack_url(
|
|
|
148
154
|
location: str,
|
|
149
155
|
download: Downloader,
|
|
150
156
|
verbosity: int,
|
|
151
|
-
download_dir:
|
|
152
|
-
hashes:
|
|
153
|
-
) ->
|
|
157
|
+
download_dir: str | None = None,
|
|
158
|
+
hashes: Hashes | None = None,
|
|
159
|
+
) -> File | None:
|
|
154
160
|
"""Unpack link into location, downloading if required.
|
|
155
161
|
|
|
156
162
|
:param hashes: A Hashes object, one of whose embedded hashes must match,
|
|
@@ -189,9 +195,9 @@ def unpack_url(
|
|
|
189
195
|
def _check_download_dir(
|
|
190
196
|
link: Link,
|
|
191
197
|
download_dir: str,
|
|
192
|
-
hashes:
|
|
198
|
+
hashes: Hashes | None,
|
|
193
199
|
warn_on_hash_mismatch: bool = True,
|
|
194
|
-
) ->
|
|
200
|
+
) -> str | None:
|
|
195
201
|
"""Check download_dir for previously downloaded file with correct hash
|
|
196
202
|
If a correct file is found return its path else None
|
|
197
203
|
"""
|
|
@@ -219,16 +225,18 @@ def _check_download_dir(
|
|
|
219
225
|
class RequirementPreparer:
|
|
220
226
|
"""Prepares a Requirement"""
|
|
221
227
|
|
|
222
|
-
def __init__(
|
|
228
|
+
def __init__( # noqa: PLR0913 (too many parameters)
|
|
223
229
|
self,
|
|
230
|
+
*,
|
|
224
231
|
build_dir: str,
|
|
225
|
-
download_dir:
|
|
232
|
+
download_dir: str | None,
|
|
226
233
|
src_dir: str,
|
|
227
234
|
build_isolation: bool,
|
|
235
|
+
build_isolation_installer: BuildEnvironmentInstaller,
|
|
228
236
|
check_build_deps: bool,
|
|
229
237
|
build_tracker: BuildTracker,
|
|
230
238
|
session: PipSession,
|
|
231
|
-
progress_bar:
|
|
239
|
+
progress_bar: BarType,
|
|
232
240
|
finder: PackageFinder,
|
|
233
241
|
require_hashes: bool,
|
|
234
242
|
use_user_site: bool,
|
|
@@ -244,7 +252,6 @@ class RequirementPreparer:
|
|
|
244
252
|
self.build_tracker = build_tracker
|
|
245
253
|
self._session = session
|
|
246
254
|
self._download = Downloader(session, progress_bar, resume_retries)
|
|
247
|
-
self._batch_download = BatchDownloader(session, progress_bar, resume_retries)
|
|
248
255
|
self.finder = finder
|
|
249
256
|
|
|
250
257
|
# Where still-packed archives should be written to. If None, they are
|
|
@@ -253,6 +260,7 @@ class RequirementPreparer:
|
|
|
253
260
|
|
|
254
261
|
# Is build isolation allowed?
|
|
255
262
|
self.build_isolation = build_isolation
|
|
263
|
+
self.build_env_installer = build_isolation_installer
|
|
256
264
|
|
|
257
265
|
# Should check build dependencies?
|
|
258
266
|
self.check_build_deps = check_build_deps
|
|
@@ -273,7 +281,7 @@ class RequirementPreparer:
|
|
|
273
281
|
self.legacy_resolver = legacy_resolver
|
|
274
282
|
|
|
275
283
|
# Memoized downloaded files, as mapping of url: path.
|
|
276
|
-
self._downloaded:
|
|
284
|
+
self._downloaded: dict[str, str] = {}
|
|
277
285
|
|
|
278
286
|
# Previous "header" printed for a link-based InstallRequirement
|
|
279
287
|
self._previous_requirement_header = ("", "")
|
|
@@ -291,7 +299,7 @@ class RequirementPreparer:
|
|
|
291
299
|
# would already be included if we used req directly)
|
|
292
300
|
if req.req and req.comes_from:
|
|
293
301
|
if isinstance(req.comes_from, str):
|
|
294
|
-
comes_from:
|
|
302
|
+
comes_from: str | None = req.comes_from
|
|
295
303
|
else:
|
|
296
304
|
comes_from = req.comes_from.from_path()
|
|
297
305
|
if comes_from:
|
|
@@ -363,7 +371,7 @@ class RequirementPreparer:
|
|
|
363
371
|
def _fetch_metadata_only(
|
|
364
372
|
self,
|
|
365
373
|
req: InstallRequirement,
|
|
366
|
-
) ->
|
|
374
|
+
) -> BaseDistribution | None:
|
|
367
375
|
if self.legacy_resolver:
|
|
368
376
|
logger.debug(
|
|
369
377
|
"Metadata-only fetching is not used in the legacy resolver",
|
|
@@ -382,7 +390,7 @@ class RequirementPreparer:
|
|
|
382
390
|
def _fetch_metadata_using_link_data_attr(
|
|
383
391
|
self,
|
|
384
392
|
req: InstallRequirement,
|
|
385
|
-
) ->
|
|
393
|
+
) -> BaseDistribution | None:
|
|
386
394
|
"""Fetch metadata from the data-dist-info-metadata attribute, if possible."""
|
|
387
395
|
# (1) Get the link to the metadata file, if provided by the backend.
|
|
388
396
|
metadata_link = req.link.metadata_link()
|
|
@@ -423,7 +431,7 @@ class RequirementPreparer:
|
|
|
423
431
|
def _fetch_metadata_using_lazy_wheel(
|
|
424
432
|
self,
|
|
425
433
|
link: Link,
|
|
426
|
-
) ->
|
|
434
|
+
) -> BaseDistribution | None:
|
|
427
435
|
"""Fetch metadata using lazy wheel, if possible."""
|
|
428
436
|
# --use-feature=fast-deps must be provided.
|
|
429
437
|
if not self.use_lazy_wheel:
|
|
@@ -462,15 +470,12 @@ class RequirementPreparer:
|
|
|
462
470
|
# Map each link to the requirement that owns it. This allows us to set
|
|
463
471
|
# `req.local_file_path` on the appropriate requirement after passing
|
|
464
472
|
# all the links at once into BatchDownloader.
|
|
465
|
-
links_to_fully_download:
|
|
473
|
+
links_to_fully_download: dict[Link, InstallRequirement] = {}
|
|
466
474
|
for req in partially_downloaded_reqs:
|
|
467
475
|
assert req.link
|
|
468
476
|
links_to_fully_download[req.link] = req
|
|
469
477
|
|
|
470
|
-
batch_download = self.
|
|
471
|
-
links_to_fully_download.keys(),
|
|
472
|
-
temp_dir,
|
|
473
|
-
)
|
|
478
|
+
batch_download = self._download.batch(links_to_fully_download.keys(), temp_dir)
|
|
474
479
|
for link, (filepath, _) in batch_download:
|
|
475
480
|
logger.debug("Downloading link %s to %s", link, filepath)
|
|
476
481
|
req = links_to_fully_download[link]
|
|
@@ -547,7 +552,7 @@ class RequirementPreparer:
|
|
|
547
552
|
|
|
548
553
|
# Prepare requirements we found were already downloaded for some
|
|
549
554
|
# reason. The other downloads will be completed separately.
|
|
550
|
-
partially_downloaded_reqs:
|
|
555
|
+
partially_downloaded_reqs: list[InstallRequirement] = []
|
|
551
556
|
for req in reqs:
|
|
552
557
|
if req.needs_more_preparation:
|
|
553
558
|
partially_downloaded_reqs.append(req)
|
|
@@ -647,7 +652,7 @@ class RequirementPreparer:
|
|
|
647
652
|
dist = _get_prepared_distribution(
|
|
648
653
|
req,
|
|
649
654
|
self.build_tracker,
|
|
650
|
-
self.
|
|
655
|
+
self.build_env_installer,
|
|
651
656
|
self.build_isolation,
|
|
652
657
|
self.check_build_deps,
|
|
653
658
|
)
|
|
@@ -703,7 +708,7 @@ class RequirementPreparer:
|
|
|
703
708
|
dist = _get_prepared_distribution(
|
|
704
709
|
req,
|
|
705
710
|
self.build_tracker,
|
|
706
|
-
self.
|
|
711
|
+
self.build_env_installer,
|
|
707
712
|
self.build_isolation,
|
|
708
713
|
self.check_build_deps,
|
|
709
714
|
)
|
pip/_internal/pyproject.py
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import importlib.util
|
|
2
4
|
import os
|
|
3
|
-
import sys
|
|
4
5
|
from collections import namedtuple
|
|
5
|
-
from typing import Any
|
|
6
|
-
|
|
7
|
-
if sys.version_info >= (3, 11):
|
|
8
|
-
import tomllib
|
|
9
|
-
else:
|
|
10
|
-
from pip._vendor import tomli as tomllib
|
|
6
|
+
from typing import Any
|
|
11
7
|
|
|
12
8
|
from pip._vendor.packaging.requirements import InvalidRequirement
|
|
13
9
|
|
|
@@ -16,6 +12,7 @@ from pip._internal.exceptions import (
|
|
|
16
12
|
InvalidPyProjectBuildRequires,
|
|
17
13
|
MissingPyProjectBuildRequires,
|
|
18
14
|
)
|
|
15
|
+
from pip._internal.utils.compat import tomllib
|
|
19
16
|
from pip._internal.utils.packaging import get_requirement
|
|
20
17
|
|
|
21
18
|
|
|
@@ -33,8 +30,8 @@ BuildSystemDetails = namedtuple(
|
|
|
33
30
|
|
|
34
31
|
|
|
35
32
|
def load_pyproject_toml(
|
|
36
|
-
use_pep517:
|
|
37
|
-
) ->
|
|
33
|
+
use_pep517: bool | None, pyproject_toml: str, setup_py: str, req_name: str
|
|
34
|
+
) -> BuildSystemDetails | None:
|
|
38
35
|
"""Load the pyproject.toml file.
|
|
39
36
|
|
|
40
37
|
Parameters:
|
|
@@ -166,7 +163,7 @@ def load_pyproject_toml(
|
|
|
166
163
|
|
|
167
164
|
backend = build_system.get("build-backend")
|
|
168
165
|
backend_path = build_system.get("backend-path", [])
|
|
169
|
-
check:
|
|
166
|
+
check: list[str] = []
|
|
170
167
|
if backend is None:
|
|
171
168
|
# If the user didn't specify a backend, we assume they want to use
|
|
172
169
|
# the setuptools backend. But we can't be sure they have included
|
pip/_internal/req/__init__.py
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import collections
|
|
2
4
|
import logging
|
|
5
|
+
from collections.abc import Generator, Sequence
|
|
3
6
|
from dataclasses import dataclass
|
|
4
|
-
from typing import Generator, List, Optional, Sequence, Tuple
|
|
5
7
|
|
|
6
|
-
from pip._internal.cli.progress_bars import get_install_progress_renderer
|
|
8
|
+
from pip._internal.cli.progress_bars import BarType, get_install_progress_renderer
|
|
7
9
|
from pip._internal.utils.logging import indent_log
|
|
8
10
|
|
|
9
11
|
from .req_file import parse_requirements
|
|
@@ -26,24 +28,24 @@ class InstallationResult:
|
|
|
26
28
|
|
|
27
29
|
|
|
28
30
|
def _validate_requirements(
|
|
29
|
-
requirements:
|
|
30
|
-
) -> Generator[
|
|
31
|
+
requirements: list[InstallRequirement],
|
|
32
|
+
) -> Generator[tuple[str, InstallRequirement], None, None]:
|
|
31
33
|
for req in requirements:
|
|
32
34
|
assert req.name, f"invalid to-be-installed requirement: {req}"
|
|
33
35
|
yield req.name, req
|
|
34
36
|
|
|
35
37
|
|
|
36
38
|
def install_given_reqs(
|
|
37
|
-
requirements:
|
|
39
|
+
requirements: list[InstallRequirement],
|
|
38
40
|
global_options: Sequence[str],
|
|
39
|
-
root:
|
|
40
|
-
home:
|
|
41
|
-
prefix:
|
|
41
|
+
root: str | None,
|
|
42
|
+
home: str | None,
|
|
43
|
+
prefix: str | None,
|
|
42
44
|
warn_script_location: bool,
|
|
43
45
|
use_user_site: bool,
|
|
44
46
|
pycompile: bool,
|
|
45
|
-
progress_bar:
|
|
46
|
-
) ->
|
|
47
|
+
progress_bar: BarType,
|
|
48
|
+
) -> list[InstallationResult]:
|
|
47
49
|
"""
|
|
48
50
|
Install everything in the given list.
|
|
49
51
|
|