Skip to content
Closed
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
68 changes: 37 additions & 31 deletions src/prefect/cli/artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,55 +36,61 @@ async def list_artifacts(
"-a",
help="Whether or not to only return the latest version of each artifact.",
),
output: Optional[str] = typer.Option(
None,
"--output",
"-o",
help="Specify an output format. Currently supports: json",
),
):
"""
List artifacts.

Arguments:
limit: Maximum number of flow runs to list. Defaults to 100.
all: Whether or not to only return the latest version of each artifact.
output: Return variables in specified format.
"""
table = Table(
title="Artifacts",
caption="List Artifacts using `prefect artifact ls`",
show_header=True,
)

table.add_column("ID", justify="right", style="cyan", no_wrap=True)
table.add_column("Key", style="blue", no_wrap=True)
table.add_column("Type", style="blue", no_wrap=True)
table.add_column("Updated", style="blue", no_wrap=True)
if output and output.lower() != "json":
exit_with_error("Only 'json' output format is supported.")

async with get_client() as client:
if all:
artifacts = await client.read_artifacts(
sort=ArtifactSort.KEY_ASC,
limit=limit,
)

for artifact in sorted(artifacts, key=lambda x: f"{x.key}"):
updated = (
human_friendly_diff(artifact.updated) if artifact.updated else ""
)
table.add_row(
str(artifact.id),
artifact.key,
artifact.type,
updated,
)

else:
artifacts = await client.read_latest_artifacts(
sort=ArtifactCollectionSort.KEY_ASC,
limit=limit,
)

for artifact in sorted(artifacts, key=lambda x: f"{x.key}"):
updated = (
human_friendly_diff(artifact.updated) if artifact.updated else ""
)
table.add_row(
str(artifact.latest_id),
artifact.key,
artifact.type,
updated,
)
if output and output.lower() == "json":
artifacts_json = [artifact.model_dump(mode="json") for artifact in artifacts]
json_output = orjson.dumps(artifacts_json, option=orjson.OPT_INDENT_2).decode()
app.console.print(json_output)
else:
table = Table(
title="Artifacts",
caption="List Artifacts using `prefect artifact ls`",
show_header=True,
)

table.add_column("ID", justify="right", style="cyan", no_wrap=True)
table.add_column("Key", style="blue", no_wrap=True)
table.add_column("Type", style="blue", no_wrap=True)
table.add_column("Updated", style="blue", no_wrap=True)

for artifact in sorted(artifacts, key=lambda x: x.key):
updated = human_friendly_diff(artifact.updated) if artifact.updated else ""
table.add_row(
str(artifact.id if all else artifact.latest_id),
artifact.key,
artifact.type,
updated,
)

app.console.print(table)

Expand Down
113 changes: 73 additions & 40 deletions src/prefect/cli/block.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from typing import TYPE_CHECKING, Any, Optional
from uuid import UUID

