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

Completely remove click echo #6324

Draft
wants to merge 19 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 4 additions & 3 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ pre-commit = "==2.*"
atomicwrites = {version = "*", sys_platform = "== 'win32'"}
pytest-cov = "==4.*"
typing-extensions = "==4.*"
waitress = {version = "*", sys_platform = "== 'win32'"}
gunicorn = {version = "*", sys_platform = "== 'linux'"}
waitress = {version = "3.*", sys_platform = "== 'win32'"}
gunicorn = {version = "23.0.*", sys_platform = "== 'linux'"}
parse = "*"
importlib-metadata = "*"
colorama= {version = "*", sys_platform = "== 'win32'"}
Expand All @@ -28,10 +28,11 @@ pyyaml = "==6.0.1"
build = "*"
twine = "*"
semver = "*"
pypiserver = {ref = "pipenv-313", git = "https://github.com/matteius/pypiserver.git"}
pypiserver = "2.3.2"

[packages]
pytz = "*"
pipenv = {file = "."}

[scripts]
tests = "bash ./run-tests.sh"
Expand Down
951 changes: 585 additions & 366 deletions Pipfile.lock

Large diffs are not rendered by default.

9 changes: 0 additions & 9 deletions pipenv/environments.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,6 @@ def normalize_pipfile_path(p):
)


NO_COLOR = False
if os.getenv("NO_COLOR") or os.getenv("PIPENV_COLORBLIND"):
NO_COLOR = True
from pipenv.utils.shell import style_no_color
from pipenv.vendor import click

click.original_style = click.style
click.style = style_no_color

