pip 25.1.1__py3-none-any.whl → 25.3__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 +186 -94
- pip/_internal/cache.py +17 -15
- pip/_internal/cli/autocompletion.py +13 -4
- pip/_internal/cli/base_command.py +18 -7
- pip/_internal/cli/cmdoptions.py +57 -80
- 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 +24 -20
- pip/_internal/cli/progress_bars.py +19 -12
- pip/_internal/cli/req_command.py +57 -33
- 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 +6 -10
- 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 +63 -53
- pip/_internal/commands/list.py +35 -26
- pip/_internal/commands/lock.py +4 -8
- 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 +7 -13
- pip/_internal/configuration.py +40 -27
- pip/_internal/distributions/base.py +6 -4
- pip/_internal/distributions/installed.py +8 -4
- pip/_internal/distributions/sdist.py +33 -27
- pip/_internal/distributions/wheel.py +6 -4
- pip/_internal/exceptions.py +78 -42
- pip/_internal/index/collector.py +24 -29
- pip/_internal/index/package_finder.py +73 -64
- 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 +14 -7
- 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 +20 -19
- 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 +12 -71
- pip/_internal/network/auth.py +20 -22
- pip/_internal/network/cache.py +28 -17
- pip/_internal/network/download.py +169 -141
- pip/_internal/network/lazy_wheel.py +15 -10
- 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 +7 -6
- pip/_internal/operations/build/wheel_editable.py +7 -6
- pip/_internal/operations/check.py +21 -26
- pip/_internal/operations/freeze.py +12 -9
- pip/_internal/operations/install/wheel.py +49 -41
- pip/_internal/operations/prepare.py +42 -31
- pip/_internal/pyproject.py +7 -69
- pip/_internal/req/__init__.py +12 -12
- pip/_internal/req/constructors.py +68 -62
- pip/_internal/req/req_dependency_group.py +7 -11
- pip/_internal/req/req_file.py +32 -36
- pip/_internal/req/req_install.py +64 -170
- 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 +49 -37
- pip/_internal/resolution/resolvelib/factory.py +72 -50
- pip/_internal/resolution/resolvelib/found_candidates.py +11 -9
- pip/_internal/resolution/resolvelib/provider.py +24 -20
- pip/_internal/resolution/resolvelib/reporter.py +26 -11
- pip/_internal/resolution/resolvelib/requirements.py +8 -6
- pip/_internal/resolution/resolvelib/resolver.py +41 -29
- pip/_internal/self_outdated_check.py +19 -9
- 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 +20 -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/subprocess.py +20 -17
- pip/_internal/utils/temp_dir.py +10 -12
- pip/_internal/utils/unpacking.py +31 -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 +30 -101
- pip/_vendor/README.rst +180 -0
- pip/_vendor/cachecontrol/LICENSE.txt +13 -0
- pip/_vendor/cachecontrol/__init__.py +1 -1
- pip/_vendor/certifi/LICENSE +20 -0
- pip/_vendor/certifi/__init__.py +1 -1
- pip/_vendor/certifi/cacert.pem +164 -261
- pip/_vendor/certifi/core.py +1 -32
- pip/_vendor/dependency_groups/LICENSE.txt +9 -0
- pip/_vendor/distlib/LICENSE.txt +284 -0
- pip/_vendor/distlib/__init__.py +2 -2
- pip/_vendor/distlib/scripts.py +1 -1
- pip/_vendor/distro/LICENSE +202 -0
- pip/_vendor/idna/LICENSE.md +31 -0
- pip/_vendor/msgpack/COPYING +14 -0
- pip/_vendor/msgpack/__init__.py +2 -2
- pip/_vendor/packaging/LICENSE +3 -0
- pip/_vendor/packaging/LICENSE.APACHE +177 -0
- pip/_vendor/packaging/LICENSE.BSD +23 -0
- pip/_vendor/pkg_resources/LICENSE +17 -0
- pip/_vendor/pkg_resources/__init__.py +1 -1
- pip/_vendor/platformdirs/LICENSE +21 -0
- pip/_vendor/platformdirs/api.py +1 -1
- pip/_vendor/platformdirs/macos.py +10 -8
- pip/_vendor/platformdirs/version.py +16 -3
- pip/_vendor/pygments/LICENSE +25 -0
- pip/_vendor/pygments/__init__.py +1 -1
- pip/_vendor/pyproject_hooks/LICENSE +21 -0
- pip/_vendor/requests/LICENSE +175 -0
- pip/_vendor/requests/__version__.py +2 -2
- pip/_vendor/requests/adapters.py +17 -40
- pip/_vendor/requests/compat.py +12 -0
- pip/_vendor/requests/models.py +3 -1
- pip/_vendor/requests/sessions.py +1 -1
- pip/_vendor/requests/utils.py +6 -16
- pip/_vendor/resolvelib/LICENSE +13 -0
- 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/abstract.py +3 -3
- pip/_vendor/resolvelib/resolvers/resolution.py +96 -10
- pip/_vendor/rich/LICENSE +19 -0
- 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/style.py +7 -11
- pip/_vendor/rich/syntax.py +24 -5
- pip/_vendor/rich/traceback.py +32 -17
- pip/_vendor/tomli/LICENSE +21 -0
- pip/_vendor/tomli/__init__.py +1 -1
- pip/_vendor/tomli/_parser.py +28 -21
- pip/_vendor/tomli/_re.py +8 -5
- pip/_vendor/tomli_w/LICENSE +21 -0
- pip/_vendor/truststore/LICENSE +21 -0
- pip/_vendor/truststore/__init__.py +1 -1
- pip/_vendor/truststore/_api.py +15 -7
- pip/_vendor/truststore/_openssl.py +3 -1
- pip/_vendor/urllib3/LICENSE.txt +21 -0
- pip/_vendor/vendor.txt +11 -12
- {pip-25.1.1.dist-info → pip-25.3.dist-info}/METADATA +32 -11
- {pip-25.1.1.dist-info → pip-25.3.dist-info}/RECORD +221 -192
- {pip-25.1.1.dist-info → pip-25.3.dist-info}/WHEEL +1 -2
- pip-25.3.dist-info/entry_points.txt +4 -0
- {pip-25.1.1.dist-info → pip-25.3.dist-info}/licenses/AUTHORS.txt +21 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/cachecontrol/LICENSE.txt +13 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/certifi/LICENSE +20 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/dependency_groups/LICENSE.txt +9 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/distlib/LICENSE.txt +284 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/distro/LICENSE +202 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/idna/LICENSE.md +31 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/msgpack/COPYING +14 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/packaging/LICENSE +3 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.APACHE +177 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.BSD +23 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/pkg_resources/LICENSE +17 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/platformdirs/LICENSE +21 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/pygments/LICENSE +25 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/pyproject_hooks/LICENSE +21 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/requests/LICENSE +175 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/resolvelib/LICENSE +13 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/rich/LICENSE +19 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/tomli/LICENSE +21 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/tomli_w/LICENSE +21 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/truststore/LICENSE +21 -0
- pip-25.3.dist-info/licenses/src/pip/_vendor/urllib3/LICENSE.txt +21 -0
- pip/_internal/operations/build/metadata_legacy.py +0 -73
- pip/_internal/operations/build/wheel_legacy.py +0 -118
- pip/_internal/operations/install/editable_legacy.py +0 -46
- pip/_internal/utils/setuptools_build.py +0 -147
- 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/entry_points.txt +0 -3
- pip-25.1.1.dist-info/top_level.txt +0 -1
- {pip-25.1.1.dist-info → pip-25.3.dist-info}/licenses/LICENSE.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
|
|
@@ -12,9 +11,6 @@ from pip._internal.cli.req_command import (
|
|
|
12
11
|
from pip._internal.cli.status_codes import SUCCESS
|
|
13
12
|
from pip._internal.models.pylock import Pylock, is_valid_pylock_file_name
|
|
14
13
|
from pip._internal.operations.build.build_tracker import get_build_tracker
|
|
15
|
-
from pip._internal.req.req_install import (
|
|
16
|
-
check_legacy_setup_py_options,
|
|
17
|
-
)
|
|
18
14
|
from pip._internal.utils.logging import getLogger
|
|
19
15
|
from pip._internal.utils.misc import (
|
|
20
16
|
get_pip_version,
|
|
@@ -60,6 +56,7 @@ class LockCommand(RequirementCommand):
|
|
|
60
56
|
)
|
|
61
57
|
self.cmd_opts.add_option(cmdoptions.requirements())
|
|
62
58
|
self.cmd_opts.add_option(cmdoptions.constraints())
|
|
59
|
+
self.cmd_opts.add_option(cmdoptions.build_constraints())
|
|
63
60
|
self.cmd_opts.add_option(cmdoptions.no_deps())
|
|
64
61
|
self.cmd_opts.add_option(cmdoptions.pre())
|
|
65
62
|
|
|
@@ -70,7 +67,6 @@ class LockCommand(RequirementCommand):
|
|
|
70
67
|
self.cmd_opts.add_option(cmdoptions.ignore_requires_python())
|
|
71
68
|
self.cmd_opts.add_option(cmdoptions.no_build_isolation())
|
|
72
69
|
self.cmd_opts.add_option(cmdoptions.use_pep517())
|
|
73
|
-
self.cmd_opts.add_option(cmdoptions.no_use_pep517())
|
|
74
70
|
self.cmd_opts.add_option(cmdoptions.check_build_deps())
|
|
75
71
|
|
|
76
72
|
self.cmd_opts.add_option(cmdoptions.config_settings())
|
|
@@ -90,7 +86,7 @@ class LockCommand(RequirementCommand):
|
|
|
90
86
|
self.parser.insert_option_group(0, self.cmd_opts)
|
|
91
87
|
|
|
92
88
|
@with_cleanup
|
|
93
|
-
def run(self, options: Values, args:
|
|
89
|
+
def run(self, options: Values, args: list[str]) -> int:
|
|
94
90
|
logger.verbose("Using %s", get_pip_version())
|
|
95
91
|
|
|
96
92
|
logger.warning(
|
|
@@ -99,6 +95,8 @@ class LockCommand(RequirementCommand):
|
|
|
99
95
|
"without prior warning."
|
|
100
96
|
)
|
|
101
97
|
|
|
98
|
+
cmdoptions.check_build_constraints(options)
|
|
99
|
+
|
|
102
100
|
session = self.get_default_session(options)
|
|
103
101
|
|
|
104
102
|
finder = self._build_package_finder(
|
|
@@ -115,7 +113,6 @@ class LockCommand(RequirementCommand):
|
|
|
115
113
|
)
|
|
116
114
|
|
|
117
115
|
reqs = self.get_requirements(args, options, finder, session)
|
|
118
|
-
check_legacy_setup_py_options(options, reqs)
|
|
119
116
|
|
|
120
117
|
wheel_cache = WheelCache(options.cache_dir)
|
|
121
118
|
|
|
@@ -143,7 +140,6 @@ class LockCommand(RequirementCommand):
|
|
|
143
140
|
ignore_installed=True,
|
|
144
141
|
ignore_requires_python=options.ignore_requires_python,
|
|
145
142
|
upgrade_strategy="to-satisfy-only",
|
|
146
|
-
use_pep517=options.use_pep517,
|
|
147
143
|
)
|
|
148
144
|
|
|
149
145
|
self.trace_basic_info(finder)
|
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
|
|
@@ -12,7 +11,6 @@ from pip._internal.exceptions import CommandError
|
|
|
12
11
|
from pip._internal.operations.build.build_tracker import get_build_tracker
|
|
13
12
|
from pip._internal.req.req_install import (
|
|
14
13
|
InstallRequirement,
|
|
15
|
-
check_legacy_setup_py_options,
|
|
16
14
|
)
|
|
17
15
|
from pip._internal.utils.misc import ensure_dir, normalize_path
|
|
18
16
|
from pip._internal.utils.temp_dir import TempDirectory
|
|
@@ -58,9 +56,9 @@ class WheelCommand(RequirementCommand):
|
|
|
58
56
|
self.cmd_opts.add_option(cmdoptions.prefer_binary())
|
|
59
57
|
self.cmd_opts.add_option(cmdoptions.no_build_isolation())
|
|
60
58
|
self.cmd_opts.add_option(cmdoptions.use_pep517())
|
|
61
|
-
self.cmd_opts.add_option(cmdoptions.no_use_pep517())
|
|
62
59
|
self.cmd_opts.add_option(cmdoptions.check_build_deps())
|
|
63
60
|
self.cmd_opts.add_option(cmdoptions.constraints())
|
|
61
|
+
self.cmd_opts.add_option(cmdoptions.build_constraints())
|
|
64
62
|
self.cmd_opts.add_option(cmdoptions.editable())
|
|
65
63
|
self.cmd_opts.add_option(cmdoptions.requirements())
|
|
66
64
|
self.cmd_opts.add_option(cmdoptions.src())
|
|
@@ -77,8 +75,6 @@ class WheelCommand(RequirementCommand):
|
|
|
77
75
|
)
|
|
78
76
|
|
|
79
77
|
self.cmd_opts.add_option(cmdoptions.config_settings())
|
|
80
|
-
self.cmd_opts.add_option(cmdoptions.build_options())
|
|
81
|
-
self.cmd_opts.add_option(cmdoptions.global_options())
|
|
82
78
|
|
|
83
79
|
self.cmd_opts.add_option(
|
|
84
80
|
"--pre",
|
|
@@ -101,7 +97,9 @@ class WheelCommand(RequirementCommand):
|
|
|
101
97
|
self.parser.insert_option_group(0, self.cmd_opts)
|
|
102
98
|
|
|
103
99
|
@with_cleanup
|
|
104
|
-
def run(self, options: Values, args:
|
|
100
|
+
def run(self, options: Values, args: list[str]) -> int:
|
|
101
|
+
cmdoptions.check_build_constraints(options)
|
|
102
|
+
|
|
105
103
|
session = self.get_default_session(options)
|
|
106
104
|
|
|
107
105
|
finder = self._build_package_finder(options, session)
|
|
@@ -118,7 +116,6 @@ class WheelCommand(RequirementCommand):
|
|
|
118
116
|
)
|
|
119
117
|
|
|
120
118
|
reqs = self.get_requirements(args, options, finder, session)
|
|
121
|
-
check_legacy_setup_py_options(options, reqs)
|
|
122
119
|
|
|
123
120
|
wheel_cache = WheelCache(options.cache_dir)
|
|
124
121
|
|
|
@@ -139,29 +136,26 @@ class WheelCommand(RequirementCommand):
|
|
|
139
136
|
options=options,
|
|
140
137
|
wheel_cache=wheel_cache,
|
|
141
138
|
ignore_requires_python=options.ignore_requires_python,
|
|
142
|
-
use_pep517=options.use_pep517,
|
|
143
139
|
)
|
|
144
140
|
|
|
145
141
|
self.trace_basic_info(finder)
|
|
146
142
|
|
|
147
143
|
requirement_set = resolver.resolve(reqs, check_supported_wheels=True)
|
|
148
144
|
|
|
149
|
-
|
|
145
|
+
preparer.prepare_linked_requirements_more(requirement_set.requirements.values())
|
|
146
|
+
|
|
147
|
+
reqs_to_build: list[InstallRequirement] = []
|
|
150
148
|
for req in requirement_set.requirements.values():
|
|
151
149
|
if req.is_wheel:
|
|
152
150
|
preparer.save_linked_requirement(req)
|
|
153
151
|
else:
|
|
154
152
|
reqs_to_build.append(req)
|
|
155
153
|
|
|
156
|
-
preparer.prepare_linked_requirements_more(requirement_set.requirements.values())
|
|
157
|
-
|
|
158
154
|
# build wheels
|
|
159
155
|
build_successes, build_failures = build(
|
|
160
156
|
reqs_to_build,
|
|
161
157
|
wheel_cache=wheel_cache,
|
|
162
158
|
verify=(not options.no_verify),
|
|
163
|
-
build_options=options.build_options or [],
|
|
164
|
-
global_options=options.global_options or [],
|
|
165
159
|
)
|
|
166
160
|
for req in build_successes:
|
|
167
161
|
assert req.link and req.link.is_wheel
|
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,
|
|
@@ -50,12 +53,11 @@ logger = getLogger(__name__)
|
|
|
50
53
|
def _normalize_name(name: str) -> str:
|
|
51
54
|
"""Make a name consistent regardless of source (environment or file)"""
|
|
52
55
|
name = name.lower().replace("_", "-")
|
|
53
|
-
|
|
54
|
-
name = name[2:] # only prefer long opts
|
|
56
|
+
name = name.removeprefix("--") # only prefer long opts
|
|
55
57
|
return name
|
|
56
58
|
|
|
57
59
|
|
|
58
|
-
def _disassemble_key(name: str) ->
|
|
60
|
+
def _disassemble_key(name: str) -> list[str]:
|
|
59
61
|
if "." not in name:
|
|
60
62
|
error_message = (
|
|
61
63
|
"Key does not contain dot separated section and key. "
|
|
@@ -65,7 +67,7 @@ def _disassemble_key(name: str) -> List[str]:
|
|
|
65
67
|
return name.split(".", 1)
|
|
66
68
|
|
|
67
69
|
|
|
68
|
-
def get_configuration_files() ->
|
|
70
|
+
def get_configuration_files() -> dict[Kind, list[str]]:
|
|
69
71
|
global_config_files = [
|
|
70
72
|
os.path.join(path, CONFIG_BASENAME) for path in appdirs.site_config_dirs("pip")
|
|
71
73
|
]
|
|
@@ -98,7 +100,7 @@ class Configuration:
|
|
|
98
100
|
and the data stored is also nice.
|
|
99
101
|
"""
|
|
100
102
|
|
|
101
|
-
def __init__(self, isolated: bool, load_only:
|
|
103
|
+
def __init__(self, isolated: bool, load_only: Kind | None = None) -> None:
|
|
102
104
|
super().__init__()
|
|
103
105
|
|
|
104
106
|
if load_only is not None and load_only not in VALID_LOAD_ONLY:
|
|
@@ -111,13 +113,13 @@ class Configuration:
|
|
|
111
113
|
self.load_only = load_only
|
|
112
114
|
|
|
113
115
|
# Because we keep track of where we got the data from
|
|
114
|
-
self._parsers:
|
|
116
|
+
self._parsers: dict[Kind, list[tuple[str, RawConfigParser]]] = {
|
|
115
117
|
variant: [] for variant in OVERRIDE_ORDER
|
|
116
118
|
}
|
|
117
|
-
self._config:
|
|
119
|
+
self._config: dict[Kind, dict[str, dict[str, Any]]] = {
|
|
118
120
|
variant: {} for variant in OVERRIDE_ORDER
|
|
119
121
|
}
|
|
120
|
-
self._modified_parsers:
|
|
122
|
+
self._modified_parsers: list[tuple[str, RawConfigParser]] = []
|
|
121
123
|
|
|
122
124
|
def load(self) -> None:
|
|
123
125
|
"""Loads configuration from configuration files and environment"""
|
|
@@ -125,7 +127,7 @@ class Configuration:
|
|
|
125
127
|
if not self.isolated:
|
|
126
128
|
self._load_environment_vars()
|
|
127
129
|
|
|
128
|
-
def get_file_to_edit(self) ->
|
|
130
|
+
def get_file_to_edit(self) -> str | None:
|
|
129
131
|
"""Returns the file with highest priority in configuration"""
|
|
130
132
|
assert self.load_only is not None, "Need to be specified a file to be editing"
|
|
131
133
|
|
|
@@ -134,7 +136,7 @@ class Configuration:
|
|
|
134
136
|
except IndexError:
|
|
135
137
|
return None
|
|
136
138
|
|
|
137
|
-
def items(self) -> Iterable[
|
|
139
|
+
def items(self) -> Iterable[tuple[str, Any]]:
|
|
138
140
|
"""Returns key-value pairs like dict.items() representing the loaded
|
|
139
141
|
configuration
|
|
140
142
|
"""
|
|
@@ -145,7 +147,10 @@ class Configuration:
|
|
|
145
147
|
orig_key = key
|
|
146
148
|
key = _normalize_name(key)
|
|
147
149
|
try:
|
|
148
|
-
|
|
150
|
+
clean_config: dict[str, Any] = {}
|
|
151
|
+
for file_values in self._dictionary.values():
|
|
152
|
+
clean_config.update(file_values)
|
|
153
|
+
return clean_config[key]
|
|
149
154
|
except KeyError:
|
|
150
155
|
# disassembling triggers a more useful error message than simply
|
|
151
156
|
# "No such key" in the case that the key isn't in the form command.option
|
|
@@ -168,7 +173,8 @@ class Configuration:
|
|
|
168
173
|
parser.add_section(section)
|
|
169
174
|
parser.set(section, name, value)
|
|
170
175
|
|
|
171
|
-
self._config[self.load_only]
|
|
176
|
+
self._config[self.load_only].setdefault(fname, {})
|
|
177
|
+
self._config[self.load_only][fname][key] = value
|
|
172
178
|
self._mark_as_modified(fname, parser)
|
|
173
179
|
|
|
174
180
|
def unset_value(self, key: str) -> None:
|
|
@@ -178,11 +184,14 @@ class Configuration:
|
|
|
178
184
|
self._ensure_have_load_only()
|
|
179
185
|
|
|
180
186
|
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
187
|
fname, parser = self._get_parser_to_modify()
|
|
185
188
|
|
|
189
|
+
if (
|
|
190
|
+
key not in self._config[self.load_only][fname]
|
|
191
|
+
and key not in self._config[self.load_only]
|
|
192
|
+
):
|
|
193
|
+
raise ConfigurationError(f"No such key - {orig_key}")
|
|
194
|
+
|
|
186
195
|
if parser is not None:
|
|
187
196
|
section, name = _disassemble_key(key)
|
|
188
197
|
if not (
|
|
@@ -197,8 +206,10 @@ class Configuration:
|
|
|
197
206
|
if not parser.items(section):
|
|
198
207
|
parser.remove_section(section)
|
|
199
208
|
self._mark_as_modified(fname, parser)
|
|
200
|
-
|
|
201
|
-
|
|
209
|
+
try:
|
|
210
|
+
del self._config[self.load_only][fname][key]
|
|
211
|
+
except KeyError:
|
|
212
|
+
del self._config[self.load_only][key]
|
|
202
213
|
|
|
203
214
|
def save(self) -> None:
|
|
204
215
|
"""Save the current in-memory state."""
|
|
@@ -230,7 +241,7 @@ class Configuration:
|
|
|
230
241
|
logger.debug("Will be working with %s variant only", self.load_only)
|
|
231
242
|
|
|
232
243
|
@property
|
|
233
|
-
def _dictionary(self) ->
|
|
244
|
+
def _dictionary(self) -> dict[str, dict[str, Any]]:
|
|
234
245
|
"""A dictionary representing the loaded configuration."""
|
|
235
246
|
# NOTE: Dictionaries are not populated if not loaded. So, conditionals
|
|
236
247
|
# are not needed here.
|
|
@@ -270,7 +281,8 @@ class Configuration:
|
|
|
270
281
|
|
|
271
282
|
for section in parser.sections():
|
|
272
283
|
items = parser.items(section)
|
|
273
|
-
self._config[variant].
|
|
284
|
+
self._config[variant].setdefault(fname, {})
|
|
285
|
+
self._config[variant][fname].update(self._normalized_keys(section, items))
|
|
274
286
|
|
|
275
287
|
return parser
|
|
276
288
|
|
|
@@ -297,13 +309,14 @@ class Configuration:
|
|
|
297
309
|
|
|
298
310
|
def _load_environment_vars(self) -> None:
|
|
299
311
|
"""Loads configuration from environment variables"""
|
|
300
|
-
self._config[kinds.ENV_VAR].
|
|
312
|
+
self._config[kinds.ENV_VAR].setdefault(":env:", {})
|
|
313
|
+
self._config[kinds.ENV_VAR][":env:"].update(
|
|
301
314
|
self._normalized_keys(":env:", self.get_environ_vars())
|
|
302
315
|
)
|
|
303
316
|
|
|
304
317
|
def _normalized_keys(
|
|
305
|
-
self, section: str, items: Iterable[
|
|
306
|
-
) ->
|
|
318
|
+
self, section: str, items: Iterable[tuple[str, Any]]
|
|
319
|
+
) -> dict[str, Any]:
|
|
307
320
|
"""Normalizes items to construct a dictionary with normalized keys.
|
|
308
321
|
|
|
309
322
|
This routine is where the names become keys and are made the same
|
|
@@ -315,7 +328,7 @@ class Configuration:
|
|
|
315
328
|
normalized[key] = val
|
|
316
329
|
return normalized
|
|
317
330
|
|
|
318
|
-
def get_environ_vars(self) -> Iterable[
|
|
331
|
+
def get_environ_vars(self) -> Iterable[tuple[str, str]]:
|
|
319
332
|
"""Returns a generator with all environmental vars with prefix PIP_"""
|
|
320
333
|
for key, val in os.environ.items():
|
|
321
334
|
if key.startswith("PIP_"):
|
|
@@ -324,7 +337,7 @@ class Configuration:
|
|
|
324
337
|
yield name, val
|
|
325
338
|
|
|
326
339
|
# XXX: This is patched in the tests.
|
|
327
|
-
def iter_config_files(self) -> Iterable[
|
|
340
|
+
def iter_config_files(self) -> Iterable[tuple[Kind, list[str]]]:
|
|
328
341
|
"""Yields variant and configuration files associated with it.
|
|
329
342
|
|
|
330
343
|
This should be treated like items of a dictionary. The order
|
|
@@ -356,11 +369,11 @@ class Configuration:
|
|
|
356
369
|
else:
|
|
357
370
|
yield kinds.ENV, []
|
|
358
371
|
|
|
359
|
-
def get_values_in_config(self, variant: Kind) ->
|
|
372
|
+
def get_values_in_config(self, variant: Kind) -> dict[str, Any]:
|
|
360
373
|
"""Get values present in a config file"""
|
|
361
374
|
return self._config[variant]
|
|
362
375
|
|
|
363
|
-
def _get_parser_to_modify(self) ->
|
|
376
|
+
def _get_parser_to_modify(self) -> tuple[str, RawConfigParser]:
|
|
364
377
|
# Determine which parser to modify
|
|
365
378
|
assert self.load_only
|
|
366
379
|
parsers = self._parsers[self.load_only]
|