trainml 0.5.4__py3-none-any.whl → 0.5.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tests/integration/test_checkpoints_integration.py +7 -5
- tests/integration/test_datasets_integration.py +4 -5
- tests/integration/test_jobs_integration.py +40 -2
- tests/integration/test_models_integration.py +8 -10
- tests/integration/test_projects_integration.py +2 -6
- tests/integration/test_volumes_integration.py +100 -0
- tests/unit/cli/test_cli_volume_unit.py +20 -0
- tests/unit/conftest.py +82 -9
- tests/unit/test_volumes_unit.py +447 -0
- trainml/__init__.py +1 -1
- trainml/cli/__init__.py +3 -6
- trainml/cli/volume.py +235 -0
- trainml/exceptions.py +21 -12
- trainml/jobs.py +36 -39
- trainml/trainml.py +7 -15
- trainml/volumes.py +255 -0
- {trainml-0.5.4.dist-info → trainml-0.5.5.dist-info}/METADATA +1 -1
- {trainml-0.5.4.dist-info → trainml-0.5.5.dist-info}/RECORD +22 -22
- tests/integration/test_providers_integration.py +0 -46
- tests/unit/test_providers_unit.py +0 -125
- trainml/cli/job.py +0 -173
- trainml/cli/provider.py +0 -75
- trainml/providers.py +0 -63
- {trainml-0.5.4.dist-info → trainml-0.5.5.dist-info}/LICENSE +0 -0
- {trainml-0.5.4.dist-info → trainml-0.5.5.dist-info}/WHEEL +0 -0
- {trainml-0.5.4.dist-info → trainml-0.5.5.dist-info}/entry_points.txt +0 -0
- {trainml-0.5.4.dist-info → trainml-0.5.5.dist-info}/top_level.txt +0 -0
trainml/cli/job.py
DELETED
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
import click
|
|
2
|
-
from webbrowser import open as browse
|
|
3
|
-
from . import cli, pass_config, search_by_id_name
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
@cli.group()
|
|
7
|
-
@pass_config
|
|
8
|
-
def job(config):
|
|
9
|
-
"""TrainML job commands."""
|
|
10
|
-
pass
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
@job.command()
|
|
14
|
-
@click.argument('job', type=click.STRING)
|
|
15
|
-
@pass_config
|
|
16
|
-
def attach(config, job):
|
|
17
|
-
"""
|
|
18
|
-
Attach to job and show logs.
|
|
19
|
-
|
|
20
|
-
JOB may be specified by name or ID, but ID is preferred.
|
|
21
|
-
"""
|
|
22
|
-
jobs = config.trainml.run(
|
|
23
|
-
config.trainml.client.jobs.list())
|
|
24
|
-
|
|
25
|
-
found = search_by_id_name(job, jobs)
|
|
26
|
-
if None is found:
|
|
27
|
-
raise click.UsageError('Cannot find specified job.')
|
|
28
|
-
|
|
29
|
-
try:
|
|
30
|
-
config.trainml.run(found.attach())
|
|
31
|
-
return config.trainml.run(found.disconnect())
|
|
32
|
-
except:
|
|
33
|
-
try:
|
|
34
|
-
config.trainml.run(found.disconnect())
|
|
35
|
-
except:
|
|
36
|
-
pass
|
|
37
|
-
raise
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
@job.command()
|
|
41
|
-
@click.option(
|
|
42
|
-
'--attach/--no-attach',
|
|
43
|
-
default=True,
|
|
44
|
-
show_default=True,
|
|
45
|
-
help='Auto attach to job.'
|
|
46
|
-
)
|
|
47
|
-
@click.argument('job', type=click.STRING)
|
|
48
|
-
@pass_config
|
|
49
|
-
def connect(config, job, attach):
|
|
50
|
-
"""
|
|
51
|
-
Connect to job.
|
|
52
|
-
|
|
53
|
-
JOB may be specified by name or ID, but ID is preferred.
|
|
54
|
-
"""
|
|
55
|
-
jobs = config.trainml.run(
|
|
56
|
-
config.trainml.client.jobs.list())
|
|
57
|
-
|
|
58
|
-
found = search_by_id_name(job, jobs)
|
|
59
|
-
if None is found:
|
|
60
|
-
raise click.UsageError('Cannot find specified job.')
|
|
61
|
-
|
|
62
|
-
try:
|
|
63
|
-
if attach:
|
|
64
|
-
config.trainml.run(found.connect(), found.attach())
|
|
65
|
-
return config.trainml.run(found.disconnect())
|
|
66
|
-
else:
|
|
67
|
-
return config.trainml.run(found.connect())
|
|
68
|
-
except:
|
|
69
|
-
try:
|
|
70
|
-
config.trainml.run(found.disconnect())
|
|
71
|
-
except:
|
|
72
|
-
pass
|
|
73
|
-
raise
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
@job.command()
|
|
77
|
-
@click.option(
|
|
78
|
-
'--attach/--no-attach',
|
|
79
|
-
default=True,
|
|
80
|
-
show_default=True,
|
|
81
|
-
help='Auto attach to job.'
|
|
82
|
-
)
|
|
83
|
-
@click.option(
|
|
84
|
-
'--connect/--no-connect',
|
|
85
|
-
default=True,
|
|
86
|
-
show_default=True,
|
|
87
|
-
help='Auto connect to job.'
|
|
88
|
-
)
|
|
89
|
-
@click.option(
|
|
90
|
-
'--disk-size', '-ds',
|
|
91
|
-
type=click.INT,
|
|
92
|
-
default=10,
|
|
93
|
-
show_default=True,
|
|
94
|
-
help='Disk size (GiB).'
|
|
95
|
-
)
|
|
96
|
-
@click.option(
|
|
97
|
-
'--gpu-count', '-gc',
|
|
98
|
-
type=click.INT,
|
|
99
|
-
default=1,
|
|
100
|
-
show_default=True,
|
|
101
|
-
help='GPU Count (per Worker.)'
|
|
102
|
-
)
|
|
103
|
-
@click.option(
|
|
104
|
-
'--gpu-type', '-gt',
|
|
105
|
-
type=click.Choice(['GTX 1060'], case_sensitive=False),
|
|
106
|
-
default='GTX 1060',
|
|
107
|
-
show_default=True,
|
|
108
|
-
help='GPU type.'
|
|
109
|
-
)
|
|
110
|
-
@click.option(
|
|
111
|
-
'--type', '-t',
|
|
112
|
-
type=click.Choice(['interactive'], case_sensitive=False),
|
|
113
|
-
default='interactive',
|
|
114
|
-
show_default=True,
|
|
115
|
-
help='Job type.'
|
|
116
|
-
)
|
|
117
|
-
@click.argument('name', type=click.STRING)
|
|
118
|
-
@pass_config
|
|
119
|
-
def create(config, attach, connect, disk_size, gpu_count, gpu_type, type, name):
|
|
120
|
-
"""
|
|
121
|
-
Create job.
|
|
122
|
-
"""
|
|
123
|
-
if type == 'interactive':
|
|
124
|
-
job = config.trainml.run(
|
|
125
|
-
config.trainml.client.jobs.create(
|
|
126
|
-
name=name,
|
|
127
|
-
type=type,
|
|
128
|
-
gpu_type=gpu_type,
|
|
129
|
-
gpu_count=gpu_count,
|
|
130
|
-
disk_size=disk_size,
|
|
131
|
-
)
|
|
132
|
-
)
|
|
133
|
-
click.echo('Created.', file=config.output)
|
|
134
|
-
if attach or connect:
|
|
135
|
-
click.echo('Waiting for job to start...', file=config.output)
|
|
136
|
-
config.trainml.run(job.wait_for('running'))
|
|
137
|
-
click.echo('Launching...', file=config.output)
|
|
138
|
-
browse(job.notebook_url)
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
@job.command()
|
|
142
|
-
@click.argument('job', type=click.STRING)
|
|
143
|
-
@pass_config
|
|
144
|
-
def disconnect(config, job):
|
|
145
|
-
"""
|
|
146
|
-
Disconnect and clean-up job.
|
|
147
|
-
|
|
148
|
-
JOB may be specified by name or ID, but ID is preferred.
|
|
149
|
-
"""
|
|
150
|
-
jobs = config.trainml.run(
|
|
151
|
-
config.trainml.client.jobs.list())
|
|
152
|
-
|
|
153
|
-
found = search_by_id_name(job, jobs)
|
|
154
|
-
if None is found:
|
|
155
|
-
raise click.UsageError('Cannot find specified job.')
|
|
156
|
-
|
|
157
|
-
return config.trainml.run(found.disconnect())
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
@job.command()
|
|
161
|
-
@pass_config
|
|
162
|
-
def list(config):
|
|
163
|
-
"""List TrainML jobs."""
|
|
164
|
-
data = [['ID', 'NAME', 'STATUS', 'PROVIDER', 'TYPE'],
|
|
165
|
-
['-'*80, '-'*80, '-'*80, '-'*80, '-'*80]]
|
|
166
|
-
|
|
167
|
-
jobs = config.trainml.run(
|
|
168
|
-
config.trainml.client.jobs.list())
|
|
169
|
-
|
|
170
|
-
for job in jobs:
|
|
171
|
-
data.append([job.id, job.name, job.status, job.provider, job.type])
|
|
172
|
-
for row in data:
|
|
173
|
-
click.echo("{: >38.36} {: >40.38} {: >13.11} {: >10.8} {: >14.12}".format(*row), file=config.output)
|
trainml/cli/provider.py
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import click
|
|
2
|
-
from trainml.cli import cli, pass_config, search_by_id_name
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
@cli.group()
|
|
6
|
-
@pass_config
|
|
7
|
-
def provider(config):
|
|
8
|
-
"""TrainML provider commands."""
|
|
9
|
-
pass
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
@provider.command()
|
|
13
|
-
@pass_config
|
|
14
|
-
def list(config):
|
|
15
|
-
"""List providers."""
|
|
16
|
-
data = [
|
|
17
|
-
["ID", "TYPE", "CREDITS"],
|
|
18
|
-
[
|
|
19
|
-
"-" * 80,
|
|
20
|
-
"-" * 80,
|
|
21
|
-
"-" * 80,
|
|
22
|
-
],
|
|
23
|
-
]
|
|
24
|
-
|
|
25
|
-
providers = config.trainml.run(config.trainml.client.providers.list())
|
|
26
|
-
|
|
27
|
-
for provider in providers:
|
|
28
|
-
data.append(
|
|
29
|
-
[
|
|
30
|
-
provider.id,
|
|
31
|
-
provider.type,
|
|
32
|
-
f"{provider.credits}",
|
|
33
|
-
]
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
for row in data:
|
|
37
|
-
click.echo(
|
|
38
|
-
"{: >38.36} {: >30.28} {: >15.13}" "".format(*row),
|
|
39
|
-
file=config.stdout,
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
@provider.command()
|
|
44
|
-
@click.argument("type", type=click.STRING)
|
|
45
|
-
@pass_config
|
|
46
|
-
def enable(config, type):
|
|
47
|
-
"""
|
|
48
|
-
Enables a provider.
|
|
49
|
-
|
|
50
|
-
Provider is created of the specified type.
|
|
51
|
-
"""
|
|
52
|
-
|
|
53
|
-
return config.trainml.run(
|
|
54
|
-
config.trainml.client.providers.enable(
|
|
55
|
-
type=type,
|
|
56
|
-
)
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
@provider.command()
|
|
61
|
-
@click.argument("provider", type=click.STRING)
|
|
62
|
-
@pass_config
|
|
63
|
-
def remove(config, provider):
|
|
64
|
-
"""
|
|
65
|
-
Remove a provider.
|
|
66
|
-
|
|
67
|
-
PROVIDER may be specified by name or ID, but ID is preferred.
|
|
68
|
-
"""
|
|
69
|
-
providers = config.trainml.run(config.trainml.client.providers.list())
|
|
70
|
-
|
|
71
|
-
found = search_by_id_name(provider, providers)
|
|
72
|
-
if None is found:
|
|
73
|
-
raise click.UsageError("Cannot find specified provider.")
|
|
74
|
-
|
|
75
|
-
return config.trainml.run(found.remove())
|
trainml/providers.py
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import logging
|
|
3
|
-
from datetime import datetime
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class Providers(object):
|
|
7
|
-
def __init__(self, trainml):
|
|
8
|
-
self.trainml = trainml
|
|
9
|
-
|
|
10
|
-
async def get(self, id):
|
|
11
|
-
resp = await self.trainml._query(f"/provider/{id}", "GET")
|
|
12
|
-
return Provider(self.trainml, **resp)
|
|
13
|
-
|
|
14
|
-
async def list(self):
|
|
15
|
-
resp = await self.trainml._query(f"/provider", "GET")
|
|
16
|
-
providers = [Provider(self.trainml, **provider) for provider in resp]
|
|
17
|
-
return providers
|
|
18
|
-
|
|
19
|
-
async def enable(self, type, **kwargs):
|
|
20
|
-
data = dict(type=type, **kwargs)
|
|
21
|
-
payload = {k: v for k, v in data.items() if v or k in ["copy_keys"]}
|
|
22
|
-
logging.info(f"Enabling Provider {type}")
|
|
23
|
-
resp = await self.trainml._query("/provider", "POST", None, payload)
|
|
24
|
-
provider = Provider(self.trainml, **resp)
|
|
25
|
-
logging.info(f"Enabled Provider {type} with id {provider.id}")
|
|
26
|
-
|
|
27
|
-
return provider
|
|
28
|
-
|
|
29
|
-
async def remove(self, id):
|
|
30
|
-
await self.trainml._query(f"/provider/{id}", "DELETE")
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
class Provider:
|
|
34
|
-
def __init__(self, trainml, **kwargs):
|
|
35
|
-
self.trainml = trainml
|
|
36
|
-
self._provider = kwargs
|
|
37
|
-
self._id = self._provider.get("provider_uuid")
|
|
38
|
-
self._type = self._provider.get("type")
|
|
39
|
-
self._credits = self._provider.get("credits")
|
|
40
|
-
|
|
41
|
-
@property
|
|
42
|
-
def id(self) -> str:
|
|
43
|
-
return self._id
|
|
44
|
-
|
|
45
|
-
@property
|
|
46
|
-
def type(self) -> str:
|
|
47
|
-
return self._type
|
|
48
|
-
|
|
49
|
-
@property
|
|
50
|
-
def credits(self) -> float:
|
|
51
|
-
return self._credits
|
|
52
|
-
|
|
53
|
-
def __str__(self):
|
|
54
|
-
return json.dumps({k: v for k, v in self._provider.items()})
|
|
55
|
-
|
|
56
|
-
def __repr__(self):
|
|
57
|
-
return f"Provider( trainml , **{self._provider.__repr__()})"
|
|
58
|
-
|
|
59
|
-
def __bool__(self):
|
|
60
|
-
return bool(self._id)
|
|
61
|
-
|
|
62
|
-
async def remove(self):
|
|
63
|
-
await self.trainml._query(f"/provider/{self._id}", "DELETE")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|