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

Commit bf86110

Browse files
committed
Merge remote-tracking branch 'origin/development' into PS-9877-upload-workspace
# Conflicts: # paperspace/cli/jobs.py # paperspace/commands/jobs.py
2 parents f8370f2 + e083ee2 commit bf86110

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
@@ -17,6 +17,7 @@ click = "*"
1717
terminaltables = "*"
1818
click-didyoumean = "*"
1919
click-help-colors = "*"
20+
tox = "*"
2021

2122

2223
[dev-packages]

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
@@ -1084,5 +1084,6 @@ def version():
10841084
cli.add_command(projects_group)
10851085
cli.add_command(models_group)
10861086

1087+
10871088
if __name__ == '__main__':
10881089
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
@@ -90,3 +90,16 @@ def create_job(api_key, **kwargs):
9090
jobs_api = client.API(config.CONFIG_HOST, api_key=api_key)
9191
command = jobs_commands.CreateJobCommand(api=jobs_api)
9292
command.execute(kwargs)
93+
94+
95+
@jobs_group.command("log", help="List job logs")
96+
@click.option(
97+
"--jobId",
98+
"job_id",
99+
required=True
100+
)
101+
@common.api_key_option
102+
def list_logs(job_id, api_key=None):
103+
logs_api = client.API(config.CONFIG_LOG_HOST, api_key=api_key)
104+
command = jobs_commands.JobLogsCommand(api=logs_api)
105+
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 import config, client
67
from paperspace.commands import CommandBase
@@ -86,6 +87,59 @@ def _make_table(jobs):
8687
return table_string
8788

8889

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

0 commit comments

Comments
 (0)