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

Commit b6371f9

Browse files
BartoszCkikossak
authored andcommitted
Add optional --apiKey to experiments commands and refactor creating client.API instance
1 parent a90fd38 commit b6371f9

File tree

5 files changed

+199
-55
lines changed

5 files changed

+199
-55
lines changed

paperspace/cli.py

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import click
55

6-
from paperspace import constants
6+
from paperspace import constants, client, config
77
from paperspace.commands import experiments as experiments_commands
88

99

@@ -113,6 +113,10 @@ def common_experiments_create_options(f):
113113
"--modelPath",
114114
"modelPath",
115115
),
116+
click.option(
117+
"--apiKey",
118+
"api_key",
119+
)
116120
]
117121
return functools.reduce(lambda x, opt: opt(x), reversed(options), f)
118122

@@ -229,60 +233,100 @@ def common_experiments_create_single_node_options(f):
229233
@create.command(name="multinode")
230234
@common_experiments_create_options
231235
@common_experiment_create_multi_node_options
232-
def create_multi_node(**kwargs):
236+
def create_multi_node(api_key, **kwargs):
233237
del_if_value_is_none(kwargs)
234-
experiments_commands.create_experiment(kwargs)
238+
experiments_api = client.API(config.CONFIG_EXPERIMENTS_HOST)
239+
if api_key:
240+
experiments_api.api_key = api_key
241+
experiments_commands.create_experiment(kwargs, api=experiments_api)
235242

236243

237244
@create.command(name="singlenode")
238245
@common_experiments_create_options
239246
@common_experiments_create_single_node_options
240-
def create_single_node(**kwargs):
247+
def create_single_node(api_key, **kwargs):
241248
kwargs["experimentTypeId"] = constants.ExperimentType.SINGLE_NODE
242249
del_if_value_is_none(kwargs)
243-
experiments_commands.create_experiment(kwargs)
250+
experiments_api = client.API(config.CONFIG_EXPERIMENTS_HOST)
251+
if api_key:
252+
experiments_api.api_key = api_key
253+
experiments_commands.create_experiment(kwargs, api=experiments_api)
244254

245255

246256
@create_and_start.command(name="multinode")
247257
@common_experiments_create_options
248258
@common_experiment_create_multi_node_options
249-
def create_and_start_multi_node(**kwargs):
259+
def create_and_start_multi_node(api_key, **kwargs):
250260
del_if_value_is_none(kwargs)
251-
experiments_commands.create_and_start_experiment(kwargs)
261+
experiments_api = client.API(config.CONFIG_EXPERIMENTS_HOST)
262+
if api_key:
263+
experiments_api.api_key = api_key
264+
experiments_commands.create_and_start_experiment(kwargs, api=experiments_api)
252265

253266

254267
@create_and_start.command(name="singlenode")
255268
@common_experiments_create_options
256269
@common_experiments_create_single_node_options
257-
def create_and_start_single_node(**kwargs):
270+
def create_and_start_single_node(api_key, **kwargs):
258271
kwargs["experimentTypeId"] = constants.ExperimentType.SINGLE_NODE
259272
del_if_value_is_none(kwargs)
260-
experiments_commands.create_and_start_experiment(kwargs)
273+
experiments_api = client.API(config.CONFIG_EXPERIMENTS_HOST)
274+
if api_key:
275+
experiments_api.api_key = api_key
276+
experiments_commands.create_and_start_experiment(kwargs, api=experiments_api)
261277

262278

263279
@experiments.command()
264280
@click.argument("experiment-handle")
265-
def start(experiment_handle):
266-
experiments_commands.start_experiment(experiment_handle)
281+
@click.option(
282+
"--apiKey",
283+
"api_key",
284+
)
285+
def start(experiment_handle, api_key):
286+
experiments_api = client.API(config.CONFIG_EXPERIMENTS_HOST)
287+
if api_key:
288+
experiments_api.api_key = api_key
289+
experiments_commands.start_experiment(experiment_handle, api=experiments_api)
267290

268291

269292
@experiments.command()
270293
@click.argument("experiment-handle")
271-
def stop(experiment_handle):
272-
experiments_commands.stop_experiment(experiment_handle)
294+
@click.option(
295+
"--apiKey",
296+
"api_key",
297+
)
298+
def stop(experiment_handle, api_key):
299+
experiments_api = client.API(config.CONFIG_EXPERIMENTS_HOST)
300+
if api_key:
301+
experiments_api.api_key = api_key
302+
experiments_commands.stop_experiment(experiment_handle, api=experiments_api)
273303

274304

