Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve pipenv update and add pipenv upgrade command #5617

Merged
merged 27 commits into from
Mar 1, 2023
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
3ada0ca
Split apart core using pycharm refactor move methods.
matteius Feb 19, 2023
6785ebf
Fix lint
matteius Feb 19, 2023
772bc4c
move init to remove cicular import.
matteius Feb 19, 2023
ed594bb
Fix imports.
matteius Feb 19, 2023
c0d9e82
fix imports
matteius Feb 19, 2023
91e3ef9
Check in concept for pipenv upgrade command
matteius Feb 19, 2023
f501084
Fix upgrade command expectation on how it updates the lockfile.
matteius Feb 19, 2023
492f619
Actually write the result to the Pipfile, and fix secondary bug with …
matteius Feb 19, 2023
4758350
fix lint
matteius Feb 19, 2023
25834dd
Fix tests
matteius Feb 20, 2023
7ade209
Merge branch 'selective-upgrades' of github.com:pypa/pipenv into sele…
matteius Feb 20, 2023
89a19e6
Fix tests
matteius Feb 20, 2023
b1790ea
Fix tests
matteius Feb 20, 2023
054fcd8
Fix tests
matteius Feb 20, 2023
b0d951f
Fix tests
matteius Feb 20, 2023
9981563
Fix tests
matteius Feb 20, 2023
9819a49
Fix issue where package being upgraded already exists.
matteius Feb 20, 2023
814f734
Add news fragment.
matteius Feb 20, 2023
600c77a
Integrate upgrade with a refactor of update.
matteius Feb 20, 2023
773b145
fix lint
matteius Feb 20, 2023
984119f
alter news fragment.
matteius Feb 20, 2023
80c3b64
fix lint
matteius Feb 20, 2023
d89d165
improve test
matteius Feb 20, 2023
762da9d
Handle cases where there is nothing to upgrade.
matteius Feb 20, 2023
2579319
Merge branch 'main' into selective-upgrades
matteius Feb 25, 2023
be39abf
PR feedback.
matteius Mar 1, 2023
61d4ae4
Add lock-only option.
matteius Mar 1, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions news/5617.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Provide a more powerful solution than ``--keep-outdated`` and ``--selective-upgrade`` which are deprecated for removal.
Introducing the ``pipenv upgrade`` command which takes the same package specifiers as ``pipenv install`` and
updates the ``Pipfile`` and ``Pipfile.lock`` with a valid lock resolution that only effects the specified packages and their dependencies.
Additionally, the ``pipenv update`` command has been updated to use the ``pipenv upgrade`` routine when packages are provided, which will install sync the new lock file as well.
153 changes: 79 additions & 74 deletions pipenv/cli/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from pipenv.utils.dependencies import get_lockfile_section_using_pipfile_category
from pipenv.utils.environment import load_dot_env
from pipenv.utils.processes import subprocess_run
from pipenv.vendor import click
from pipenv.vendor.click import (
Choice,
argument,
Expand Down Expand Up @@ -85,15 +86,10 @@ def cli(

load_dot_env(state.project, quiet=state.quiet)

from ..core import (
cleanup_virtualenv,
do_clear,
do_py,
do_where,
ensure_project,
format_help,
warn_in_virtualenv,
)
from pipenv.routines.clear import do_clear
from pipenv.utils.display import format_help
from pipenv.utils.project import ensure_project
from pipenv.utils.virtualenv import cleanup_virtualenv, do_where, warn_in_virtualenv

if "PIPENV_COLORBLIND" in os.environ:
echo(
Expand Down Expand Up @@ -233,7 +229,7 @@ def cli(
@pass_state
def install(state, **kwargs):
"""Installs provided packages and adds them to Pipfile, or (if no packages are given), installs all packages from Pipfile."""
from ..core import do_install
from pipenv.routines.install import do_install

do_install(
state.project,
Expand All @@ -257,6 +253,39 @@ def install(state, **kwargs):
)


@cli.command(
short_help="Resolves provided packages and adds them to Pipfile, or (if no packages are given), merges results to Pipfile.lock",
context_settings=subcommand_context,
)
@system_option
@deploy_option
@site_packages_option
@skip_lock_option
@install_options
@pass_state
def upgrade(state, **kwargs):
from pipenv.routines.update import upgrade
from pipenv.utils.project import ensure_project

ensure_project(
state.project,
python=state.python,
pypi_mirror=state.pypi_mirror,
warn=(not state.quiet),
site_packages=state.site_packages,
clear=state.clear,
)

upgrade(
state.project,
pre=state.installstate.pre,
packages=state.installstate.packages,
editable_packages=state.installstate.editables,
categories=state.installstate.categories,
system=state.system,
)


@cli.command(
short_help="Uninstalls a provided package and removes it from Pipfile.",
context_settings=subcommand_context,
Expand All @@ -278,7 +307,7 @@ def install(state, **kwargs):
@pass_context
def uninstall(ctx, state, all_dev=False, all=False, **kwargs):
"""Uninstalls a provided package and removes it from Pipfile."""
from ..core import do_uninstall
from pipenv.routines.uninstall import do_uninstall

retcode = do_uninstall(
state.project,
Expand Down Expand Up @@ -320,7 +349,8 @@ def uninstall(ctx, state, all_dev=False, all=False, **kwargs):
@pass_context
def lock(ctx, state, **kwargs):
"""Generates Pipfile.lock."""
from ..core import do_lock, ensure_project
from pipenv.routines.lock import do_lock
from pipenv.utils.project import ensure_project

# Ensure that virtualenv is available.
# Note that we don't pass clear on to ensure_project as it is also
Expand All @@ -335,7 +365,6 @@ def lock(ctx, state, **kwargs):
pre = state.installstate.pre
do_lock(
state.project,
ctx=ctx,
clear=state.clear,
pre=pre,
keep_outdated=state.installstate.keep_outdated,
Expand Down Expand Up @@ -373,7 +402,7 @@ def shell(
anyway=False,
):
"""Spawns a shell within the virtualenv."""
from ..core import do_shell
from pipenv.routines.shell import do_shell

# Prevent user from activating nested environments.
if "PIPENV_ACTIVE" in os.environ:
Expand Down Expand Up @@ -413,7 +442,7 @@ def shell(
@pass_state
def run(state, command, args):
"""Spawns a command installed into the virtualenv."""
from ..core import do_run
from pipenv.routines.shell import do_run

do_run(
state.project,
Expand Down Expand Up @@ -510,7 +539,7 @@ def check(
**kwargs,
):
"""Checks for PyUp Safety security vulnerabilities and against PEP 508 markers provided in Pipfile."""
from ..core import do_check
from pipenv.routines.check import do_check

do_check(
state.project,
Expand Down Expand Up @@ -540,70 +569,27 @@ def check(
@pass_state
@pass_context
def update(ctx, state, bare=False, dry_run=None, outdated=False, **kwargs):
"""Runs lock, then sync."""
from ..core import do_lock, do_outdated, do_sync, ensure_project
"""Runs lock when no packages are specified, or upgrade, and then sync."""
from pipenv.routines.update import do_update

ensure_project(
do_update(
state.project,
python=state.python,
pypi_mirror=state.pypi_mirror,
warn=(not state.quiet),
site_packages=state.site_packages,
clear=state.clear,
)
if not outdated:
outdated = bool(dry_run)
if outdated:
do_outdated(
state.project,
clear=state.clear,
pre=state.installstate.pre,
pypi_mirror=state.pypi_mirror,
)
packages = [p for p in state.installstate.packages if p]
editable = [p for p in state.installstate.editables if p]
if not packages:
echo(
"{} {} {} {}{}".format(
style("Running", bold=True),
style("$ pipenv lock", fg="yellow", bold=True),
style("then", bold=True),
style("$ pipenv sync", fg="yellow", bold=True),
style(".", bold=True),
)
)
else:
for package in packages + editable:
if package not in state.project.all_packages:
echo(
"{}: {} was not found in your Pipfile! Aborting."
"".format(
style("Warning", fg="red", bold=True),
style(package, fg="green", bold=True),
),
err=True,
)
ctx.abort()
do_lock(
state.project,
ctx=ctx,
clear=state.clear,
pre=state.installstate.pre,
keep_outdated=state.installstate.keep_outdated,
pypi_mirror=state.pypi_mirror,
write=not state.quiet,
)
do_sync(
state.project,
keep_outdated=state.installstate.keep_outdated,
system=False,
packages=state.installstate.packages,
editable_packages=state.installstate.editables,
dev=state.installstate.dev,
python=state.python,
bare=bare,
dont_upgrade=not state.installstate.keep_outdated,
user=False,
clear=state.clear,
unused=False,
pypi_mirror=state.pypi_mirror,
extra_pip_args=state.installstate.extra_pip_args,
categories=state.installstate.categories,
quiet=state.quiet,
dry_run=dry_run,
outdated=outdated,
)


Expand All @@ -618,7 +604,7 @@ def update(ctx, state, bare=False, dry_run=None, outdated=False, **kwargs):
@pass_state
def graph(state, bare=False, json=False, json_tree=False, reverse=False):
"""Displays currently-installed dependency graph information."""
from ..core import do_graph
from pipenv.routines.graph import do_graph

do_graph(state.project, bare=bare, json=json, json_tree=json_tree, reverse=reverse)

Expand All @@ -639,7 +625,8 @@ def run_open(state, module, *args, **kwargs):

EDITOR=atom pipenv open requests
"""
from ..core import ensure_project, inline_activate_virtual_environment
from pipenv.utils.project import ensure_project
from pipenv.utils.virtualenv import inline_activate_virtual_environment

# Ensure that virtualenv is available.
ensure_project(
Expand Down Expand Up @@ -679,7 +666,7 @@ def run_open(state, module, *args, **kwargs):
@pass_context
def sync(ctx, state, bare=False, user=False, unused=False, **kwargs):
"""Installs all packages specified in Pipfile.lock."""
from ..core import do_sync
from pipenv.routines.install import do_sync

retcode = do_sync(
state.project,
Expand Down Expand Up @@ -710,7 +697,7 @@ def sync(ctx, state, bare=False, user=False, unused=False, **kwargs):
@pass_state
def clean(state, dry_run=False, bare=False, user=False):
"""Uninstalls all packages not specified in Pipfile.lock."""
from ..core import do_clean
from pipenv.routines.clean import do_clean

do_clean(
state.project,
Expand Down Expand Up @@ -822,3 +809,21 @@ def requirements(

if __name__ == "__main__":
cli()


def do_py(project, ctx=None, system=False):
if not project.virtualenv_exists:
click.echo(
"{}({}){}".format(
click.style("No virtualenv has been created for this project ", fg="red"),
click.style(project.project_directory, fg="yellow", bold=True),
click.style(" yet!", fg="red"),
),
err=True,
)
ctx.abort()

try:
click.echo(project._which("python", allow_global=system))
except AttributeError:
click.echo(click.style("No project found!", fg="red"))
13 changes: 11 additions & 2 deletions pipenv/cli/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class PipenvGroup(DYMMixin, Group):
"""Custom Group class provides formatted main help"""

def get_help_option(self, ctx):
from ..core import format_help
from pipenv.utils.display import format_help

"""Override for showing formatted main help via --help and -h options"""
help_options = self.get_help_option_names(ctx)
Expand Down Expand Up @@ -159,7 +159,7 @@ def callback(ctx, param, value):
click.secho(
"The flag --keep-outdated has been deprecated for removal."
matteius marked this conversation as resolved.
Show resolved Hide resolved
"The flag does not respect package resolver results and leads to inconsistent lock files. "
"Please pin relevant requirements in your Pipfile and discontinue use of this flag.",
"Consider using the new `pipenv upgrade` command to selectively upgrade packages.",
fg="yellow",
bold=True,
err=True,
Expand All @@ -182,6 +182,15 @@ def selective_upgrade_option(f):
def callback(ctx, param, value):
state = ctx.ensure_object(State)
state.installstate.selective_upgrade = value
if value:
click.secho(
"The flag --selective-upgrade has been deprecated for removal."
"The flag is buggy and leads to inconsistent lock files. "
oz123 marked this conversation as resolved.
Show resolved Hide resolved
"Consider using the new `pipenv upgrade` command to selectively upgrade packages.",
fg="yellow",
bold=True,
err=True,
)
return value

return option(
Expand Down
Loading