未验证 提交 b6877c17 编写于 作者: F Frost Ming 提交者: GitHub

Feature: prerelease option for add and update (#779)

上级 99612031
......@@ -90,6 +90,10 @@ for the dependency):
- `exact`: Save the exact version specifier: `==2.21.0`.
- `wildcard`: Don't constrain version and leave the specifier to be wildcard: `*`.
### Add prereleases
One can give `--pre/--prerelease` option to `pdm add` so that prereleases are allowed to be pinned for the given packages.
## Update existing dependencies
To update all dependencies in the lock file:
......@@ -136,6 +140,12 @@ which is given by `--update-<strategy>` option:
- `eager`: Try to lock a newer version of the packages in command line and their recursive sub-dependencies
and keep other dependencies as they are.
### Update packages to the versions that break the version specifiers
One can give `-u/--unconstrained` to tell PDM to ignore the version specifiers in the `pyproject.toml`.
This works similarly to the `yarn upgrade -L/--latest` command. Besides, `pdm update` also supports the
`--pre/--prerelease` option.
## Remove existing dependencies
To remove existing dependencies from project file and the library directory:
......
Support `--pre/--prelease` option for `pdm add` and `pdm update`. It will allow prereleases to be pinned.
......@@ -181,6 +181,7 @@ def do_add(
no_editable: bool = False,
no_self: bool = False,
dry_run: bool = False,
prerelease: bool = False,
) -> None:
"""Add packages and install"""
check_project_file(project)
......@@ -194,6 +195,7 @@ def do_add(
parse_requirement(line) for line in packages
]:
key = r.identify()
r.prerelease = prerelease
tracked_names.add(key)
requirements[key] = r
project.core.ui.echo(
......@@ -244,6 +246,7 @@ def do_update(
sync: bool = True,
no_editable: bool = False,
no_self: bool = False,
prerelease: bool = False,
) -> None:
"""Update specified packages or all packages"""
check_project_file(project)
......@@ -256,6 +259,8 @@ def do_update(
updated_deps: dict[str, dict[str, Requirement]] = defaultdict(dict)
install_dev = True if dev is None else dev
if not packages:
if prerelease:
raise PdmUsageError("--prerelease must be used with packages given")
groups = translate_groups(project, default, install_dev, groups or ())
for group in groups:
updated_deps[group] = all_dependencies[group]
......@@ -277,6 +282,7 @@ def do_update(
termui.green(name, bold=True), group, "dev-" if dev else ""
)
)
dependencies[matched_name].prerelease = prerelease
updated_deps[group][matched_name] = dependencies[matched_name]
project.core.ui.echo(
"Updating packages: {}.".format(
......
......@@ -6,7 +6,9 @@ from pdm.cli.options import (
dry_run_option,
install_group,
packages_group,
prerelease_option,
save_strategy_group,
unconstrained_option,
update_strategy_group,
)
from pdm.exceptions import PdmUsageError
......@@ -16,6 +18,16 @@ from pdm.project import Project
class Command(BaseCommand):
"""Add package(s) to pyproject.toml and install them"""
arguments = BaseCommand.arguments + [
save_strategy_group,
update_strategy_group,
prerelease_option,
unconstrained_option,
packages_group,
install_group,
dry_run_option,
]
def add_arguments(self, parser: argparse.ArgumentParser) -> None:
parser.add_argument(
"-d",
......@@ -27,13 +39,6 @@ class Command(BaseCommand):
parser.add_argument(
"-G", "--group", help="Specify the target dependency group to add into"
)
parser.add_argument(
"-u",
"--unconstrained",
action="store_true",
default=False,
help="Ignore the version constraint of pinned packages",
)
parser.add_argument(
"--no-sync",
dest="sync",
......@@ -41,11 +46,6 @@ class Command(BaseCommand):
action="store_false",
help="Only write pyproject.toml and do not sync the working set",
)
save_strategy_group.add_to_parser(parser)
update_strategy_group.add_to_parser(parser)
packages_group.add_to_parser(parser)
install_group.add_to_parser(parser)
dry_run_option.add_to_parser(parser)
def handle(self, project: Project, options: argparse.Namespace) -> None:
if options.editables and options.no_editable:
......@@ -63,4 +63,5 @@ class Command(BaseCommand):
no_editable=options.no_editable,
no_self=options.no_self,
dry_run=options.dry_run,
prerelease=options.prerelease,
)
......@@ -5,7 +5,9 @@ from pdm.cli.commands.base import BaseCommand
from pdm.cli.options import (
groups_group,
install_group,
prerelease_option,
save_strategy_group,
unconstrained_option,
update_strategy_group,
)
from pdm.project import Project
......@@ -14,18 +16,16 @@ from pdm.project import Project
class Command(BaseCommand):
"""Update package(s) in pyproject.toml"""
arguments = BaseCommand.arguments + [
groups_group,
install_group,
save_strategy_group,
update_strategy_group,
prerelease_option,
unconstrained_option,
]
def add_arguments(self, parser: argparse.ArgumentParser) -> None:
groups_group.add_to_parser(parser)
save_strategy_group.add_to_parser(parser)
update_strategy_group.add_to_parser(parser)
install_group.add_to_parser(parser)
parser.add_argument(
"-u",
"--unconstrained",
action="store_true",
default=False,
help="Ignore the version constraint of packages",
)
parser.add_argument(
"-t",
"--top",
......@@ -66,4 +66,5 @@ class Command(BaseCommand):
sync=options.sync,
no_editable=options.no_editable,
no_self=options.no_self,
prerelease=options.prerelease,
)
# BASH completion script for pdm
# Generated by pycomplete 0.3.2
_pdm_e7edb5cd940e5db5_complete()
_pdm_a919b69078acdf0a_complete()
{
local cur script coms opts com
COMPREPLY=()
......@@ -29,7 +29,7 @@ _pdm_e7edb5cd940e5db5_complete()
case "$com" in
(add)
opts="--dev --dry-run --editable --global --group --help --no-editable --no-isolation --no-self --no-sync --project --save-compatible --save-exact --save-minimum --save-wildcard --unconstrained --update-eager --update-reuse --verbose"
opts="--dev --dry-run --editable --global --group --help --no-editable --no-isolation --no-self --no-sync --prerelease --project --save-compatible --save-exact --save-minimum --save-wildcard --unconstrained --update-eager --update-reuse --verbose"
;;
(build)
......@@ -101,7 +101,7 @@ _pdm_e7edb5cd940e5db5_complete()
;;
(update)
opts="--dev --global --group --help --no-default --no-editable --no-isolation --no-self --no-sync --outdated --production --project --save-compatible --save-exact --save-minimum --save-wildcard --top --unconstrained --update-eager --update-reuse --verbose"
opts="--dev --global --group --help --no-default --no-editable --no-isolation --no-self --no-sync --outdated --prerelease --production --project --save-compatible --save-exact --save-minimum --save-wildcard --top --unconstrained --update-eager --update-reuse --verbose"
;;
(use)
......@@ -127,4 +127,4 @@ _pdm_e7edb5cd940e5db5_complete()
fi
}
complete -o default -F _pdm_e7edb5cd940e5db5_complete pdm
complete -o default -F _pdm_a919b69078acdf0a_complete pdm
# FISH completion script for pdm
# Generated by pycomplete 0.3.2
function __fish_pdm_e7edb5cd940e5db5_complete_no_subcommand
function __fish_pdm_a919b69078acdf0a_complete_no_subcommand
for i in (commandline -opc)
if contains -- $i add build cache completion config export import info init install list lock plugin remove run search show sync update use
return 1
......@@ -11,33 +11,33 @@ function __fish_pdm_e7edb5cd940e5db5_complete_no_subcommand
end
# global options
complete -c pdm -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -l help -d 'show this help message and exit'
complete -c pdm -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -l ignore-python -d 'Ignore the Python path saved in the pdm.toml config'
complete -c pdm -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -l pep582 -d 'Print the command line to be eval\'d by the shell'
complete -c pdm -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -l verbose -d '-v for detailed output and -vv for more detailed'
complete -c pdm -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -l version -d 'Show version'
complete -c pdm -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -l help -d 'show this help message and exit'
complete -c pdm -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -l ignore-python -d 'Ignore the Python path saved in the pdm.toml config'
complete -c pdm -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -l pep582 -d 'Print the command line to be eval\'d by the shell'
complete -c pdm -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -l verbose -d '-v for detailed output and -vv for more detailed'
complete -c pdm -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -l version -d 'Show version'
# commands
complete -c pdm -f -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -a add -d 'Add package(s) to pyproject.toml and install them'
complete -c pdm -f -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -a build -d 'Build artifacts for distribution'
complete -c pdm -f -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -a cache -d 'Control the caches of PDM'
complete -c pdm -f -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -a completion -d 'Generate completion scripts for the given shell'
complete -c pdm -f -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -a config -d 'Display the current configuration'
complete -c pdm -f -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -a export -d 'Export the locked packages set to other formats'
complete -c pdm -f -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -a import -d 'Import project metadata from other formats'
complete -c pdm -f -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -a info -d 'Show the project information'
complete -c pdm -f -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -a init -d 'Initialize a pyproject.toml for PDM'
complete -c pdm -f -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -a install -d 'Install dependencies from lock file'
complete -c pdm -f -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -a list -d 'List packages installed in the current working set'
complete -c pdm -f -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -a lock -d 'Resolve and lock dependencies'
complete -c pdm -f -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -a plugin -d 'Manage the PDM plugins'
complete -c pdm -f -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -a remove -d 'Remove packages from pyproject.toml'
complete -c pdm -f -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -a run -d 'Run commands or scripts with local packages loaded'
complete -c pdm -f -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -a search -d 'Search for PyPI packages'
complete -c pdm -f -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -a show -d 'Show the package information'
complete -c pdm -f -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -a sync -d 'Synchronize the current working set with lock file'
complete -c pdm -f -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -a update -d 'Update package(s) in pyproject.toml'
complete -c pdm -f -n '__fish_pdm_e7edb5cd940e5db5_complete_no_subcommand' -a use -d 'Use the given python version or path as base interpreter'
complete -c pdm -f -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -a add -d 'Add package(s) to pyproject.toml and install them'
complete -c pdm -f -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -a build -d 'Build artifacts for distribution'
complete -c pdm -f -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -a cache -d 'Control the caches of PDM'
complete -c pdm -f -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -a completion -d 'Generate completion scripts for the given shell'
complete -c pdm -f -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -a config -d 'Display the current configuration'
complete -c pdm -f -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -a export -d 'Export the locked packages set to other formats'
complete -c pdm -f -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -a import -d 'Import project metadata from other formats'
complete -c pdm -f -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -a info -d 'Show the project information'
complete -c pdm -f -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -a init -d 'Initialize a pyproject.toml for PDM'
complete -c pdm -f -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -a install -d 'Install dependencies from lock file'
complete -c pdm -f -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -a list -d 'List packages installed in the current working set'
complete -c pdm -f -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -a lock -d 'Resolve and lock dependencies'
complete -c pdm -f -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -a plugin -d 'Manage the PDM plugins'
complete -c pdm -f -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -a remove -d 'Remove packages from pyproject.toml'
complete -c pdm -f -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -a run -d 'Run commands or scripts with local packages loaded'
complete -c pdm -f -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -a search -d 'Search for PyPI packages'
complete -c pdm -f -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -a show -d 'Show the package information'
complete -c pdm -f -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -a sync -d 'Synchronize the current working set with lock file'
complete -c pdm -f -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -a update -d 'Update package(s) in pyproject.toml'
complete -c pdm -f -n '__fish_pdm_a919b69078acdf0a_complete_no_subcommand' -a use -d 'Use the given python version or path as base interpreter'
# command options
......@@ -52,13 +52,13 @@ complete -c pdm -A -n '__fish_seen_subcommand_from add' -l no-editable -d 'Insta
complete -c pdm -A -n '__fish_seen_subcommand_from add' -l no-isolation -d 'Do not isolate the build in a clean environment'
complete -c pdm -A -n '__fish_seen_subcommand_from add' -l no-self -d 'Don\'t install the project itself'
complete -c pdm -A -n '__fish_seen_subcommand_from add' -l no-sync -d 'Only write pyproject.toml and do not sync the working set'
complete -c pdm -A -n '__fish_seen_subcommand_from add' -l prerelease -d 'Allow prereleases to be pinned'
complete -c pdm -A -n '__fish_seen_subcommand_from add' -l project -d 'Specify another path as the project root, which changes the base of pyproject.toml and __pypackages__'
complete -c pdm -A -n '__fish_seen_subcommand_from add' -l save-compatible -d 'Save compatible version specifiers'
complete -c pdm -A -n '__fish_seen_subcommand_from add' -l save-exact -d 'Save exact version specifiers'
complete -c pdm -A -n '__fish_seen_subcommand_from add' -l save-minimum -d 'Save minimum version specifiers'
complete -c pdm -A -n '__fish_seen_subcommand_from add' -l save-wildcard -d 'Save wildcard version specifiers'
complete -c pdm -A -n '__fish_seen_subcommand_from add' -l section -d '(DEPRECATED) Alias of `-G/--group`'
complete -c pdm -A -n '__fish_seen_subcommand_from add' -l unconstrained -d 'Ignore the version constraint of pinned packages'
complete -c pdm -A -n '__fish_seen_subcommand_from add' -l unconstrained -d 'Ignore the version constraint of packages'
complete -c pdm -A -n '__fish_seen_subcommand_from add' -l update-eager -d 'Try to update the packages and their dependencies recursively'
complete -c pdm -A -n '__fish_seen_subcommand_from add' -l update-reuse -d 'Reuse pinned versions already present in lock file if possible'
complete -c pdm -A -n '__fish_seen_subcommand_from add' -l verbose -d '-v for detailed output and -vv for more detailed'
......@@ -100,7 +100,6 @@ complete -c pdm -A -n '__fish_seen_subcommand_from export' -l output -d 'Write o
complete -c pdm -A -n '__fish_seen_subcommand_from export' -l production -d 'Unselect dev dependencies'
complete -c pdm -A -n '__fish_seen_subcommand_from export' -l project -d 'Specify another path as the project root, which changes the base of pyproject.toml and __pypackages__'
complete -c pdm -A -n '__fish_seen_subcommand_from export' -l pyproject -d 'Read the list of packages from pyproject.toml'
complete -c pdm -A -n '__fish_seen_subcommand_from export' -l section -d '(DEPRECATED) alias of `--group`'
complete -c pdm -A -n '__fish_seen_subcommand_from export' -l verbose -d '-v for detailed output and -vv for more detailed'
complete -c pdm -A -n '__fish_seen_subcommand_from export' -l without-hashes -d 'Don\'t include artifact hashes'
......@@ -111,7 +110,6 @@ complete -c pdm -A -n '__fish_seen_subcommand_from import' -l global -d 'Use the
complete -c pdm -A -n '__fish_seen_subcommand_from import' -l group -d 'Specify the target dependency group to import into'
complete -c pdm -A -n '__fish_seen_subcommand_from import' -l help -d 'show this help message and exit'
complete -c pdm -A -n '__fish_seen_subcommand_from import' -l project -d 'Specify another path as the project root, which changes the base of pyproject.toml and __pypackages__'
complete -c pdm -A -n '__fish_seen_subcommand_from import' -l section -d '(DEPRECATED) Alias of `-G/--group`'
complete -c pdm -A -n '__fish_seen_subcommand_from import' -l verbose -d '-v for detailed output and -vv for more detailed'
# info
......@@ -144,7 +142,6 @@ complete -c pdm -A -n '__fish_seen_subcommand_from install' -l no-lock -d 'Don\'
complete -c pdm -A -n '__fish_seen_subcommand_from install' -l no-self -d 'Don\'t install the project itself'
complete -c pdm -A -n '__fish_seen_subcommand_from install' -l production -d 'Unselect dev dependencies'
complete -c pdm -A -n '__fish_seen_subcommand_from install' -l project -d 'Specify another path as the project root, which changes the base of pyproject.toml and __pypackages__'
complete -c pdm -A -n '__fish_seen_subcommand_from install' -l section -d '(DEPRECATED) alias of `--group`'
complete -c pdm -A -n '__fish_seen_subcommand_from install' -l verbose -d '-v for detailed output and -vv for more detailed'
# list
......@@ -179,7 +176,6 @@ complete -c pdm -A -n '__fish_seen_subcommand_from remove' -l no-isolation -d 'D
complete -c pdm -A -n '__fish_seen_subcommand_from remove' -l no-self -d 'Don\'t install the project itself'
complete -c pdm -A -n '__fish_seen_subcommand_from remove' -l no-sync -d 'Only write pyproject.toml and do not uninstall packages'
complete -c pdm -A -n '__fish_seen_subcommand_from remove' -l project -d 'Specify another path as the project root, which changes the base of pyproject.toml and __pypackages__'
complete -c pdm -A -n '__fish_seen_subcommand_from remove' -l section -d '(DEPRECATED) Alias of `-G/--group`'
complete -c pdm -A -n '__fish_seen_subcommand_from remove' -l verbose -d '-v for detailed output and -vv for more detailed'
# run
......@@ -221,7 +217,6 @@ complete -c pdm -A -n '__fish_seen_subcommand_from sync' -l no-self -d 'Don\'t i
complete -c pdm -A -n '__fish_seen_subcommand_from sync' -l production -d 'Unselect dev dependencies'
complete -c pdm -A -n '__fish_seen_subcommand_from sync' -l project -d 'Specify another path as the project root, which changes the base of pyproject.toml and __pypackages__'
complete -c pdm -A -n '__fish_seen_subcommand_from sync' -l reinstall -d 'Force reinstall existing dependencies'
complete -c pdm -A -n '__fish_seen_subcommand_from sync' -l section -d '(DEPRECATED) alias of `--group`'
complete -c pdm -A -n '__fish_seen_subcommand_from sync' -l verbose -d '-v for detailed output and -vv for more detailed'
# update
......@@ -235,13 +230,13 @@ complete -c pdm -A -n '__fish_seen_subcommand_from update' -l no-isolation -d 'D
complete -c pdm -A -n '__fish_seen_subcommand_from update' -l no-self -d 'Don\'t install the project itself'
complete -c pdm -A -n '__fish_seen_subcommand_from update' -l no-sync -d 'Only update lock file but do not sync packages'
complete -c pdm -A -n '__fish_seen_subcommand_from update' -l outdated -d 'Show the difference only without modifying the lockfile content'
complete -c pdm -A -n '__fish_seen_subcommand_from update' -l prerelease -d 'Allow prereleases to be pinned'
complete -c pdm -A -n '__fish_seen_subcommand_from update' -l production -d 'Unselect dev dependencies'
complete -c pdm -A -n '__fish_seen_subcommand_from update' -l project -d 'Specify another path as the project root, which changes the base of pyproject.toml and __pypackages__'
complete -c pdm -A -n '__fish_seen_subcommand_from update' -l save-compatible -d 'Save compatible version specifiers'
complete -c pdm -A -n '__fish_seen_subcommand_from update' -l save-exact -d 'Save exact version specifiers'
complete -c pdm -A -n '__fish_seen_subcommand_from update' -l save-minimum -d 'Save minimum version specifiers'
complete -c pdm -A -n '__fish_seen_subcommand_from update' -l save-wildcard -d 'Save wildcard version specifiers'
complete -c pdm -A -n '__fish_seen_subcommand_from update' -l section -d '(DEPRECATED) alias of `--group`'
complete -c pdm -A -n '__fish_seen_subcommand_from update' -l top -d 'Only update those list in pyproject.toml'
complete -c pdm -A -n '__fish_seen_subcommand_from update' -l unconstrained -d 'Ignore the version constraint of packages'
complete -c pdm -A -n '__fish_seen_subcommand_from update' -l update-eager -d 'Try to update the packages and their dependencies recursively'
......
......@@ -198,7 +198,7 @@ function TabExpansion($line, $lastWord) {
"add" {
$completer.AddOpts(@(
[Option]::new(("-d", "--dev", "--save-compatible", "--save-wildcard", "--dry-run", "--save-exact", "--save-minimum", "--update-eager", "--update-reuse", "-g", "--global", "--no-sync", "--no-editable", "--no-self", "-u", "--unconstrained", "--no-isolation")),
[Option]::new(("-d", "--dev", "--save-compatible", "--save-wildcard", "--dry-run", "--save-exact", "--save-minimum", "--update-eager", "--update-reuse", "-g", "--global", "--no-sync", "--no-editable", "--no-self", "-u", "--unconstrained", "--no-isolation", "--pre", "--prerelease")),
$sectionOption,
$projectOption,
[Option]::new(@("-e", "--editable")).WithValues(@(getPyPIPackages))
......@@ -345,7 +345,7 @@ function TabExpansion($line, $lastWord) {
}
"update" {
$completer.AddOpts(@(
[Option]::new(("-d", "--dev", "--save-compatible", "--prod", "--production", "--save-wildcard", "--save-exact", "--save-minimum", "--update-eager", "--update-reuse", "-g", "--global", "--dry-run", "--outdated", "--top", "-u", "--unconstrained", "--no-editable", "--no-self", "--no-isolation", "--no-sync")),
[Option]::new(("-d", "--dev", "--save-compatible", "--prod", "--production", "--save-wildcard", "--save-exact", "--save-minimum", "--update-eager", "--update-reuse", "-g", "--global", "--dry-run", "--outdated", "--top", "-u", "--unconstrained", "--no-editable", "--no-self", "--no-isolation", "--no-sync", "--pre", "--prerelease")),
$sectionOption,
$projectOption
))
......
......@@ -68,6 +68,7 @@ _pdm() {
'--no-editable[Install non-editable versions for all packages]'
"--no-self[Don't install the project itself]"
{-u,--unconstrained}'[Ignore the version constraint of packages]'
{--pre,--prerelease}'[Allow prereleases to be pinned]'
{-e+,--editable+}'[Specify editable packages]:packages'
"--no-isolation[do not isolate the build in a clean environment]"
"--dry-run[Show the difference only without modifying the lockfile content]"
......@@ -302,6 +303,7 @@ _pdm() {
"--no-self[Don't install the project itself]"
"--no-sync[Only update lock file but do not sync packages]"
{-u,--unconstrained}'[Ignore the version constraint of packages]'
{--pre,--prerelease}'[Allow prereleases to be pinned]'
{-d,--dev}'[Select dev dependencies]'
{--prod,--production}"[Unselect dev dependencies]"
"--no-default[Don\'t include dependencies from the default group]"
......
......@@ -289,3 +289,18 @@ ignore_python_option = Option(
action="store_true",
help="Ignore the Python path saved in the pdm.toml config",
)
prerelease_option = Option(
"--pre",
"--prerelease",
action="store_true",
dest="prerelease",
help="Allow prereleases to be pinned",
)
unconstrained_option = Option(
"-u",
"--unconstrained",
action="store_true",
default=False,
help="Ignore the version constraint of packages",
)
......@@ -80,6 +80,7 @@ class Requirement:
extras: Sequence[str] | None = None
specifier: SpecifierSet | None = None
editable: bool = False
prerelease: bool = False
def __post_init__(self) -> None:
self.requires_python = (
......
......@@ -35,9 +35,9 @@ class BaseProvider(AbstractProvider):
editable = requirement.editable
is_file = requirement.is_file_or_url
is_prerelease = (
bool(requirement.specifier.prereleases)
if requirement.specifier is not None
else False
requirement.prerelease
or requirement.specifier is not None
and bool(requirement.specifier.prereleases)
)
specifier_parts = len(requirement.specifier) if requirement.specifier else 0
return (editable, is_file, is_prerelease, specifier_parts)
......@@ -84,8 +84,9 @@ class BaseProvider(AbstractProvider):
can.metadata
candidates = [can]
else:
req = reqs[0]
candidates = self.repository.find_candidates(
reqs[0], self.allow_prereleases
req, req.prerelease or self.allow_prereleases
)
return [
can
......
......@@ -29,128 +29,6 @@ def test_remove_both_normal_and_editable_packages(project, is_dev):
assert "demo" not in project.locked_repository.all_candidates
@pytest.mark.usefixtures("working_set")
def test_update_all_packages(project, repository, capsys):
actions.do_add(project, packages=["requests", "pytz"])
repository.add_candidate("pytz", "2019.6")
repository.add_candidate("chardet", "3.0.5")
repository.add_candidate("requests", "2.20.0")
repository.add_dependencies(
"requests",
"2.20.0",
[
"certifi>=2017.4.17",
"chardet<3.1.0,>=3.0.2",
"idna<2.8,>=2.5",
"urllib3<1.24,>=1.21.1",
],
)
actions.do_update(project)
locked_candidates = project.locked_repository.all_candidates
assert locked_candidates["requests"].version == "2.20.0"
assert locked_candidates["chardet"].version == "3.0.5"
assert locked_candidates["pytz"].version == "2019.6"
out, _ = capsys.readouterr()
assert "3 to update" in out, out
actions.do_sync(project)
out, _ = capsys.readouterr()
assert "All packages are synced to date" in out
@pytest.mark.usefixtures("working_set")
def test_update_dry_run(project, repository, capsys):
actions.do_add(project, packages=["requests", "pytz"])
repository.add_candidate("pytz", "2019.6")
repository.add_candidate("chardet", "3.0.5")
repository.add_candidate("requests", "2.20.0")
repository.add_dependencies(
"requests",
"2.20.0",
[
"certifi>=2017.4.17",
"chardet<3.1.0,>=3.0.2",
"idna<2.8,>=2.5",
"urllib3<1.24,>=1.21.1",
],
)
actions.do_update(project, dry_run=True)
project.lockfile = None
locked_candidates = project.locked_repository.all_candidates
assert locked_candidates["requests"].version == "2.19.1"
assert locked_candidates["chardet"].version == "3.0.4"
assert locked_candidates["pytz"].version == "2019.3"
out, _ = capsys.readouterr()
assert "requests 2.19.1 -> 2.20.0" in out
@pytest.mark.usefixtures("working_set")
def test_update_top_packages_dry_run(project, repository, capsys):
actions.do_add(project, packages=["requests", "pytz"])
repository.add_candidate("pytz", "2019.6")
repository.add_candidate("chardet", "3.0.5")
repository.add_candidate("requests", "2.20.0")
repository.add_dependencies(
"requests",
"2.20.0",
[
"certifi>=2017.4.17",
"chardet<3.1.0,>=3.0.2",
"idna<2.8,>=2.5",
"urllib3<1.24,>=1.21.1",
],
)
actions.do_update(project, top=True, dry_run=True)
out, _ = capsys.readouterr()
assert "requests 2.19.1 -> 2.20.0" in out
assert "- chardet 3.0.4 -> 3.0.5" not in out
@pytest.mark.usefixtures("working_set")
def test_update_specified_packages(project, repository):
actions.do_add(project, sync=False, packages=["requests", "pytz"])
repository.add_candidate("pytz", "2019.6")
repository.add_candidate("chardet", "3.0.5")
repository.add_candidate("requests", "2.20.0")
repository.add_dependencies(
"requests",
"2.20.0",
[
"certifi>=2017.4.17",
"chardet<3.1.0,>=3.0.2",
"idna<2.8,>=2.5",
"urllib3<1.24,>=1.21.1",
],
)
actions.do_update(project, packages=["requests"])
locked_candidates = project.locked_repository.all_candidates
assert locked_candidates["requests"].version == "2.20.0"
assert locked_candidates["chardet"].version == "3.0.4"
@pytest.mark.usefixtures("working_set")
def test_update_specified_packages_eager_mode(project, repository):
actions.do_add(project, sync=False, packages=["requests", "pytz"])
repository.add_candidate("pytz", "2019.6")
repository.add_candidate("chardet", "3.0.5")
repository.add_candidate("requests", "2.20.0")
repository.add_dependencies(
"requests",
"2.20.0",
[
"certifi>=2017.4.17",
"chardet<3.1.0,>=3.0.2",
"idna<2.8,>=2.5",
"urllib3<1.24,>=1.21.1",
],
)
actions.do_update(project, strategy="eager", packages=["requests"])
locked_candidates = project.locked_repository.all_candidates
assert locked_candidates["requests"].version == "2.20.0"
assert locked_candidates["chardet"].version == "3.0.5"
assert locked_candidates["pytz"].version == "2019.3"
@pytest.mark.usefixtures("repository")
def test_remove_package(project, working_set, is_dev):
actions.do_add(project, dev=is_dev, packages=["requests", "pytz"])
......@@ -210,16 +88,6 @@ def test_add_remove_no_package(project):
actions.do_remove(project, packages=())
@pytest.mark.usefixtures("repository", "working_set")
def test_update_with_package_and_groups_argument(project):
actions.do_add(project, packages=["requests", "pytz"])
with pytest.raises(PdmUsageError):
actions.do_update(project, groups=("default", "dev"), packages=("requests",))
with pytest.raises(PdmUsageError):
actions.do_update(project, default=False, packages=("requests",))
@pytest.mark.usefixtures("repository")
def test_lock_dependencies(project):
project.add_dependencies({"requests": parse_requirement("requests")})
......@@ -520,28 +388,6 @@ def test_list_json_with_circular_reverse(project, capsys, repository):
assert expected == loads(content)
@pytest.mark.usefixtures("repository", "working_set")
def test_update_packages_with_top(project):
actions.do_add(project, packages=("requests",))
with pytest.raises(PdmUsageError):
actions.do_update(project, packages=("requests",), top=True)
@pytest.mark.usefixtures("working_set")
def test_update_ignore_constraints(project, repository):
actions.do_add(project, packages=("pytz",))
assert project.meta.dependencies == ["pytz~=2019.3"]
repository.add_candidate("pytz", "2020.2")
actions.do_update(project, unconstrained=False, packages=("pytz",))
assert project.meta.dependencies == ["pytz~=2019.3"]
assert project.locked_repository.all_candidates["pytz"].version == "2019.3"
actions.do_update(project, unconstrained=True, packages=("pytz",))
assert project.meta.dependencies == ["pytz~=2020.2"]
assert project.locked_repository.all_candidates["pytz"].version == "2020.2"
def test_init_validate_python_requires(project_no_init):
with pytest.raises(ValueError):
actions.do_init(project_no_init, python_requires="3.7")
......
......@@ -260,3 +260,10 @@ def test_add_with_dry_run(project, capsys):
assert not project.get_dependencies()
assert "requests 2.19.1" in out
assert "urllib3 1.22" in out
@pytest.mark.usefixtures("repository")
def test_add_with_prerelease(project, working_set):
actions.do_add(project, packages=["urllib3"], prerelease=True)
assert working_set["urllib3"].version == "1.23b0"
assert project.meta.dependencies[0] == "urllib3<2,>=1.23b0"
import pytest
from pdm.cli import actions
from pdm.exceptions import PdmUsageError
@pytest.mark.usefixtures("repository", "working_set")
def test_update_packages_with_top(project):
actions.do_add(project, packages=("requests",))
with pytest.raises(PdmUsageError):
actions.do_update(project, packages=("requests",), top=True)
@pytest.mark.usefixtures("working_set")
def test_update_ignore_constraints(project, repository):
actions.do_add(project, packages=("pytz",))
assert project.meta.dependencies == ["pytz~=2019.3"]
repository.add_candidate("pytz", "2020.2")
actions.do_update(project, unconstrained=False, packages=("pytz",))
assert project.meta.dependencies == ["pytz~=2019.3"]
assert project.locked_repository.all_candidates["pytz"].version == "2019.3"
actions.do_update(project, unconstrained=True, packages=("pytz",))
assert project.meta.dependencies == ["pytz~=2020.2"]
assert project.locked_repository.all_candidates["pytz"].version == "2020.2"
@pytest.mark.usefixtures("working_set")
def test_update_all_packages(project, repository, capsys):
actions.do_add(project, packages=["requests", "pytz"])
repository.add_candidate("pytz", "2019.6")
repository.add_candidate("chardet", "3.0.5")
repository.add_candidate("requests", "2.20.0")
repository.add_dependencies(
"requests",
"2.20.0",
[
"certifi>=2017.4.17",
"chardet<3.1.0,>=3.0.2",
"idna<2.8,>=2.5",
"urllib3<1.24,>=1.21.1",
],
)
actions.do_update(project)
locked_candidates = project.locked_repository.all_candidates
assert locked_candidates["requests"].version == "2.20.0"
assert locked_candidates["chardet"].version == "3.0.5"
assert locked_candidates["pytz"].version == "2019.6"
out, _ = capsys.readouterr()
assert "3 to update" in out, out
actions.do_sync(project)
out, _ = capsys.readouterr()
assert "All packages are synced to date" in out
@pytest.mark.usefixtures("working_set")
def test_update_dry_run(project, repository, capsys):
actions.do_add(project, packages=["requests", "pytz"])
repository.add_candidate("pytz", "2019.6")
repository.add_candidate("chardet", "3.0.5")
repository.add_candidate("requests", "2.20.0")
repository.add_dependencies(
"requests",
"2.20.0",
[
"certifi>=2017.4.17",
"chardet<3.1.0,>=3.0.2",
"idna<2.8,>=2.5",
"urllib3<1.24,>=1.21.1",
],
)
actions.do_update(project, dry_run=True)
project.lockfile = None
locked_candidates = project.locked_repository.all_candidates
assert locked_candidates["requests"].version == "2.19.1"
assert locked_candidates["chardet"].version == "3.0.4"
assert locked_candidates["pytz"].version == "2019.3"
out, _ = capsys.readouterr()
assert "requests 2.19.1 -> 2.20.0" in out
@pytest.mark.usefixtures("working_set")
def test_update_top_packages_dry_run(project, repository, capsys):
actions.do_add(project, packages=["requests", "pytz"])
repository.add_candidate("pytz", "2019.6")
repository.add_candidate("chardet", "3.0.5")
repository.add_candidate("requests", "2.20.0")
repository.add_dependencies(
"requests",
"2.20.0",
[
"certifi>=2017.4.17",
"chardet<3.1.0,>=3.0.2",
"idna<2.8,>=2.5",
"urllib3<1.24,>=1.21.1",
],
)
actions.do_update(project, top=True, dry_run=True)
out, _ = capsys.readouterr()
assert "requests 2.19.1 -> 2.20.0" in out
assert "- chardet 3.0.4 -> 3.0.5" not in out
@pytest.mark.usefixtures("working_set")
def test_update_specified_packages(project, repository):
actions.do_add(project, sync=False, packages=["requests", "pytz"])
repository.add_candidate("pytz", "2019.6")
repository.add_candidate("chardet", "3.0.5")
repository.add_candidate("requests", "2.20.0")
repository.add_dependencies(
"requests",
"2.20.0",
[
"certifi>=2017.4.17",
"chardet<3.1.0,>=3.0.2",
"idna<2.8,>=2.5",
"urllib3<1.24,>=1.21.1",
],
)
actions.do_update(project, packages=["requests"])
locked_candidates = project.locked_repository.all_candidates
assert locked_candidates["requests"].version == "2.20.0"
assert locked_candidates["chardet"].version == "3.0.4"
@pytest.mark.usefixtures("working_set")
def test_update_specified_packages_eager_mode(project, repository):
actions.do_add(project, sync=False, packages=["requests", "pytz"])
repository.add_candidate("pytz", "2019.6")
repository.add_candidate("chardet", "3.0.5")
repository.add_candidate("requests", "2.20.0")
repository.add_dependencies(
"requests",
"2.20.0",
[
"certifi>=2017.4.17",
"chardet<3.1.0,>=3.0.2",
"idna<2.8,>=2.5",
"urllib3<1.24,>=1.21.1",
],
)
actions.do_update(project, strategy="eager", packages=["requests"])
locked_candidates = project.locked_repository.all_candidates
assert locked_candidates["requests"].version == "2.20.0"
assert locked_candidates["chardet"].version == "3.0.5"
assert locked_candidates["pytz"].version == "2019.3"
@pytest.mark.usefixtures("repository", "working_set")
def test_update_with_package_and_groups_argument(project):
actions.do_add(project, packages=["requests", "pytz"])
with pytest.raises(PdmUsageError):
actions.do_update(project, groups=("default", "dev"), packages=("requests",))
with pytest.raises(PdmUsageError):
actions.do_update(project, default=False, packages=("requests",))
def test_update_with_prerelease_without_package_argument(project):
actions.do_add(project, packages=["requests"])
with pytest.raises(
PdmUsageError, match="--prerelease must be used with packages given"
):
actions.do_update(project, prerelease=True)
@pytest.mark.usefixtures("repository")
def test_update_existing_package_with_prerelease(project, working_set):
actions.do_add(project, packages=["urllib3"])
assert project.meta.dependencies[0] == "urllib3~=1.22"
assert working_set["urllib3"].version == "1.22"
actions.do_update(project, packages=["urllib3"], prerelease=True)
assert project.meta.dependencies[0] == "urllib3~=1.22"
assert working_set["urllib3"].version == "1.23b0"
actions.do_update(
project, packages=["urllib3"], prerelease=True, unconstrained=True
)
assert project.meta.dependencies[0] == "urllib3<2,>=1.23b0"
assert working_set["urllib3"].version == "1.23b0"
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册