Skip to content

Commit

Permalink
Merge branch 'main' of github.com:latchbio/latch
Browse files Browse the repository at this point in the history
  • Loading branch information
kennyworkman committed Mar 11, 2022
2 parents 4cacae4 + e449820 commit f5cfb02
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 103 deletions.
142 changes: 74 additions & 68 deletions latch/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,13 @@ def register(pkg_root: str, dockerfile: Union[str, None], pkg_name: Union[str, N
Visit docs.latch.bio to learn more.
"""
_register(pkg_root, dockerfile, pkg_name)
click.secho(
"Successfully registered workflow. View @ console.latch.bio.", fg="green"
)
try:
_register(pkg_root, dockerfile, pkg_name)
click.secho(
"Successfully registered workflow. View @ console.latch.bio.", fg="green"
)
except Exception as e:
click.secho(f"Unable to register workflow: {str(e)}", fg="red")


@click.command("login")
Expand All @@ -51,8 +54,11 @@ def login():
Visit docs.latch.bio to learn more.
"""
_login()
click.secho("Successfully logged into LatchBio.", fg="green")
try:
_login()
click.secho("Successfully logged into LatchBio.", fg="green")
except Exception as e:
click.secho(f"Unable to log in: {str(e)}", fg="red")


@click.command("init")
Expand All @@ -62,7 +68,11 @@ def init(pkg_name: str):
Visit docs.latch.bio to learn more.
"""
_init(pkg_name)
try:
_init(pkg_name)
except Exception as e:
click.secho(f"Unable to initialize {pkg_name}: {str(e)}", fg="red")
return
click.secho(f"Created a latch workflow called {pkg_name}.", fg="green")
click.secho("Run", fg="green")
click.secho(f"\t$ latch register {pkg_name}", fg="green")
Expand All @@ -77,9 +87,15 @@ def cp(source_file: str, destination_file: str):
Visit docs.latch.bio to learn more.
"""
_cp(source_file, destination_file)
click.secho(
f"Successfully copied {source_file} to {destination_file}.", fg="green")
try:
_cp(source_file, destination_file)
click.secho(
f"Successfully copied {source_file} to {destination_file}.", fg="green"
)
except Exception as e:
click.secho(
f"Unable to copy {source_file} to {destination_file}: {str(e)}", fg="red"
)


@click.command("ls")
Expand All @@ -90,74 +106,54 @@ def ls(remote_directories: Union[None, List[str]]):
Visit docs.latch.bio to learn more.
"""
_item_padding = 3
_item_padding = lambda k: 0 if k == "modifyTime" else 3

# If the user doesn't provide any arguments, default to root
if not remote_directories:
remote_directories = ["latch:///"]

# conditional formatting based on whether the user asks for multiple ls's or not
_initial_padding = 0 if len(remote_directories) < 2 else 3

def _emit_directory_header(remote_directory):
if len(remote_directories) > 1:
click.secho(f"{remote_directory}:")
click.secho("")

def _emit_directory_footer():
if len(remote_directories) > 1:
click.secho("")

for remote_directory in remote_directories:
output, max_lengths = _ls(remote_directory, padding=_item_padding)

header_name_padding = max_lengths["name"] - len("Name")
header_content_type_padding = max_lengths["content_type"] - len("Type")
header_content_size_padding = max_lengths["content_size"] - len("Size")
header_modify_time_padding = max_lengths["modify_time"] - len("Last Modified")

header = (
"Name"
+ " " * header_name_padding
+ "Type"
+ " " * header_content_type_padding
+ "Size"
+ " " * header_content_size_padding
+ "Last Modified"
+ " " * header_modify_time_padding
)

_emit_directory_header(remote_directory=remote_directory)
try:
output = _ls(remote_directory)
except Exception as e:
click.secho(
f"Unable to display contents of {remote_directory}: {str(e)}", fg="red"
)
continue

click.secho(" " * _initial_padding, nl=False)
click.secho(header, underline=True)
header = {
"name": "Name:",
"contentType": "Type:",
"contentSize": "Size:",
"modifyTime": "Last Modified:",
}

max_lengths = {key: len(key) + _item_padding(key) for key in header}
for row in output:
name, t, content_type, content_size, modify_time = row
for key in header:
max_lengths[key] = max(
len(row[key]) + _item_padding(key), max_lengths[key]
)

def _display(row, style):
click.secho(f"{row['name']:<{max_lengths['name']}}", nl=False, **style)
click.secho(
f"{row['contentType']:<{max_lengths['contentType']}}", nl=False, **style
)
click.secho(
f"{row['contentSize']:<{max_lengths['contentSize']}}", nl=False, **style
)
click.secho(f"{row['modifyTime']}", **style)

_display(header, style={"underline": True})

for row in output:
style = {
"fg": "cyan" if t == "obj" else "green",
"fg": "cyan" if row["type"] == "obj" else "green",
"bold": True,
}

name_padding = max_lengths["name"] - len(name)
content_type_padding = max_lengths["content_type"] - len(content_type)
content_size_padding = max_lengths["content_size"] - len(content_size)

output_str = (
name
+ " " * name_padding
+ content_type
+ " " * content_type_padding
+ content_size
+ " " * content_size_padding
+ modify_time
)

click.secho(" " * _initial_padding, nl=False)
click.secho(output_str, **style)

_emit_directory_footer()
_display(row, style)


@click.command("execute")
Expand All @@ -172,7 +168,11 @@ def execute(params_file: Path, version: Union[str, None] = None):
Visit docs.latch.bio to learn more.
"""
wf_name = _execute(params_file, version)
try:
wf_name = _execute(params_file, version)
except Exception as e:
click.secho(f"Unable to execute workflow: {str(e)}", fg="red")
return
if version is None:
version = "latest"
click.secho(
Expand All @@ -192,7 +192,11 @@ def get_wf(name: Union[str, None] = None):
Visit docs.latch.bio to learn more.
"""
wfs = _get_wf(name)
try:
wfs = _get_wf(name)
except Exception as e:
click.secho(f"Unable to get workflows: {str(e)}", fg="red")
return
id_padding, name_padding, version_padding = 0, 0, 0
for wf in wfs:
id, name, version = wf
Expand All @@ -202,10 +206,12 @@ def get_wf(name: Union[str, None] = None):
version_padding = max(version_padding, version_len)

click.secho(
f"ID{id_padding * ' '}\tName{name_padding * ' '}\tVersion{version_padding * ' '}")
f"ID{id_padding * ' '}\tName{name_padding * ' '}\tVersion{version_padding * ' '}"
)
for wf in wfs:
click.secho(
f"{wf[0]}{(id_padding - len(str(wf[0]))) * ' '}\t{wf[1]}{(name_padding - len(wf[1])) * ' '}\t{wf[2]}{(version_padding - len(wf[2])) * ' '}")
f"{wf[0]}{(id_padding - len(str(wf[0]))) * ' '}\t{wf[1]}{(name_padding - len(wf[1])) * ' '}\t{wf[2]}{(version_padding - len(wf[2])) * ' '}"
)


main.add_command(register)
Expand Down
4 changes: 2 additions & 2 deletions latch/services/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from urllib3.util.retry import Retry


def execute(params_file: Path, version: Union[None, str] = None) -> bool:
def execute(params_file: Path, version: Union[None, str] = None) -> str:
"""Executes a versioned workflow with parameters specified in python.
Args:
Expand All @@ -30,7 +30,7 @@ def execute(params_file: Path, version: Union[None, str] = None) -> bool:
`execute` service.
Returns:
True if successful
The name of the workflow if successful
Example: ::
Expand Down
51 changes: 19 additions & 32 deletions latch/services/ls.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,49 +5,36 @@
import requests
from latch.utils import retrieve_or_login

def _str_none(s: Optional[str]) -> str:
if s is None:
return "-"
return str(s)

def ls(remote_directory: str, padding: int = 3):
def ls(remote_directory: str):

if remote_directory.startswith("latch://"):
remote_directory = remote_directory[len("latch://") :]
if not remote_directory.startswith("/"):
remote_directory = f"/{remote_directory}"

url = "https://nucleus.latch.bio/sdk/list"
token = retrieve_or_login()
headers = {"Authorization": f"Bearer {token}"}
data = {"directory": remote_directory}

response = requests.post(url, headers=headers, json=data)
json_data = response.json()


# used for pretty printing
# Initial values are the number of characters in the output header
max_lengths = {
"name": len("Name") + padding,
"content_type": len("Type") + padding,
"content_size": len("Size") + padding,
"modify_time": len("Last Modified"),
}
if response.status_code == 403:
raise ValueError(
"you need access to the latch sdk beta ~ join the waitlist @ https://latch.bio/sdk"
)
elif response.status_code == 500:
raise ValueError(f"the directory does not exist.")

json_data = response.json()

output = []
for i in json_data:
name_data = json_data[i]
name = _str_none(name_data["name"])
t = _str_none(name_data["type"])
if t == "dir" and name[-1] != "/":
name = name_data["name"] = f"{name}/"
name_data["content_type"] = "directory"
content_type = _str_none(name_data["content_type"])
content_size = _str_none(name_data["content_size"])
modify_time = _str_none(name_data["modify_time"])

output.append((name, t, content_type, content_size, modify_time))

for i in max_lengths:
_padding = 0 if i == "modify_time" else padding
max_lengths[i] = max(max_lengths[i], _padding + len(_str_none(name_data[i])))
output.append(name_data)

output.sort()
output.sort(key=lambda x: x[1])
output.sort(key=lambda x: x["name"])
output.sort(key=lambda x: x["type"])

return output, max_lengths
return output
Binary file not shown.
2 changes: 1 addition & 1 deletion tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def test_ls(test_account_jwt):

# todo(ayush) add more ls tests
_cmd = ["latch", "ls"]
_run_and_verify(_cmd, "welcome/")
_run_and_verify(_cmd, "welcome")


def test_execute(test_account_jwt):
Expand Down

0 comments on commit f5cfb02

Please sign in to comment.