comparison lib/python3.8/site-packages/pip/_internal/cli/cmdoptions.py @ 1:64071f2a4cf0 draft default tip

Deleted selected files
author guerler
date Mon, 27 Jul 2020 03:55:49 -0400
parents 9e54283cc701
children
comparison
equal deleted inserted replaced
0:9e54283cc701 1:64071f2a4cf0
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 from __future__ import absolute_import
14
15 import logging
16 import os
17 import textwrap
18 import warnings
19 from distutils.util import strtobool
20 from functools import partial
21 from optparse import SUPPRESS_HELP, Option, OptionGroup
22 from textwrap import dedent
23
24 from pip._internal.exceptions import CommandError
25 from pip._internal.locations import USER_CACHE_DIR, get_src_prefix
26 from pip._internal.models.format_control import FormatControl
27 from pip._internal.models.index import PyPI
28 from pip._internal.models.target_python import TargetPython
29 from pip._internal.utils.hashes import STRONG_HASHES
30 from pip._internal.utils.typing import MYPY_CHECK_RUNNING
31 from pip._internal.utils.ui import BAR_TYPES
32
33 if MYPY_CHECK_RUNNING:
34 from typing import Any, Callable, Dict, Optional, Tuple
35 from optparse import OptionParser, Values
36 from pip._internal.cli.parser import ConfigOptionParser
37
38 logger = logging.getLogger(__name__)
39
40
41 def raise_option_error(parser, option, msg):
42 # type: (OptionParser, Option, str) -> None
43 """
44 Raise an option parsing error using parser.error().
45
46 Args:
47 parser: an OptionParser instance.
48 option: an Option instance.
49 msg: the error text.
50 """
51 msg = '{} error: {}'.format(option, msg)
52 msg = textwrap.fill(' '.join(msg.split()))
53 parser.error(msg)
54
55
56 def make_option_group(group, parser):
57 # type: (Dict[str, Any], ConfigOptionParser) -> OptionGroup
58 """
59 Return an OptionGroup object
60 group -- assumed to be dict with 'name' and 'options' keys
61 parser -- an optparse Parser
62 """
63 option_group = OptionGroup(parser, group['name'])
64 for option in group['options']:
65 option_group.add_option(option())
66 return option_group
67
68
69 def check_install_build_global(options, check_options=None):
70 # type: (Values, Optional[Values]) -> None
71 """Disable wheels if per-setup.py call options are set.
72
73 :param options: The OptionParser options to update.
74 :param check_options: The options to check, if not supplied defaults to
75 options.
76 """
77 if check_options is None:
78 check_options = options
79
80 def getname(n):
81 # type: (str) -> Optional[Any]
82 return getattr(check_options, n, None)
83 names = ["build_options", "global_options", "install_options"]
84 if any(map(getname, names)):
85 control = options.format_control
86 control.disallow_binaries()
87 warnings.warn(
88 'Disabling all use of wheels due to the use of --build-option '
89 '/ --global-option / --install-option.', stacklevel=2,
90 )
91
92
93 def check_dist_restriction(options, check_target=False):
94 # type: (Values, bool) -> None
95 """Function for determining if custom platform options are allowed.
96
97 :param options: The OptionParser options.
98 :param check_target: Whether or not to check if --target is being used.
99 """
100 dist_restriction_set = any([
101 options.python_version,
102 options.platform,
103 options.abi,
104 options.implementation,
105 ])
106
107 binary_only = FormatControl(set(), {':all:'})
108 sdist_dependencies_allowed = (
109 options.format_control != binary_only and
110 not options.ignore_dependencies
111 )
112
113 # Installations or downloads using dist restrictions must not combine
114 # source distributions and dist-specific wheels, as they are not
115 # guaranteed to be locally compatible.
116 if dist_restriction_set and sdist_dependencies_allowed:
117 raise CommandError(
118 "When restricting platform and interpreter constraints using "
119 "--python-version, --platform, --abi, or --implementation, "
120 "either --no-deps must be set, or --only-binary=:all: must be "
121 "set and --no-binary must not be set (or must be set to "
122 ":none:)."
123 )
124
125 if check_target:
126 if dist_restriction_set and not options.target_dir:
127 raise CommandError(
128 "Can not use any platform or abi specific options unless "
129 "installing via '--target'"
130 )
131
132
133 def _path_option_check(option, opt, value):
134 # type: (Option, str, str) -> str
135 return os.path.expanduser(value)
136
137
138 class PipOption(Option):
139 TYPES = Option.TYPES + ("path",)
140 TYPE_CHECKER = Option.TYPE_CHECKER.copy()
141 TYPE_CHECKER["path"] = _path_option_check
142
143
144 ###########
145 # options #
146 ###########
147
148 help_ = partial(
149 Option,
150 '-h', '--help',
151 dest='help',
152 action='help',
153 help='Show help.',
154 ) # type: Callable[..., Option]
155
156 isolated_mode = partial(
157 Option,
158 "--isolated",
159 dest="isolated_mode",
160 action="store_true",
161 default=False,
162 help=(
163 "Run pip in an isolated mode, ignoring environment variables and user "
164 "configuration."
165 ),
166 ) # type: Callable[..., Option]
167
168 require_virtualenv = partial(
169 Option,
170 # Run only if inside a virtualenv, bail if not.
171 '--require-virtualenv', '--require-venv',
172 dest='require_venv',
173 action='store_true',
174 default=False,
175 help=SUPPRESS_HELP
176 ) # type: Callable[..., Option]
177
178 verbose = partial(
179 Option,
180 '-v', '--verbose',
181 dest='verbose',
182 action='count',
183 default=0,
184 help='Give more output. Option is additive, and can be used up to 3 times.'
185 ) # type: Callable[..., Option]
186
187 no_color = partial(
188 Option,
189 '--no-color',
190 dest='no_color',
191 action='store_true',
192 default=False,
193 help="Suppress colored output",
194 ) # type: Callable[..., Option]
195
196 version = partial(
197 Option,
198 '-V', '--version',
199 dest='version',
200 action='store_true',
201 help='Show version and exit.',
202 ) # type: Callable[..., Option]
203
204 quiet = partial(
205 Option,
206 '-q', '--quiet',
207 dest='quiet',
208 action='count',
209 default=0,
210 help=(
211 'Give less output. Option is additive, and can be used up to 3'
212 ' times (corresponding to WARNING, ERROR, and CRITICAL logging'
213 ' levels).'
214 ),
215 ) # type: Callable[..., Option]
216
217 progress_bar = partial(
218 Option,
219 '--progress-bar',
220 dest='progress_bar',
221 type='choice',
222 choices=list(BAR_TYPES.keys()),
223 default='on',
224 help=(
225 'Specify type of progress to be displayed [' +
226 '|'.join(BAR_TYPES.keys()) + '] (default: %default)'
227 ),
228 ) # type: Callable[..., Option]
229
230 log = partial(
231 PipOption,
232 "--log", "--log-file", "--local-log",
233 dest="log",
234 metavar="path",
235 type="path",
236 help="Path to a verbose appending log."
237 ) # type: Callable[..., Option]
238
239 no_input = partial(
240 Option,
241 # Don't ask for input
242 '--no-input',
243 dest='no_input',
244 action='store_true',
245 default=False,
246 help=SUPPRESS_HELP
247 ) # type: Callable[..., Option]
248
249 proxy = partial(
250 Option,
251 '--proxy',
252 dest='proxy',
253 type='str',
254 default='',
255 help="Specify a proxy in the form [user:passwd@]proxy.server:port."
256 ) # type: Callable[..., Option]
257
258 retries = partial(
259 Option,
260 '--retries',
261 dest='retries',
262 type='int',
263 default=5,
264 help="Maximum number of retries each connection should attempt "
265 "(default %default times).",
266 ) # type: Callable[..., Option]
267
268 timeout = partial(
269 Option,
270 '--timeout', '--default-timeout',
271 metavar='sec',
272 dest='timeout',
273 type='float',
274 default=15,
275 help='Set the socket timeout (default %default seconds).',
276 ) # type: Callable[..., Option]
277
278 skip_requirements_regex = partial(
279 Option,
280 # A regex to be used to skip requirements
281 '--skip-requirements-regex',
282 dest='skip_requirements_regex',
283 type='str',
284 default='',
285 help=SUPPRESS_HELP,
286 ) # type: Callable[..., Option]
287
288
289 def exists_action():
290 # type: () -> Option
291 return Option(
292 # Option when path already exist
293 '--exists-action',
294 dest='exists_action',
295 type='choice',
296 choices=['s', 'i', 'w', 'b', 'a'],
297 default=[],
298 action='append',
299 metavar='action',
300 help="Default action when a path already exists: "
301 "(s)witch, (i)gnore, (w)ipe, (b)ackup, (a)bort.",
302 )
303
304
305 cert = partial(
306 PipOption,
307 '--cert',
308 dest='cert',
309 type='path',
310 metavar='path',
311 help="Path to alternate CA bundle.",
312 ) # type: Callable[..., Option]
313
314 client_cert = partial(
315 PipOption,
316 '--client-cert',
317 dest='client_cert',
318 type='path',
319 default=None,
320 metavar='path',
321 help="Path to SSL client certificate, a single file containing the "
322 "private key and the certificate in PEM format.",
323 ) # type: Callable[..., Option]
324
325 index_url = partial(
326 Option,
327 '-i', '--index-url', '--pypi-url',
328 dest='index_url',
329 metavar='URL',
330 default=PyPI.simple_url,
331 help="Base URL of the Python Package Index (default %default). "
332 "This should point to a repository compliant with PEP 503 "
333 "(the simple repository API) or a local directory laid out "
334 "in the same format.",
335 ) # type: Callable[..., Option]
336
337
338 def extra_index_url():
339 # type: () -> Option
340 return Option(
341 '--extra-index-url',
342 dest='extra_index_urls',
343 metavar='URL',
344 action='append',
345 default=[],
346 help="Extra URLs of package indexes to use in addition to "
347 "--index-url. Should follow the same rules as "
348 "--index-url.",
349 )
350
351
352 no_index = partial(
353 Option,
354 '--no-index',
355 dest='no_index',
356 action='store_true',
357 default=False,
358 help='Ignore package index (only looking at --find-links URLs instead).',
359 ) # type: Callable[..., Option]
360
361
362 def find_links():
363 # type: () -> Option
364 return Option(
365 '-f', '--find-links',
366 dest='find_links',
367 action='append',
368 default=[],
369 metavar='url',
370 help="If a url or path to an html file, then parse for links to "
371 "archives. If a local path or file:// url that's a directory, "
372 "then look for archives in the directory listing.",
373 )
374
375
376 def trusted_host():
377 # type: () -> Option
378 return Option(
379 "--trusted-host",
380 dest="trusted_hosts",
381 action="append",
382 metavar="HOSTNAME",
383 default=[],
384 help="Mark this host or host:port pair as trusted, even though it "
385 "does not have valid or any HTTPS.",
386 )
387
388
389 def constraints():
390 # type: () -> Option
391 return Option(
392 '-c', '--constraint',
393 dest='constraints',
394 action='append',
395 default=[],
396 metavar='file',
397 help='Constrain versions using the given constraints file. '
398 'This option can be used multiple times.'
399 )
400
401
402 def requirements():
403 # type: () -> Option
404 return Option(
405 '-r', '--requirement',
406 dest='requirements',
407 action='append',
408 default=[],
409 metavar='file',
410 help='Install from the given requirements file. '
411 'This option can be used multiple times.'
412 )
413
414
415 def editable():
416 # type: () -> Option
417 return Option(
418 '-e', '--editable',
419 dest='editables',
420 action='append',
421 default=[],
422 metavar='path/url',
423 help=('Install a project in editable mode (i.e. setuptools '
424 '"develop mode") from a local project path or a VCS url.'),
425 )
426
427
428 def _handle_src(option, opt_str, value, parser):
429 # type: (Option, str, str, OptionParser) -> None
430 value = os.path.abspath(value)
431 setattr(parser.values, option.dest, value)
432
433
434 src = partial(
435 PipOption,
436 '--src', '--source', '--source-dir', '--source-directory',
437 dest='src_dir',
438 type='path',
439 metavar='dir',
440 default=get_src_prefix(),
441 action='callback',
442 callback=_handle_src,
443 help='Directory to check out editable projects into. '
444 'The default in a virtualenv is "<venv path>/src". '
445 'The default for global installs is "<current dir>/src".'
446 ) # type: Callable[..., Option]
447
448
449 def _get_format_control(values, option):
450 # type: (Values, Option) -> Any
451 """Get a format_control object."""
452 return getattr(values, option.dest)
453
454
455 def _handle_no_binary(option, opt_str, value, parser):
456 # type: (Option, str, str, OptionParser) -> None
457 existing = _get_format_control(parser.values, option)
458 FormatControl.handle_mutual_excludes(
459 value, existing.no_binary, existing.only_binary,
460 )
461
462
463 def _handle_only_binary(option, opt_str, value, parser):
464 # type: (Option, str, str, OptionParser) -> None
465 existing = _get_format_control(parser.values, option)
466 FormatControl.handle_mutual_excludes(
467 value, existing.only_binary, existing.no_binary,
468 )
469
470
471 def no_binary():
472 # type: () -> Option
473 format_control = FormatControl(set(), set())
474 return Option(
475 "--no-binary", dest="format_control", action="callback",
476 callback=_handle_no_binary, type="str",
477 default=format_control,
478 help="Do not use binary packages. Can be supplied multiple times, and "
479 "each time adds to the existing value. Accepts either :all: to "
480 "disable all binary packages, :none: to empty the set, or one or "
481 "more package names with commas between them (no colons). Note "
482 "that some packages are tricky to compile and may fail to "
483 "install when this option is used on them.",
484 )
485
486
487 def only_binary():
488 # type: () -> Option
489 format_control = FormatControl(set(), set())
490 return Option(
491 "--only-binary", dest="format_control", action="callback",
492 callback=_handle_only_binary, type="str",
493 default=format_control,
494 help="Do not use source packages. Can be supplied multiple times, and "
495 "each time adds to the existing value. Accepts either :all: to "
496 "disable all source packages, :none: to empty the set, or one or "
497 "more package names with commas between them. Packages without "
498 "binary distributions will fail to install when this option is "
499 "used on them.",
500 )
501
502
503 platform = partial(
504 Option,
505 '--platform',
506 dest='platform',
507 metavar='platform',
508 default=None,
509 help=("Only use wheels compatible with <platform>. "
510 "Defaults to the platform of the running system."),
511 ) # type: Callable[..., Option]
512
513
514 # This was made a separate function for unit-testing purposes.
515 def _convert_python_version(value):
516 # type: (str) -> Tuple[Tuple[int, ...], Optional[str]]
517 """
518 Convert a version string like "3", "37", or "3.7.3" into a tuple of ints.
519
520 :return: A 2-tuple (version_info, error_msg), where `error_msg` is
521 non-None if and only if there was a parsing error.
522 """
523 if not value:
524 # The empty string is the same as not providing a value.
525 return (None, None)
526
527 parts = value.split('.')
528 if len(parts) > 3:
529 return ((), 'at most three version parts are allowed')
530
531 if len(parts) == 1:
532 # Then we are in the case of "3" or "37".
533 value = parts[0]
534 if len(value) > 1:
535 parts = [value[0], value[1:]]
536
537 try:
538 version_info = tuple(int(part) for part in parts)
539 except ValueError:
540 return ((), 'each version part must be an integer')
541
542 return (version_info, None)
543
544
545 def _handle_python_version(option, opt_str, value, parser):
546 # type: (Option, str, str, OptionParser) -> None
547 """
548 Handle a provided --python-version value.
549 """
550 version_info, error_msg = _convert_python_version(value)
551 if error_msg is not None:
552 msg = (
553 'invalid --python-version value: {!r}: {}'.format(
554 value, error_msg,
555 )
556 )
557 raise_option_error(parser, option=option, msg=msg)
558
559 parser.values.python_version = version_info
560
561
562 python_version = partial(
563 Option,
564 '--python-version',
565 dest='python_version',
566 metavar='python_version',
567 action='callback',
568 callback=_handle_python_version, type='str',
569 default=None,
570 help=dedent("""\
571 The Python interpreter version to use for wheel and "Requires-Python"
572 compatibility checks. Defaults to a version derived from the running
573 interpreter. The version can be specified using up to three dot-separated
574 integers (e.g. "3" for 3.0.0, "3.7" for 3.7.0, or "3.7.3"). A major-minor
575 version can also be given as a string without dots (e.g. "37" for 3.7.0).
576 """),
577 ) # type: Callable[..., Option]
578
579
580 implementation = partial(
581 Option,
582 '--implementation',
583 dest='implementation',
584 metavar='implementation',
585 default=None,
586 help=("Only use wheels compatible with Python "
587 "implementation <implementation>, e.g. 'pp', 'jy', 'cp', "
588 " or 'ip'. If not specified, then the current "
589 "interpreter implementation is used. Use 'py' to force "
590 "implementation-agnostic wheels."),
591 ) # type: Callable[..., Option]
592
593
594 abi = partial(
595 Option,
596 '--abi',
597 dest='abi',
598 metavar='abi',
599 default=None,
600 help=("Only use wheels compatible with Python "
601 "abi <abi>, e.g. 'pypy_41'. If not specified, then the "
602 "current interpreter abi tag is used. Generally "
603 "you will need to specify --implementation, "
604 "--platform, and --python-version when using "
605 "this option."),
606 ) # type: Callable[..., Option]
607
608
609 def add_target_python_options(cmd_opts):
610 # type: (OptionGroup) -> None
611 cmd_opts.add_option(platform())
612 cmd_opts.add_option(python_version())
613 cmd_opts.add_option(implementation())
614 cmd_opts.add_option(abi())
615
616
617 def make_target_python(options):
618 # type: (Values) -> TargetPython
619 target_python = TargetPython(
620 platform=options.platform,
621 py_version_info=options.python_version,
622 abi=options.abi,
623 implementation=options.implementation,
624 )
625
626 return target_python
627
628
629 def prefer_binary():
630 # type: () -> Option
631 return Option(
632 "--prefer-binary",
633 dest="prefer_binary",
634 action="store_true",
635 default=False,
636 help="Prefer older binary packages over newer source packages."
637 )
638
639
640 cache_dir = partial(
641 PipOption,
642 "--cache-dir",
643 dest="cache_dir",
644 default=USER_CACHE_DIR,
645 metavar="dir",
646 type='path',
647 help="Store the cache data in <dir>."
648 ) # type: Callable[..., Option]
649
650
651 def _handle_no_cache_dir(option, opt, value, parser):
652 # type: (Option, str, str, OptionParser) -> None
653 """
654 Process a value provided for the --no-cache-dir option.
655
656 This is an optparse.Option callback for the --no-cache-dir option.
657 """
658 # The value argument will be None if --no-cache-dir is passed via the
659 # command-line, since the option doesn't accept arguments. However,
660 # the value can be non-None if the option is triggered e.g. by an
661 # environment variable, like PIP_NO_CACHE_DIR=true.
662 if value is not None:
663 # Then parse the string value to get argument error-checking.
664 try:
665 strtobool(value)
666 except ValueError as exc:
667 raise_option_error(parser, option=option, msg=str(exc))
668
669 # Originally, setting PIP_NO_CACHE_DIR to a value that strtobool()
670 # converted to 0 (like "false" or "no") caused cache_dir to be disabled
671 # rather than enabled (logic would say the latter). Thus, we disable
672 # the cache directory not just on values that parse to True, but (for
673 # backwards compatibility reasons) also on values that parse to False.
674 # In other words, always set it to False if the option is provided in
675 # some (valid) form.
676 parser.values.cache_dir = False
677
678
679 no_cache = partial(
680 Option,
681 "--no-cache-dir",
682 dest="cache_dir",
683 action="callback",
684 callback=_handle_no_cache_dir,
685 help="Disable the cache.",
686 ) # type: Callable[..., Option]
687
688 no_deps = partial(
689 Option,
690 '--no-deps', '--no-dependencies',
691 dest='ignore_dependencies',
692 action='store_true',
693 default=False,
694 help="Don't install package dependencies.",
695 ) # type: Callable[..., Option]
696
697
698 def _handle_build_dir(option, opt, value, parser):
699 # type: (Option, str, str, OptionParser) -> None
700 if value:
701 value = os.path.abspath(value)
702 setattr(parser.values, option.dest, value)
703
704
705 build_dir = partial(
706 PipOption,
707 '-b', '--build', '--build-dir', '--build-directory',
708 dest='build_dir',
709 type='path',
710 metavar='dir',
711 action='callback',
712 callback=_handle_build_dir,
713 help='Directory to unpack packages into and build in. Note that '
714 'an initial build still takes place in a temporary directory. '
715 'The location of temporary directories can be controlled by setting '
716 'the TMPDIR environment variable (TEMP on Windows) appropriately. '
717 'When passed, build directories are not cleaned in case of failures.'
718 ) # type: Callable[..., Option]
719
720 ignore_requires_python = partial(
721 Option,
722 '--ignore-requires-python',
723 dest='ignore_requires_python',
724 action='store_true',
725 help='Ignore the Requires-Python information.'
726 ) # type: Callable[..., Option]
727
728 no_build_isolation = partial(
729 Option,
730 '--no-build-isolation',
731 dest='build_isolation',
732 action='store_false',
733 default=True,
734 help='Disable isolation when building a modern source distribution. '
735 'Build dependencies specified by PEP 518 must be already installed '
736 'if this option is used.'
737 ) # type: Callable[..., Option]
738
739
740 def _handle_no_use_pep517(option, opt, value, parser):
741 # type: (Option, str, str, OptionParser) -> None
742 """
743 Process a value provided for the --no-use-pep517 option.
744
745 This is an optparse.Option callback for the no_use_pep517 option.
746 """
747 # Since --no-use-pep517 doesn't accept arguments, the value argument
748 # will be None if --no-use-pep517 is passed via the command-line.
749 # However, the value can be non-None if the option is triggered e.g.
750 # by an environment variable, for example "PIP_NO_USE_PEP517=true".
751 if value is not None:
752 msg = """A value was passed for --no-use-pep517,
753 probably using either the PIP_NO_USE_PEP517 environment variable
754 or the "no-use-pep517" config file option. Use an appropriate value
755 of the PIP_USE_PEP517 environment variable or the "use-pep517"
756 config file option instead.
757 """
758 raise_option_error(parser, option=option, msg=msg)
759
760 # Otherwise, --no-use-pep517 was passed via the command-line.
761 parser.values.use_pep517 = False
762
763
764 use_pep517 = partial(
765 Option,
766 '--use-pep517',
767 dest='use_pep517',
768 action='store_true',
769 default=None,
770 help='Use PEP 517 for building source distributions '
771 '(use --no-use-pep517 to force legacy behaviour).'
772 ) # type: Any
773
774 no_use_pep517 = partial(
775 Option,
776 '--no-use-pep517',
777 dest='use_pep517',
778 action='callback',
779 callback=_handle_no_use_pep517,
780 default=None,
781 help=SUPPRESS_HELP
782 ) # type: Any
783
784 install_options = partial(
785 Option,
786 '--install-option',
787 dest='install_options',
788 action='append',
789 metavar='options',
790 help="Extra arguments to be supplied to the setup.py install "
791 "command (use like --install-option=\"--install-scripts=/usr/local/"
792 "bin\"). Use multiple --install-option options to pass multiple "
793 "options to setup.py install. If you are using an option with a "
794 "directory path, be sure to use absolute path.",
795 ) # type: Callable[..., Option]
796
797 global_options = partial(
798 Option,
799 '--global-option',
800 dest='global_options',
801 action='append',
802 metavar='options',
803 help="Extra global options to be supplied to the setup.py "
804 "call before the install command.",
805 ) # type: Callable[..., Option]
806
807 no_clean = partial(
808 Option,
809 '--no-clean',
810 action='store_true',
811 default=False,
812 help="Don't clean up build directories."
813 ) # type: Callable[..., Option]
814
815 pre = partial(
816 Option,
817 '--pre',
818 action='store_true',
819 default=False,
820 help="Include pre-release and development versions. By default, "
821 "pip only finds stable versions.",
822 ) # type: Callable[..., Option]
823
824 disable_pip_version_check = partial(
825 Option,
826 "--disable-pip-version-check",
827 dest="disable_pip_version_check",
828 action="store_true",
829 default=False,
830 help="Don't periodically check PyPI to determine whether a new version "
831 "of pip is available for download. Implied with --no-index.",
832 ) # type: Callable[..., Option]
833
834
835 # Deprecated, Remove later
836 always_unzip = partial(
837 Option,
838 '-Z', '--always-unzip',
839 dest='always_unzip',
840 action='store_true',
841 help=SUPPRESS_HELP,
842 ) # type: Callable[..., Option]
843
844
845 def _handle_merge_hash(option, opt_str, value, parser):
846 # type: (Option, str, str, OptionParser) -> None
847 """Given a value spelled "algo:digest", append the digest to a list
848 pointed to in a dict by the algo name."""
849 if not parser.values.hashes:
850 parser.values.hashes = {}
851 try:
852 algo, digest = value.split(':', 1)
853 except ValueError:
854 parser.error('Arguments to %s must be a hash name '
855 'followed by a value, like --hash=sha256:abcde...' %
856 opt_str)
857 if algo not in STRONG_HASHES:
858 parser.error('Allowed hash algorithms for %s are %s.' %
859 (opt_str, ', '.join(STRONG_HASHES)))
860 parser.values.hashes.setdefault(algo, []).append(digest)
861
862
863 hash = partial(
864 Option,
865 '--hash',
866 # Hash values eventually end up in InstallRequirement.hashes due to
867 # __dict__ copying in process_line().
868 dest='hashes',
869 action='callback',
870 callback=_handle_merge_hash,
871 type='string',
872 help="Verify that the package's archive matches this "
873 'hash before installing. Example: --hash=sha256:abcdef...',
874 ) # type: Callable[..., Option]
875
876
877 require_hashes = partial(
878 Option,
879 '--require-hashes',
880 dest='require_hashes',
881 action='store_true',
882 default=False,
883 help='Require a hash to check each requirement against, for '
884 'repeatable installs. This option is implied when any package in a '
885 'requirements file has a --hash option.',
886 ) # type: Callable[..., Option]
887
888
889 list_path = partial(
890 PipOption,
891 '--path',
892 dest='path',
893 type='path',
894 action='append',
895 help='Restrict to the specified installation path for listing '
896 'packages (can be used multiple times).'
897 ) # type: Callable[..., Option]
898
899
900 def check_list_path_option(options):
901 # type: (Values) -> None
902 if options.path and (options.user or options.local):
903 raise CommandError(
904 "Cannot combine '--path' with '--user' or '--local'"
905 )
906
907
908 no_python_version_warning = partial(
909 Option,
910 '--no-python-version-warning',
911 dest='no_python_version_warning',
912 action='store_true',
913 default=False,
914 help='Silence deprecation warnings for upcoming unsupported Pythons.',
915 ) # type: Callable[..., Option]
916
917
918 ##########
919 # groups #
920 ##########
921
922 general_group = {
923 'name': 'General Options',
924 'options': [
925 help_,
926 isolated_mode,
927 require_virtualenv,
928 verbose,
929 version,
930 quiet,
931 log,
932 no_input,
933 proxy,
934 retries,
935 timeout,
936 skip_requirements_regex,
937 exists_action,
938 trusted_host,
939 cert,
940 client_cert,
941 cache_dir,
942 no_cache,
943 disable_pip_version_check,
944 no_color,
945 no_python_version_warning,
946 ]
947 } # type: Dict[str, Any]
948
949 index_group = {
950 'name': 'Package Index Options',
951 'options': [
952 index_url,
953 extra_index_url,
954 no_index,
955 find_links,
956 ]
957 } # type: Dict[str, Any]