import orjson
import typer
import yaml
from rich.table import Table
Expand Down Expand Up @@ -255,32 +256,46 @@ async def register(


@blocks_app.command("ls")
async def block_ls():
async def block_ls(
output: Optional[str] = typer.Option(
None,
"--output",
"-o",
help="Specify an output format. Currently supports: json",
),
):
"""
View all configured blocks.
"""
if output and output.lower() != "json":
exit_with_error("Only 'json' output format is supported.")

async with get_client() as client:
blocks = await client.read_block_documents()

table = Table(
title="Blocks", caption="List Block Types using `prefect block type ls`"
)
table.add_column("ID", style="cyan", no_wrap=True)
table.add_column("Type", style="blue", no_wrap=True)
table.add_column("Name", style="blue", no_wrap=True)
table.add_column("Slug", style="blue", no_wrap=True)

for block in sorted(
blocks, key=lambda x: f"{getattr(x.block_type, 'slug', '')}/{x.name}"
):
table.add_row(
str(block.id),
getattr(block.block_type, "name", ""),
str(block.name),
f"{getattr(block.block_type, 'slug', '')}/{block.name}",
if output and output.lower() == "json":
blocks_json = [block.model_dump(mode="json") for block in blocks]
json_output = orjson.dumps(blocks_json, option=orjson.OPT_INDENT_2).decode()
app.console.print(json_output)
else:
table = Table(
title="Blocks", caption="List Block Types using `prefect block type ls`"
)
table.add_column("ID", style="cyan", no_wrap=True)
table.add_column("Type", style="blue", no_wrap=True)
table.add_column("Name", style="blue", no_wrap=True)
table.add_column("Slug", style="blue", no_wrap=True)

app.console.print(table)
for block in sorted(
blocks, key=lambda x: f"{getattr(x.block_type, 'slug', '')}/{x.name}"
):
table.add_row(
str(block.id),
getattr(block.block_type, "name", ""),
str(block.name),
f"{getattr(block.block_type, 'slug', '')}/{block.name}",
)

app.console.print(table)


@blocks_app.command("delete")
Expand Down Expand Up @@ -402,36 +417,54 @@ async def block_inspect(


@blocktypes_app.command("ls")
async def list_types():
async def list_types(
output: Optional[str] = typer.Option(
None,
"--output",
"-o",
help="Specify an output format. Currently supports: json",
),
):
"""
List all block types.
"""
if output and output.lower() != "json":
exit_with_error("Only 'json' output format is supported.")
async with get_client() as client:
block_types = await client.read_block_types()

table = Table(
title="Block Types",
show_lines=True,
)

table.add_column("Block Type Slug", style="italic cyan", no_wrap=True)
table.add_column("Description", style="blue", no_wrap=False, justify="left")
table.add_column(
"Generate creation link", style="italic cyan", no_wrap=False, justify="left"
)
if output and output.lower() == "json":
block_types_json = [
block_type.model_dump(mode="json") for block_type in block_types
]
json_output = orjson.dumps(
block_types_json, option=orjson.OPT_INDENT_2
).decode()
app.console.print(json_output)
else:
table = Table(
title="Block Types",
show_lines=True,
)

for blocktype in sorted(block_types, key=lambda x: x.name):
table.add_row(
str(blocktype.slug),
(
str(blocktype.description.splitlines()[0].partition(".")[0])
if blocktype.description is not None
else ""
),
f"prefect block create {blocktype.slug}",
table.add_column("Block Type Slug", style="italic cyan", no_wrap=True)
table.add_column("Description", style="blue", no_wrap=False, justify="left")
table.add_column(
"Generate creation link", style="italic cyan", no_wrap=False, justify="left"
)

app.console.print(table)
for blocktype in sorted(block_types, key=lambda x: x.name):
table.add_row(
str(blocktype.slug),
(
str(blocktype.description.splitlines()[0].partition(".")[0])
if blocktype.description is not None
else ""
),
f"prefect block create {blocktype.slug}",
)

app.console.print(table)


@blocktypes_app.command("inspect")
Expand Down
108 changes: 75 additions & 33 deletions src/prefect/cli/deployment.py
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,15 @@ async def resume_schedule(


@schedule_app.command("ls")
async def list_schedules(deployment_name: str):
async def list_schedules(
deployment_name: str,
output: Optional[str] = typer.Option(
None,
"--output",
"-o",
help="Specify an output format. Currently supports: json",
),
):
"""
View all schedules for a deployment.
"""
Expand All @@ -675,6 +683,9 @@ async def list_schedules(deployment_name: str):
except ObjectNotFound:
return exit_with_error(f"Deployment {deployment_name!r} not found!")

if output and output.lower() != "json":
exit_with_error("Only 'json' output format is supported.")

def sort_by_created_key(schedule: DeploymentSchedule): # type: ignore
assert schedule.created is not None, "All schedules should have a created time."
return prefect.types._datetime.now("UTC") - schedule.created
Expand All @@ -689,21 +700,32 @@ def schedule_details(schedule: DeploymentSchedule) -> str:
else:
return "unknown"

table = Table(
title="Deployment Schedules",
)
table.add_column("ID", style="blue", no_wrap=True)
table.add_column("Schedule", style="cyan", no_wrap=False)
table.add_column("Active", style="purple", no_wrap=True)

for schedule in sorted(deployment.schedules, key=sort_by_created_key):
table.add_row(
str(schedule.id),
schedule_details(schedule),
str(schedule.active),
if output and output.lower() == "json":
schedules_json = [
{
**schedule.model_dump(mode="json"),
"schedule": schedule_details(schedule),
}
for schedule in deployment.schedules
]
json_output = orjson.dumps(schedules_json, option=orjson.OPT_INDENT_2).decode()
app.console.print(json_output)
else:
table = Table(
title="Deployment Schedules",
)
table.add_column("ID", style="blue", no_wrap=True)
table.add_column("Schedule", style="cyan", no_wrap=False)
table.add_column("Active", style="purple", no_wrap=True)

for schedule in sorted(deployment.schedules, key=sort_by_created_key):
table.add_row(
str(schedule.id),
schedule_details(schedule),
str(schedule.active),
)

app.console.print(table)
app.console.print(table)


@schedule_app.command("clear")
Expand Down Expand Up @@ -744,10 +766,21 @@ async def clear_schedules(


@deployment_app.command()
async def ls(flow_name: Optional[list[str]] = None, by_created: bool = False):
async def ls(
flow_name: Optional[list[str]] = None,
by_created: bool = False,
output: Optional[str] = typer.Option(
None,
"--output",
"-o",
help="Specify an output format. Currently supports: json",
),
):
"""
View all deployments or deployments for specific flows.
"""
if output and output.lower() != "json":
exit_with_error("Only 'json' output format is supported.")
async with get_client() as client:
deployments = await client.read_deployments(
flow_filter=FlowFilter(name=FlowFilterName(any_=flow_name))
Expand All @@ -770,26 +803,35 @@ def sort_by_created_key(d: DeploymentResponse):
assert d.created is not None, "All deployments should have a created time."
return DateTime.now("utc") - d.created

table = Table(
title="Deployments",
expand=True,
)
table.add_column("Name", style="blue", no_wrap=True, ratio=40)
table.add_column("ID", style="cyan", no_wrap=True, ratio=40)
table.add_column(
"Work Pool", style="green", no_wrap=True, ratio=20, overflow="crop"
)

for deployment in sorted(
deployments, key=sort_by_created_key if by_created else sort_by_name_keys
):
table.add_row(
f"{flows[deployment.flow_id].name}/[bold]{deployment.name}[/]",
str(deployment.id),
deployment.work_pool_name or "",
if output and output.lower() == "json":
deployments_json = [
deployment.model_dump(mode="json") for deployment in deployments
]
json_output = orjson.dumps(
deployments_json, option=orjson.OPT_INDENT_2
).decode()
app.console.print(json_output)
else:
table = Table(
title="Deployments",
expand=True,
)
table.add_column("Name", style="blue", no_wrap=True, ratio=40)
table.add_column("ID", style="cyan", no_wrap=True, ratio=40)
table.add_column(
"Work Pool", style="green", no_wrap=True, ratio=20, overflow="crop"
)

for deployment in sorted(
deployments, key=sort_by_created_key if by_created else sort_by_name_keys
):
table.add_row(
f"{flows[deployment.flow_id].name}/[bold]{deployment.name}[/]",
str(deployment.id),
deployment.work_pool_name or "",
)

app.console.print(table)
app.console.print(table)


@deployment_app.command()
Expand Down
Loading