PIPENV_HIDE_EMOJIS = (
os.environ.get("PIPENV_HIDE_EMOJIS") is None
and (os.name == "nt" or PIPENV_IS_CI)
Expand Down
27 changes: 12 additions & 15 deletions pipenv/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,22 +84,19 @@ def show(self, file=None):
console.print(f"{self.message}")


class PipenvCmdError(PipenvException):
def __init__(self, cmd, out="", err="", exit_code=1):
class PipenvCmdError(OSError):
def __init__(self, cmd, stdout, stderr, return_code):
self.cmd = cmd
self.out = out
self.err = err
self.exit_code = exit_code
message = f"Error running command: {cmd}"
PipenvException.__init__(self, message)

def show(self, file=None):
console = Console(stderr=True, file=file, highlight=False)
console.print(f"[red]Error running command:[/red] [bold]$ {self.cmd}[/bold]")
if self.out:
console.print(f"OUTPUT: {self.out}")
if self.err:
console.print(f"STDERR: {self.err}")
self.stdout = stdout
self.stderr = stderr
self.return_code = return_code

def __str__(self):
return (
f"Command {self.cmd!r} failed with return code {self.return_code}.\n"
f"Output: {self.stdout}\n"
f"Error: {self.stderr}"
)


class JSONParseError(PipenvException):
Expand Down
2 changes: 1 addition & 1 deletion pipenv/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,7 @@ def build_script(self, name: str, extra_args: list[str] | None = None) -> Script
def update_settings(self, d: dict[str, str | bool]) -> None:
settings = self.settings
changed = False
for new in d:
for new in d.keys(): # noqa: PLC0206
if new not in settings:
settings[new] = d[new]
changed = True
Expand Down
86 changes: 37 additions & 49 deletions pipenv/routines/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@

from pipenv import pep508checker
from pipenv.patched.safety.cli import cli
from pipenv.utils import console, err
from pipenv.utils.processes import run_command
from pipenv.utils.project import ensure_project
from pipenv.utils.shell import project_python
from pipenv.vendor import click, plette
from pipenv.vendor import plette


def build_safety_options(
Expand Down Expand Up @@ -58,9 +59,8 @@ def run_pep508_check(project, system, python):
try:
return json.loads(c.stdout.strip())
except json.JSONDecodeError:
click.echo(
err.print(
f"Failed parsing pep508 results:\n{c.stdout.strip()}\n{c.stderr.strip()}",
err=True,
)
sys.exit(1)
return {}
Expand All @@ -75,21 +75,16 @@ def check_pep508_requirements(project, results, quiet):
if marker in results:
if results[marker] != specifier:
failed = True
click.echo(
"Specifier {} does not match {} ({})."
"".format(
click.style(marker, fg="green"),
click.style(specifier, fg="cyan"),
click.style(results[marker], fg="yellow"),
),
err=True,
err.print(
f"Specifier [green]{marker}[/green]does not match "
f"[cyan]{specifier}[/cyan] [yellow]({marker}[/yello])."
)

if failed:
click.secho("Failed!", fg="red", err=True)
err.print("[red]Failed![/red]")
sys.exit(1)
elif not quiet and not project.s.is_quiet():
click.secho("Passed!", fg="green")
console.print("Passed!", fg="green")


def get_requirements(project, use_installed, categories):
Expand Down Expand Up @@ -143,37 +138,32 @@ def parse_safety_output(output, quiet):
meta = json_report.get("report_meta", {})
vulnerabilities_found = meta.get("vulnerabilities_found", 0)
db_type = "commercial" if meta.get("api_key", False) else "free"

style = "red" if vulnerabilities_found else "green"
if quiet:
click.secho(
f"{vulnerabilities_found} vulnerabilities found.",
fg="red" if vulnerabilities_found else "green",
console.print(
f"[{style}]{vulnerabilities_found} vulnerabilities found[/{style}]."
)
else:
fg = "red" if vulnerabilities_found else "green"
message = f"Scan complete using Safety's {db_type} vulnerability database."
click.echo()
click.secho(f"{vulnerabilities_found} vulnerabilities found.", fg=fg)
click.echo()

console.print(
f"[{style}]{vulnerabilities_found} vulnerabilities found[/{style}]."
)
for vuln in json_report.get("vulnerabilities", []):
click.echo(
"{}: {} {} open to vulnerability {} ({}). More info: {}".format(
click.style(vuln["vulnerability_id"], bold=True, fg="red"),
click.style(vuln["package_name"], fg="green"),
click.style(vuln["analyzed_version"], fg="yellow", bold=True),
click.style(vuln["vulnerability_id"], bold=True),
click.style(vuln["vulnerable_spec"], fg="yellow", bold=False),
click.style(vuln["more_info_url"], bold=True),
)
console.print(
f"\n[red]{vuln['vulnerability_id']}[/red]: "
f"[green]{vuln['package_name']}[/green] "
f"[yellow]{vuln['analyzed_version']}[/yellow] "
f"open to vulnerability [red]{vuln['vulnerability_id']}[/red] "
f"([yellow]{vuln['vulnerable_spec']}[/yellow]). "
f"More info: {vuln['more_info_url']}"
f"{vuln['advisory']}"
f"\n"
)
click.echo(f"{vuln['advisory']}")
click.echo()

click.secho(message, fg="white", bold=True)
console.print(f"[bold][white]{message}[/white][/bold]")

except json.JSONDecodeError:
click.echo("Failed to parse Safety output.")
err.print("Failed to parse Safety output.")


def do_check(
Expand Down Expand Up @@ -208,7 +198,7 @@ def do_check(
)

if not quiet and not project.s.is_quiet():
click.secho("Checking PEP 508 requirements...", bold=True)
console.print("[bold]Checking PEP 508 requirements...[/bold]")

results = run_pep508_check(project, system, python)
check_pep508_requirements(project, results, quiet)
Expand All @@ -218,25 +208,23 @@ def do_check(

if not quiet and not project.s.is_quiet():
if use_installed:
click.secho(
"Checking installed packages for vulnerabilities...",
bold=True,
console.print(
"[bold]Checking installed packages for vulnerabilities...[/bold]",
)
else:
click.secho(
"Checking Pipfile.lock packages for vulnerabilities...",
bold=True,
console.print(
"[bold]Checking Pipfile.lock packages for vulnerabilities...",
"[/bold]",
)

if ignore:
ignore = [ignore] if not isinstance(ignore, (tuple, list)) else ignore
if not quiet and not project.s.is_quiet():
click.echo(
"Notice: Ignoring Vulnerabilit{} {}".format(
"ies" if len(ignore) > 1 else "y",
click.style(", ".join(ignore), fg="yellow"),
),
err=True,
suffix = "ies" if len(ignore) > 1 else "y"
err.print(
"[yellow]"
f"Notice: Ignoring Vulnerabilit{suffix} {', '.join(ignore)}"
"[/yellow]"
)

requirements = get_requirements(project, use_installed, categories)
Expand All @@ -259,7 +247,7 @@ def do_check(

if db:
if not quiet and not project.s.is_quiet():
click.echo(f"Using {db} database")
console.print(f"Using {db} database")
cmd.append(f"--db={db}")
elif key or project.s.PIPENV_PYUP_API_KEY:
cmd.append(f"--key={key or project.s.PIPENV_PYUP_API_KEY}")
Expand Down
5 changes: 2 additions & 3 deletions pipenv/routines/clean.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from pipenv.utils.project import ensure_project
from pipenv.utils.requirements import BAD_PACKAGES
from pipenv.utils.shell import project_python
from pipenv.vendor import click


def do_clean(
Expand All @@ -30,7 +29,7 @@ def do_clean(
for bad_package in BAD_PACKAGES:
if canonicalize_name(bad_package) in installed_package_names:
if project.s.is_verbose():
click.echo(f"Ignoring {bad_package}.", err=True)
err.print(f"Ignoring {bad_package}.", err=True)
installed_package_names.remove(canonicalize_name(bad_package))
# Intelligently detect if --dev should be used or not.
locked_packages = {
Expand All @@ -42,7 +41,7 @@ def do_clean(
failure = False
for apparent_bad_package in installed_package_names:
if dry_run and not bare:
click.echo(apparent_bad_package)
console.print(apparent_bad_package)
else:
if not bare:
console.print(
Expand Down
4 changes: 2 additions & 2 deletions pipenv/routines/clear.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import shutil

from pipenv import environments
from pipenv.utils import console
from pipenv.utils.funktools import handle_remove_readonly
from pipenv.vendor import click


def do_clear(project):
from pipenv.patched.pip._internal import locations

click.secho("Clearing caches...", bold=True)
console.print("[bold]Clearing caches...[/bold]")
try:
shutil.rmtree(project.s.PIPENV_CACHE_DIR, onerror=handle_remove_readonly)
# Other processes may be writing into this directory simultaneously.
Expand Down
2 changes: 1 addition & 1 deletion pipenv/routines/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def do_graph(project, bare=False, json=False, json_tree=False, reverse=False):
cmd_args.append("--reverse")

if not project.virtualenv_exists:
err.echo(
err.print(
"[bold][red]Warning: No virtualenv has been created for this project yet! Consider "
"running `pipenv install` first to automatically generate one for you or see "
"`pipenv install --help` for further instructions.[/red][/bold]",
Expand Down
2 changes: 1 addition & 1 deletion pipenv/routines/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ def _cleanup_procs(project, procs):
# The Installation failed...
if failed:
# The Installation failed...
# We echo both c.stdout and c.stderr because pip returns error details on out.
# We write both c.stdout and c.stderr because pip returns error details on out.
err = err.strip().splitlines() if err else []
out = out.strip().splitlines() if out else []
err_lines = [line for message in [out, err] for line in message]
Expand Down
21 changes: 4 additions & 17 deletions pipenv/routines/lock.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import contextlib

from pipenv.utils import err
from pipenv.utils.dependencies import (
get_pipfile_category_using_lockfile_section,
)
from pipenv.vendor import click


def do_lock(
Expand Down Expand Up @@ -48,14 +48,7 @@ def do_lock(

if write:
if not quiet: # Alert the user of progress.
click.echo(
"{} {} {}".format(
click.style("Locking"),
click.style(f"[{pipfile_category}]", fg="yellow"),
click.style("dependencies..."),
),
err=True,
)
err.print(f"Locking [yellow]{pipfile_category}[/yellow] dependencies...")

# Prune old lockfile category as new one will be created.
with contextlib.suppress(KeyError):
Expand Down Expand Up @@ -91,14 +84,8 @@ def do_lock(
lockfile.update({"_meta": project.get_lockfile_meta()})
project.write_lockfile(lockfile)
if not quiet:
click.echo(
"{}".format(
click.style(
f"Updated Pipfile.lock ({project.get_lockfile_hash()})!",
bold=True,
)
),
err=True,
err.print(
f"[bold]Updated Pipfile.lock ({project.get_lockfile_hash()})![/bold]",
)
else:
return lockfile
Expand Down
16 changes: 7 additions & 9 deletions pipenv/routines/outdated.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
from pipenv.patched.pip._vendor.packaging.utils import canonicalize_name
from pipenv.patched.pip._vendor.packaging.version import parse as parse_version
from pipenv.routines.lock import do_lock
from pipenv.utils import console, err
from pipenv.utils.dependencies import (
as_pipfile,
expansive_install_req_from_line,
get_version,
pep423_name,
)
from pipenv.vendor import click


def do_outdated(project, pypi_mirror=None, pre=False, clear=False):
Expand Down Expand Up @@ -47,7 +47,7 @@ def do_outdated(project, pypi_mirror=None, pre=False, clear=False):
pass
outdated = []
skipped = []
for package in packages:
for package in packages.keys(): # noqa: PLC0206
norm_name = pep423_name(package)
if norm_name in updated_packages:
version = packages[package]
Expand Down Expand Up @@ -77,17 +77,15 @@ def do_outdated(project, pypi_mirror=None, pre=False, clear=False):
pipfile_version_text = f" ({version} set in Pipfile)"
else:
pipfile_version_text = " (Unpinned in Pipfile)"
click.secho(
f"Skipped Update of Package {package!s}:"
err.print(
f"[yellow]Skipped Update of Package {package!s}:"
f" {old_version!s} installed,{required!s}{pipfile_version_text!s}, "
f"{new_version!s} available.",
fg="yellow",
err=True,
f"{new_version!s} available.[/yellow]"
)
for package, old_version, new_version in set(outdated).union(set(skipped)):
click.echo(
console.print(
f"Package {package!r} out-of-date: {old_version!r} installed, {new_version!r} available."
)
if not outdated:
click.echo(click.style("All packages are up to date!", fg="green", bold=True))
console.print("[bold green]All packages are up to date![/bold green]")
sys.exit(bool(outdated))
Loading
Loading