Skip to content
This repository was archived by the owner on Aug 11, 2020. It is now read-only.
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
clean-tests:
rm -rf .tox paperspace.egg-info

run-tests: clean-tests
tox
1 change: 1 addition & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ click = "*"
terminaltables = "*"
click-didyoumean = "*"
click-help-colors = "*"
tox = "*"

[dev-packages]
twine = "*"
Expand Down
158 changes: 72 additions & 86 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion paperspace/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from paperspace.cli.jobs import jobs_group
from paperspace.cli.models import models_group
from paperspace.cli.projects import projects_group
from paperspace.cli.types import ChoiceType, json_string
from paperspace.cli.cli_types import ChoiceType, json_string
from paperspace.cli.validators import validate_mutually_exclusive, validate_email
from paperspace.commands import experiments as experiments_commands, deployments as deployments_commands, \
machines as machines_commands, login as login_commands
Expand Down Expand Up @@ -1068,5 +1068,6 @@ def version():
cli.add_command(projects_group)
cli.add_command(models_group)


if __name__ == '__main__':
cli()
2 changes: 1 addition & 1 deletion paperspace/cli/types.py → paperspace/cli/cli_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ def convert(self, value, param, ctx):

def json_string(val):
"""Wraps json.loads so the cli help shows proper option's type name instead of 'LOADS'"""
return json.loads(val)
return json.loads(val)
13 changes: 13 additions & 0 deletions paperspace/cli/jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,16 @@ def list_jobs(api_key, **filters):
jobs_api = client.API(config.CONFIG_HOST, api_key=api_key)
command = jobs_commands.ListJobsCommand(api=jobs_api)
command.execute(filters)


@jobs_group.command("log", help="List job logs")
@click.option(
"--jobId",
"job_id",
required=True
)
@common.api_key_option
def list_logs(job_id, api_key=None):
logs_api = client.API(config.CONFIG_LOG_HOST, api_key=api_key)
command = jobs_commands.JobLogsCommand(api=logs_api)
command.execute(job_id)
54 changes: 54 additions & 0 deletions paperspace/commands/jobs.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pydoc

import terminaltables
from click import style

from paperspace.commands import CommandBase
from paperspace.utils import get_terminal_lines
Expand Down Expand Up @@ -82,3 +83,56 @@ def _make_table(jobs):
ascii_table = terminaltables.AsciiTable(data)
table_string = ascii_table.table
return table_string


class JobLogsCommand(CommandBase):
last_line_number = 0
base_url = "/jobs/logs?jobId={}&line={}"

is_logs_complete = False

def execute(self, job_id):
table_title = "Job %s logs" % job_id
table_data = [("LINE", "MESSAGE")]
table = terminaltables.AsciiTable(table_data, title=table_title)

while not self.is_logs_complete:
response = self._get_logs(job_id)

try:
data = response.json()
if not response.ok:
self.logger.log_error_response(data)
return
except (ValueError, KeyError) as e:
if response.status_code == 204:
continue
self.logger.log("Error while parsing response data: {}".format(e))
return
else:
self._log_logs_list(data, table, table_data)

def _get_logs(self, job_id):
url = self.base_url.format(job_id, self.last_line_number)
return self.api.get(url)

def _log_logs_list(self, data, table, table_data):
if not data:
self.logger.log("No Logs found")
else:
table_str = self._make_table(data, table, table_data)
if len(table_str.splitlines()) > get_terminal_lines():
pydoc.pager(table_str)
else:
self.logger.log(table_str)

def _make_table(self, logs, table, table_data):
if logs[-1].get("message") == "PSEOF":
self.is_logs_complete = True
else:
self.last_line_number = logs[-1].get("line")

for log in logs:
table_data.append((style(fg="red", text=str(log.get("line"))), log.get("message")))

return table.table
Loading