Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pip/_internal/cli/cmdoptions.py: 69%
200 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:48 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:48 +0000
1"""
2shared options and groups
4The principle here is to define options once, but *not* instantiate them
5globally. One reason being that options with action='append' can carry state
6between parses. pip parses general options twice internally, and shouldn't
7pass on state. To be consistent, all options will follow this design.
8"""
10# The following comment should be removed at some point in the future.
11# mypy: strict-optional=False
13import importlib.util
14import logging
15import os
16import textwrap
17from functools import partial
18from optparse import SUPPRESS_HELP, Option, OptionGroup, OptionParser, Values
19from textwrap import dedent
20from typing import Any, Callable, Dict, Optional, Tuple
22from pip._vendor.packaging.utils import canonicalize_name
24from pip._internal.cli.parser import ConfigOptionParser
25from pip._internal.exceptions import CommandError
26from pip._internal.locations import USER_CACHE_DIR, get_src_prefix
27from pip._internal.models.format_control import FormatControl
28from pip._internal.models.index import PyPI
29from pip._internal.models.target_python import TargetPython
30from pip._internal.utils.hashes import STRONG_HASHES
31from pip._internal.utils.misc import strtobool
33logger = logging.getLogger(__name__)
36def raise_option_error(parser: OptionParser, option: Option, msg: str) -> None:
37 """
38 Raise an option parsing error using parser.error().
40 Args:
41 parser: an OptionParser instance.
42 option: an Option instance.
43 msg: the error text.
44 """
45 msg = f"{option} error: {msg}"
46 msg = textwrap.fill(" ".join(msg.split()))
47 parser.error(msg)
50def make_option_group(group: Dict[str, Any], parser: ConfigOptionParser) -> OptionGroup:
51 """
52 Return an OptionGroup object
53 group -- assumed to be dict with 'name' and 'options' keys
54 parser -- an optparse Parser
55 """
56 option_group = OptionGroup(parser, group["name"])
57 for option in group["options"]:
58 option_group.add_option(option())
59 return option_group
62def check_dist_restriction(options: Values, check_target: bool = False) -> None:
63 """Function for determining if custom platform options are allowed.
65 :param options: The OptionParser options.
66 :param check_target: Whether or not to check if --target is being used.
67 """
68 dist_restriction_set = any(
69 [
70 options.python_version,
71 options.platforms,
72 options.abis,
73 options.implementation,
74 ]
75 )
77 binary_only = FormatControl(set(), {":all:"})
78 sdist_dependencies_allowed = (
79 options.format_control != binary_only and not options.ignore_dependencies
80 )
82 # Installations or downloads using dist restrictions must not combine
83 # source distributions and dist-specific wheels, as they are not
84 # guaranteed to be locally compatible.
85 if dist_restriction_set and sdist_dependencies_allowed:
86 raise CommandError(
87 "When restricting platform and interpreter constraints using "
88 "--python-version, --platform, --abi, or --implementation, "
89 "either --no-deps must be set, or --only-binary=:all: must be "
90 "set and --no-binary must not be set (or must be set to "
91 ":none:)."
92 )
94 if check_target:
95 if dist_restriction_set and not options.target_dir:
96 raise CommandError(
97 "Can not use any platform or abi specific options unless "
98 "installing via '--target'"
99 )
102def _path_option_check(option: Option, opt: str, value: str) -> str:
103 return os.path.expanduser(value)
106def _package_name_option_check(option: Option, opt: str, value: str) -> str:
107 return canonicalize_name(value)
110class PipOption(Option):
111 TYPES = Option.TYPES + ("path", "package_name")
112 TYPE_CHECKER = Option.TYPE_CHECKER.copy()
113 TYPE_CHECKER["package_name"] = _package_name_option_check
114 TYPE_CHECKER["path"] = _path_option_check
117###########
118# options #
119###########
121help_: Callable[..., Option] = partial(
122 Option,
123 "-h",
124 "--help",
125 dest="help",
126 action="help",
127 help="Show help.",
128)
130debug_mode: Callable[..., Option] = partial(
131 Option,
132 "--debug",
133 dest="debug_mode",
134 action="store_true",
135 default=False,
136 help=(
137 "Let unhandled exceptions propagate outside the main subroutine, "
138 "instead of logging them to stderr."
139 ),
140)
142isolated_mode: Callable[..., Option] = partial(
143 Option,
144 "--isolated",
145 dest="isolated_mode",
146 action="store_true",
147 default=False,
148 help=(
149 "Run pip in an isolated mode, ignoring environment variables and user "
150 "configuration."
151 ),
152)
154require_virtualenv: Callable[..., Option] = partial(
155 Option,
156 "--require-virtualenv",
157 "--require-venv",
158 dest="require_venv",
159 action="store_true",
160 default=False,
161 help=(
162 "Allow pip to only run in a virtual environment; "
163 "exit with an error otherwise."
164 ),
165)
167override_externally_managed: Callable[..., Option] = partial(
168 Option,
169 "--break-system-packages",
170 dest="override_externally_managed",
171 action="store_true",
172 help="Allow pip to modify an EXTERNALLY-MANAGED Python installation",
173)
175python: Callable[..., Option] = partial(
176 Option,
177 "--python",
178 dest="python",
179 help="Run pip with the specified Python interpreter.",
180)
182verbose: Callable[..., Option] = partial(
183 Option,
184 "-v",
185 "--verbose",
186 dest="verbose",
187 action="count",
188 default=0,
189 help="Give more output. Option is additive, and can be used up to 3 times.",
190)
192no_color: Callable[..., Option] = partial(
193 Option,
194 "--no-color",
195 dest="no_color",
196 action="store_true",
197 default=False,
198 help="Suppress colored output.",
199)
201version: Callable[..., Option] = partial(
202 Option,
203 "-V",
204 "--version",
205 dest="version",
206 action="store_true",
207 help="Show version and exit.",
208)
210quiet: Callable[..., Option] = partial(
211 Option,
212 "-q",
213 "--quiet",
214 dest="quiet",
215 action="count",
216 default=0,
217 help=(
218 "Give less output. Option is additive, and can be used up to 3"
219 " times (corresponding to WARNING, ERROR, and CRITICAL logging"
220 " levels)."
221 ),
222)
224progress_bar: Callable[..., Option] = partial(
225 Option,
226 "--progress-bar",
227 dest="progress_bar",
228 type="choice",
229 choices=["on", "off"],
230 default="on",
231 help="Specify whether the progress bar should be used [on, off] (default: on)",
232)
234log: Callable[..., Option] = partial(
235 PipOption,
236 "--log",
237 "--log-file",
238 "--local-log",
239 dest="log",
240 metavar="path",
241 type="path",
242 help="Path to a verbose appending log.",
243)
245no_input: Callable[..., Option] = partial(
246 Option,
247 # Don't ask for input
248 "--no-input",
249 dest="no_input",
250 action="store_true",
251 default=False,
252 help="Disable prompting for input.",
253)
255keyring_provider: Callable[..., Option] = partial(
256 Option,
257 "--keyring-provider",
258 dest="keyring_provider",
259 choices=["auto", "disabled", "import", "subprocess"],
260 default="auto",
261 help=(
262 "Enable the credential lookup via the keyring library if user input is allowed."
263 " Specify which mechanism to use [disabled, import, subprocess]."
264 " (default: disabled)"
265 ),
266)
268proxy: Callable[..., Option] = partial(
269 Option,
270 "--proxy",
271 dest="proxy",
272 type="str",
273 default="",
274 help="Specify a proxy in the form scheme://[user:passwd@]proxy.server:port.",
275)
277retries: Callable[..., Option] = partial(
278 Option,
279 "--retries",
280 dest="retries",
281 type="int",
282 default=5,
283 help="Maximum number of retries each connection should attempt "
284 "(default %default times).",
285)
287timeout: Callable[..., Option] = partial(
288 Option,
289 "--timeout",
290 "--default-timeout",
291 metavar="sec",
292 dest="timeout",
293 type="float",
294 default=15,
295 help="Set the socket timeout (default %default seconds).",
296)
299def exists_action() -> Option:
300 return Option(
301 # Option when path already exist
302 "--exists-action",
303 dest="exists_action",
304 type="choice",
305 choices=["s", "i", "w", "b", "a"],
306 default=[],
307 action="append",
308 metavar="action",
309 help="Default action when a path already exists: "
310 "(s)witch, (i)gnore, (w)ipe, (b)ackup, (a)bort.",
311 )
314cert: Callable[..., Option] = partial(
315 PipOption,
316 "--cert",
317 dest="cert",
318 type="path",
319 metavar="path",
320 help=(
321 "Path to PEM-encoded CA certificate bundle. "
322 "If provided, overrides the default. "
323 "See 'SSL Certificate Verification' in pip documentation "
324 "for more information."
325 ),
326)
328client_cert: Callable[..., Option] = partial(
329 PipOption,
330 "--client-cert",
331 dest="client_cert",
332 type="path",
333 default=None,
334 metavar="path",
335 help="Path to SSL client certificate, a single file containing the "
336 "private key and the certificate in PEM format.",
337)
339index_url: Callable[..., Option] = partial(
340 Option,
341 "-i",
342 "--index-url",
343 "--pypi-url",
344 dest="index_url",
345 metavar="URL",
346 default=PyPI.simple_url,
347 help="Base URL of the Python Package Index (default %default). "
348 "This should point to a repository compliant with PEP 503 "
349 "(the simple repository API) or a local directory laid out "
350 "in the same format.",
351)
354def extra_index_url() -> Option:
355 return Option(
356 "--extra-index-url",
357 dest="extra_index_urls",
358 metavar="URL",
359 action="append",
360 default=[],
361 help="Extra URLs of package indexes to use in addition to "
362 "--index-url. Should follow the same rules as "
363 "--index-url.",
364 )
367no_index: Callable[..., Option] = partial(
368 Option,
369 "--no-index",
370 dest="no_index",
371 action="store_true",
372 default=False,
373 help="Ignore package index (only looking at --find-links URLs instead).",
374)
377def find_links() -> Option:
378 return Option(
379 "-f",
380 "--find-links",
381 dest="find_links",
382 action="append",
383 default=[],
384 metavar="url",
385 help="If a URL or path to an html file, then parse for links to "
386 "archives such as sdist (.tar.gz) or wheel (.whl) files. "
387 "If a local path or file:// URL that's a directory, "
388 "then look for archives in the directory listing. "
389 "Links to VCS project URLs are not supported.",
390 )
393def trusted_host() -> Option:
394 return Option(
395 "--trusted-host",
396 dest="trusted_hosts",
397 action="append",
398 metavar="HOSTNAME",
399 default=[],
400 help="Mark this host or host:port pair as trusted, even though it "
401 "does not have valid or any HTTPS.",
402 )
405def constraints() -> Option:
406 return Option(
407 "-c",
408 "--constraint",
409 dest="constraints",
410 action="append",
411 default=[],
412 metavar="file",
413 help="Constrain versions using the given constraints file. "
414 "This option can be used multiple times.",
415 )
418def requirements() -> Option:
419 return Option(
420 "-r",
421 "--requirement",
422 dest="requirements",
423 action="append",
424 default=[],
425 metavar="file",
426 help="Install from the given requirements file. "
427 "This option can be used multiple times.",
428 )
431def editable() -> Option:
432 return Option(
433 "-e",
434 "--editable",
435 dest="editables",
436 action="append",
437 default=[],
438 metavar="path/url",
439 help=(
440 "Install a project in editable mode (i.e. setuptools "
441 '"develop mode") from a local project path or a VCS url.'
442 ),
443 )
446def _handle_src(option: Option, opt_str: str, value: str, parser: OptionParser) -> None:
447 value = os.path.abspath(value)
448 setattr(parser.values, option.dest, value)
451src: Callable[..., Option] = partial(
452 PipOption,
453 "--src",
454 "--source",
455 "--source-dir",
456 "--source-directory",
457 dest="src_dir",
458 type="path",
459 metavar="dir",
460 default=get_src_prefix(),
461 action="callback",
462 callback=_handle_src,
463 help="Directory to check out editable projects into. "
464 'The default in a virtualenv is "<venv path>/src". '
465 'The default for global installs is "<current dir>/src".',
466)
469def _get_format_control(values: Values, option: Option) -> Any:
470 """Get a format_control object."""
471 return getattr(values, option.dest)
474def _handle_no_binary(
475 option: Option, opt_str: str, value: str, parser: OptionParser
476) -> None:
477 existing = _get_format_control(parser.values, option)
478 FormatControl.handle_mutual_excludes(
479 value,
480 existing.no_binary,
481 existing.only_binary,
482 )
485def _handle_only_binary(
486 option: Option, opt_str: str, value: str, parser: OptionParser
487) -> None:
488 existing = _get_format_control(parser.values, option)
489 FormatControl.handle_mutual_excludes(
490 value,
491 existing.only_binary,
492 existing.no_binary,
493 )
496def no_binary() -> Option:
497 format_control = FormatControl(set(), set())
498 return Option(
499 "--no-binary",
500 dest="format_control",
501 action="callback",
502 callback=_handle_no_binary,
503 type="str",
504 default=format_control,
505 help="Do not use binary packages. Can be supplied multiple times, and "
506 'each time adds to the existing value. Accepts either ":all:" to '
507 'disable all binary packages, ":none:" to empty the set (notice '
508 "the colons), or one or more package names with commas between "
509 "them (no colons). Note that some packages are tricky to compile "
510 "and may fail to install when this option is used on them.",
511 )
514def only_binary() -> Option:
515 format_control = FormatControl(set(), set())
516 return Option(
517 "--only-binary",
518 dest="format_control",
519 action="callback",
520 callback=_handle_only_binary,
521 type="str",
522 default=format_control,
523 help="Do not use source packages. Can be supplied multiple times, and "
524 'each time adds to the existing value. Accepts either ":all:" to '
525 'disable all source packages, ":none:" to empty the set, or one '
526 "or more package names with commas between them. Packages "
527 "without binary distributions will fail to install when this "
528 "option is used on them.",
529 )
532platforms: Callable[..., Option] = partial(
533 Option,
534 "--platform",
535 dest="platforms",
536 metavar="platform",
537 action="append",
538 default=None,
539 help=(
540 "Only use wheels compatible with <platform>. Defaults to the "
541 "platform of the running system. Use this option multiple times to "
542 "specify multiple platforms supported by the target interpreter."
543 ),
544)
547# This was made a separate function for unit-testing purposes.
548def _convert_python_version(value: str) -> Tuple[Tuple[int, ...], Optional[str]]:
549 """
550 Convert a version string like "3", "37", or "3.7.3" into a tuple of ints.
552 :return: A 2-tuple (version_info, error_msg), where `error_msg` is
553 non-None if and only if there was a parsing error.
554 """
555 if not value:
556 # The empty string is the same as not providing a value.
557 return (None, None)
559 parts = value.split(".")
560 if len(parts) > 3:
561 return ((), "at most three version parts are allowed")
563 if len(parts) == 1:
564 # Then we are in the case of "3" or "37".
565 value = parts[0]
566 if len(value) > 1:
567 parts = [value[0], value[1:]]
569 try:
570 version_info = tuple(int(part) for part in parts)
571 except ValueError:
572 return ((), "each version part must be an integer")
574 return (version_info, None)
577def _handle_python_version(
578 option: Option, opt_str: str, value: str, parser: OptionParser
579) -> None:
580 """
581 Handle a provided --python-version value.
582 """
583 version_info, error_msg = _convert_python_version(value)
584 if error_msg is not None:
585 msg = "invalid --python-version value: {!r}: {}".format(
586 value,
587 error_msg,
588 )
589 raise_option_error(parser, option=option, msg=msg)
591 parser.values.python_version = version_info
594python_version: Callable[..., Option] = partial(
595 Option,
596 "--python-version",
597 dest="python_version",
598 metavar="python_version",
599 action="callback",
600 callback=_handle_python_version,
601 type="str",
602 default=None,
603 help=dedent(
604 """\
605 The Python interpreter version to use for wheel and "Requires-Python"
606 compatibility checks. Defaults to a version derived from the running
607 interpreter. The version can be specified using up to three dot-separated
608 integers (e.g. "3" for 3.0.0, "3.7" for 3.7.0, or "3.7.3"). A major-minor
609 version can also be given as a string without dots (e.g. "37" for 3.7.0).
610 """
611 ),
612)
615implementation: Callable[..., Option] = partial(
616 Option,
617 "--implementation",
618 dest="implementation",
619 metavar="implementation",
620 default=None,
621 help=(
622 "Only use wheels compatible with Python "
623 "implementation <implementation>, e.g. 'pp', 'jy', 'cp', "
624 " or 'ip'. If not specified, then the current "
625 "interpreter implementation is used. Use 'py' to force "
626 "implementation-agnostic wheels."
627 ),
628)
631abis: Callable[..., Option] = partial(
632 Option,
633 "--abi",
634 dest="abis",
635 metavar="abi",
636 action="append",
637 default=None,
638 help=(
639 "Only use wheels compatible with Python abi <abi>, e.g. 'pypy_41'. "
640 "If not specified, then the current interpreter abi tag is used. "
641 "Use this option multiple times to specify multiple abis supported "
642 "by the target interpreter. Generally you will need to specify "
643 "--implementation, --platform, and --python-version when using this "
644 "option."
645 ),
646)
649def add_target_python_options(cmd_opts: OptionGroup) -> None:
650 cmd_opts.add_option(platforms())
651 cmd_opts.add_option(python_version())
652 cmd_opts.add_option(implementation())
653 cmd_opts.add_option(abis())
656def make_target_python(options: Values) -> TargetPython:
657 target_python = TargetPython(
658 platforms=options.platforms,
659 py_version_info=options.python_version,
660 abis=options.abis,
661 implementation=options.implementation,
662 )
664 return target_python
667def prefer_binary() -> Option:
668 return Option(
669 "--prefer-binary",
670 dest="prefer_binary",
671 action="store_true",
672 default=False,
673 help="Prefer older binary packages over newer source packages.",
674 )
677cache_dir: Callable[..., Option] = partial(
678 PipOption,
679 "--cache-dir",
680 dest="cache_dir",
681 default=USER_CACHE_DIR,
682 metavar="dir",
683 type="path",
684 help="Store the cache data in <dir>.",
685)
688def _handle_no_cache_dir(
689 option: Option, opt: str, value: str, parser: OptionParser
690) -> None:
691 """
692 Process a value provided for the --no-cache-dir option.
694 This is an optparse.Option callback for the --no-cache-dir option.
695 """
696 # The value argument will be None if --no-cache-dir is passed via the
697 # command-line, since the option doesn't accept arguments. However,
698 # the value can be non-None if the option is triggered e.g. by an
699 # environment variable, like PIP_NO_CACHE_DIR=true.
700 if value is not None:
701 # Then parse the string value to get argument error-checking.
702 try:
703 strtobool(value)
704 except ValueError as exc:
705 raise_option_error(parser, option=option, msg=str(exc))
707 # Originally, setting PIP_NO_CACHE_DIR to a value that strtobool()
708 # converted to 0 (like "false" or "no") caused cache_dir to be disabled
709 # rather than enabled (logic would say the latter). Thus, we disable
710 # the cache directory not just on values that parse to True, but (for
711 # backwards compatibility reasons) also on values that parse to False.
712 # In other words, always set it to False if the option is provided in
713 # some (valid) form.
714 parser.values.cache_dir = False
717no_cache: Callable[..., Option] = partial(
718 Option,
719 "--no-cache-dir",
720 dest="cache_dir",
721 action="callback",
722 callback=_handle_no_cache_dir,
723 help="Disable the cache.",
724)
726no_deps: Callable[..., Option] = partial(
727 Option,
728 "--no-deps",
729 "--no-dependencies",
730 dest="ignore_dependencies",
731 action="store_true",
732 default=False,
733 help="Don't install package dependencies.",
734)
736ignore_requires_python: Callable[..., Option] = partial(
737 Option,
738 "--ignore-requires-python",
739 dest="ignore_requires_python",
740 action="store_true",
741 help="Ignore the Requires-Python information.",
742)
744no_build_isolation: Callable[..., Option] = partial(
745 Option,
746 "--no-build-isolation",
747 dest="build_isolation",
748 action="store_false",
749 default=True,
750 help="Disable isolation when building a modern source distribution. "
751 "Build dependencies specified by PEP 518 must be already installed "
752 "if this option is used.",
753)
755check_build_deps: Callable[..., Option] = partial(
756 Option,
757 "--check-build-dependencies",
758 dest="check_build_deps",
759 action="store_true",
760 default=False,
761 help="Check the build dependencies when PEP517 is used.",
762)
765def _handle_no_use_pep517(
766 option: Option, opt: str, value: str, parser: OptionParser
767) -> None:
768 """
769 Process a value provided for the --no-use-pep517 option.
771 This is an optparse.Option callback for the no_use_pep517 option.
772 """
773 # Since --no-use-pep517 doesn't accept arguments, the value argument
774 # will be None if --no-use-pep517 is passed via the command-line.
775 # However, the value can be non-None if the option is triggered e.g.
776 # by an environment variable, for example "PIP_NO_USE_PEP517=true".
777 if value is not None:
778 msg = """A value was passed for --no-use-pep517,
779 probably using either the PIP_NO_USE_PEP517 environment variable
780 or the "no-use-pep517" config file option. Use an appropriate value
781 of the PIP_USE_PEP517 environment variable or the "use-pep517"
782 config file option instead.
783 """
784 raise_option_error(parser, option=option, msg=msg)
786 # If user doesn't wish to use pep517, we check if setuptools and wheel are installed
787 # and raise error if it is not.
788 packages = ("setuptools", "wheel")
789 if not all(importlib.util.find_spec(package) for package in packages):
790 msg = (
791 f"It is not possible to use --no-use-pep517 "
792 f"without {' and '.join(packages)} installed."
793 )
794 raise_option_error(parser, option=option, msg=msg)
796 # Otherwise, --no-use-pep517 was passed via the command-line.
797 parser.values.use_pep517 = False
800use_pep517: Any = partial(
801 Option,
802 "--use-pep517",
803 dest="use_pep517",
804 action="store_true",
805 default=None,
806 help="Use PEP 517 for building source distributions "
807 "(use --no-use-pep517 to force legacy behaviour).",
808)
810no_use_pep517: Any = partial(
811 Option,
812 "--no-use-pep517",
813 dest="use_pep517",
814 action="callback",
815 callback=_handle_no_use_pep517,
816 default=None,
817 help=SUPPRESS_HELP,
818)
821def _handle_config_settings(
822 option: Option, opt_str: str, value: str, parser: OptionParser
823) -> None:
824 key, sep, val = value.partition("=")
825 if sep != "=":
826 parser.error(f"Arguments to {opt_str} must be of the form KEY=VAL") # noqa
827 dest = getattr(parser.values, option.dest)
828 if dest is None:
829 dest = {}
830 setattr(parser.values, option.dest, dest)
831 if key in dest:
832 if isinstance(dest[key], list):
833 dest[key].append(val)
834 else:
835 dest[key] = [dest[key], val]
836 else:
837 dest[key] = val
840config_settings: Callable[..., Option] = partial(
841 Option,
842 "-C",
843 "--config-settings",
844 dest="config_settings",
845 type=str,
846 action="callback",
847 callback=_handle_config_settings,
848 metavar="settings",
849 help="Configuration settings to be passed to the PEP 517 build backend. "
850 "Settings take the form KEY=VALUE. Use multiple --config-settings options "
851 "to pass multiple keys to the backend.",
852)
854build_options: Callable[..., Option] = partial(
855 Option,
856 "--build-option",
857 dest="build_options",
858 metavar="options",
859 action="append",
860 help="Extra arguments to be supplied to 'setup.py bdist_wheel'.",
861)
863global_options: Callable[..., Option] = partial(
864 Option,
865 "--global-option",
866 dest="global_options",
867 action="append",
868 metavar="options",
869 help="Extra global options to be supplied to the setup.py "
870 "call before the install or bdist_wheel command.",
871)
873no_clean: Callable[..., Option] = partial(
874 Option,
875 "--no-clean",
876 action="store_true",
877 default=False,
878 help="Don't clean up build directories.",
879)
881pre: Callable[..., Option] = partial(
882 Option,
883 "--pre",
884 action="store_true",
885 default=False,
886 help="Include pre-release and development versions. By default, "
887 "pip only finds stable versions.",
888)
890disable_pip_version_check: Callable[..., Option] = partial(
891 Option,
892 "--disable-pip-version-check",
893 dest="disable_pip_version_check",
894 action="store_true",
895 default=False,
896 help="Don't periodically check PyPI to determine whether a new version "
897 "of pip is available for download. Implied with --no-index.",
898)
900root_user_action: Callable[..., Option] = partial(
901 Option,
902 "--root-user-action",
903 dest="root_user_action",
904 default="warn",
905 choices=["warn", "ignore"],
906 help="Action if pip is run as a root user. By default, a warning message is shown.",
907)
910def _handle_merge_hash(
911 option: Option, opt_str: str, value: str, parser: OptionParser
912) -> None:
913 """Given a value spelled "algo:digest", append the digest to a list
914 pointed to in a dict by the algo name."""
915 if not parser.values.hashes:
916 parser.values.hashes = {}
917 try:
918 algo, digest = value.split(":", 1)
919 except ValueError:
920 parser.error(
921 "Arguments to {} must be a hash name " # noqa
922 "followed by a value, like --hash=sha256:"
923 "abcde...".format(opt_str)
924 )
925 if algo not in STRONG_HASHES:
926 parser.error(
927 "Allowed hash algorithms for {} are {}.".format( # noqa
928 opt_str, ", ".join(STRONG_HASHES)
929 )
930 )
931 parser.values.hashes.setdefault(algo, []).append(digest)
934hash: Callable[..., Option] = partial(
935 Option,
936 "--hash",
937 # Hash values eventually end up in InstallRequirement.hashes due to
938 # __dict__ copying in process_line().
939 dest="hashes",
940 action="callback",
941 callback=_handle_merge_hash,
942 type="string",
943 help="Verify that the package's archive matches this "
944 "hash before installing. Example: --hash=sha256:abcdef...",
945)
948require_hashes: Callable[..., Option] = partial(
949 Option,
950 "--require-hashes",
951 dest="require_hashes",
952 action="store_true",
953 default=False,
954 help="Require a hash to check each requirement against, for "
955 "repeatable installs. This option is implied when any package in a "
956 "requirements file has a --hash option.",
957)
960list_path: Callable[..., Option] = partial(
961 PipOption,
962 "--path",
963 dest="path",
964 type="path",
965 action="append",
966 help="Restrict to the specified installation path for listing "
967 "packages (can be used multiple times).",
968)
971def check_list_path_option(options: Values) -> None:
972 if options.path and (options.user or options.local):
973 raise CommandError("Cannot combine '--path' with '--user' or '--local'")
976list_exclude: Callable[..., Option] = partial(
977 PipOption,
978 "--exclude",
979 dest="excludes",
980 action="append",
981 metavar="package",
982 type="package_name",
983 help="Exclude specified package from the output",
984)
987no_python_version_warning: Callable[..., Option] = partial(
988 Option,
989 "--no-python-version-warning",
990 dest="no_python_version_warning",
991 action="store_true",
992 default=False,
993 help="Silence deprecation warnings for upcoming unsupported Pythons.",
994)
997# Features that are now always on. A warning is printed if they are used.
998ALWAYS_ENABLED_FEATURES = [
999 "no-binary-enable-wheel-cache", # always on since 23.1
1000]
1002use_new_feature: Callable[..., Option] = partial(
1003 Option,
1004 "--use-feature",
1005 dest="features_enabled",
1006 metavar="feature",
1007 action="append",
1008 default=[],
1009 choices=[
1010 "fast-deps",
1011 "truststore",
1012 ]
1013 + ALWAYS_ENABLED_FEATURES,
1014 help="Enable new functionality, that may be backward incompatible.",
1015)
1017use_deprecated_feature: Callable[..., Option] = partial(
1018 Option,
1019 "--use-deprecated",
1020 dest="deprecated_features_enabled",
1021 metavar="feature",
1022 action="append",
1023 default=[],
1024 choices=[
1025 "legacy-resolver",
1026 ],
1027 help=("Enable deprecated functionality, that will be removed in the future."),
1028)
1031##########
1032# groups #
1033##########
1035general_group: Dict[str, Any] = {
1036 "name": "General Options",
1037 "options": [
1038 help_,
1039 debug_mode,
1040 isolated_mode,
1041 require_virtualenv,
1042 python,
1043 verbose,
1044 version,
1045 quiet,
1046 log,
1047 no_input,
1048 keyring_provider,
1049 proxy,
1050 retries,
1051 timeout,
1052 exists_action,
1053 trusted_host,
1054 cert,
1055 client_cert,
1056 cache_dir,
1057 no_cache,
1058 disable_pip_version_check,
1059 no_color,
1060 no_python_version_warning,
1061 use_new_feature,
1062 use_deprecated_feature,
1063 ],
1064}
1066index_group: Dict[str, Any] = {
1067 "name": "Package Index Options",
1068 "options": [
1069 index_url,
1070 extra_index_url,
1071 no_index,
1072 find_links,
1073 ],
1074}