275305
@experiments.command("list")
276306
@click.option("--projectHandle", "-p", "project_handles", multiple=True)
277-
def list_experiments(project_handles):
278-
command = experiments_commands.ListExperimentsCommand()
307+
@click.option(
308+
"--apiKey",
309+
"api_key",
310+
)
311+
def list_experiments(project_handles, api_key):
312+
experiments_api = client.API(config.CONFIG_EXPERIMENTS_HOST)
313+
if api_key:
314+
experiments_api.api_key = api_key
315+
command = experiments_commands.ListExperimentsCommand(api=experiments_api)
279316
command.execute(project_handles)
280317

281318

282319
@experiments.command("details")
283320
@click.argument("experiment-handle")
284-
def get_experiment_details(experiment_handle):
285-
experiments_commands.get_experiment_details(experiment_handle)
321+
@click.option(
322+
"--apiKey",
323+
"api_key",
324+
)
325+
def get_experiment_details(experiment_handle, api_key):
326+
experiments_api = client.API(config.CONFIG_EXPERIMENTS_HOST)
327+
if api_key:
328+
experiments_api.api_key = api_key
329+
experiments_commands.get_experiment_details(experiment_handle, api=experiments_api)
286330

287331
# TODO: delete experiment - not implemented in the api
288332
# TODO: modify experiment - not implemented in the api

paperspace/client.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
import requests
22

3-
from paperspace import logger
3+
from paperspace import logger, config, version
4+
5+
default_headers = {"X-API-Key": config.PAPERSPACE_API_KEY,
6+
"ps_client_name": "paperspace-python",
7+
"ps_client_version": version.version}
48

59

610
class API(object):
711
def __init__(self, api_url, headers=None):
812
self.api_url = api_url
9-
self.headers = headers or {}
13+
headers = headers or default_headers
14+
self.headers = headers.copy()
1015

1116
def get_path(self, url):
1217
api_url = self.api_url if not self.api_url.endswith("/") else self.api_url[:-1]
@@ -36,3 +41,11 @@ def get(self, url, params=None):
3641
logger.debug("Response status code: {}".format(response.status_code))
3742
logger.debug("Response content: {}".format(response.content))
3843
return response
44+
45+
@property
46+
def api_key(self):
47+
return self.headers.get("X-API-Key")
48+
49+
@api_key.setter
50+
def api_key(self, value):
51+
self.headers["X-API-Key"] = value

paperspace/commands/experiments.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,11 @@
22

33
import terminaltables
44

5-
from paperspace import config, version, client, logger, constants
5+
from paperspace import logger, constants, client, config
66
from paperspace.logger import log_response
77
from paperspace.utils import get_terminal_lines
88

9-
default_headers = {"X-API-Key": config.PAPERSPACE_API_KEY,
10-
"ps_client_name": "paperspace-python",
11-
"ps_client_version": version.version}
12-
experiments_api = client.API(config.CONFIG_EXPERIMENTS_HOST, headers=default_headers)
9+
experiments_api = client.API(config.CONFIG_EXPERIMENTS_HOST, headers=client.default_headers)
1310

1411

1512
def _log_create_experiment(response, success_msg_template, error_msg, logger_=logger):
@@ -183,4 +180,4 @@ def get_experiment_details(experiment_handle, api=experiments_api):
183180
logger.log("Error parsing response data")
184181
logger.debug(e)
185182

186-
log_response(response, details, "Unknown error while retrieving details of the experiment")
183+
log_response(response, details, "Unknown error while retrieving details of the experiment")

tests/test_click_commands.py

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,20 @@
44
from paperspace import cli, constants
55

66

