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

feat: use rich.print to replace click.echo #4827

Merged
merged 1 commit into from
Jun 26, 2024
Merged
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
6 changes: 3 additions & 3 deletions src/bentoml/_internal/cloud/deployment.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from threading import Thread

import attr
import click
import rich
import yaml
from deepmerge.merger import Merger
from simple_di import Provide
Expand Down Expand Up @@ -163,14 +163,14 @@ def verify(
if isinstance(bento_name, str) and path.exists(bento_name):
# target is a path
if self.cli:
click.echo(f"building bento from {bento_name} ...")
rich.print(f"building bento from [green]{bento_name}[/] ...")
bento_info = get_bento_info(
project_path=bento_name,
context=self.context,
)
else:
if self.cli:
click.echo(f"using bento {bento_name}...")
rich.print(f"using bento [green]{bento_name}[/]...")
bento_info = get_bento_info(
bento=str(bento_name),
context=self.context,
Expand Down
20 changes: 9 additions & 11 deletions src/bentoml_cli/bentos.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import click
import click_option_group as cog
import rich
import yaml
from rich.syntax import Syntax
from rich.table import Table
Expand Down Expand Up @@ -217,7 +218,7 @@ def delete_target(target: str) -> None:

if delete_confirmed:
bento_store.delete(bento.tag)
click.echo(f"{bento} deleted.")
rich.print(f"{bento} deleted.")

for target in delete_targets:
delete_target(target)
Expand Down Expand Up @@ -255,7 +256,7 @@ def export(
"""
bento = bento_store.get(bento_tag)
out_path = bento.export(out_path)
click.echo(f"{bento} exported to {out_path}.")
rich.print(f"{bento} exported to {out_path}.")

@bentos.command(name="import")
@click.argument("bento_path", type=click.STRING)
Expand All @@ -272,7 +273,7 @@ def import_bento_(bento_path: str) -> None: # type: ignore (not accessed)
bentoml import s3://mybucket/bentos/my_bento.bento
"""
bento = import_bento(bento_path)
click.echo(f"{bento} imported.")
rich.print(f"{bento} imported.")

@bentos.command()
@click.argument("bento_tag", type=click.STRING)
Expand Down Expand Up @@ -417,11 +418,11 @@ def build( # type: ignore (not accessed)
# NOTE: Don't remove the return statement here, since we will need this
# for usage stats collection if users are opt-in.
if output == "tag":
click.echo(f"__tag__:{bento.tag}")
rich.print(f"__tag__:{bento.tag}")
else:
if not get_quiet_mode():
click.echo(BENTOML_FIGLET)
click.secho(f"Successfully built {bento}.", fg="green")
rich.print(BENTOML_FIGLET)
rich.print(f"[green]Successfully built {bento}.")
next_steps = [
f"\n\n* Deploy to BentoCloud:\n $ bentoml deploy {bento.tag} -n ${{DEPLOYMENT_NAME}}",
"\n\n* Update an existing deployment on BentoCloud:\n"
Expand All @@ -439,13 +440,10 @@ def build( # type: ignore (not accessed)
)

if next_steps:
click.secho(
"\nNext steps:" + "".join(next_steps),
fg="blue",
)
rich.print(f"\n[blue]Next steps: {''.join(next_steps)}[/]")
if push:
if not get_quiet_mode():
click.secho(f"\nPushing {bento} to BentoCloud...", fg="magenta")
rich.print(f"\n[magenta]Pushing {bento} to BentoCloud...[/]")
_cloud_client.push_bento(
bento,
force=force,
Expand Down
48 changes: 22 additions & 26 deletions src/bentoml_cli/cloud.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
from __future__ import annotations

import contextlib
import json
import typing as t
import urllib.parse
import webbrowser
from os import environ

import click
import click_option_group as cog
import rich
from InquirerPy import inquirer
from rich.prompt import Confirm

from bentoml._internal.cloud.client import RestApiClient
from bentoml._internal.cloud.config import CloudClientConfig
Expand Down Expand Up @@ -39,14 +39,18 @@ def cloud_command():
@cog.optgroup.option(
"--endpoint",
type=click.STRING,
help="BentoCloud or Yatai endpoint, default as https://cloud.bentoml.com",
default=environ.get("BENTO_CLOUD_API_ENDPOINT", "https://cloud.bentoml.com"),
help="BentoCloud or Yatai endpoint",
default="https://cloud.bentoml.com",
envvar="BENTO_CLOUD_API_ENDPOINT",
show_default=True,
show_envvar=True,
)
@cog.optgroup.option(
"--api-token",
type=click.STRING,
help="BentoCloud or Yatai user API token",
default=environ.get("BENTO_CLOUD_API_KEY"),
envvar="BENTO_CLOUD_API_KEY",
show_envvar=True,
)
@click.pass_obj
def login(shared_options: SharedOptions, endpoint: str, api_token: str) -> None: # type: ignore (not accessed)
Expand All @@ -72,12 +76,11 @@ def login(shared_options: SharedOptions, endpoint: str, api_token: str) -> None:
baseURL = f"{endpoint}/api_tokens"
encodedCallback = urllib.parse.quote(callback_server.callback_url)
authURL = f"{baseURL}?callback={encodedCallback}"
authURL_display = click.style(authURL, fg="blue", underline=True)
input(f"Press Enter to open {authURL_display} in your browser...")
Confirm.ask(f"Press Enter to open [blue]{authURL}[/] in your browser...")
if webbrowser.open_new_tab(authURL):
click.echo(f"✅ Opened {authURL_display} in your web browser.")
rich.print(f"✅ Opened [blue]{authURL}[/] in your web browser.")
else:
click.echo(
rich.print(
f"🚨 Failed to open browser. Try create a new API token at {baseURL}"
)
try:
Expand All @@ -88,7 +91,7 @@ def login(shared_options: SharedOptions, endpoint: str, api_token: str) -> None:
)
api_token = code
except Exception:
click.echo("🚨 Error accquiring token from web browser")
rich.print("🚨 Error accquiring token from web browser")
return
elif choice == "paste":
api_token = click.prompt(
Expand Down Expand Up @@ -116,30 +119,27 @@ def login(shared_options: SharedOptions, endpoint: str, api_token: str) -> None:
)

add_context(ctx)
click.echo(
rich.print(
f"✅ Configured BentoCloud credentials (current-context: {ctx.name})"
)
email = click.style(user.email, fg="green")
org_name = click.style(org.name, fg="green")
click.echo(f"✅ Logged in as {email} at {org_name} organization")
rich.print(f"✅ Logged in as {email} at {org_name} organization")
except CloudRESTApiClientError as e:
if e.error_code == 401:
click.echo(
rich.print(
f"🚨 Error validating token: HTTP 401: Bad credentials ({endpoint}/api-token)"
)
else:
click.echo(f"✗ Error validating token: HTTP {e.error_code}")
rich.print(f"✗ Error validating token: HTTP {e.error_code}")


@cloud_command.command()
def current_context() -> None: # type: ignore (not accessed)
"""Get current cloud context."""
click.echo(
json.dumps(
bentoml_cattr.unstructure(
CloudClientConfig.get_config().get_current_context()
),
indent=2,
rich.print_json(
data=bentoml_cattr.unstructure(
CloudClientConfig.get_config().get_current_context()
)
)

Expand All @@ -148,16 +148,12 @@ def current_context() -> None: # type: ignore (not accessed)
def list_context() -> None: # type: ignore (not accessed)
"""List all available context."""
config = CloudClientConfig.get_config()
click.echo(
json.dumps(
bentoml_cattr.unstructure([i.name for i in config.contexts]), indent=2
)
)
rich.print_json(data=bentoml_cattr.unstructure([i.name for i in config.contexts]))


@cloud_command.command()
@click.argument("context_name", type=click.STRING)
def update_current_context(context_name: str) -> None: # type: ignore (not accessed)
"""Update current context"""
ctx = CloudClientConfig.get_config().set_current_context(context_name)
click.echo(f"Successfully switched to context: {ctx.name}")
rich.print(f"Successfully switched to context: {ctx.name}")
49 changes: 19 additions & 30 deletions src/bentoml_cli/containerize.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from functools import partial

import click
import rich
from click_option_group import optgroup

from bentoml import container
Expand Down Expand Up @@ -553,47 +554,35 @@ def containerize_command( # type: ignore
elif shutil.which("nerdctl") is not None:
container_runtime = "nerdctl"
else:
click.echo(
click.style(
"To load image built with 'buildctl' requires one of "
"docker, podman, nerdctl (None are found in PATH). "
"Make sure they are visible to PATH and try again.",
fg="yellow",
),
color=True,
rich.print(
"[yellow]To load image built with 'buildctl' requires one of "
"docker, podman, nerdctl (None are found in PATH). "
"Make sure they are visible to PATH and try again.[/]",
)
sys.exit(0)
if "output" not in _memoized:
tmp_path = tempfile.gettempdir()
type_prefix = "type=oci,name="
if container_runtime == "docker":
type_prefix = "type=docker,name=docker.io/"
click.echo(
click.style(
"Autoconfig is now deprecated and will be removed "
"in the next future release. We recommend setting "
"output to a tarfile should you wish to load the "
"image locally. For example:",
fg="yellow",
),
color=True,
rich.print(
"[yellow]Autoconfig is now deprecated and will be removed "
"in the next future release. We recommend setting "
"output to a tarfile should you wish to load the "
"image locally. For example:[/]",
)
click.echo(
click.style(
f" bentoml containerize {bento_tag} --backend buildctl --opt output={type_prefix}{tags[0]},dest={tmp_path}/{tags[0].replace(':', '_')}.tar\n"
f" {container_runtime} load -i {tmp_path}/{tags[0].replace(':', '_')}.tar",
fg="yellow",
),
color=True,
rich.print(
f"[yellow] bentoml containerize {bento_tag} --backend buildctl --opt output={type_prefix}{tags[0]},dest={tmp_path}/{tags[0].replace(':', '_')}.tar\n"
f" {container_runtime} load -i {tmp_path}/{tags[0].replace(':', '_')}.tar[/]",
)
o = subprocess.check_output([container_runtime, "load"], input=result)
if get_debug_mode():
click.echo(o.decode("utf-8").strip())
rich.print(o.decode("utf-8").strip())
sys.exit(0)
return result

click.echo(
f'Successfully built Bento container for "{bento_tag}" with tag(s) "{",".join(tags)}"',
rich.print(
f'Successfully built Bento container for [green]"{bento_tag}"[/] with tag(s) "{",".join(tags)}"',
)
instructions = (
"To run your newly built Bento container, run:\n"
Expand All @@ -606,8 +595,8 @@ def containerize_command( # type: ignore
):
instructions += (
"To serve with gRPC instead, run:\n"
+ f" {container_runtime} run --rm -p 3000:3000 -p 3001:3001 {tags[0]} serve-grpc\n"
+ f" {container_runtime} run --rm -p 3000:3000 -p 3001:3001 {tags[0]} serve-grpc"
)
click.echo(instructions, nl=False)
raise SystemExit(0)
rich.print(instructions)
sys.exit(0)
raise SystemExit(1)
9 changes: 5 additions & 4 deletions src/bentoml_cli/deployment.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from http import HTTPStatus

import click
import rich
import yaml
from rich.syntax import Syntax
from rich.table import Table
Expand Down Expand Up @@ -306,7 +307,7 @@ def update( # type: ignore
context=shared_options.cloud_context,
)

click.echo(f"Deployment '{deployment_info.name}' updated successfully.")
rich.print(f"Deployment [green]'{deployment_info.name}'[/] updated successfully.")


@deployment_command.command()
Expand Down Expand Up @@ -428,7 +429,7 @@ def apply( # type: ignore
context=shared_options.cloud_context,
)

click.echo(f"Deployment '{deployment_info.name}' applied successfully.")
rich.print(f"Deployment [green]'{deployment_info.name}'[/] applied successfully.")


@deployment_command.command()
Expand Down Expand Up @@ -595,7 +596,7 @@ def terminate( # type: ignore
) -> None:
"""Terminate a deployment on BentoCloud."""
Deployment.terminate(name, context=shared_options.cloud_context, cluster=cluster)
click.echo(f"Deployment '{name}' terminated successfully.")
rich.print(f"Deployment [green]'{name}'[/] terminated successfully.")


@deployment_command.command()
Expand All @@ -613,7 +614,7 @@ def delete( # type: ignore
) -> None:
"""Delete a deployment on BentoCloud."""
Deployment.delete(name, context=shared_options.cloud_context, cluster=cluster)
click.echo(f"Deployment '{name}' deleted successfully.")
rich.print(f"Deployment [green]'{name}'[/] deleted successfully.")


@deployment_command.command(name="list")
Expand Down
5 changes: 3 additions & 2 deletions src/bentoml_cli/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
from gettext import gettext

import click
import rich
import rich.pretty

from bentoml._internal.utils.pkg import PackageNotFoundError
from bentoml._internal.utils.pkg import get_pkg_version
Expand Down Expand Up @@ -165,5 +167,4 @@ def env_command(ctx: click.Context, output: t.Literal["md", "bash"]) -> None: #
# process info from `pip freeze`
pip_packages = run_cmd([sys.executable, "-m", "pip", "freeze"])
info_dict["pip_packages"] = pip_packages
click.echo(pretty_format(info_dict, output=output))
ctx.exit(0)
rich.print(pretty_format(info_dict, output=output))
Loading
Loading