793 lines
24 KiB
Python
793 lines
24 KiB
Python
import os
|
|
import sys
|
|
|
|
from pipenv import environments
|
|
from pipenv.__version__ import __version__
|
|
from pipenv.cli.options import (
|
|
CONTEXT_SETTINGS,
|
|
PipenvGroup,
|
|
common_options,
|
|
deploy_option,
|
|
general_options,
|
|
install_options,
|
|
lock_options,
|
|
pass_state,
|
|
pypi_mirror_option,
|
|
python_option,
|
|
site_packages_option,
|
|
sync_options,
|
|
system_option,
|
|
uninstall_options,
|
|
upgrade_options,
|
|
verbose_option,
|
|
)
|
|
from pipenv.utils import console, err
|
|
from pipenv.utils.environment import load_dot_env
|
|
from pipenv.utils.processes import subprocess_run
|
|
from pipenv.vendor.click import (
|
|
Choice,
|
|
argument,
|
|
edit,
|
|
group,
|
|
option,
|
|
pass_context,
|
|
version_option,
|
|
)
|
|
|
|
with console.capture() as capture:
|
|
console.print("[bold]pipenv[/bold]", end="")
|
|
|
|
prog_name = capture.get()
|
|
|
|
subcommand_context = CONTEXT_SETTINGS.copy()
|
|
subcommand_context.update({"ignore_unknown_options": True, "allow_extra_args": True})
|
|
subcommand_context_no_interspersion = subcommand_context.copy()
|
|
subcommand_context_no_interspersion["allow_interspersed_args"] = False
|
|
|
|
|
|
@group(cls=PipenvGroup, invoke_without_command=True, context_settings=CONTEXT_SETTINGS)
|
|
@option("--where", is_flag=True, default=False, help="Output project home information.")
|
|
@option("--venv", is_flag=True, default=False, help="Output virtualenv information.")
|
|
@option(
|
|
"--py", is_flag=True, default=False, help="Output Python interpreter information."
|
|
)
|
|
@option(
|
|
"--envs", is_flag=True, default=False, help="Output Environment Variable options."
|
|
)
|
|
@option("--rm", is_flag=True, default=False, help="Remove the virtualenv.")
|
|
@option("--bare", is_flag=True, default=False, help="Minimal output.")
|
|
@option("--man", is_flag=True, default=False, help="Display manpage.")
|
|
@option(
|
|
"--support",
|
|
is_flag=True,
|
|
help="Output diagnostic information for use in GitHub issues.",
|
|
)
|
|
@general_options
|
|
@version_option(prog_name=prog_name, version=__version__)
|
|
@pass_state
|
|
@pass_context
|
|
def cli(
|
|
ctx,
|
|
state,
|
|
where=False,
|
|
venv=False,
|
|
py=False,
|
|
envs=False,
|
|
rm=False,
|
|
bare=False,
|
|
man=False,
|
|
support=None,
|
|
help=False,
|
|
site_packages=None,
|
|
**kwargs,
|
|
):
|
|
from pipenv.utils.shell import system_which
|
|
|
|
load_dot_env(state.project, quiet=state.quiet)
|
|
|
|
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:
|
|
err.print(
|
|
"PIPENV_COLORBLIND is deprecated, use NO_COLOR"
|
|
" per https://no-color.org/ instead",
|
|
)
|
|
|
|
if man:
|
|
if system_which("man"):
|
|
path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "pipenv.1")
|
|
os.execle(system_which("man"), "man", path, os.environ)
|
|
return 0
|
|
else:
|
|
err.print(
|
|
"man does not appear to be available on your system.", style="bold yellow"
|
|
)
|
|
return 1
|
|
if envs:
|
|
console.print(
|
|
"The following environment variables can be set, to do various things:\n"
|
|
)
|
|
for key in state.project.__dict__:
|
|
if key.startswith("PIPENV"):
|
|
console.print(f" - {key}", style="bold")
|
|
console.print(
|
|
"\nYou can learn more at:\n "
|
|
"[green]https://pipenv.pypa.io/en/latest/advanced/#configuration-with-environment-variables[/green]",
|
|
)
|
|
return 0
|
|
warn_in_virtualenv(state.project)
|
|
if ctx.invoked_subcommand is None:
|
|
# --where was passed...
|
|
if where:
|
|
do_where(state.project, bare=True)
|
|
return 0
|
|
elif py:
|
|
do_py(state.project, ctx=ctx, bare=True)
|
|
return 0
|
|
# --support was passed...
|
|
elif support:
|
|
from ..help import get_pipenv_diagnostics
|
|
|
|
get_pipenv_diagnostics(state.project)
|
|
return 0
|
|
# --clear was passed...
|
|
elif state.clear:
|
|
do_clear(state.project)
|
|
return 0
|
|
# --venv was passed...
|
|
elif venv:
|
|
# There is no virtualenv yet.
|
|
if not state.project.virtualenv_exists:
|
|
err.print(
|
|
"[red]No virtualenv has been created for this project[/red]"
|
|
f"[bold]{state.project.project_directory}[/bold]"
|
|
" [red]yet![/red]"
|
|
)
|
|
ctx.abort()
|
|
else:
|
|
print(state.project.virtualenv_location)
|
|
return 0
|
|
# --rm was passed...
|
|
elif rm:
|
|
# Abort if --system (or running in a virtualenv).
|
|
if state.project.s.PIPENV_USE_SYSTEM or environments.is_in_virtualenv():
|
|
console.print(
|
|
"You are attempting to remove a virtualenv that "
|
|
"Pipenv did not create. Aborting.",
|
|
style="red",
|
|
)
|
|
ctx.abort()
|
|
if state.project.virtualenv_exists:
|
|
loc = state.project.virtualenv_location
|
|
console.print(
|
|
f"[bold]Removing virtualenv[/bold] ([green]{loc}[green])..."
|
|
)
|
|
|
|
with console.status("Running..."):
|
|
# Remove the virtualenv.
|
|
cleanup_virtualenv(state.project, bare=True)
|
|
return 0
|
|
else:
|
|
err.print(
|
|
"No virtualenv has been created for this project yet!",
|
|
style="red bold",
|
|
)
|
|
ctx.abort()
|
|
# --python was passed...
|
|
if (state.python) or state.site_packages:
|
|
ensure_project(
|
|
state.project,
|
|
python=state.python,
|
|
warn=True,
|
|
site_packages=state.site_packages,
|
|
pypi_mirror=state.pypi_mirror,
|
|
clear=state.clear,
|
|
)
|
|
# Check this again before exiting for empty ``pipenv`` command.
|
|
elif ctx.invoked_subcommand is None:
|
|
# Display help to user, if no commands were passed.
|
|
print(format_help(ctx.get_help()))
|
|
|
|
|
|
@cli.command(
|
|
short_help="Installs provided packages and adds them to Pipfile, or (if no packages are given), installs all packages from Pipfile.",
|
|
context_settings=subcommand_context,
|
|
)
|
|
@system_option
|
|
@deploy_option
|
|
@site_packages_option
|
|
@install_options
|
|
@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 pipenv.routines.install import do_install
|
|
|
|
do_install(
|
|
state.project,
|
|
dev=state.installstate.dev,
|
|
python=state.python,
|
|
pypi_mirror=state.pypi_mirror,
|
|
system=state.system,
|
|
ignore_pipfile=state.installstate.ignore_pipfile,
|
|
requirementstxt=state.installstate.requirementstxt,
|
|
pre=state.installstate.pre,
|
|
deploy=state.installstate.deploy,
|
|
index=state.index,
|
|
packages=state.installstate.packages,
|
|
editable_packages=state.installstate.editables,
|
|
site_packages=state.site_packages,
|
|
extra_pip_args=state.installstate.extra_pip_args,
|
|
categories=state.installstate.categories,
|
|
skip_lock=state.installstate.skip_lock,
|
|
)
|
|
|
|
|
|
@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
|
|
@site_packages_option
|
|
@install_options
|
|
@upgrade_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,
|
|
index_url=state.index,
|
|
dev=state.installstate.dev,
|
|
system=state.system,
|
|
lock_only=state.installstate.lock_only,
|
|
extra_pip_args=state.installstate.extra_pip_args,
|
|
)
|
|
|
|
|
|
@cli.command(
|
|
short_help="Uninstalls a provided package and removes it from Pipfile.",
|
|
context_settings=subcommand_context,
|
|
)
|
|
@option(
|
|
"--all-dev",
|
|
is_flag=True,
|
|
default=False,
|
|
help="Uninstall all package from [dev-packages].",
|
|
)
|
|
@option(
|
|
"--all",
|
|
is_flag=True,
|
|
default=False,
|
|
help="Purge all package(s) from virtualenv. Does not edit Pipfile.",
|
|
)
|
|
@uninstall_options
|
|
@pass_state
|
|
@pass_context
|
|
def uninstall(ctx, state, all_dev=False, all=False, **kwargs):
|
|
"""Uninstalls a provided package and removes it from Pipfile."""
|
|
from pipenv.routines.uninstall import do_uninstall
|
|
|
|
pre = state.installstate.pre
|
|
|
|
retcode = do_uninstall(
|
|
state.project,
|
|
packages=state.installstate.packages,
|
|
editable_packages=state.installstate.editables,
|
|
python=state.python,
|
|
system=state.system,
|
|
lock=False,
|
|
all_dev=all_dev,
|
|
all=all,
|
|
pre=pre,
|
|
pypi_mirror=state.pypi_mirror,
|
|
categories=state.installstate.categories,
|
|
ctx=ctx,
|
|
)
|
|
if retcode:
|
|
sys.exit(retcode)
|
|
|
|
|
|
LOCK_HEADER = """\
|
|
#
|
|
# These requirements were autogenerated by pipenv
|
|
# To regenerate from the project's Pipfile, run:
|
|
#
|
|
# pipenv requirements {options}
|
|
#
|
|
"""
|
|
|
|
|
|
LOCK_DEV_NOTE = """\
|
|
# Note: in pipenv 2020.x, "--dev" changed to emit both default and development
|
|
# requirements. To emit only development requirements, pass "--dev-only".
|
|
"""
|
|
|
|
|
|
@cli.command(short_help="Generates Pipfile.lock.", context_settings=CONTEXT_SETTINGS)
|
|
@lock_options
|
|
@pass_state
|
|
@pass_context
|
|
def lock(ctx, state, **kwargs):
|
|
"""Generates Pipfile.lock."""
|
|
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
|
|
# handled in do_lock
|
|
ensure_project(
|
|
state.project,
|
|
python=state.python,
|
|
pypi_mirror=state.pypi_mirror,
|
|
warn=(not state.quiet),
|
|
site_packages=state.site_packages,
|
|
)
|
|
pre = state.installstate.pre
|
|
do_lock(
|
|
state.project,
|
|
clear=state.clear,
|
|
pre=pre,
|
|
pypi_mirror=state.pypi_mirror,
|
|
write=not state.quiet,
|
|
categories=state.installstate.categories,
|
|
)
|
|
|
|
|
|
@cli.command(
|
|
short_help="Spawns a shell within the virtualenv.",
|
|
context_settings=subcommand_context,
|
|
)
|
|
@option(
|
|
"--fancy",
|
|
is_flag=True,
|
|
default=False,
|
|
help="Run in shell in fancy mode. Make sure the shell have no path manipulating"
|
|
" scripts. Run $pipenv shell for issues with compatibility mode.",
|
|
)
|
|
@option(
|
|
"--anyway",
|
|
is_flag=True,
|
|
default=False,
|
|
help="Always spawn a sub-shell, even if one is already spawned.",
|
|
)
|
|
@option(
|
|
"--quiet", is_flag=True, help="Quiet standard output, except vulnerability report."
|
|
)
|
|
@argument("shell_args", nargs=-1)
|
|
@pypi_mirror_option
|
|
@python_option
|
|
@pass_state
|
|
def shell(state, fancy=False, shell_args=None, anyway=False, quiet=False):
|
|
"""Spawns a shell within the virtualenv."""
|
|
from pipenv.routines.shell import do_shell
|
|
|
|
# Prevent user from activating nested environments.
|
|
if "PIPENV_ACTIVE" in os.environ:
|
|
# If PIPENV_ACTIVE is set, VIRTUAL_ENV should always be set too.
|
|
venv_name = os.environ.get("VIRTUAL_ENV", "UNKNOWN_VIRTUAL_ENVIRONMENT")
|
|
if not anyway:
|
|
err.print(
|
|
f"Shell for [green bold]{venv_name}[/green bold] "
|
|
"[bold]already activated[/bold].\n"
|
|
"New shell not activated to avoid nested environments."
|
|
)
|
|
sys.exit(1)
|
|
# Load .env file.
|
|
load_dot_env(state.project)
|
|
# Use fancy mode for Windows or pwsh on *nix.
|
|
if (
|
|
os.name == "nt"
|
|
or (os.environ.get("PIPENV_SHELL") or "").split(os.path.sep)[-1] == "pwsh"
|
|
or (os.environ.get("SHELL") or "").split(os.path.sep)[-1] == "pwsh"
|
|
):
|
|
fancy = True
|
|
do_shell(
|
|
state.project,
|
|
python=state.python,
|
|
fancy=fancy,
|
|
shell_args=shell_args,
|
|
pypi_mirror=state.pypi_mirror,
|
|
quiet=quiet,
|
|
)
|
|
|
|
|
|
@cli.command(
|
|
short_help="Spawns a command installed into the virtualenv.",
|
|
context_settings=subcommand_context_no_interspersion,
|
|
)
|
|
@common_options
|
|
@argument("command")
|
|
@argument("args", nargs=-1)
|
|
@pass_state
|
|
def run(state, command, args):
|
|
"""Spawns a command installed into the virtualenv."""
|
|
from pipenv.routines.shell import do_run
|
|
|
|
do_run(
|
|
state.project,
|
|
command=command,
|
|
args=args,
|
|
python=state.python,
|
|
pypi_mirror=state.pypi_mirror,
|
|
)
|
|
|
|
|
|
@cli.command(
|
|
short_help="Checks for PyUp Safety security vulnerabilities and against"
|
|
" PEP 508 markers provided in Pipfile.",
|
|
context_settings=subcommand_context,
|
|
)
|
|
@option(
|
|
"--db",
|
|
nargs=1,
|
|
default=lambda: os.environ.get("PIPENV_SAFETY_DB"),
|
|
help="Path or URL to a PyUp Safety vulnerabilities database."
|
|
" Default: ENV PIPENV_SAFETY_DB or None.",
|
|
)
|
|
@option(
|
|
"--ignore",
|
|
"-i",
|
|
multiple=True,
|
|
help="Ignore specified vulnerability during PyUp Safety checks.",
|
|
)
|
|
@option(
|
|
"--output",
|
|
type=Choice(["default", "json", "full-report", "bare", "screen", "text", "minimal"]),
|
|
default="default",
|
|
help="Translates to --json, --full-report or --bare from PyUp Safety check",
|
|
)
|
|
@option(
|
|
"--key",
|
|
help="Safety API key from PyUp.io for scanning dependencies against a live"
|
|
" vulnerabilities database. Leave blank for scanning against a"
|
|
" database that only updates once a month.",
|
|
)
|
|
@option(
|
|
"--quiet", is_flag=True, help="Quiet standard output, except vulnerability report."
|
|
)
|
|
@option("--policy-file", default="", help="Define the policy file to be used")
|
|
@option(
|
|
"--exit-code/--continue-on-error",
|
|
default=True,
|
|
help="Output standard exit codes. Default: --exit-code",
|
|
)
|
|
@option(
|
|
"--audit-and-monitor/--disable-audit-and-monitor",
|
|
default=True,
|
|
help="Send results back to pyup.io for viewing on your dashboard. Requires an API key.",
|
|
)
|
|
@option(
|
|
"--project",
|
|
default=None,
|
|
help="Project to associate this scan with on pyup.io. Defaults to a canonicalized github style name if available, otherwise unknown",
|
|
)
|
|
@option(
|
|
"--save-json",
|
|
default="",
|
|
help="Path to where output file will be placed, if the path is a directory, "
|
|
"Safety will use safety-report.json as filename. Default: empty",
|
|
)
|
|
@option(
|
|
"--use-installed",
|
|
is_flag=True,
|
|
help="Whether to use the lockfile as input to check (instead of result from pip list).",
|
|
)
|
|
@option(
|
|
"--categories",
|
|
is_flag=False,
|
|
default="",
|
|
help="Use the specified categories from the lockfile as input to check.",
|
|
)
|
|
@common_options
|
|
@system_option
|
|
@pass_state
|
|
def check(
|
|
state,
|
|
db=None,
|
|
ignore=None,
|
|
output="screen",
|
|
key=None,
|
|
quiet=False,
|
|
exit_code=True,
|
|
policy_file="",
|
|
save_json="",
|
|
audit_and_monitor=True,
|
|
project=None,
|
|
use_installed=False,
|
|
categories="",
|
|
**kwargs,
|
|
):
|
|
"""Checks for PyUp Safety security vulnerabilities and against PEP 508 markers provided in Pipfile."""
|
|
from pipenv.routines.check import do_check
|
|
|
|
do_check(
|
|
state.project,
|
|
python=state.python,
|
|
system=state.system,
|
|
db=db,
|
|
ignore=ignore,
|
|
output=output,
|
|
key=key,
|
|
quiet=quiet,
|
|
verbose=state.verbose,
|
|
exit_code=exit_code,
|
|
policy_file=policy_file,
|
|
save_json=save_json,
|
|
audit_and_monitor=audit_and_monitor,
|
|
safety_project=project,
|
|
pypi_mirror=state.pypi_mirror,
|
|
use_installed=use_installed,
|
|
categories=categories,
|
|
)
|
|
|
|
|
|
@cli.command(short_help="Runs lock, then sync.", context_settings=CONTEXT_SETTINGS)
|
|
@option("--bare", is_flag=True, default=False, help="Minimal output.")
|
|
@option("--outdated", is_flag=True, default=False, help="List out-of-date dependencies.")
|
|
@option("--dry-run", is_flag=True, default=None, help="List out-of-date dependencies.")
|
|
@install_options
|
|
@upgrade_options
|
|
@pass_state
|
|
@pass_context
|
|
def update(ctx, state, bare=False, dry_run=None, outdated=False, **kwargs):
|
|
"""Runs lock when no packages are specified, or upgrade, and then sync."""
|
|
from pipenv.routines.update import do_update
|
|
|
|
do_update(
|
|
state.project,
|
|
python=state.python,
|
|
site_packages=state.site_packages,
|
|
clear=state.clear,
|
|
pre=state.installstate.pre,
|
|
pypi_mirror=state.pypi_mirror,
|
|
system=False,
|
|
packages=state.installstate.packages,
|
|
editable_packages=state.installstate.editables,
|
|
dev=state.installstate.dev,
|
|
bare=bare,
|
|
extra_pip_args=state.installstate.extra_pip_args,
|
|
categories=state.installstate.categories,
|
|
index_url=state.index,
|
|
quiet=state.quiet,
|
|
dry_run=dry_run,
|
|
outdated=outdated,
|
|
lock_only=state.installstate.lock_only,
|
|
)
|
|
|
|
|
|
@cli.command(
|
|
short_help="Displays currently-installed dependency graph information.",
|
|
context_settings=CONTEXT_SETTINGS,
|
|
)
|
|
@option("--bare", is_flag=True, default=False, help="Minimal output.")
|
|
@option("--json", is_flag=True, default=False, help="Output JSON.")
|
|
@option("--json-tree", is_flag=True, default=False, help="Output JSON in nested tree.")
|
|
@option("--reverse", is_flag=True, default=False, help="Reversed dependency graph.")
|
|
@pass_state
|
|
def graph(state, bare=False, json=False, json_tree=False, reverse=False):
|
|
"""Displays currently-installed dependency graph information."""
|
|
from pipenv.routines.graph import do_graph
|
|
|
|
do_graph(state.project, bare=bare, json=json, json_tree=json_tree, reverse=reverse)
|
|
|
|
|
|
@cli.command(
|
|
short_help="View a given module in your editor.",
|
|
name="open",
|
|
context_settings=CONTEXT_SETTINGS,
|
|
)
|
|
@common_options
|
|
@argument("module", nargs=1)
|
|
@pass_state
|
|
def run_open(state, module, *args, **kwargs):
|
|
"""View a given module in your editor.
|
|
|
|
This uses the EDITOR environment variable. You can temporarily override it,
|
|
for example:
|
|
|
|
EDITOR=atom pipenv open requests
|
|
"""
|
|
from pipenv.utils.project import ensure_project
|
|
from pipenv.utils.virtualenv import inline_activate_virtual_environment
|
|
|
|
# Ensure that virtualenv is available.
|
|
ensure_project(
|
|
state.project,
|
|
python=state.python,
|
|
validate=False,
|
|
pypi_mirror=state.pypi_mirror,
|
|
)
|
|
c = subprocess_run(
|
|
[
|
|
state.project._which("python"),
|
|
"-c",
|
|
f"import {module}; print({module}.__file__)",
|
|
]
|
|
)
|
|
if c.returncode:
|
|
console.print("Module not found!", style="red")
|
|
sys.exit(1)
|
|
if "__init__.py" in c.stdout:
|
|
p = os.path.dirname(c.stdout.strip().rstrip("cdo"))
|
|
else:
|
|
p = c.stdout.strip().rstrip("cdo")
|
|
console.print(f"Opening {p!r} in your EDITOR.", style="bold")
|
|
inline_activate_virtual_environment(state.project)
|
|
edit(filename=p)
|
|
return 0
|
|
|
|
|
|
@cli.command(
|
|
short_help="Installs all packages specified in Pipfile.lock.",
|
|
context_settings=CONTEXT_SETTINGS,
|
|
)
|
|
@system_option
|
|
@option("--bare", is_flag=True, default=False, help="Minimal output.")
|
|
@sync_options
|
|
@site_packages_option
|
|
@pass_state
|
|
@pass_context
|
|
def sync(ctx, state, bare=False, user=False, unused=False, **kwargs):
|
|
"""Installs all packages specified in Pipfile.lock."""
|
|
from pipenv.routines.sync import do_sync
|
|
|
|
retcode = do_sync(
|
|
state.project,
|
|
dev=state.installstate.dev,
|
|
python=state.python,
|
|
bare=bare,
|
|
clear=state.clear,
|
|
pypi_mirror=state.pypi_mirror,
|
|
system=state.system,
|
|
extra_pip_args=state.installstate.extra_pip_args,
|
|
categories=state.installstate.categories,
|
|
site_packages=state.site_packages,
|
|
)
|
|
if retcode:
|
|
ctx.abort()
|
|
|
|
|
|
@cli.command(
|
|
short_help="Uninstalls all packages not specified in Pipfile.lock.",
|
|
context_settings=CONTEXT_SETTINGS,
|
|
)
|
|
@option("--bare", is_flag=True, default=False, help="Minimal output.")
|
|
@option("--dry-run", is_flag=True, default=False, help="Just output unneeded packages.")
|
|
@verbose_option
|
|
@python_option
|
|
@pass_state
|
|
def clean(state, dry_run=False, bare=False, user=False):
|
|
"""Uninstalls all packages not specified in Pipfile.lock."""
|
|
from pipenv.routines.clean import do_clean
|
|
|
|
do_clean(
|
|
state.project,
|
|
python=state.python,
|
|
dry_run=dry_run,
|
|
system=state.system,
|
|
)
|
|
|
|
|
|
@cli.command(
|
|
short_help="Lists scripts in current environment config.",
|
|
context_settings=subcommand_context_no_interspersion,
|
|
)
|
|
@common_options
|
|
@pass_state
|
|
def scripts(state):
|
|
"""Lists scripts in current environment config."""
|
|
if not state.project.pipfile_exists:
|
|
err.print("No Pipfile present at project home.")
|
|
sys.exit(1)
|
|
scripts = state.project.parsed_pipfile.get("scripts", {})
|
|
first_column_width = max(len(word) for word in ["Command"] + list(scripts))
|
|
second_column_width = max(len(word) for word in ["Script"] + list(scripts.values()))
|
|
lines = [f"{command:<{first_column_width}} Script" for command in ["Command"]]
|
|
lines.append(f"{'-' * first_column_width} {'-' * second_column_width}")
|
|
lines.extend(
|
|
f"{name:<{first_column_width}} {script}" for name, script in scripts.items()
|
|
)
|
|
console.print("\n".join(line for line in lines))
|
|
|
|
|
|
@cli.command(
|
|
short_help="Verify the hash in Pipfile.lock is up-to-date.",
|
|
context_settings=CONTEXT_SETTINGS,
|
|
)
|
|
@pass_state
|
|
def verify(state):
|
|
"""Verify the hash in Pipfile.lock is up-to-date."""
|
|
if not state.project.pipfile_exists:
|
|
err.print("No Pipfile present at project home.")
|
|
sys.exit(1)
|
|
if state.project.get_lockfile_hash() != state.project.calculate_pipfile_hash():
|
|
err.print(
|
|
"Pipfile.lock is out-of-date. Run [yellow bold]$ pipenv lock[/yellow bold] to update."
|
|
)
|
|
sys.exit(1)
|
|
console.print("Pipfile.lock is up-to-date.", style="green")
|
|
sys.exit(0)
|
|
|
|
|
|
@cli.command(
|
|
short_help="Generate a requirements.txt from Pipfile.lock.",
|
|
context_settings=CONTEXT_SETTINGS,
|
|
)
|
|
@option("--dev", is_flag=True, default=False, help="Also add development requirements.")
|
|
@option(
|
|
"--dev-only", is_flag=True, default=False, help="Only add development requirements."
|
|
)
|
|
@option("--hash", is_flag=True, default=False, help="Add package hashes.")
|
|
@option("--exclude-markers", is_flag=True, default=False, help="Exclude markers.")
|
|
@option(
|
|
"--categories",
|
|
is_flag=False,
|
|
default="",
|
|
help="Only add requirement of the specified categories.",
|
|
)
|
|
@option(
|
|
"--from-pipfile",
|
|
is_flag=True,
|
|
default=False,
|
|
help="Only include dependencies from Pipfile.",
|
|
)
|
|
@pass_state
|
|
def requirements(
|
|
state,
|
|
dev=False,
|
|
dev_only=False,
|
|
hash=False,
|
|
exclude_markers=False,
|
|
categories="",
|
|
from_pipfile=False,
|
|
):
|
|
from pipenv.routines.requirements import generate_requirements
|
|
|
|
generate_requirements(
|
|
project=state.project,
|
|
dev=dev,
|
|
dev_only=dev_only,
|
|
include_hashes=hash,
|
|
include_markers=not exclude_markers,
|
|
categories=categories,
|
|
from_pipfile=from_pipfile,
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
cli()
|
|
|
|
|
|
def do_py(project, ctx=None, system=False, bare=False):
|
|
if not project.virtualenv_exists:
|
|
err.print(
|
|
"[red]No virtualenv has been created for this project[/red] "
|
|
f"[yellow bold]{project.project_directory}[/yellow bold] "
|
|
"[red] yet![/red]"
|
|
)
|
|
ctx.abort()
|
|
|
|
try:
|
|
(print if bare else console.print)(project._which("python", allow_global=system))
|
|
except AttributeError:
|
|
console.print("No project found!", style="red")
|
|
ctx.abort()
|