Skip to content
This repository was archived by the owner on Aug 11, 2020. It is now read-only.

Commit e083ee2

Browse files
committed
Merge branch 'PS-9868' into development
2 parents e640ebe + cc3e745 commit e083ee2

File tree

10 files changed

+317
-88
lines changed

10 files changed

+317
-88
lines changed

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
clean-tests:
2+
rm -rf .tox paperspace.egg-info
3+
4+
run-tests: clean-tests
5+
tox

Pipfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ click = "*"
1515
terminaltables = "*"
1616
click-didyoumean = "*"
1717
click-help-colors = "*"
18+
tox = "*"
1819

1920
[dev-packages]
2021
twine = "*"

Pipfile.lock

Lines changed: 66 additions & 86 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

paperspace/cli/cli.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from paperspace.cli.jobs import jobs_group
1010
from paperspace.cli.models import models_group
1111
from paperspace.cli.projects import projects_group
12-
from paperspace.cli.types import ChoiceType, json_string
12+
from paperspace.cli.cli_types import ChoiceType, json_string
1313
from paperspace.cli.validators import validate_mutually_exclusive, validate_email
1414
from paperspace.commands import experiments as experiments_commands, deployments as deployments_commands, \
1515
machines as machines_commands, login as login_commands
@@ -1068,5 +1068,6 @@ def version():
10681068
cli.add_command(projects_group)
10691069
cli.add_command(models_group)
10701070

1071+
10711072
if __name__ == '__main__':
10721073
cli()
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ def convert(self, value, param, ctx):
1717

1818
def json_string(val):
1919
"""Wraps json.loads so the cli help shows proper option's type name instead of 'LOADS'"""
20-
return json.loads(val)
20+
return json.loads(val)

paperspace/cli/jobs.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,16 @@ def list_jobs(api_key, **filters):
6060
jobs_api = client.API(config.CONFIG_HOST, api_key=api_key)
6161
command = jobs_commands.ListJobsCommand(api=jobs_api)
6262
command.execute(filters)
63+
64+
65+
@jobs_group.command("log", help="List job logs")
66+
@click.option(
67+
"--jobId",
68+
"job_id",
69+
required=True
70+
)
71+
@common.api_key_option
72+
def list_logs(job_id, api_key=None):
73+
logs_api = client.API(config.CONFIG_LOG_HOST, api_key=api_key)
74+
command = jobs_commands.JobLogsCommand(api=logs_api)
75+
command.execute(job_id)

paperspace/commands/jobs.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import pydoc
22

33
import terminaltables
4+
from click import style
45

56
from paperspace.commands import CommandBase
67
from paperspace.utils import get_terminal_lines
@@ -82,3 +83,56 @@ def _make_table(jobs):
8283
ascii_table = terminaltables.AsciiTable(data)
8384
table_string = ascii_table.table
8485
return table_string
86+
87+
88+
class JobLogsCommand(CommandBase):
89+
last_line_number = 0
90+
base_url = "/jobs/logs?jobId={}&line={}"
91+
92+
is_logs_complete = False
93+
94+
def execute(self, job_id):
95+
table_title = "Job %s logs" % job_id
96+
table_data = [("LINE", "MESSAGE")]
97+
table = terminaltables.AsciiTable(table_data, title=table_title)
98+
99+
while not self.is_logs_complete:
100+
response = self._get_logs(job_id)
101+
102+
try:
103+
data = response.json()
104+
if not response.ok:
105+
self.logger.log_error_response(data)
106+
return
107+
except (ValueError, KeyError) as e:
108+
if response.status_code == 204:
109+
continue
110+
self.logger.log("Error while parsing response data: {}".format(e))
111+
return
112+
else:
113+
self._log_logs_list(data, table, table_data)
114+
115+
def _get_logs(self, job_id):
116+
url = self.base_url.format(job_id, self.last_line_number)
117+
return self.api.get(url)
118+
119+
def _log_logs_list(self, data, table, table_data):
120+
if not data:
121+
self.logger.log("No Logs found")
122+
else:
123+
table_str = self._make_table(data, table, table_data)
124+
if len(table_str.splitlines()) > get_terminal_lines():
125+
pydoc.pager(table_str)
126+
else:
127+
self.logger.log(table_str)
128+
129+
def _make_table(self, logs, table, table_data):
130+
if logs[-1].get("message") == "PSEOF":
131+
self.is_logs_complete = True
132+
else:
133+
self.last_line_number = logs[-1].get("line")
134+
135+
for log in logs:
136+
table_data.append((style(fg="red", text=str(log.get("line"))), log.get("message")))
137+
138+
return table.table

0 commit comments

Comments
 (0)