trainml 0.5.4__py3-none-any.whl → 0.5.6__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.
Files changed (37) hide show
  1. tests/integration/test_checkpoints_integration.py +7 -5
  2. tests/integration/test_datasets_integration.py +4 -5
  3. tests/integration/test_jobs_integration.py +40 -2
  4. tests/integration/test_models_integration.py +8 -10
  5. tests/integration/test_projects_integration.py +2 -6
  6. tests/integration/test_volumes_integration.py +100 -0
  7. tests/unit/cli/cloudbender/test_cli_reservation_unit.py +10 -14
  8. tests/unit/cli/test_cli_project_unit.py +5 -9
  9. tests/unit/cli/test_cli_volume_unit.py +20 -0
  10. tests/unit/cloudbender/test_services_unit.py +161 -0
  11. tests/unit/conftest.py +94 -21
  12. tests/unit/test_projects_unit.py +34 -48
  13. tests/unit/test_volumes_unit.py +447 -0
  14. trainml/__init__.py +1 -1
  15. trainml/cli/__init__.py +3 -6
  16. trainml/cli/cloudbender/__init__.py +1 -1
  17. trainml/cli/cloudbender/service.py +129 -0
  18. trainml/cli/project.py +10 -15
  19. trainml/cli/volume.py +235 -0
  20. trainml/cloudbender/cloudbender.py +2 -2
  21. trainml/cloudbender/services.py +115 -0
  22. trainml/exceptions.py +21 -12
  23. trainml/jobs.py +36 -39
  24. trainml/projects.py +19 -30
  25. trainml/trainml.py +7 -15
  26. trainml/volumes.py +255 -0
  27. {trainml-0.5.4.dist-info → trainml-0.5.6.dist-info}/METADATA +1 -1
  28. {trainml-0.5.4.dist-info → trainml-0.5.6.dist-info}/RECORD +32 -29
  29. tests/integration/test_providers_integration.py +0 -46
  30. tests/unit/test_providers_unit.py +0 -125
  31. trainml/cli/job.py +0 -173
  32. trainml/cli/provider.py +0 -75
  33. trainml/providers.py +0 -63
  34. {trainml-0.5.4.dist-info → trainml-0.5.6.dist-info}/LICENSE +0 -0
  35. {trainml-0.5.4.dist-info → trainml-0.5.6.dist-info}/WHEEL +0 -0
  36. {trainml-0.5.4.dist-info → trainml-0.5.6.dist-info}/entry_points.txt +0 -0
  37. {trainml-0.5.4.dist-info → trainml-0.5.6.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")