cmdoptions.py 26 KB

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