pip 25.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 +45 -40
- 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 +53 -44
- 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 +9 -8
- 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 +54 -44
- 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/dependency_groups/_implementation.py +7 -11
- 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 +10 -11
- {pip-25.1.dist-info → pip-25.2.dist-info}/METADATA +26 -4
- {pip-25.1.dist-info → pip-25.2.dist-info}/RECORD +194 -181
- {pip-25.1.dist-info → pip-25.2.dist-info}/WHEEL +1 -1
- {pip-25.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.dist-info → pip-25.2.dist-info}/entry_points.txt +0 -0
- {pip-25.1.dist-info → pip-25.2.dist-info}/licenses/LICENSE.txt +0 -0
- {pip-25.1.dist-info → pip-25.2.dist-info}/top_level.txt +0 -0
pip/_internal/commands/list.py
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import json
|
|
2
4
|
import logging
|
|
5
|
+
from collections.abc import Generator, Sequence
|
|
3
6
|
from email.parser import Parser
|
|
4
7
|
from optparse import Values
|
|
5
|
-
from typing import TYPE_CHECKING,
|
|
8
|
+
from typing import TYPE_CHECKING, cast
|
|
6
9
|
|
|
7
10
|
from pip._vendor.packaging.utils import canonicalize_name
|
|
8
|
-
from pip._vendor.packaging.version import Version
|
|
11
|
+
from pip._vendor.packaging.version import InvalidVersion, Version
|
|
9
12
|
|
|
10
13
|
from pip._internal.cli import cmdoptions
|
|
11
14
|
from pip._internal.cli.index_command import IndexGroupCommand
|
|
@@ -140,8 +143,8 @@ class ListCommand(IndexGroupCommand):
|
|
|
140
143
|
super().handle_pip_version_check(options)
|
|
141
144
|
|
|
142
145
|
def _build_package_finder(
|
|
143
|
-
self, options: Values, session:
|
|
144
|
-
) ->
|
|
146
|
+
self, options: Values, session: PipSession
|
|
147
|
+
) -> PackageFinder:
|
|
145
148
|
"""
|
|
146
149
|
Create a package finder appropriate to this list command.
|
|
147
150
|
"""
|
|
@@ -162,7 +165,7 @@ class ListCommand(IndexGroupCommand):
|
|
|
162
165
|
selection_prefs=selection_prefs,
|
|
163
166
|
)
|
|
164
167
|
|
|
165
|
-
def run(self, options: Values, args:
|
|
168
|
+
def run(self, options: Values, args: list[str]) -> int:
|
|
166
169
|
if options.outdated and options.uptodate:
|
|
167
170
|
raise CommandError("Options --outdated and --uptodate cannot be combined.")
|
|
168
171
|
|
|
@@ -204,8 +207,8 @@ class ListCommand(IndexGroupCommand):
|
|
|
204
207
|
return SUCCESS
|
|
205
208
|
|
|
206
209
|
def get_outdated(
|
|
207
|
-
self, packages:
|
|
208
|
-
) ->
|
|
210
|
+
self, packages: _ProcessedDists, options: Values
|
|
211
|
+
) -> _ProcessedDists:
|
|
209
212
|
return [
|
|
210
213
|
dist
|
|
211
214
|
for dist in self.iter_packages_latest_infos(packages, options)
|
|
@@ -213,8 +216,8 @@ class ListCommand(IndexGroupCommand):
|
|
|
213
216
|
]
|
|
214
217
|
|
|
215
218
|
def get_uptodate(
|
|
216
|
-
self, packages:
|
|
217
|
-
) ->
|
|
219
|
+
self, packages: _ProcessedDists, options: Values
|
|
220
|
+
) -> _ProcessedDists:
|
|
218
221
|
return [
|
|
219
222
|
dist
|
|
220
223
|
for dist in self.iter_packages_latest_infos(packages, options)
|
|
@@ -222,8 +225,8 @@ class ListCommand(IndexGroupCommand):
|
|
|
222
225
|
]
|
|
223
226
|
|
|
224
227
|
def get_not_required(
|
|
225
|
-
self, packages:
|
|
226
|
-
) ->
|
|
228
|
+
self, packages: _ProcessedDists, options: Values
|
|
229
|
+
) -> _ProcessedDists:
|
|
227
230
|
dep_keys = {
|
|
228
231
|
canonicalize_name(dep.name)
|
|
229
232
|
for dist in packages
|
|
@@ -236,14 +239,14 @@ class ListCommand(IndexGroupCommand):
|
|
|
236
239
|
return list({pkg for pkg in packages if pkg.canonical_name not in dep_keys})
|
|
237
240
|
|
|
238
241
|
def iter_packages_latest_infos(
|
|
239
|
-
self, packages:
|
|
240
|
-
) -> Generator[
|
|
242
|
+
self, packages: _ProcessedDists, options: Values
|
|
243
|
+
) -> Generator[_DistWithLatestInfo, None, None]:
|
|
241
244
|
with self._build_session(options) as session:
|
|
242
245
|
finder = self._build_package_finder(options, session)
|
|
243
246
|
|
|
244
247
|
def latest_info(
|
|
245
|
-
dist:
|
|
246
|
-
) ->
|
|
248
|
+
dist: _DistWithLatestInfo,
|
|
249
|
+
) -> _DistWithLatestInfo | None:
|
|
247
250
|
all_candidates = finder.find_all_candidates(dist.canonical_name)
|
|
248
251
|
if not options.pre:
|
|
249
252
|
# Remove prereleases
|
|
@@ -274,7 +277,7 @@ class ListCommand(IndexGroupCommand):
|
|
|
274
277
|
yield dist
|
|
275
278
|
|
|
276
279
|
def output_package_listing(
|
|
277
|
-
self, packages:
|
|
280
|
+
self, packages: _ProcessedDists, options: Values
|
|
278
281
|
) -> None:
|
|
279
282
|
packages = sorted(
|
|
280
283
|
packages,
|
|
@@ -285,17 +288,19 @@ class ListCommand(IndexGroupCommand):
|
|
|
285
288
|
self.output_package_listing_columns(data, header)
|
|
286
289
|
elif options.list_format == "freeze":
|
|
287
290
|
for dist in packages:
|
|
291
|
+
try:
|
|
292
|
+
req_string = f"{dist.raw_name}=={dist.version}"
|
|
293
|
+
except InvalidVersion:
|
|
294
|
+
req_string = f"{dist.raw_name}==={dist.raw_version}"
|
|
288
295
|
if options.verbose >= 1:
|
|
289
|
-
write_output(
|
|
290
|
-
"%s==%s (%s)", dist.raw_name, dist.version, dist.location
|
|
291
|
-
)
|
|
296
|
+
write_output("%s (%s)", req_string, dist.location)
|
|
292
297
|
else:
|
|
293
|
-
write_output(
|
|
298
|
+
write_output(req_string)
|
|
294
299
|
elif options.list_format == "json":
|
|
295
300
|
write_output(format_for_json(packages, options))
|
|
296
301
|
|
|
297
302
|
def output_package_listing_columns(
|
|
298
|
-
self, data:
|
|
303
|
+
self, data: list[list[str]], header: list[str]
|
|
299
304
|
) -> None:
|
|
300
305
|
# insert the header first: we need to know the size of column names
|
|
301
306
|
if len(data) > 0:
|
|
@@ -312,8 +317,8 @@ class ListCommand(IndexGroupCommand):
|
|
|
312
317
|
|
|
313
318
|
|
|
314
319
|
def format_for_columns(
|
|
315
|
-
pkgs:
|
|
316
|
-
) ->
|
|
320
|
+
pkgs: _ProcessedDists, options: Values
|
|
321
|
+
) -> tuple[list[list[str]], list[str]]:
|
|
317
322
|
"""
|
|
318
323
|
Convert the package data into something usable
|
|
319
324
|
by output_package_listing_columns.
|
|
@@ -324,7 +329,7 @@ def format_for_columns(
|
|
|
324
329
|
if running_outdated:
|
|
325
330
|
header.extend(["Latest", "Type"])
|
|
326
331
|
|
|
327
|
-
def wheel_build_tag(dist: BaseDistribution) ->
|
|
332
|
+
def wheel_build_tag(dist: BaseDistribution) -> str | None:
|
|
328
333
|
try:
|
|
329
334
|
wheel_file = dist.read_text("WHEEL")
|
|
330
335
|
except FileNotFoundError:
|
|
@@ -371,12 +376,16 @@ def format_for_columns(
|
|
|
371
376
|
return data, header
|
|
372
377
|
|
|
373
378
|
|
|
374
|
-
def format_for_json(packages:
|
|
379
|
+
def format_for_json(packages: _ProcessedDists, options: Values) -> str:
|
|
375
380
|
data = []
|
|
376
381
|
for dist in packages:
|
|
382
|
+
try:
|
|
383
|
+
version = str(dist.version)
|
|
384
|
+
except InvalidVersion:
|
|
385
|
+
version = dist.raw_version
|
|
377
386
|
info = {
|
|
378
387
|
"name": dist.raw_name,
|
|
379
|
-
"version":
|
|
388
|
+
"version": version,
|
|
380
389
|
}
|
|
381
390
|
if options.verbose >= 1:
|
|
382
391
|
info["location"] = dist.location or ""
|
pip/_internal/commands/lock.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import sys
|
|
2
2
|
from optparse import Values
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import List
|
|
5
4
|
|
|
6
5
|
from pip._internal.cache import WheelCache
|
|
7
6
|
from pip._internal.cli import cmdoptions
|
|
@@ -90,7 +89,7 @@ class LockCommand(RequirementCommand):
|
|
|
90
89
|
self.parser.insert_option_group(0, self.cmd_opts)
|
|
91
90
|
|
|
92
91
|
@with_cleanup
|
|
93
|
-
def run(self, options: Values, args:
|
|
92
|
+
def run(self, options: Values, args: list[str]) -> int:
|
|
94
93
|
logger.verbose("Using %s", get_pip_version())
|
|
95
94
|
|
|
96
95
|
logger.warning(
|
pip/_internal/commands/search.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import logging
|
|
2
4
|
import shutil
|
|
3
5
|
import sys
|
|
@@ -5,7 +7,7 @@ import textwrap
|
|
|
5
7
|
import xmlrpc.client
|
|
6
8
|
from collections import OrderedDict
|
|
7
9
|
from optparse import Values
|
|
8
|
-
from typing import
|
|
10
|
+
from typing import TypedDict
|
|
9
11
|
|
|
10
12
|
from pip._vendor.packaging.version import parse as parse_version
|
|
11
13
|
|
|
@@ -24,7 +26,7 @@ from pip._internal.utils.misc import write_output
|
|
|
24
26
|
class TransformedHit(TypedDict):
|
|
25
27
|
name: str
|
|
26
28
|
summary: str
|
|
27
|
-
versions:
|
|
29
|
+
versions: list[str]
|
|
28
30
|
|
|
29
31
|
|
|
30
32
|
logger = logging.getLogger(__name__)
|
|
@@ -49,7 +51,7 @@ class SearchCommand(Command, SessionCommandMixin):
|
|
|
49
51
|
|
|
50
52
|
self.parser.insert_option_group(0, self.cmd_opts)
|
|
51
53
|
|
|
52
|
-
def run(self, options: Values, args:
|
|
54
|
+
def run(self, options: Values, args: list[str]) -> int:
|
|
53
55
|
if not args:
|
|
54
56
|
raise CommandError("Missing required argument (search query).")
|
|
55
57
|
query = args
|
|
@@ -65,7 +67,7 @@ class SearchCommand(Command, SessionCommandMixin):
|
|
|
65
67
|
return SUCCESS
|
|
66
68
|
return NO_MATCHES_FOUND
|
|
67
69
|
|
|
68
|
-
def search(self, query:
|
|
70
|
+
def search(self, query: list[str], options: Values) -> list[dict[str, str]]:
|
|
69
71
|
index_url = options.index
|
|
70
72
|
|
|
71
73
|
session = self.get_default_session(options)
|
|
@@ -83,13 +85,13 @@ class SearchCommand(Command, SessionCommandMixin):
|
|
|
83
85
|
return hits
|
|
84
86
|
|
|
85
87
|
|
|
86
|
-
def transform_hits(hits:
|
|
88
|
+
def transform_hits(hits: list[dict[str, str]]) -> list[TransformedHit]:
|
|
87
89
|
"""
|
|
88
90
|
The list from pypi is really a list of versions. We want a list of
|
|
89
91
|
packages with the list of versions stored inline. This converts the
|
|
90
92
|
list from pypi into one we can use.
|
|
91
93
|
"""
|
|
92
|
-
packages:
|
|
94
|
+
packages: dict[str, TransformedHit] = OrderedDict()
|
|
93
95
|
for hit in hits:
|
|
94
96
|
name = hit["name"]
|
|
95
97
|
summary = hit["summary"]
|
|
@@ -111,7 +113,7 @@ def transform_hits(hits: List[Dict[str, str]]) -> List["TransformedHit"]:
|
|
|
111
113
|
return list(packages.values())
|
|
112
114
|
|
|
113
115
|
|
|
114
|
-
def print_dist_installation_info(latest: str, dist:
|
|
116
|
+
def print_dist_installation_info(latest: str, dist: BaseDistribution | None) -> None:
|
|
115
117
|
if dist is not None:
|
|
116
118
|
with indent_log():
|
|
117
119
|
if dist.version == latest:
|
|
@@ -128,15 +130,15 @@ def print_dist_installation_info(latest: str, dist: Optional[BaseDistribution])
|
|
|
128
130
|
write_output("LATEST: %s", latest)
|
|
129
131
|
|
|
130
132
|
|
|
131
|
-
def get_installed_distribution(name: str) ->
|
|
133
|
+
def get_installed_distribution(name: str) -> BaseDistribution | None:
|
|
132
134
|
env = get_default_environment()
|
|
133
135
|
return env.get_distribution(name)
|
|
134
136
|
|
|
135
137
|
|
|
136
138
|
def print_results(
|
|
137
|
-
hits:
|
|
138
|
-
name_column_width:
|
|
139
|
-
terminal_width:
|
|
139
|
+
hits: list[TransformedHit],
|
|
140
|
+
name_column_width: int | None = None,
|
|
141
|
+
terminal_width: int | None = None,
|
|
140
142
|
) -> None:
|
|
141
143
|
if not hits:
|
|
142
144
|
return
|
|
@@ -172,5 +174,5 @@ def print_results(
|
|
|
172
174
|
pass
|
|
173
175
|
|
|
174
176
|
|
|
175
|
-
def highest_version(versions:
|
|
177
|
+
def highest_version(versions: list[str]) -> str:
|
|
176
178
|
return max(versions, key=parse_version)
|
pip/_internal/commands/show.py
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import logging
|
|
2
4
|
import string
|
|
5
|
+
from collections.abc import Generator, Iterable, Iterator
|
|
3
6
|
from optparse import Values
|
|
4
|
-
from typing import
|
|
7
|
+
from typing import NamedTuple
|
|
5
8
|
|
|
6
9
|
from pip._vendor.packaging.requirements import InvalidRequirement
|
|
7
10
|
from pip._vendor.packaging.utils import canonicalize_name
|
|
@@ -44,7 +47,7 @@ class ShowCommand(Command):
|
|
|
44
47
|
|
|
45
48
|
self.parser.insert_option_group(0, self.cmd_opts)
|
|
46
49
|
|
|
47
|
-
def run(self, options: Values, args:
|
|
50
|
+
def run(self, options: Values, args: list[str]) -> int:
|
|
48
51
|
if not args:
|
|
49
52
|
logger.warning("ERROR: Please provide a package name or names.")
|
|
50
53
|
return ERROR
|
|
@@ -62,24 +65,24 @@ class _PackageInfo(NamedTuple):
|
|
|
62
65
|
name: str
|
|
63
66
|
version: str
|
|
64
67
|
location: str
|
|
65
|
-
editable_project_location:
|
|
66
|
-
requires:
|
|
67
|
-
required_by:
|
|
68
|
+
editable_project_location: str | None
|
|
69
|
+
requires: list[str]
|
|
70
|
+
required_by: list[str]
|
|
68
71
|
installer: str
|
|
69
72
|
metadata_version: str
|
|
70
|
-
classifiers:
|
|
73
|
+
classifiers: list[str]
|
|
71
74
|
summary: str
|
|
72
75
|
homepage: str
|
|
73
|
-
project_urls:
|
|
76
|
+
project_urls: list[str]
|
|
74
77
|
author: str
|
|
75
78
|
author_email: str
|
|
76
79
|
license: str
|
|
77
80
|
license_expression: str
|
|
78
|
-
entry_points:
|
|
79
|
-
files:
|
|
81
|
+
entry_points: list[str]
|
|
82
|
+
files: list[str] | None
|
|
80
83
|
|
|
81
84
|
|
|
82
|
-
def search_packages_info(query:
|
|
85
|
+
def search_packages_info(query: list[str]) -> Generator[_PackageInfo, None, None]:
|
|
83
86
|
"""
|
|
84
87
|
Gather details from installed distributions. Print distribution name,
|
|
85
88
|
version, location, and installed files. Installed files requires a
|
|
@@ -132,7 +135,7 @@ def search_packages_info(query: List[str]) -> Generator[_PackageInfo, None, None
|
|
|
132
135
|
|
|
133
136
|
files_iter = dist.iter_declared_entries()
|
|
134
137
|
if files_iter is None:
|
|
135
|
-
files:
|
|
138
|
+
files: list[str] | None = None
|
|
136
139
|
else:
|
|
137
140
|
files = sorted(files_iter)
|
|
138
141
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from optparse import Values
|
|
3
|
-
from typing import List
|
|
4
3
|
|
|
5
4
|
from pip._vendor.packaging.utils import canonicalize_name
|
|
6
5
|
|
|
@@ -62,7 +61,7 @@ class UninstallCommand(Command, SessionCommandMixin):
|
|
|
62
61
|
self.cmd_opts.add_option(cmdoptions.override_externally_managed())
|
|
63
62
|
self.parser.insert_option_group(0, self.cmd_opts)
|
|
64
63
|
|
|
65
|
-
def run(self, options: Values, args:
|
|
64
|
+
def run(self, options: Values, args: list[str]) -> int:
|
|
66
65
|
session = self.get_default_session(options)
|
|
67
66
|
|
|
68
67
|
reqs_to_uninstall = {}
|
pip/_internal/commands/wheel.py
CHANGED
|
@@ -2,7 +2,6 @@ import logging
|
|
|
2
2
|
import os
|
|
3
3
|
import shutil
|
|
4
4
|
from optparse import Values
|
|
5
|
-
from typing import List
|
|
6
5
|
|
|
7
6
|
from pip._internal.cache import WheelCache
|
|
8
7
|
from pip._internal.cli import cmdoptions
|
|
@@ -101,7 +100,7 @@ class WheelCommand(RequirementCommand):
|
|
|
101
100
|
self.parser.insert_option_group(0, self.cmd_opts)
|
|
102
101
|
|
|
103
102
|
@with_cleanup
|
|
104
|
-
def run(self, options: Values, args:
|
|
103
|
+
def run(self, options: Values, args: list[str]) -> int:
|
|
105
104
|
session = self.get_default_session(options)
|
|
106
105
|
|
|
107
106
|
finder = self._build_package_finder(options, session)
|
|
@@ -146,7 +145,7 @@ class WheelCommand(RequirementCommand):
|
|
|
146
145
|
|
|
147
146
|
requirement_set = resolver.resolve(reqs, check_supported_wheels=True)
|
|
148
147
|
|
|
149
|
-
reqs_to_build:
|
|
148
|
+
reqs_to_build: list[InstallRequirement] = []
|
|
150
149
|
for req in requirement_set.requirements.values():
|
|
151
150
|
if req.is_wheel:
|
|
152
151
|
preparer.save_linked_requirement(req)
|
pip/_internal/configuration.py
CHANGED
|
@@ -11,11 +11,14 @@ Some terminology:
|
|
|
11
11
|
A single word describing where the configuration key-value pair came from
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
14
16
|
import configparser
|
|
15
17
|
import locale
|
|
16
18
|
import os
|
|
17
19
|
import sys
|
|
18
|
-
from
|
|
20
|
+
from collections.abc import Iterable
|
|
21
|
+
from typing import Any, NewType
|
|
19
22
|
|
|
20
23
|
from pip._internal.exceptions import (
|
|
21
24
|
ConfigurationError,
|
|
@@ -55,7 +58,7 @@ def _normalize_name(name: str) -> str:
|
|
|
55
58
|
return name
|
|
56
59
|
|
|
57
60
|
|
|
58
|
-
def _disassemble_key(name: str) ->
|
|
61
|
+
def _disassemble_key(name: str) -> list[str]:
|
|
59
62
|
if "." not in name:
|
|
60
63
|
error_message = (
|
|
61
64
|
"Key does not contain dot separated section and key. "
|
|
@@ -65,7 +68,7 @@ def _disassemble_key(name: str) -> List[str]:
|
|
|
65
68
|
return name.split(".", 1)
|
|
66
69
|
|
|
67
70
|
|
|
68
|
-
def get_configuration_files() ->
|
|
71
|
+
def get_configuration_files() -> dict[Kind, list[str]]:
|
|
69
72
|
global_config_files = [
|
|
70
73
|
os.path.join(path, CONFIG_BASENAME) for path in appdirs.site_config_dirs("pip")
|
|
71
74
|
]
|
|
@@ -98,7 +101,7 @@ class Configuration:
|
|
|
98
101
|
and the data stored is also nice.
|
|
99
102
|
"""
|
|
100
103
|
|
|
101
|
-
def __init__(self, isolated: bool, load_only:
|
|
104
|
+
def __init__(self, isolated: bool, load_only: Kind | None = None) -> None:
|
|
102
105
|
super().__init__()
|
|
103
106
|
|
|
104
107
|
if load_only is not None and load_only not in VALID_LOAD_ONLY:
|
|
@@ -111,13 +114,13 @@ class Configuration:
|
|
|
111
114
|
self.load_only = load_only
|
|
112
115
|
|
|
113
116
|
# Because we keep track of where we got the data from
|
|
114
|
-
self._parsers:
|
|
117
|
+
self._parsers: dict[Kind, list[tuple[str, RawConfigParser]]] = {
|
|
115
118
|
variant: [] for variant in OVERRIDE_ORDER
|
|
116
119
|
}
|
|
117
|
-
self._config:
|
|
120
|
+
self._config: dict[Kind, dict[str, dict[str, Any]]] = {
|
|
118
121
|
variant: {} for variant in OVERRIDE_ORDER
|
|
119
122
|
}
|
|
120
|
-
self._modified_parsers:
|
|
123
|
+
self._modified_parsers: list[tuple[str, RawConfigParser]] = []
|
|
121
124
|
|
|
122
125
|
def load(self) -> None:
|
|
123
126
|
"""Loads configuration from configuration files and environment"""
|
|
@@ -125,7 +128,7 @@ class Configuration:
|
|
|
125
128
|
if not self.isolated:
|
|
126
129
|
self._load_environment_vars()
|
|
127
130
|
|
|
128
|
-
def get_file_to_edit(self) ->
|
|
131
|
+
def get_file_to_edit(self) -> str | None:
|
|
129
132
|
"""Returns the file with highest priority in configuration"""
|
|
130
133
|
assert self.load_only is not None, "Need to be specified a file to be editing"
|
|
131
134
|
|
|
@@ -134,7 +137,7 @@ class Configuration:
|
|
|
134
137
|
except IndexError:
|
|
135
138
|
return None
|
|
136
139
|
|
|
137
|
-
def items(self) -> Iterable[
|
|
140
|
+
def items(self) -> Iterable[tuple[str, Any]]:
|
|
138
141
|
"""Returns key-value pairs like dict.items() representing the loaded
|
|
139
142
|
configuration
|
|
140
143
|
"""
|
|
@@ -145,7 +148,10 @@ class Configuration:
|
|
|
145
148
|
orig_key = key
|
|
146
149
|
key = _normalize_name(key)
|
|
147
150
|
try:
|
|
148
|
-
|
|
151
|
+
clean_config: dict[str, Any] = {}
|
|
152
|
+
for file_values in self._dictionary.values():
|
|
153
|
+
clean_config.update(file_values)
|
|
154
|
+
return clean_config[key]
|
|
149
155
|
except KeyError:
|
|
150
156
|
# disassembling triggers a more useful error message than simply
|
|
151
157
|
# "No such key" in the case that the key isn't in the form command.option
|
|
@@ -168,7 +174,8 @@ class Configuration:
|
|
|
168
174
|
parser.add_section(section)
|
|
169
175
|
parser.set(section, name, value)
|
|
170
176
|
|
|
171
|
-
self._config[self.load_only]
|
|
177
|
+
self._config[self.load_only].setdefault(fname, {})
|
|
178
|
+
self._config[self.load_only][fname][key] = value
|
|
172
179
|
self._mark_as_modified(fname, parser)
|
|
173
180
|
|
|
174
181
|
def unset_value(self, key: str) -> None:
|
|
@@ -178,11 +185,14 @@ class Configuration:
|
|
|
178
185
|
self._ensure_have_load_only()
|
|
179
186
|
|
|
180
187
|
assert self.load_only
|
|
181
|
-
if key not in self._config[self.load_only]:
|
|
182
|
-
raise ConfigurationError(f"No such key - {orig_key}")
|
|
183
|
-
|
|
184
188
|
fname, parser = self._get_parser_to_modify()
|
|
185
189
|
|
|
190
|
+
if (
|
|
191
|
+
key not in self._config[self.load_only][fname]
|
|
192
|
+
and key not in self._config[self.load_only]
|
|
193
|
+
):
|
|
194
|
+
raise ConfigurationError(f"No such key - {orig_key}")
|
|
195
|
+
|
|
186
196
|
if parser is not None:
|
|
187
197
|
section, name = _disassemble_key(key)
|
|
188
198
|
if not (
|
|
@@ -197,8 +207,10 @@ class Configuration:
|
|
|
197
207
|
if not parser.items(section):
|
|
198
208
|
parser.remove_section(section)
|
|
199
209
|
self._mark_as_modified(fname, parser)
|
|
200
|
-
|
|
201
|
-
|
|
210
|
+
try:
|
|
211
|
+
del self._config[self.load_only][fname][key]
|
|
212
|
+
except KeyError:
|
|
213
|
+
del self._config[self.load_only][key]
|
|
202
214
|
|
|
203
215
|
def save(self) -> None:
|
|
204
216
|
"""Save the current in-memory state."""
|
|
@@ -230,7 +242,7 @@ class Configuration:
|
|
|
230
242
|
logger.debug("Will be working with %s variant only", self.load_only)
|
|
231
243
|
|
|
232
244
|
@property
|
|
233
|
-
def _dictionary(self) ->
|
|
245
|
+
def _dictionary(self) -> dict[str, dict[str, Any]]:
|
|
234
246
|
"""A dictionary representing the loaded configuration."""
|
|
235
247
|
# NOTE: Dictionaries are not populated if not loaded. So, conditionals
|
|
236
248
|
# are not needed here.
|
|
@@ -270,7 +282,8 @@ class Configuration:
|
|
|
270
282
|
|
|
271
283
|
for section in parser.sections():
|
|
272
284
|
items = parser.items(section)
|
|
273
|
-
self._config[variant].
|
|
285
|
+
self._config[variant].setdefault(fname, {})
|
|
286
|
+
self._config[variant][fname].update(self._normalized_keys(section, items))
|
|
274
287
|
|
|
275
288
|
return parser
|
|
276
289
|
|
|
@@ -297,13 +310,14 @@ class Configuration:
|
|
|
297
310
|
|
|
298
311
|
def _load_environment_vars(self) -> None:
|
|
299
312
|
"""Loads configuration from environment variables"""
|
|
300
|
-
self._config[kinds.ENV_VAR].
|
|
313
|
+
self._config[kinds.ENV_VAR].setdefault(":env:", {})
|
|
314
|
+
self._config[kinds.ENV_VAR][":env:"].update(
|
|
301
315
|
self._normalized_keys(":env:", self.get_environ_vars())
|
|
302
316
|
)
|
|
303
317
|
|
|
304
318
|
def _normalized_keys(
|
|
305
|
-
self, section: str, items: Iterable[
|
|
306
|
-
) ->
|
|
319
|
+
self, section: str, items: Iterable[tuple[str, Any]]
|
|
320
|
+
) -> dict[str, Any]:
|
|
307
321
|
"""Normalizes items to construct a dictionary with normalized keys.
|
|
308
322
|
|
|
309
323
|
This routine is where the names become keys and are made the same
|
|
@@ -315,7 +329,7 @@ class Configuration:
|
|
|
315
329
|
normalized[key] = val
|
|
316
330
|
return normalized
|
|
317
331
|
|
|
318
|
-
def get_environ_vars(self) -> Iterable[
|
|
332
|
+
def get_environ_vars(self) -> Iterable[tuple[str, str]]:
|
|
319
333
|
"""Returns a generator with all environmental vars with prefix PIP_"""
|
|
320
334
|
for key, val in os.environ.items():
|
|
321
335
|
if key.startswith("PIP_"):
|
|
@@ -324,7 +338,7 @@ class Configuration:
|
|
|
324
338
|
yield name, val
|
|
325
339
|
|
|
326
340
|
# XXX: This is patched in the tests.
|
|
327
|
-
def iter_config_files(self) -> Iterable[
|
|
341
|
+
def iter_config_files(self) -> Iterable[tuple[Kind, list[str]]]:
|
|
328
342
|
"""Yields variant and configuration files associated with it.
|
|
329
343
|
|
|
330
344
|
This should be treated like items of a dictionary. The order
|
|
@@ -356,11 +370,11 @@ class Configuration:
|
|
|
356
370
|
else:
|
|
357
371
|
yield kinds.ENV, []
|
|
358
372
|
|
|
359
|
-
def get_values_in_config(self, variant: Kind) ->
|
|
373
|
+
def get_values_in_config(self, variant: Kind) -> dict[str, Any]:
|
|
360
374
|
"""Get values present in a config file"""
|
|
361
375
|
return self._config[variant]
|
|
362
376
|
|
|
363
|
-
def _get_parser_to_modify(self) ->
|
|
377
|
+
def _get_parser_to_modify(self) -> tuple[str, RawConfigParser]:
|
|
364
378
|
# Determine which parser to modify
|
|
365
379
|
assert self.load_only
|
|
366
380
|
parsers = self._parsers[self.load_only]
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import abc
|
|
2
|
-
from typing import TYPE_CHECKING
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
3
5
|
|
|
4
6
|
from pip._internal.metadata.base import BaseDistribution
|
|
5
7
|
from pip._internal.req import InstallRequirement
|
|
6
8
|
|
|
7
9
|
if TYPE_CHECKING:
|
|
8
|
-
from pip._internal.
|
|
10
|
+
from pip._internal.build_env import BuildEnvironmentInstaller
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
class AbstractDistribution(metaclass=abc.ABCMeta):
|
|
@@ -32,7 +34,7 @@ class AbstractDistribution(metaclass=abc.ABCMeta):
|
|
|
32
34
|
self.req = req
|
|
33
35
|
|
|
34
36
|
@abc.abstractproperty
|
|
35
|
-
def build_tracker_id(self) ->
|
|
37
|
+
def build_tracker_id(self) -> str | None:
|
|
36
38
|
"""A string that uniquely identifies this requirement to the build tracker.
|
|
37
39
|
|
|
38
40
|
If None, then this dist has no work to do in the build tracker, and
|
|
@@ -46,7 +48,7 @@ class AbstractDistribution(metaclass=abc.ABCMeta):
|
|
|
46
48
|
@abc.abstractmethod
|
|
47
49
|
def prepare_distribution_metadata(
|
|
48
50
|
self,
|
|
49
|
-
|
|
51
|
+
build_env_installer: BuildEnvironmentInstaller,
|
|
50
52
|
build_isolation: bool,
|
|
51
53
|
check_build_deps: bool,
|
|
52
54
|
) -> None:
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
from
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
2
4
|
|
|
3
5
|
from pip._internal.distributions.base import AbstractDistribution
|
|
4
|
-
from pip._internal.index.package_finder import PackageFinder
|
|
5
6
|
from pip._internal.metadata import BaseDistribution
|
|
6
7
|
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from pip._internal.build_env import BuildEnvironmentInstaller
|
|
10
|
+
|
|
7
11
|
|
|
8
12
|
class InstalledDistribution(AbstractDistribution):
|
|
9
13
|
"""Represents an installed package.
|
|
@@ -13,7 +17,7 @@ class InstalledDistribution(AbstractDistribution):
|
|
|
13
17
|
"""
|
|
14
18
|
|
|
15
19
|
@property
|
|
16
|
-
def build_tracker_id(self) ->
|
|
20
|
+
def build_tracker_id(self) -> str | None:
|
|
17
21
|
return None
|
|
18
22
|
|
|
19
23
|
def get_metadata_distribution(self) -> BaseDistribution:
|
|
@@ -22,7 +26,7 @@ class InstalledDistribution(AbstractDistribution):
|
|
|
22
26
|
|
|
23
27
|
def prepare_distribution_metadata(
|
|
24
28
|
self,
|
|
25
|
-
|
|
29
|
+
build_env_installer: BuildEnvironmentInstaller,
|
|
26
30
|
build_isolation: bool,
|
|
27
31
|
check_build_deps: bool,
|
|
28
32
|
) -> None:
|