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

Commit dbcc3db

Browse files
committed
Merge remote-tracking branch 'origin/development' into PS-9877-upload-workspace
2 parents f80f436 + 575ddae commit dbcc3db

26 files changed

+2430
-121
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Paperspace Python
22
=================
33

4-
Release 0.1.0a0
4+
Release 0.1.0
55

66
See [releasenotes.md](https://github.com/Paperspace/paperspace-python/blob/master/releasenotes.md) for details on the current release, as well as release history.
77

paperspace/cli/cli.py

Lines changed: 22 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,18 @@
11
import collections
22
import functools
3-
import json
4-
import re
53

64
import click
75

86
from paperspace import constants, client, config
9-
from paperspace.cli.jobs.commands import jobs_group
7+
from paperspace.cli.common import api_key_option, del_if_value_is_none
8+
from paperspace.cli.jobs import jobs_group
9+
from paperspace.cli.models import models_group
10+
from paperspace.cli.projects import projects_group
11+
from paperspace.cli.types import ChoiceType, json_string
12+
from paperspace.cli.validators import validate_mutually_exclusive, validate_email
1013
from paperspace.commands import experiments as experiments_commands, deployments as deployments_commands, \
1114
machines as machines_commands, login as login_commands
1215

13-
14-
class ChoiceType(click.Choice):
15-
"""Takes a string-keyed map and converts cli-provided parameter to corresponding value"""
16-
17-
def __init__(self, type_map, case_sensitive=True):
18-
super(ChoiceType, self).__init__(tuple(type_map.keys()), case_sensitive=case_sensitive)
19-
self.type_map = type_map
20-
21-
def convert(self, value, param, ctx):
22-
value = super(ChoiceType, self).convert(value, param, ctx).upper()
23-
return self.type_map[value]
24-
25-
2616
MULTI_NODE_EXPERIMENT_TYPES_MAP = collections.OrderedDict(
2717
(
2818
("GRPC", constants.ExperimentType.GRPC_MULTI_NODE),
@@ -31,55 +21,6 @@ def convert(self, value, param, ctx):
3121
)
3222

3323

34-
class Number(click.ParamType):
35-
name = "number"
36-
37-
def convert(self, value, param, ctx):
38-
try:
39-
number = int(value)
40-
except ValueError:
41-
try:
42-
number = float(value)
43-
except ValueError:
44-
self.fail('{} is not a valid number'.format(value), param, ctx)
45-
46-
return number
47-
48-
49-
def json_string(val):
50-
"""Wraps json.loads so the cli help shows proper option's type name instead of 'LOADS'"""
51-
return json.loads(val)
52-
53-
54-
def del_if_value_is_none(dict_):
55-
"""Remove all elements with value == None"""
56-
for key, val in list(dict_.items()):
57-
if val is None:
58-
del dict_[key]
59-
60-
61-
api_key_option = click.option(
62-
"--apiKey",
63-
"api_key",
64-
help="API key to use this time only",
65-
)
66-
67-
68-
def validate_mutually_exclusive(options_1, options_2, error_message):
69-
used_option_in_options_1 = any(option is not None for option in options_1)
70-
used_option_in_options_2 = any(option is not None for option in options_2)
71-
if used_option_in_options_1 and used_option_in_options_2:
72-
raise click.UsageError(error_message)
73-
74-
75-
def validate_email(ctx, param, value):
76-
if value is not None \
77-
and not re.match(r"[^@]+@[^@]+\.[^@]+", value):
78-
raise click.BadParameter("Bad email address format")
79-
80-
return value
81-
82-
8324
@click.group()
8425
def cli():
8526
pass
@@ -471,12 +412,22 @@ def create_deployment(api_key=None, **kwargs):
471412
type=ChoiceType(DEPLOYMENT_STATES_MAP, case_sensitive=False),
472413
help="Filter by deployment state",
473414
)
415+
@click.option(
416+
"--projectId",
417+
"projectId",
418+
help="Use to filter by project ID",
419+
)
420+
@click.option(
421+
"--modelId",
422+
"modelId",
423+
help="Use to filter by project ID",
424+
)
474425
@api_key_option
475-
def get_deployments_list(api_key=None, **kwargs):
476-
del_if_value_is_none(kwargs)
426+
def get_deployments_list(api_key=None, **filters):
427+
del_if_value_is_none(filters)
477428
deployments_api = client.API(config.CONFIG_HOST, api_key=api_key)
478429
command = deployments_commands.ListDeploymentsCommand(api=deployments_api)
479-
command.execute(kwargs)
430+
command.execute(filters)
480431

481432

482433
@deployments.command("update", help="Update deployment properties")
@@ -516,7 +467,7 @@ def get_deployments_list(api_key=None, **kwargs):
516467
def update_deployment_model(id_, api_key, **kwargs):
517468
del_if_value_is_none(kwargs)
518469
deployments_api = client.API(config.CONFIG_HOST, api_key=api_key)
519-
command = deployments_commands.UpdateModelCommand(api=deployments_api)
470+
command = deployments_commands.UpdateDeploymentCommand(api=deployments_api)
520471
command.execute(id_, kwargs)
521472

522473

@@ -1124,3 +1075,5 @@ def version():
11241075

11251076

11261077
cli.add_command(jobs_group)
1078+
cli.add_command(projects_group)
1079+
cli.add_command(models_group)

paperspace/cli/common.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import click
2+
3+
api_key_option = click.option(
4+
"--apiKey",
5+
"api_key",
6+
help="API key to use this time only",
7+
)
8+
9+
10+
def del_if_value_is_none(dict_):
11+
"""Remove all elements with value == None"""
12+
for key, val in list(dict_.items()):
13+
if val is None:
14+
del dict_[key]

paperspace/cli/jobs.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import click
2+
3+
from paperspace import client, config
4+
from paperspace.cli import common
5+
from paperspace.commands import jobs as jobs_commands
6+
7+
8+
@click.group("jobs", help="Manage gradient jobs")
9+
def jobs_group():
10+
pass
11+
12+
13+
@jobs_group.command("delete", help="Delete job")
14+
@click.option(
15+
"--jobId",
16+
"job_id",
17+
required=True,
18+
help="Delete job with given ID",
19+
)
20+
@common.api_key_option
21+
def delete_job(job_id, api_key=None):
22+
jobs_api = client.API(config.CONFIG_HOST, api_key=api_key)
23+
command = jobs_commands.DeleteJobCommand(api=jobs_api)
24+
command.execute(job_id)
25+
26+
27+
@jobs_group.command("stop", help="Stop running job")
28+
@click.option(
29+
"--jobId",
30+
"job_id",
31+
required=True,
32+
help="Stop job with given ID",
33+
)
34+
@common.api_key_option
35+
def stop_job(job_id, api_key=None):
36+
jobs_api = client.API(config.CONFIG_HOST, api_key=api_key)
37+
command = jobs_commands.StopJobCommand(api=jobs_api)
38+
command.execute(job_id)
39+
40+
41+
@jobs_group.command("list", help="List jobs with optional filtering")
42+
@click.option(
43+
"--project",
44+
"project",
45+
help="Use to filter jobs by project name",
46+
)
47+
@click.option(
48+
"--projectId",
49+
"projectId",
50+
help="Use to filter jobs by project ID",
51+
)
52+
@click.option(
53+
"--experimentId",
54+
"experimentId",
55+
help="Use to filter jobs by experiment ID",
56+
)
57+
@common.api_key_option
58+
def list_jobs(api_key, **filters):
59+
common.del_if_value_is_none(filters)
60+
jobs_api = client.API(config.CONFIG_HOST, api_key=api_key)
61+
command = jobs_commands.ListJobsCommand(api=jobs_api)
62+
command.execute(filters)

paperspace/cli/jobs/__init__.py

Whitespace-only changes.

paperspace/cli/jobs/commands.py

Lines changed: 0 additions & 21 deletions
This file was deleted.

paperspace/cli/models.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import click
2+
3+
from paperspace import client, config
4+
from paperspace.cli import common
5+
from paperspace.commands import models as models_commands
6+
7+
8+
@click.group("models", help="Manage models")
9+
def models_group():
10+
pass
11+
12+
13+
@models_group.command("list", help="List models with optional filtering")
14+
@click.option(
15+
"--experimentId",
16+
"experimentId",
17+
help="Use to filter by experiment ID",
18+
)
19+
@click.option(
20+
"--projectId",
21+
"projectId",
22+
help="Use to filter by project ID",
23+
)
24+
@common.api_key_option
25+
def list_models(api_key, **filters):
26+
common.del_if_value_is_none(filters)
27+
models_api = client.API(config.CONFIG_HOST, api_key=api_key)
28+
command = models_commands.ListModelsCommand(api=models_api)
29+
command.execute(filters)

paperspace/cli/projects.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import click
2+
3+
from paperspace import client, config
4+
from paperspace.commands import projects as projects_commands
5+
from . import common
6+
7+
8+
@click.group("projects", help="Manage projects")
9+
def projects_group():
10+
pass
11+
12+
13+
@projects_group.command("list", help="List projects")
14+
@common.api_key_option
15+
def delete_job(api_key):
16+
projects_api = client.API(config.CONFIG_HOST, api_key=api_key)
17+
command = projects_commands.ListProjectsCommand(api=projects_api)
18+
command.execute()

paperspace/cli/types.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import json
2+
3+
import click
4+
5+
6+
class ChoiceType(click.Choice):
7+
"""Takes a string-keyed map and converts cli-provided parameter to corresponding value"""
8+
9+
def __init__(self, type_map, case_sensitive=True):
10+
super(ChoiceType, self).__init__(tuple(type_map.keys()), case_sensitive=case_sensitive)
11+
self.type_map = type_map
12+
13+
def convert(self, value, param, ctx):
14+
value = super(ChoiceType, self).convert(value, param, ctx).upper()
15+
return self.type_map[value]
16+
17+
18+
def json_string(val):
19+
"""Wraps json.loads so the cli help shows proper option's type name instead of 'LOADS'"""
20+
return json.loads(val)

paperspace/cli/validators.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import re
2+
3+
import click
4+
5+
6+
def validate_mutually_exclusive(options_1, options_2, error_message):
7+
used_option_in_options_1 = any(option is not None for option in options_1)
8+
used_option_in_options_2 = any(option is not None for option in options_2)
9+
if used_option_in_options_1 and used_option_in_options_2:
10+
raise click.UsageError(error_message)
11+
12+
13+
def validate_email(ctx, param, value):
14+
if value is not None \
15+
and not re.match(r"[^@]+@[^@]+\.[^@]+", value):
16+
raise click.BadParameter("Bad email address format")
17+
18+
return value

0 commit comments

Comments
 (0)