|
27 | 27 | from pip._internal.locations import USER_CACHE_DIR, get_src_prefix |
28 | 28 | from pip._internal.models.format_control import FormatControl |
29 | 29 | from pip._internal.models.index import PyPI |
| 30 | +from pip._internal.models.release_control import ReleaseControl |
30 | 31 | from pip._internal.models.target_python import TargetPython |
31 | 32 | from pip._internal.utils.hashes import STRONG_HASHES |
32 | 33 | from pip._internal.utils.misc import strtobool |
@@ -580,6 +581,86 @@ def only_binary() -> Option: |
580 | 581 | ) |
581 | 582 |
|
582 | 583 |
|
| 584 | +def _get_release_control(values: Values, option: Option) -> Any: |
| 585 | + """Get a release_control object.""" |
| 586 | + return getattr(values, option.dest) |
| 587 | + |
| 588 | + |
| 589 | +def _handle_all_releases( |
| 590 | + option: Option, opt_str: str, value: str, parser: OptionParser |
| 591 | +) -> None: |
| 592 | + existing = _get_release_control(parser.values, option) |
| 593 | + existing.handle_mutual_excludes( |
| 594 | + value, |
| 595 | + existing.all_releases, |
| 596 | + existing.only_final, |
| 597 | + "all_releases", |
| 598 | + ) |
| 599 | + |
| 600 | + |
| 601 | +def _handle_only_final( |
| 602 | + option: Option, opt_str: str, value: str, parser: OptionParser |
| 603 | +) -> None: |
| 604 | + existing = _get_release_control(parser.values, option) |
| 605 | + existing.handle_mutual_excludes( |
| 606 | + value, |
| 607 | + existing.only_final, |
| 608 | + existing.all_releases, |
| 609 | + "only_final", |
| 610 | + ) |
| 611 | + |
| 612 | + |
| 613 | +def all_releases() -> Option: |
| 614 | + release_control = ReleaseControl(set(), set()) |
| 615 | + return Option( |
| 616 | + "--all-releases", |
| 617 | + dest="release_control", |
| 618 | + action="callback", |
| 619 | + callback=_handle_all_releases, |
| 620 | + type="str", |
| 621 | + default=release_control, |
| 622 | + help="Allow all release types (including pre-releases) for a package. " |
| 623 | + "Can be supplied multiple times, and each time adds to the existing " |
| 624 | + 'value. Accepts either ":all:" to allow pre-releases for all ' |
| 625 | + 'packages, ":none:" to empty the set (notice the colons), or one or ' |
| 626 | + "more package names with commas between them (no colons). Cannot be " |
| 627 | + "used with --pre.", |
| 628 | + ) |
| 629 | + |
| 630 | + |
| 631 | +def only_final() -> Option: |
| 632 | + release_control = ReleaseControl(set(), set()) |
| 633 | + return Option( |
| 634 | + "--only-final", |
| 635 | + dest="release_control", |
| 636 | + action="callback", |
| 637 | + callback=_handle_only_final, |
| 638 | + type="str", |
| 639 | + default=release_control, |
| 640 | + help="Only allow final releases (no pre-releases) for a package. Can be " |
| 641 | + "supplied multiple times, and each time adds to the existing value. " |
| 642 | + 'Accepts either ":all:" to disable pre-releases for all packages, ' |
| 643 | + '":none:" to empty the set, or one or more package names with commas ' |
| 644 | + "between them. Cannot be used with --pre.", |
| 645 | + ) |
| 646 | + |
| 647 | + |
| 648 | +def check_release_control_exclusive(options: Values) -> None: |
| 649 | + """ |
| 650 | + Raise an error if --pre is used with --all-releases or --only-final, |
| 651 | + and transform --pre into --all-releases :all: if used alone. |
| 652 | + """ |
| 653 | + if not hasattr(options, "pre") or not options.pre: |
| 654 | + return |
| 655 | + |
| 656 | + release_control = options.release_control |
| 657 | + if release_control.all_releases or release_control.only_final: |
| 658 | + raise CommandError("--pre cannot be used with --all-releases or --only-final.") |
| 659 | + |
| 660 | + # Transform --pre into --all-releases :all: |
| 661 | + release_control.all_releases.add(":all:") |
| 662 | + |
| 663 | + |
583 | 664 | platforms: Callable[..., Option] = partial( |
584 | 665 | Option, |
585 | 666 | "--platform", |
|
0 commit comments