7+
@mock.patch("paperspace.cli.client.API")
78
@mock.patch("paperspace.cli.experiments_commands")
8-
def test_should_execute_create_experiment_command_when_cli_singlenode_command_was_executed(commands_patched):
9+
def test_should_execute_create_experiment_command_when_cli_singlenode_command_was_executed(commands_patched,
10+
api_patched):
11+
api_patched.return_value = mock.MagicMock()
912
runner = CliRunner()
1013
command = "experiments create singlenode " \
1114
"--name exp1 " \
1215
"--projectHandle testHandle " \
1316
"--container testContainer " \
1417
"--machineType testType " \
1518
"--command testCommand " \
16-
"--workspaceUrl wUrl"
19+
"--workspaceUrl wUrl " \
20+
"--apiKey some_key"
1721
expected_kwargs = {"name": u"exp1",
1822
"projectHandle": u"testHandle",
1923
"container": u"testContainer",
@@ -26,11 +30,14 @@ def test_should_execute_create_experiment_command_when_cli_singlenode_command_wa
2630
result = runner.invoke(cli.cli, command.split())
2731

2832
assert result.exit_code == 0
29-
commands_patched.create_experiment.assert_called_once_with(expected_kwargs)
33+
commands_patched.create_experiment.assert_called_once_with(expected_kwargs, api=api_patched())
3034

3135

36+
@mock.patch("paperspace.cli.client.API")
3237
@mock.patch("paperspace.cli.experiments_commands")
33-
def test_should_execute_create_experiment_command_when_cli_multinode_mpi_command_was_executed(commands_patched):
38+
def test_should_execute_create_experiment_command_when_cli_multinode_mpi_command_was_executed(commands_patched,
39+
api_patched):
40+
api_patched.return_value = mock.MagicMock()
3441
runner = CliRunner()
3542
command = "experiments create multinode " \
3643
"--name exp1 " \
@@ -44,7 +51,8 @@ def test_should_execute_create_experiment_command_when_cli_multinode_mpi_command
4451
"--parameterServerMachineType testParameterServerMachineType " \
4552
"--parameterServerCommand testParameterServerCommand " \
4653
"--parameterServerCount 3 " \
47-
"--workspaceUrl wUrl"
54+
"--workspaceUrl wUrl " \
55+
"--apiKey some_key"
4856
expected_kwargs = {"name": u"exp1",
4957
"projectHandle": u"testHandle",
5058
"experimentTypeId": constants.ExperimentType.MPI_MULTI_NODE,
@@ -62,11 +70,14 @@ def test_should_execute_create_experiment_command_when_cli_multinode_mpi_command
6270
result = runner.invoke(cli.cli, command.split())
6371

6472
assert result.exit_code == 0
65-
commands_patched.create_experiment.assert_called_once_with(expected_kwargs)
73+
commands_patched.create_experiment.assert_called_once_with(expected_kwargs, api=api_patched())
6674

6775

76+
@mock.patch("paperspace.cli.client.API")
6877
@mock.patch("paperspace.cli.experiments_commands")
69-
def test_should_execute_create_experiment_command_when_cli_multinode_grpc_command_was_executed(commands_patched):
78+
def test_should_execute_create_experiment_command_when_cli_multinode_grpc_command_was_executed(commands_patched,
79+
api_patched):
80+
api_patched.return_value = mock.MagicMock()
7081
runner = CliRunner()
7182
command = "experiments create multinode " \
7283
"--name exp1 " \
@@ -98,20 +109,23 @@ def test_should_execute_create_experiment_command_when_cli_multinode_grpc_comman
98109
result = runner.invoke(cli.cli, command.split())
99110

100111
assert result.exit_code == 0
101-
commands_patched.create_experiment.assert_called_once_with(expected_kwargs)
112+
commands_patched.create_experiment.assert_called_once_with(expected_kwargs, api=api_patched())
102113

103114

115+
@mock.patch("paperspace.cli.client.API")
104116
@mock.patch("paperspace.cli.experiments_commands")
105117
def test_should_execute_create_experiment_command_when_cli_create_and_start_singlenode_command_was_executed(
106-
commands_patched):
118+
commands_patched, api_patched):
119+
api_patched.return_value = mock.MagicMock()
107120
runner = CliRunner()
108121
command = "experiments createAndStart singlenode " \
109122
"--name exp1 " \
110123
"--projectHandle testHandle " \
111124
"--container testContainer " \
112125
"--machineType testType " \
113126
"--command testCommand " \
114-
"--workspaceUrl wUrl"
127+
"--workspaceUrl wUrl " \
128+
"--apiKey some_key"
115129
expected_kwargs = {"name": u"exp1",
116130
"projectHandle": u"testHandle",
117131
"container": u"testContainer",
@@ -124,12 +138,14 @@ def test_should_execute_create_experiment_command_when_cli_create_and_start_sing
124138
result = runner.invoke(cli.cli, command.split())
125139

126140
assert result.exit_code == 0
127-
commands_patched.create_and_start_experiment.assert_called_once_with(expected_kwargs)
141+
commands_patched.create_and_start_experiment.assert_called_once_with(expected_kwargs, api=api_patched())
128142

129143

144+
@mock.patch("paperspace.cli.client.API")
130145
@mock.patch("paperspace.cli.experiments_commands")
131146
def test_should_execute_create_experiment_command_when_cli_create_and_start_multinode_mpi_command_was_executed(
132-
commands_patched):
147+
commands_patched, api_patched):
148+
api_patched.return_value = mock.MagicMock()
133149
runner = CliRunner()
134150
command = "experiments createAndStart multinode " \
135151
"--name exp1 " \
@@ -161,4 +177,4 @@ def test_should_execute_create_experiment_command_when_cli_create_and_start_mult
161177
result = runner.invoke(cli.cli, command.split())
162178

163179
assert result.exit_code == 0
164-
commands_patched.create_and_start_experiment.assert_called_once_with(expected_kwargs)
180+
commands_patched.create_and_start_experiment.assert_called_once_with(expected_kwargs, api=api_patched())

0 commit comments

Comments
 (0)