]> jfr.im git - dlqueue.git/blob - venv/lib/python3.11/site-packages/pip/_internal/cli/cmdoptions.py
init: venv aand flask
[dlqueue.git] / venv / lib / python3.11 / site-packages / pip / _internal / cli / cmdoptions.py
1 """
2 shared options and groups
3
4 The principle here is to define options once, but *not* instantiate them
5 globally. One reason being that options with action='append' can carry state
6 between parses. pip parses general options twice internally, and shouldn't
7 pass on state. To be consistent, all options will follow this design.
8 """
9
10 # The following comment should be removed at some point in the future.
11 # mypy: strict-optional=False
12
13 import importlib.util
14 import logging
15 import os
16 import textwrap
17 from functools import partial
18 from optparse import SUPPRESS_HELP, Option, OptionGroup, OptionParser, Values
19 from textwrap import dedent
20 from typing import Any, Callable, Dict, Optional, Tuple
21
22 from pip._vendor.packaging.utils import canonicalize_name
23
24 from pip._internal.cli.parser import ConfigOptionParser
25 from pip._internal.exceptions import CommandError
26 from pip._internal.locations import USER_CACHE_DIR, get_src_prefix
27 from pip._internal.models.format_control import FormatControl
28 from pip._internal.models.index import PyPI
29 from pip._internal.models.target_python import TargetPython
30 from pip._internal.utils.hashes import STRONG_HASHES
31 from pip._internal.utils.misc import strtobool
32
33 logger = logging.getLogger(__name__)
34
35
36 def raise_option_error(parser: OptionParser, option: Option, msg: str) -> None:
37 """
38 Raise an option parsing error using parser.error().
39
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)
48
49
50 def 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
60
61
62 def check_dist_restriction(options: Values, check_target: bool = False) -> None:
63 """Function for determining if custom platform options are allowed.
64
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 )
76
77 binary_only = FormatControl(set(), {":all:"})
78 sdist_dependencies_allowed = (
79 options.format_control != binary_only and not options.ignore_dependencies
80 )
81
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 )
93
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 )
100
101
102 def _path_option_check(option: Option, opt: str, value: str) -> str:
103 return os.path.expanduser(value)
104
105
106 def _package_name_option_check(option: Option, opt: str, value: str) -> str:
107 return canonicalize_name(value)
108
109
110 class 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
115
116
117 ###########
118 # options #
119 ###########
120
121 help_: Callable[..., Option] = partial(
122 Option,
123 "-h",
124 "--help",
125 dest="help",
126 action="help",
127 help="Show help.",
128 )
129
130 debug_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 )
141
142 isolated_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 )
153
154 require_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 )
166
167 override_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 )
174
175 python: Callable[..., Option] = partial(
176 Option,
177 "--python",
178 dest="python",
179 help="Run pip with the specified Python interpreter.",
180 )
181
182 verbose: 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 )
191
192 no_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 )
200
201 version: Callable[..., Option] = partial(
202 Option,
203 "-V",
204 "--version",
205 dest="version",
206 action="store_true",
207 help="Show version and exit.",
208 )
209
210 quiet: 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 )
223
224 progress_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 )
233
234 log: 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 )
244
245 no_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 )
254
255 keyring_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 )
267
268 proxy: 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 )
276
277 retries: 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 )
286
287 timeout: 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 )
297
298
299 def 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 )
312
313
314 cert: 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 )
327
328 client_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 )
338
339 index_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 )
352
353
354 def 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 )
365
366
367 no_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 )
375
376
377 def 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 )
391
392
393 def 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 )
403
404
405 def 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 )
416
417
418 def 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 )
429
430
431 def 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 )
444
445
446 def _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)
449
450
451 src: 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 )
467
468
469 def _get_format_control(values: Values, option: Option) -> Any:
470 """Get a format_control object."""
471 return getattr(values, option.dest)
472
473
474 def _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 )
483
484
485 def _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 )
494
495
496 def 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 )
512
513
514 def 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 )
530
531
532 platforms: 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 )
545
546
547 # This was made a separate function for unit-testing purposes.
548 def _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.
551
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)
558
559 parts = value.split(".")
560 if len(parts) > 3:
561 return ((), "at most three version parts are allowed")
562
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:]]
568
569 try:
570 version_info = tuple(int(part) for part in parts)
571 except ValueError:
572 return ((), "each version part must be an integer")
573
574 return (version_info, None)
575
576
577 def _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)
590
591 parser.values.python_version = version_info
592
593
594 python_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 )
613
614
615 implementation: 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 )
629
630
631 abis: 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 )
647
648
649 def 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())
654
655
656 def 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 )
663
664 return target_python
665
666
667 def 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 )
675
676
677 cache_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 )
686
687
688 def _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.
693
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))
706
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
715
716
717 no_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 )
725
726 no_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 )
735
736 ignore_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 )
743
744 no_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 )
754
755 check_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 )
763
764
765 def _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.
770
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)
785
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)
795
796 # Otherwise, --no-use-pep517 was passed via the command-line.
797 parser.values.use_pep517 = False
798
799
800 use_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 )
809
810 no_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 )
819
820
821 def _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
838
839
840 config_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 )
853
854 build_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 )
862
863 global_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 )
872
873 no_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 )
880
881 pre: 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 )
889
890 disable_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 )
899
900 root_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 )
908
909
910 def _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)
932
933
934 hash: 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 )
946
947
948 require_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 )
958
959
960 list_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 )
969
970
971 def 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'")
974
975
976 list_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 )
985
986
987 no_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 )
995
996
997 # Features that are now always on. A warning is printed if they are used.
998 ALWAYS_ENABLED_FEATURES = [
999 "no-binary-enable-wheel-cache", # always on since 23.1
1000 ]
1001
1002 use_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 )
1016
1017 use_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 )
1029
1030
1031 ##########
1032 # groups #
1033 ##########
1034
1035 general_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 }
1065
1066 index_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 }