cmdoptions.py 28 KB

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