pip 25.0.1__py3-none-any.whl → 25.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pip/__init__.py +1 -1
- pip/__pip-runner__.py +1 -1
- pip/_internal/build_env.py +5 -2
- pip/_internal/cache.py +1 -2
- pip/_internal/cli/__init__.py +1 -2
- pip/_internal/cli/autocompletion.py +1 -2
- pip/_internal/cli/base_command.py +2 -9
- pip/_internal/cli/cmdoptions.py +64 -6
- pip/_internal/cli/index_command.py +2 -0
- pip/_internal/cli/main.py +1 -2
- pip/_internal/cli/main_parser.py +1 -2
- pip/_internal/cli/progress_bars.py +59 -9
- pip/_internal/cli/req_command.py +19 -1
- pip/_internal/commands/__init__.py +5 -0
- pip/_internal/commands/completion.py +11 -5
- pip/_internal/commands/freeze.py +0 -1
- pip/_internal/commands/index.py +24 -10
- pip/_internal/commands/install.py +9 -0
- pip/_internal/commands/list.py +21 -5
- pip/_internal/commands/lock.py +171 -0
- pip/_internal/commands/search.py +14 -10
- pip/_internal/commands/show.py +9 -5
- pip/_internal/commands/wheel.py +2 -2
- pip/_internal/exceptions.py +53 -0
- pip/_internal/index/__init__.py +1 -2
- pip/_internal/index/package_finder.py +37 -16
- pip/_internal/locations/__init__.py +1 -18
- pip/_internal/metadata/__init__.py +47 -13
- pip/_internal/metadata/base.py +3 -1
- pip/_internal/metadata/importlib/_envs.py +11 -60
- pip/_internal/models/__init__.py +1 -2
- pip/_internal/models/direct_url.py +1 -1
- pip/_internal/models/link.py +7 -3
- pip/_internal/models/pylock.py +183 -0
- pip/_internal/models/wheel.py +64 -43
- pip/_internal/network/__init__.py +1 -2
- pip/_internal/network/cache.py +1 -2
- pip/_internal/network/download.py +170 -43
- pip/_internal/network/xmlrpc.py +1 -2
- pip/_internal/operations/build/metadata.py +1 -2
- pip/_internal/operations/build/metadata_editable.py +1 -2
- pip/_internal/operations/build/metadata_legacy.py +1 -2
- pip/_internal/operations/build/wheel_legacy.py +16 -0
- pip/_internal/operations/check.py +1 -2
- pip/_internal/operations/install/__init__.py +1 -2
- pip/_internal/operations/install/editable_legacy.py +1 -2
- pip/_internal/operations/install/wheel.py +10 -14
- pip/_internal/operations/prepare.py +10 -5
- pip/_internal/req/__init__.py +14 -1
- pip/_internal/req/req_dependency_group.py +74 -0
- pip/_internal/req/req_install.py +2 -2
- pip/_internal/req/req_uninstall.py +7 -4
- pip/_internal/resolution/resolvelib/candidates.py +6 -1
- pip/_internal/resolution/resolvelib/factory.py +1 -1
- pip/_internal/resolution/resolvelib/found_candidates.py +10 -20
- pip/_internal/resolution/resolvelib/provider.py +88 -65
- pip/_internal/resolution/resolvelib/reporter.py +6 -4
- pip/_internal/resolution/resolvelib/resolver.py +5 -2
- pip/_internal/utils/appdirs.py +2 -1
- pip/_internal/utils/compatibility_tags.py +14 -2
- pip/_internal/utils/datetime.py +1 -2
- pip/_internal/utils/entrypoints.py +4 -1
- pip/_internal/utils/filetypes.py +1 -2
- pip/_internal/utils/logging.py +20 -13
- pip/_internal/utils/misc.py +0 -18
- pip/_internal/utils/packaging.py +2 -17
- pip/_internal/utils/setuptools_build.py +5 -4
- pip/_internal/utils/unpacking.py +1 -3
- pip/_internal/utils/wheel.py +1 -2
- pip/_internal/vcs/git.py +10 -1
- pip/_internal/wheel_builder.py +5 -27
- pip/_vendor/__init__.py +1 -0
- pip/_vendor/cachecontrol/__init__.py +1 -1
- pip/_vendor/cachecontrol/adapter.py +13 -6
- pip/_vendor/cachecontrol/caches/file_cache.py +10 -47
- pip/_vendor/cachecontrol/controller.py +12 -1
- pip/_vendor/certifi/__init__.py +1 -1
- pip/_vendor/certifi/cacert.pem +122 -154
- pip/_vendor/dependency_groups/__init__.py +13 -0
- pip/_vendor/dependency_groups/__main__.py +65 -0
- pip/_vendor/dependency_groups/_implementation.py +213 -0
- pip/_vendor/dependency_groups/_lint_dependency_groups.py +59 -0
- pip/_vendor/dependency_groups/_pip_wrapper.py +62 -0
- pip/_vendor/dependency_groups/_toml_compat.py +9 -0
- pip/_vendor/packaging/__init__.py +1 -1
- pip/_vendor/packaging/_elffile.py +1 -2
- pip/_vendor/packaging/_manylinux.py +1 -2
- pip/_vendor/packaging/_parser.py +1 -2
- pip/_vendor/packaging/_tokenizer.py +5 -4
- pip/_vendor/packaging/licenses/__init__.py +1 -1
- pip/_vendor/packaging/markers.py +53 -22
- pip/_vendor/packaging/metadata.py +1 -2
- pip/_vendor/packaging/specifiers.py +1 -2
- pip/_vendor/packaging/tags.py +39 -0
- pip/_vendor/platformdirs/__init__.py +20 -20
- pip/_vendor/platformdirs/android.py +3 -3
- pip/_vendor/platformdirs/api.py +3 -2
- pip/_vendor/platformdirs/unix.py +4 -1
- pip/_vendor/platformdirs/version.py +9 -4
- pip/_vendor/pygments/__init__.py +2 -2
- pip/_vendor/pygments/__main__.py +1 -1
- pip/_vendor/pygments/console.py +1 -1
- pip/_vendor/pygments/filter.py +1 -1
- pip/_vendor/pygments/filters/__init__.py +1 -1
- pip/_vendor/pygments/formatter.py +1 -1
- pip/_vendor/pygments/formatters/__init__.py +1 -1
- pip/_vendor/pygments/lexer.py +1 -1
- pip/_vendor/pygments/lexers/__init__.py +1 -1
- pip/_vendor/pygments/lexers/_mapping.py +16 -3
- pip/_vendor/pygments/lexers/python.py +27 -24
- pip/_vendor/pygments/modeline.py +1 -1
- pip/_vendor/pygments/plugin.py +1 -1
- pip/_vendor/pygments/regexopt.py +1 -1
- pip/_vendor/pygments/scanner.py +1 -1
- pip/_vendor/pygments/sphinxext.py +1 -1
- pip/_vendor/pygments/style.py +1 -1
- pip/_vendor/pygments/styles/__init__.py +1 -1
- pip/_vendor/pygments/token.py +1 -1
- pip/_vendor/pygments/unistring.py +1 -1
- pip/_vendor/pygments/util.py +1 -1
- pip/_vendor/resolvelib/__init__.py +3 -2
- pip/_vendor/resolvelib/providers.py +103 -40
- pip/_vendor/resolvelib/reporters.py +21 -9
- pip/_vendor/resolvelib/resolvers/__init__.py +27 -0
- pip/_vendor/resolvelib/resolvers/abstract.py +47 -0
- pip/_vendor/resolvelib/resolvers/criterion.py +48 -0
- pip/_vendor/resolvelib/resolvers/exceptions.py +57 -0
- pip/_vendor/resolvelib/{resolvers.py → resolvers/resolution.py} +211 -217
- pip/_vendor/resolvelib/structs.py +93 -54
- pip/_vendor/rich/console.py +21 -7
- pip/_vendor/rich/default_styles.py +3 -1
- pip/_vendor/rich/diagnose.py +7 -6
- pip/_vendor/rich/panel.py +1 -1
- pip/_vendor/rich/style.py +1 -1
- pip/_vendor/rich/table.py +0 -1
- pip/_vendor/rich/traceback.py +129 -42
- pip/_vendor/tomli_w/__init__.py +4 -0
- pip/_vendor/tomli_w/_writer.py +229 -0
- pip/_vendor/tomli_w/py.typed +1 -0
- pip/_vendor/truststore/__init__.py +2 -2
- pip/_vendor/truststore/_api.py +18 -1
- pip/_vendor/typing_extensions.py +1027 -84
- pip/_vendor/vendor.txt +11 -9
- {pip-25.0.1.dist-info → pip-25.1.dist-info}/METADATA +4 -4
- {pip-25.0.1.dist-info → pip-25.1.dist-info}/RECORD +151 -149
- {pip-25.0.1.dist-info → pip-25.1.dist-info}/WHEEL +1 -1
- {pip-25.0.1.dist-info → pip-25.1.dist-info/licenses}/AUTHORS.txt +15 -0
- pip/_vendor/pygments/cmdline.py +0 -668
- pip/_vendor/pygments/formatters/bbcode.py +0 -108
- pip/_vendor/pygments/formatters/groff.py +0 -170
- pip/_vendor/pygments/formatters/html.py +0 -987
- pip/_vendor/pygments/formatters/img.py +0 -685
- pip/_vendor/pygments/formatters/irc.py +0 -154
- pip/_vendor/pygments/formatters/latex.py +0 -518
- pip/_vendor/pygments/formatters/other.py +0 -160
- pip/_vendor/pygments/formatters/pangomarkup.py +0 -83
- pip/_vendor/pygments/formatters/rtf.py +0 -349
- pip/_vendor/pygments/formatters/svg.py +0 -185
- pip/_vendor/pygments/formatters/terminal.py +0 -127
- pip/_vendor/pygments/formatters/terminal256.py +0 -338
- pip/_vendor/resolvelib/compat/collections_abc.py +0 -6
- /pip/_vendor/{resolvelib/compat/__init__.py → dependency_groups/py.typed} +0 -0
- {pip-25.0.1.dist-info → pip-25.1.dist-info}/entry_points.txt +0 -0
- {pip-25.0.1.dist-info → pip-25.1.dist-info/licenses}/LICENSE.txt +0 -0
- {pip-25.0.1.dist-info → pip-25.1.dist-info}/top_level.txt +0 -0
pip/__init__.py
CHANGED
pip/__pip-runner__.py
CHANGED
pip/_internal/build_env.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
"""Build Environment used for isolation during sdist building
|
|
2
|
-
"""
|
|
1
|
+
"""Build Environment used for isolation during sdist building"""
|
|
3
2
|
|
|
4
3
|
import logging
|
|
5
4
|
import os
|
|
@@ -241,6 +240,10 @@ class BuildEnvironment:
|
|
|
241
240
|
prefix.path,
|
|
242
241
|
"--no-warn-script-location",
|
|
243
242
|
"--disable-pip-version-check",
|
|
243
|
+
# As the build environment is ephemeral, it's wasteful to
|
|
244
|
+
# pre-compile everything, especially as not every Python
|
|
245
|
+
# module will be used/compiled in most cases.
|
|
246
|
+
"--no-compile",
|
|
244
247
|
# The prefix specified two lines above, thus
|
|
245
248
|
# target from config file or env var should be ignored
|
|
246
249
|
"--target",
|
pip/_internal/cache.py
CHANGED
pip/_internal/cli/__init__.py
CHANGED
|
@@ -29,7 +29,6 @@ from pip._internal.exceptions import (
|
|
|
29
29
|
NetworkConnectionError,
|
|
30
30
|
PreviousBuildDirError,
|
|
31
31
|
)
|
|
32
|
-
from pip._internal.utils.deprecation import deprecated
|
|
33
32
|
from pip._internal.utils.filesystem import check_path_owner
|
|
34
33
|
from pip._internal.utils.logging import BrokenStdoutLoggingError, setup_logging
|
|
35
34
|
from pip._internal.utils.misc import get_prog, normalize_path
|
|
@@ -172,6 +171,8 @@ class Command(CommandContextMixIn):
|
|
|
172
171
|
|
|
173
172
|
# Set verbosity so that it can be used elsewhere.
|
|
174
173
|
self.verbosity = options.verbose - options.quiet
|
|
174
|
+
if options.debug_mode:
|
|
175
|
+
self.verbosity = 2
|
|
175
176
|
|
|
176
177
|
reconfigure(no_color=options.no_color)
|
|
177
178
|
level_number = setup_logging(
|
|
@@ -229,12 +230,4 @@ class Command(CommandContextMixIn):
|
|
|
229
230
|
)
|
|
230
231
|
options.cache_dir = None
|
|
231
232
|
|
|
232
|
-
if options.no_python_version_warning:
|
|
233
|
-
deprecated(
|
|
234
|
-
reason="--no-python-version-warning is deprecated.",
|
|
235
|
-
replacement="to remove the flag as it's a no-op",
|
|
236
|
-
gone_in="25.1",
|
|
237
|
-
issue=13154,
|
|
238
|
-
)
|
|
239
|
-
|
|
240
233
|
return self._run_wrapper(level_number, options, args)
|
pip/_internal/cli/cmdoptions.py
CHANGED
|
@@ -13,6 +13,7 @@ pass on state. To be consistent, all options will follow this design.
|
|
|
13
13
|
import importlib.util
|
|
14
14
|
import logging
|
|
15
15
|
import os
|
|
16
|
+
import pathlib
|
|
16
17
|
import textwrap
|
|
17
18
|
from functools import partial
|
|
18
19
|
from optparse import SUPPRESS_HELP, Option, OptionGroup, OptionParser, Values
|
|
@@ -280,8 +281,17 @@ retries: Callable[..., Option] = partial(
|
|
|
280
281
|
dest="retries",
|
|
281
282
|
type="int",
|
|
282
283
|
default=5,
|
|
283
|
-
help="Maximum
|
|
284
|
-
|
|
284
|
+
help="Maximum attempts to establish a new HTTP connection. (default: %default)",
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
resume_retries: Callable[..., Option] = partial(
|
|
288
|
+
Option,
|
|
289
|
+
"--resume-retries",
|
|
290
|
+
dest="resume_retries",
|
|
291
|
+
type="int",
|
|
292
|
+
default=0,
|
|
293
|
+
help="Maximum attempts to resume or restart an incomplete download. "
|
|
294
|
+
"(default: %default)",
|
|
285
295
|
)
|
|
286
296
|
|
|
287
297
|
timeout: Callable[..., Option] = partial(
|
|
@@ -733,6 +743,46 @@ no_deps: Callable[..., Option] = partial(
|
|
|
733
743
|
help="Don't install package dependencies.",
|
|
734
744
|
)
|
|
735
745
|
|
|
746
|
+
|
|
747
|
+
def _handle_dependency_group(
|
|
748
|
+
option: Option, opt: str, value: str, parser: OptionParser
|
|
749
|
+
) -> None:
|
|
750
|
+
"""
|
|
751
|
+
Process a value provided for the --group option.
|
|
752
|
+
|
|
753
|
+
Splits on the rightmost ":", and validates that the path (if present) ends
|
|
754
|
+
in `pyproject.toml`. Defaults the path to `pyproject.toml` when one is not given.
|
|
755
|
+
|
|
756
|
+
`:` cannot appear in dependency group names, so this is a safe and simple parse.
|
|
757
|
+
|
|
758
|
+
This is an optparse.Option callback for the dependency_groups option.
|
|
759
|
+
"""
|
|
760
|
+
path, sep, groupname = value.rpartition(":")
|
|
761
|
+
if not sep:
|
|
762
|
+
path = "pyproject.toml"
|
|
763
|
+
else:
|
|
764
|
+
# check for 'pyproject.toml' filenames using pathlib
|
|
765
|
+
if pathlib.PurePath(path).name != "pyproject.toml":
|
|
766
|
+
msg = "group paths use 'pyproject.toml' filenames"
|
|
767
|
+
raise_option_error(parser, option=option, msg=msg)
|
|
768
|
+
|
|
769
|
+
parser.values.dependency_groups.append((path, groupname))
|
|
770
|
+
|
|
771
|
+
|
|
772
|
+
dependency_groups: Callable[..., Option] = partial(
|
|
773
|
+
Option,
|
|
774
|
+
"--group",
|
|
775
|
+
dest="dependency_groups",
|
|
776
|
+
default=[],
|
|
777
|
+
type=str,
|
|
778
|
+
action="callback",
|
|
779
|
+
callback=_handle_dependency_group,
|
|
780
|
+
metavar="[path:]group",
|
|
781
|
+
help='Install a named dependency-group from a "pyproject.toml" file. '
|
|
782
|
+
'If a path is given, the name of the file must be "pyproject.toml". '
|
|
783
|
+
'Defaults to using "pyproject.toml" in the current directory.',
|
|
784
|
+
)
|
|
785
|
+
|
|
736
786
|
ignore_requires_python: Callable[..., Option] = partial(
|
|
737
787
|
Option,
|
|
738
788
|
"--ignore-requires-python",
|
|
@@ -783,9 +833,9 @@ def _handle_no_use_pep517(
|
|
|
783
833
|
"""
|
|
784
834
|
raise_option_error(parser, option=option, msg=msg)
|
|
785
835
|
|
|
786
|
-
# If user doesn't wish to use pep517, we check if setuptools
|
|
836
|
+
# If user doesn't wish to use pep517, we check if setuptools is installed
|
|
787
837
|
# and raise error if it is not.
|
|
788
|
-
packages = ("setuptools",
|
|
838
|
+
packages = ("setuptools",)
|
|
789
839
|
if not all(importlib.util.find_spec(package) for package in packages):
|
|
790
840
|
msg = (
|
|
791
841
|
f"It is not possible to use --no-use-pep517 "
|
|
@@ -887,6 +937,14 @@ pre: Callable[..., Option] = partial(
|
|
|
887
937
|
"pip only finds stable versions.",
|
|
888
938
|
)
|
|
889
939
|
|
|
940
|
+
json: Callable[..., Option] = partial(
|
|
941
|
+
Option,
|
|
942
|
+
"--json",
|
|
943
|
+
action="store_true",
|
|
944
|
+
default=False,
|
|
945
|
+
help="Output data in a machine-readable JSON format.",
|
|
946
|
+
)
|
|
947
|
+
|
|
890
948
|
disable_pip_version_check: Callable[..., Option] = partial(
|
|
891
949
|
Option,
|
|
892
950
|
"--disable-pip-version-check",
|
|
@@ -990,7 +1048,7 @@ no_python_version_warning: Callable[..., Option] = partial(
|
|
|
990
1048
|
dest="no_python_version_warning",
|
|
991
1049
|
action="store_true",
|
|
992
1050
|
default=False,
|
|
993
|
-
help=
|
|
1051
|
+
help=SUPPRESS_HELP, # No-op, a hold-over from the Python 2->3 transition.
|
|
994
1052
|
)
|
|
995
1053
|
|
|
996
1054
|
|
|
@@ -1028,7 +1086,6 @@ use_deprecated_feature: Callable[..., Option] = partial(
|
|
|
1028
1086
|
help=("Enable deprecated functionality, that will be removed in the future."),
|
|
1029
1087
|
)
|
|
1030
1088
|
|
|
1031
|
-
|
|
1032
1089
|
##########
|
|
1033
1090
|
# groups #
|
|
1034
1091
|
##########
|
|
@@ -1061,6 +1118,7 @@ general_group: Dict[str, Any] = {
|
|
|
1061
1118
|
no_python_version_warning,
|
|
1062
1119
|
use_new_feature,
|
|
1063
1120
|
use_deprecated_feature,
|
|
1121
|
+
resume_retries,
|
|
1064
1122
|
],
|
|
1065
1123
|
}
|
|
1066
1124
|
|
|
@@ -9,6 +9,7 @@ so commands which don't always hit the network (e.g. list w/o --outdated or
|
|
|
9
9
|
import logging
|
|
10
10
|
import os
|
|
11
11
|
import sys
|
|
12
|
+
from functools import lru_cache
|
|
12
13
|
from optparse import Values
|
|
13
14
|
from typing import TYPE_CHECKING, List, Optional
|
|
14
15
|
|
|
@@ -25,6 +26,7 @@ if TYPE_CHECKING:
|
|
|
25
26
|
logger = logging.getLogger(__name__)
|
|
26
27
|
|
|
27
28
|
|
|
29
|
+
@lru_cache
|
|
28
30
|
def _create_truststore_ssl_context() -> Optional["SSLContext"]:
|
|
29
31
|
if sys.version_info < (3, 10):
|
|
30
32
|
logger.debug("Disabling truststore because Python version isn't 3.10+")
|
pip/_internal/cli/main.py
CHANGED
pip/_internal/cli/main_parser.py
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import functools
|
|
2
2
|
import sys
|
|
3
|
-
from typing import Callable, Generator, Iterable, Iterator, Optional, Tuple
|
|
3
|
+
from typing import Callable, Generator, Iterable, Iterator, Optional, Tuple, TypeVar
|
|
4
4
|
|
|
5
5
|
from pip._vendor.rich.progress import (
|
|
6
6
|
BarColumn,
|
|
7
7
|
DownloadColumn,
|
|
8
8
|
FileSizeColumn,
|
|
9
|
+
MofNCompleteColumn,
|
|
9
10
|
Progress,
|
|
10
11
|
ProgressColumn,
|
|
11
12
|
SpinnerColumn,
|
|
@@ -16,16 +17,19 @@ from pip._vendor.rich.progress import (
|
|
|
16
17
|
)
|
|
17
18
|
|
|
18
19
|
from pip._internal.cli.spinners import RateLimiter
|
|
19
|
-
from pip._internal.
|
|
20
|
+
from pip._internal.req.req_install import InstallRequirement
|
|
21
|
+
from pip._internal.utils.logging import get_console, get_indentation
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
T = TypeVar("T")
|
|
24
|
+
ProgressRenderer = Callable[[Iterable[T]], Iterator[T]]
|
|
22
25
|
|
|
23
26
|
|
|
24
|
-
def
|
|
27
|
+
def _rich_download_progress_bar(
|
|
25
28
|
iterable: Iterable[bytes],
|
|
26
29
|
*,
|
|
27
30
|
bar_type: str,
|
|
28
31
|
size: Optional[int],
|
|
32
|
+
initial_progress: Optional[int] = None,
|
|
29
33
|
) -> Generator[bytes, None, None]:
|
|
30
34
|
assert bar_type == "on", "This should only be used in the default mode."
|
|
31
35
|
|
|
@@ -51,22 +55,47 @@ def _rich_progress_bar(
|
|
|
51
55
|
|
|
52
56
|
progress = Progress(*columns, refresh_per_second=5)
|
|
53
57
|
task_id = progress.add_task(" " * (get_indentation() + 2), total=total)
|
|
58
|
+
if initial_progress is not None:
|
|
59
|
+
progress.update(task_id, advance=initial_progress)
|
|
54
60
|
with progress:
|
|
55
61
|
for chunk in iterable:
|
|
56
62
|
yield chunk
|
|
57
63
|
progress.update(task_id, advance=len(chunk))
|
|
58
64
|
|
|
59
65
|
|
|
66
|
+
def _rich_install_progress_bar(
|
|
67
|
+
iterable: Iterable[InstallRequirement], *, total: int
|
|
68
|
+
) -> Iterator[InstallRequirement]:
|
|
69
|
+
columns = (
|
|
70
|
+
TextColumn("{task.fields[indent]}"),
|
|
71
|
+
BarColumn(),
|
|
72
|
+
MofNCompleteColumn(),
|
|
73
|
+
TextColumn("{task.description}"),
|
|
74
|
+
)
|
|
75
|
+
console = get_console()
|
|
76
|
+
|
|
77
|
+
bar = Progress(*columns, refresh_per_second=6, console=console, transient=True)
|
|
78
|
+
# Hiding the progress bar at initialization forces a refresh cycle to occur
|
|
79
|
+
# until the bar appears, avoiding very short flashes.
|
|
80
|
+
task = bar.add_task("", total=total, indent=" " * get_indentation(), visible=False)
|
|
81
|
+
with bar:
|
|
82
|
+
for req in iterable:
|
|
83
|
+
bar.update(task, description=rf"\[{req.name}]", visible=True)
|
|
84
|
+
yield req
|
|
85
|
+
bar.advance(task)
|
|
86
|
+
|
|
87
|
+
|
|
60
88
|
def _raw_progress_bar(
|
|
61
89
|
iterable: Iterable[bytes],
|
|
62
90
|
*,
|
|
63
91
|
size: Optional[int],
|
|
92
|
+
initial_progress: Optional[int] = None,
|
|
64
93
|
) -> Generator[bytes, None, None]:
|
|
65
94
|
def write_progress(current: int, total: int) -> None:
|
|
66
95
|
sys.stdout.write(f"Progress {current} of {total}\n")
|
|
67
96
|
sys.stdout.flush()
|
|
68
97
|
|
|
69
|
-
current = 0
|
|
98
|
+
current = initial_progress or 0
|
|
70
99
|
total = size or 0
|
|
71
100
|
rate_limiter = RateLimiter(0.25)
|
|
72
101
|
|
|
@@ -80,15 +109,36 @@ def _raw_progress_bar(
|
|
|
80
109
|
|
|
81
110
|
|
|
82
111
|
def get_download_progress_renderer(
|
|
83
|
-
*, bar_type: str, size: Optional[int] = None
|
|
84
|
-
) ->
|
|
112
|
+
*, bar_type: str, size: Optional[int] = None, initial_progress: Optional[int] = None
|
|
113
|
+
) -> ProgressRenderer[bytes]:
|
|
85
114
|
"""Get an object that can be used to render the download progress.
|
|
86
115
|
|
|
87
116
|
Returns a callable, that takes an iterable to "wrap".
|
|
88
117
|
"""
|
|
89
118
|
if bar_type == "on":
|
|
90
|
-
return functools.partial(
|
|
119
|
+
return functools.partial(
|
|
120
|
+
_rich_download_progress_bar,
|
|
121
|
+
bar_type=bar_type,
|
|
122
|
+
size=size,
|
|
123
|
+
initial_progress=initial_progress,
|
|
124
|
+
)
|
|
91
125
|
elif bar_type == "raw":
|
|
92
|
-
return functools.partial(
|
|
126
|
+
return functools.partial(
|
|
127
|
+
_raw_progress_bar,
|
|
128
|
+
size=size,
|
|
129
|
+
initial_progress=initial_progress,
|
|
130
|
+
)
|
|
93
131
|
else:
|
|
94
132
|
return iter # no-op, when passed an iterator
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def get_install_progress_renderer(
|
|
136
|
+
*, bar_type: str, total: int
|
|
137
|
+
) -> ProgressRenderer[InstallRequirement]:
|
|
138
|
+
"""Get an object that can be used to render the install progress.
|
|
139
|
+
Returns a callable, that takes an iterable to "wrap".
|
|
140
|
+
"""
|
|
141
|
+
if bar_type == "on":
|
|
142
|
+
return functools.partial(_rich_install_progress_bar, total=total)
|
|
143
|
+
else:
|
|
144
|
+
return iter
|
pip/_internal/cli/req_command.py
CHANGED
|
@@ -28,6 +28,7 @@ from pip._internal.req.constructors import (
|
|
|
28
28
|
install_req_from_parsed_requirement,
|
|
29
29
|
install_req_from_req_string,
|
|
30
30
|
)
|
|
31
|
+
from pip._internal.req.req_dependency_group import parse_dependency_groups
|
|
31
32
|
from pip._internal.req.req_file import parse_requirements
|
|
32
33
|
from pip._internal.req.req_install import InstallRequirement
|
|
33
34
|
from pip._internal.resolution.base import BaseResolver
|
|
@@ -79,6 +80,7 @@ class RequirementCommand(IndexGroupCommand):
|
|
|
79
80
|
def __init__(self, *args: Any, **kw: Any) -> None:
|
|
80
81
|
super().__init__(*args, **kw)
|
|
81
82
|
|
|
83
|
+
self.cmd_opts.add_option(cmdoptions.dependency_groups())
|
|
82
84
|
self.cmd_opts.add_option(cmdoptions.no_clean())
|
|
83
85
|
|
|
84
86
|
@staticmethod
|
|
@@ -142,6 +144,7 @@ class RequirementCommand(IndexGroupCommand):
|
|
|
142
144
|
lazy_wheel=lazy_wheel,
|
|
143
145
|
verbosity=verbosity,
|
|
144
146
|
legacy_resolver=legacy_resolver,
|
|
147
|
+
resume_retries=options.resume_retries,
|
|
145
148
|
)
|
|
146
149
|
|
|
147
150
|
@classmethod
|
|
@@ -240,6 +243,16 @@ class RequirementCommand(IndexGroupCommand):
|
|
|
240
243
|
)
|
|
241
244
|
requirements.append(req_to_add)
|
|
242
245
|
|
|
246
|
+
if options.dependency_groups:
|
|
247
|
+
for req in parse_dependency_groups(options.dependency_groups):
|
|
248
|
+
req_to_add = install_req_from_req_string(
|
|
249
|
+
req,
|
|
250
|
+
isolated=options.isolated_mode,
|
|
251
|
+
use_pep517=options.use_pep517,
|
|
252
|
+
user_supplied=True,
|
|
253
|
+
)
|
|
254
|
+
requirements.append(req_to_add)
|
|
255
|
+
|
|
243
256
|
for req in options.editables:
|
|
244
257
|
req_to_add = install_req_from_editable(
|
|
245
258
|
req,
|
|
@@ -272,7 +285,12 @@ class RequirementCommand(IndexGroupCommand):
|
|
|
272
285
|
if any(req.has_hash_options for req in requirements):
|
|
273
286
|
options.require_hashes = True
|
|
274
287
|
|
|
275
|
-
if not (
|
|
288
|
+
if not (
|
|
289
|
+
args
|
|
290
|
+
or options.editables
|
|
291
|
+
or options.requirements
|
|
292
|
+
or options.dependency_groups
|
|
293
|
+
):
|
|
276
294
|
opts = {"name": self.name}
|
|
277
295
|
if options.find_links:
|
|
278
296
|
raise CommandError(
|
|
@@ -23,6 +23,11 @@ commands_dict: Dict[str, CommandInfo] = {
|
|
|
23
23
|
"InstallCommand",
|
|
24
24
|
"Install packages.",
|
|
25
25
|
),
|
|
26
|
+
"lock": CommandInfo(
|
|
27
|
+
"pip._internal.commands.lock",
|
|
28
|
+
"LockCommand",
|
|
29
|
+
"Generate a lock file.",
|
|
30
|
+
),
|
|
26
31
|
"download": CommandInfo(
|
|
27
32
|
"pip._internal.commands.download",
|
|
28
33
|
"DownloadCommand",
|
|
@@ -38,12 +38,18 @@ COMPLETION_SCRIPTS = {
|
|
|
38
38
|
""",
|
|
39
39
|
"fish": """
|
|
40
40
|
function __fish_complete_pip
|
|
41
|
-
set -lx COMP_WORDS
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
)
|
|
41
|
+
set -lx COMP_WORDS \\
|
|
42
|
+
(commandline --current-process --tokenize --cut-at-cursor) \\
|
|
43
|
+
(commandline --current-token --cut-at-cursor)
|
|
44
|
+
set -lx COMP_CWORD (math (count $COMP_WORDS) - 1)
|
|
45
45
|
set -lx PIP_AUTO_COMPLETE 1
|
|
46
|
-
|
|
46
|
+
set -l completions
|
|
47
|
+
if string match -q '2.*' $version
|
|
48
|
+
set completions (eval $COMP_WORDS[1])
|
|
49
|
+
else
|
|
50
|
+
set completions ($COMP_WORDS[1])
|
|
51
|
+
end
|
|
52
|
+
string split \\ -- $completions
|
|
47
53
|
end
|
|
48
54
|
complete -fa "(__fish_complete_pip)" -c {prog}
|
|
49
55
|
""",
|
pip/_internal/commands/freeze.py
CHANGED
pip/_internal/commands/index.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import json
|
|
1
2
|
import logging
|
|
2
3
|
from optparse import Values
|
|
3
4
|
from typing import Any, Iterable, List, Optional
|
|
@@ -7,7 +8,10 @@ from pip._vendor.packaging.version import Version
|
|
|
7
8
|
from pip._internal.cli import cmdoptions
|
|
8
9
|
from pip._internal.cli.req_command import IndexGroupCommand
|
|
9
10
|
from pip._internal.cli.status_codes import ERROR, SUCCESS
|
|
10
|
-
from pip._internal.commands.search import
|
|
11
|
+
from pip._internal.commands.search import (
|
|
12
|
+
get_installed_distribution,
|
|
13
|
+
print_dist_installation_info,
|
|
14
|
+
)
|
|
11
15
|
from pip._internal.exceptions import CommandError, DistributionNotFound, PipError
|
|
12
16
|
from pip._internal.index.collector import LinkCollector
|
|
13
17
|
from pip._internal.index.package_finder import PackageFinder
|
|
@@ -34,6 +38,7 @@ class IndexCommand(IndexGroupCommand):
|
|
|
34
38
|
|
|
35
39
|
self.cmd_opts.add_option(cmdoptions.ignore_requires_python())
|
|
36
40
|
self.cmd_opts.add_option(cmdoptions.pre())
|
|
41
|
+
self.cmd_opts.add_option(cmdoptions.json())
|
|
37
42
|
self.cmd_opts.add_option(cmdoptions.no_binary())
|
|
38
43
|
self.cmd_opts.add_option(cmdoptions.only_binary())
|
|
39
44
|
|
|
@@ -50,12 +55,6 @@ class IndexCommand(IndexGroupCommand):
|
|
|
50
55
|
"versions": self.get_available_package_versions,
|
|
51
56
|
}
|
|
52
57
|
|
|
53
|
-
logger.warning(
|
|
54
|
-
"pip index is currently an experimental command. "
|
|
55
|
-
"It may be removed/changed in a future release "
|
|
56
|
-
"without prior warning."
|
|
57
|
-
)
|
|
58
|
-
|
|
59
58
|
# Determine action
|
|
60
59
|
if not args or args[0] not in handlers:
|
|
61
60
|
logger.error(
|
|
@@ -134,6 +133,21 @@ class IndexCommand(IndexGroupCommand):
|
|
|
134
133
|
formatted_versions = [str(ver) for ver in sorted(versions, reverse=True)]
|
|
135
134
|
latest = formatted_versions[0]
|
|
136
135
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
136
|
+
dist = get_installed_distribution(query)
|
|
137
|
+
|
|
138
|
+
if options.json:
|
|
139
|
+
structured_output = {
|
|
140
|
+
"name": query,
|
|
141
|
+
"versions": formatted_versions,
|
|
142
|
+
"latest": latest,
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if dist is not None:
|
|
146
|
+
structured_output["installed_version"] = str(dist.version)
|
|
147
|
+
|
|
148
|
+
write_output(json.dumps(structured_output))
|
|
149
|
+
|
|
150
|
+
else:
|
|
151
|
+
write_output(f"{query} ({latest})")
|
|
152
|
+
write_output("Available versions: {}".format(", ".join(formatted_versions)))
|
|
153
|
+
print_dist_installation_info(latest, dist)
|
|
@@ -8,6 +8,7 @@ from optparse import SUPPRESS_HELP, Values
|
|
|
8
8
|
from typing import List, Optional
|
|
9
9
|
|
|
10
10
|
from pip._vendor.packaging.utils import canonicalize_name
|
|
11
|
+
from pip._vendor.requests.exceptions import InvalidProxyURL
|
|
11
12
|
from pip._vendor.rich import print_json
|
|
12
13
|
|
|
13
14
|
# Eagerly import self_outdated_check to avoid crashes. Otherwise,
|
|
@@ -464,6 +465,7 @@ class InstallCommand(RequirementCommand):
|
|
|
464
465
|
warn_script_location=warn_script_location,
|
|
465
466
|
use_user_site=options.use_user_site,
|
|
466
467
|
pycompile=options.compile,
|
|
468
|
+
progress_bar=options.progress_bar,
|
|
467
469
|
)
|
|
468
470
|
|
|
469
471
|
lib_locations = get_lib_location_guesses(
|
|
@@ -765,6 +767,13 @@ def create_os_error_message(
|
|
|
765
767
|
parts.append(permissions_part)
|
|
766
768
|
parts.append(".\n")
|
|
767
769
|
|
|
770
|
+
# Suggest to check "pip config debug" in case of invalid proxy
|
|
771
|
+
if type(error) is InvalidProxyURL:
|
|
772
|
+
parts.append(
|
|
773
|
+
'Consider checking your local proxy configuration with "pip config debug"'
|
|
774
|
+
)
|
|
775
|
+
parts.append(".\n")
|
|
776
|
+
|
|
768
777
|
# Suggest the user to enable Long Paths if path length is
|
|
769
778
|
# more than 260
|
|
770
779
|
if (
|
pip/_internal/commands/list.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import logging
|
|
3
|
+
from email.parser import Parser
|
|
3
4
|
from optparse import Values
|
|
4
5
|
from typing import TYPE_CHECKING, Generator, List, Optional, Sequence, Tuple, cast
|
|
5
6
|
|
|
@@ -125,7 +126,7 @@ class ListCommand(IndexGroupCommand):
|
|
|
125
126
|
"--include-editable",
|
|
126
127
|
action="store_true",
|
|
127
128
|
dest="include_editable",
|
|
128
|
-
help="Include editable package
|
|
129
|
+
help="Include editable package in output.",
|
|
129
130
|
default=True,
|
|
130
131
|
)
|
|
131
132
|
self.cmd_opts.add_option(cmdoptions.list_exclude())
|
|
@@ -323,17 +324,29 @@ def format_for_columns(
|
|
|
323
324
|
if running_outdated:
|
|
324
325
|
header.extend(["Latest", "Type"])
|
|
325
326
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
327
|
+
def wheel_build_tag(dist: BaseDistribution) -> Optional[str]:
|
|
328
|
+
try:
|
|
329
|
+
wheel_file = dist.read_text("WHEEL")
|
|
330
|
+
except FileNotFoundError:
|
|
331
|
+
return None
|
|
332
|
+
return Parser().parsestr(wheel_file).get("Build")
|
|
333
|
+
|
|
334
|
+
build_tags = [wheel_build_tag(p) for p in pkgs]
|
|
335
|
+
has_build_tags = any(build_tags)
|
|
336
|
+
if has_build_tags:
|
|
337
|
+
header.append("Build")
|
|
329
338
|
|
|
330
339
|
if options.verbose >= 1:
|
|
331
340
|
header.append("Location")
|
|
332
341
|
if options.verbose >= 1:
|
|
333
342
|
header.append("Installer")
|
|
334
343
|
|
|
344
|
+
has_editables = any(x.editable for x in pkgs)
|
|
345
|
+
if has_editables:
|
|
346
|
+
header.append("Editable project location")
|
|
347
|
+
|
|
335
348
|
data = []
|
|
336
|
-
for proj in pkgs:
|
|
349
|
+
for i, proj in enumerate(pkgs):
|
|
337
350
|
# if we're working on the 'outdated' list, separate out the
|
|
338
351
|
# latest_version and type
|
|
339
352
|
row = [proj.raw_name, proj.raw_version]
|
|
@@ -342,6 +355,9 @@ def format_for_columns(
|
|
|
342
355
|
row.append(str(proj.latest_version))
|
|
343
356
|
row.append(proj.latest_filetype)
|
|
344
357
|
|
|
358
|
+
if has_build_tags:
|
|
359
|
+
row.append(build_tags[i] or "")
|
|
360
|
+
|
|
345
361
|
if has_editables:
|
|
346
362
|
row.append(proj.editable_project_location or "")
|
|
347
363
|
|