trainml 0.5.9__py3-none-any.whl → 0.5.12__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/projects/conftest.py +3 -1
- tests/integration/projects/test_projects_credentials_integration.py +45 -0
- tests/integration/projects/test_projects_data_connectors_integration.py +44 -0
- tests/integration/projects/test_projects_datastores_integration.py +42 -0
- tests/integration/projects/test_projects_secrets_integration.py +1 -1
- tests/integration/projects/test_projects_services_integration.py +44 -0
- tests/integration/test_checkpoints_integration.py +1 -2
- tests/integration/test_models_integration.py +0 -1
- tests/unit/cli/projects/__init__.py +0 -0
- tests/unit/cli/projects/test_cli_project_credential_unit.py +26 -0
- tests/unit/cli/projects/test_cli_project_data_connector_unit.py +28 -0
- tests/unit/cli/projects/test_cli_project_datastore_unit.py +26 -0
- tests/unit/cli/projects/test_cli_project_key_unit.py +26 -0
- tests/unit/cli/projects/test_cli_project_secret_unit.py +26 -0
- tests/unit/cli/projects/test_cli_project_service_unit.py +26 -0
- tests/unit/cli/projects/test_cli_project_unit.py +19 -0
- tests/unit/cloudbender/test_datastores_unit.py +1 -5
- tests/unit/conftest.py +79 -6
- tests/unit/projects/test_project_credentials_unit.py +100 -0
- tests/unit/projects/test_projects_unit.py +1 -1
- tests/unit/test_checkpoints_unit.py +15 -23
- tests/unit/test_datasets_unit.py +15 -20
- tests/unit/test_models_unit.py +13 -16
- tests/unit/test_volumes_unit.py +3 -0
- trainml/__init__.py +1 -1
- trainml/checkpoints.py +14 -3
- trainml/cli/cloudbender/datastore.py +2 -7
- trainml/cli/job/create.py +16 -16
- trainml/cli/project/__init__.py +4 -73
- trainml/cli/project/credential.py +128 -0
- trainml/cli/project/data_connector.py +61 -0
- trainml/cli/project/datastore.py +61 -0
- trainml/cli/project/secret.py +12 -3
- trainml/cli/project/service.py +61 -0
- trainml/cloudbender/data_connectors.py +8 -0
- trainml/cloudbender/datastores.py +9 -19
- trainml/cloudbender/nodes.py +44 -1
- trainml/cloudbender/providers.py +53 -0
- trainml/cloudbender/regions.py +48 -0
- trainml/datasets.py +14 -3
- trainml/exceptions.py +51 -0
- trainml/jobs.py +2 -13
- trainml/models.py +14 -3
- trainml/projects/credentials.py +71 -0
- trainml/projects/projects.py +7 -4
- trainml/projects/secrets.py +1 -1
- trainml/volumes.py +15 -3
- {trainml-0.5.9.dist-info → trainml-0.5.12.dist-info}/METADATA +1 -1
- {trainml-0.5.9.dist-info → trainml-0.5.12.dist-info}/RECORD +53 -46
- tests/integration/test_projects_integration.py +0 -44
- tests/unit/cli/cloudbender/test_cli_reservation_unit.py +0 -34
- tests/unit/cli/test_cli_project_unit.py +0 -42
- tests/unit/cloudbender/test_reservations_unit.py +0 -173
- tests/unit/test_auth.py +0 -30
- tests/unit/test_projects_unit.py +0 -320
- tests/unit/test_trainml.py +0 -54
- trainml/cli/cloudbender/reservation.py +0 -159
- trainml/cli/project.py +0 -149
- trainml/cloudbender/reservations.py +0 -126
- trainml/projects.py +0 -228
- {trainml-0.5.9.dist-info → trainml-0.5.12.dist-info}/LICENSE +0 -0
- {trainml-0.5.9.dist-info → trainml-0.5.12.dist-info}/WHEEL +0 -0
- {trainml-0.5.9.dist-info → trainml-0.5.12.dist-info}/entry_points.txt +0 -0
- {trainml-0.5.9.dist-info → trainml-0.5.12.dist-info}/top_level.txt +0 -0
trainml/exceptions.py
CHANGED
|
@@ -147,3 +147,54 @@ class SpecificationError(TrainMLException):
|
|
|
147
147
|
|
|
148
148
|
def __str__(self):
|
|
149
149
|
return "SpecificationError({self.attribute}, {self.message})".format(self=self)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class NodeError(TrainMLException):
|
|
153
|
+
def __init__(self, status, data, *args):
|
|
154
|
+
super().__init__(data, *args)
|
|
155
|
+
self._status = status
|
|
156
|
+
self._message = data
|
|
157
|
+
|
|
158
|
+
@property
|
|
159
|
+
def status(self) -> str:
|
|
160
|
+
return self._status
|
|
161
|
+
|
|
162
|
+
def __repr__(self):
|
|
163
|
+
return "NodeError({self.status}, {self.message})".format(self=self)
|
|
164
|
+
|
|
165
|
+
def __str__(self):
|
|
166
|
+
return "NodeError({self.status}, {self.message})".format(self=self)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
class ProviderError(TrainMLException):
|
|
170
|
+
def __init__(self, status, data, *args):
|
|
171
|
+
super().__init__(data, *args)
|
|
172
|
+
self._status = status
|
|
173
|
+
self._message = data
|
|
174
|
+
|
|
175
|
+
@property
|
|
176
|
+
def status(self) -> str:
|
|
177
|
+
return self._status
|
|
178
|
+
|
|
179
|
+
def __repr__(self):
|
|
180
|
+
return "ProviderError({self.status}, {self.message})".format(self=self)
|
|
181
|
+
|
|
182
|
+
def __str__(self):
|
|
183
|
+
return "ProviderError({self.status}, {self.message})".format(self=self)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class RegionError(TrainMLException):
|
|
187
|
+
def __init__(self, status, data, *args):
|
|
188
|
+
super().__init__(data, *args)
|
|
189
|
+
self._status = status
|
|
190
|
+
self._message = data
|
|
191
|
+
|
|
192
|
+
@property
|
|
193
|
+
def status(self) -> str:
|
|
194
|
+
return self._status
|
|
195
|
+
|
|
196
|
+
def __repr__(self):
|
|
197
|
+
return "RegionError({self.status}, {self.message})".format(self=self)
|
|
198
|
+
|
|
199
|
+
def __str__(self):
|
|
200
|
+
return "RegionError({self.status}, {self.message})".format(self=self)
|
trainml/jobs.py
CHANGED
|
@@ -476,7 +476,6 @@ class Job:
|
|
|
476
476
|
return
|
|
477
477
|
valid_statuses = [
|
|
478
478
|
"waiting for data/model download",
|
|
479
|
-
"waiting for GPUs",
|
|
480
479
|
"waiting for resources",
|
|
481
480
|
"running",
|
|
482
481
|
"stopped",
|
|
@@ -488,11 +487,6 @@ class Job:
|
|
|
488
487
|
"status",
|
|
489
488
|
f"Invalid wait_for status {status}. Valid statuses are: {valid_statuses}",
|
|
490
489
|
)
|
|
491
|
-
if status == "waiting for GPUs":
|
|
492
|
-
warnings.warn(
|
|
493
|
-
"'waiting for GPUs' status is deprecated, use 'waiting for resources' instead.",
|
|
494
|
-
DeprecationWarning,
|
|
495
|
-
)
|
|
496
490
|
if (self.type == "training") and status == "stopped":
|
|
497
491
|
warnings.warn(
|
|
498
492
|
"'stopped' status is deprecated for training jobs, use 'finished' instead.",
|
|
@@ -523,12 +517,8 @@ class Job:
|
|
|
523
517
|
self.status == status
|
|
524
518
|
or (
|
|
525
519
|
status
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
"waiting for resources",
|
|
529
|
-
] ## this status could be very short and the polling could miss it
|
|
530
|
-
and self.status
|
|
531
|
-
not in ["new", "waiting for GPUs", "waiting for resources"]
|
|
520
|
+
== "waiting for resources" ## this status could be very short and the polling could miss it
|
|
521
|
+
and self.status not in ["new", "waiting for resources"]
|
|
532
522
|
)
|
|
533
523
|
or (
|
|
534
524
|
status
|
|
@@ -536,7 +526,6 @@ class Job:
|
|
|
536
526
|
and self.status
|
|
537
527
|
not in [
|
|
538
528
|
"new",
|
|
539
|
-
"waiting for GPUs",
|
|
540
529
|
"waiting for resources",
|
|
541
530
|
"waiting for data/model download",
|
|
542
531
|
]
|
trainml/models.py
CHANGED
|
@@ -26,13 +26,24 @@ class Models(object):
|
|
|
26
26
|
models = [Model(self.trainml, **model) for model in resp]
|
|
27
27
|
return models
|
|
28
28
|
|
|
29
|
-
async def create(
|
|
29
|
+
async def create(
|
|
30
|
+
self,
|
|
31
|
+
name,
|
|
32
|
+
source_type,
|
|
33
|
+
source_uri,
|
|
34
|
+
type="evefs",
|
|
35
|
+
project_uuid=None,
|
|
36
|
+
**kwargs,
|
|
37
|
+
):
|
|
38
|
+
if not project_uuid:
|
|
39
|
+
project_uuid = self.trainml.active_project
|
|
30
40
|
data = dict(
|
|
31
41
|
name=name,
|
|
32
42
|
source_type=source_type,
|
|
33
43
|
source_uri=source_uri,
|
|
34
|
-
|
|
35
|
-
|
|
44
|
+
project_uuid=project_uuid,
|
|
45
|
+
type=type,
|
|
46
|
+
**kwargs,
|
|
36
47
|
)
|
|
37
48
|
payload = {k: v for k, v in data.items() if v is not None}
|
|
38
49
|
logging.info(f"Creating Model {name}")
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from dateutil import parser, tz
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ProjectCredentials(object):
|
|
8
|
+
def __init__(self, trainml, project_id):
|
|
9
|
+
self.trainml = trainml
|
|
10
|
+
self.project_id = project_id
|
|
11
|
+
|
|
12
|
+
async def list(self, **kwargs):
|
|
13
|
+
resp = await self.trainml._query(
|
|
14
|
+
f"/project/{self.project_id}/credentials", "GET", kwargs
|
|
15
|
+
)
|
|
16
|
+
credentials = [ProjectCredential(self.trainml, **service) for service in resp]
|
|
17
|
+
return credentials
|
|
18
|
+
|
|
19
|
+
async def put(self, type, key_id, secret, tenant=None, **kwargs):
|
|
20
|
+
data = dict(key_id=key_id, secret=secret, tenant=tenant)
|
|
21
|
+
payload = {k: v for k, v in data.items() if v is not None}
|
|
22
|
+
logging.info(f"Creating Project Credential {type}")
|
|
23
|
+
resp = await self.trainml._query(
|
|
24
|
+
f"/project/{self.project_id}/credential/{type}", "PUT", None, payload
|
|
25
|
+
)
|
|
26
|
+
credential = ProjectCredential(self.trainml, **resp)
|
|
27
|
+
logging.info(f"Created Project Credential {type} in project {self.project_id}")
|
|
28
|
+
|
|
29
|
+
return credential
|
|
30
|
+
|
|
31
|
+
async def remove(self, type, **kwargs):
|
|
32
|
+
await self.trainml._query(
|
|
33
|
+
f"/project/{self.project_id}/credential/{type}", "DELETE", kwargs
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class ProjectCredential:
|
|
38
|
+
def __init__(self, trainml, **kwargs):
|
|
39
|
+
self.trainml = trainml
|
|
40
|
+
self._entity = kwargs
|
|
41
|
+
self._type = self._entity.get("type")
|
|
42
|
+
self._project_uuid = self._entity.get("project_uuid")
|
|
43
|
+
self._key_id = self._entity.get("key_id")
|
|
44
|
+
self._updated_at = self._entity.get("updatedAt")
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def type(self) -> str:
|
|
48
|
+
return self._type
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def project_uuid(self) -> str:
|
|
52
|
+
return self._project_uuid
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def key_id(self) -> str:
|
|
56
|
+
return self._key_id
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def updated_at(self) -> datetime:
|
|
60
|
+
timestamp = parser.isoparse(self._updated_at)
|
|
61
|
+
timezone = tz.tzlocal()
|
|
62
|
+
return timestamp.astimezone(timezone)
|
|
63
|
+
|
|
64
|
+
def __str__(self):
|
|
65
|
+
return json.dumps({k: v for k, v in self._entity.items()})
|
|
66
|
+
|
|
67
|
+
def __repr__(self):
|
|
68
|
+
return f"ProjectCredential( trainml , **{self._entity.__repr__()})"
|
|
69
|
+
|
|
70
|
+
def __bool__(self):
|
|
71
|
+
return bool(self._type)
|
trainml/projects/projects.py
CHANGED
|
@@ -3,7 +3,7 @@ import logging
|
|
|
3
3
|
from .datastores import ProjectDatastores
|
|
4
4
|
from .data_connectors import ProjectDataConnectors
|
|
5
5
|
from .services import ProjectServices
|
|
6
|
-
from .
|
|
6
|
+
from .credentials import ProjectCredentials
|
|
7
7
|
from .secrets import ProjectSecrets
|
|
8
8
|
|
|
9
9
|
|
|
@@ -26,8 +26,11 @@ class Projects(object):
|
|
|
26
26
|
projects = [Project(self.trainml, **project) for project in resp]
|
|
27
27
|
return projects
|
|
28
28
|
|
|
29
|
-
async def create(self, name,
|
|
30
|
-
data = dict(
|
|
29
|
+
async def create(self, name, copy_credentials=False, **kwargs):
|
|
30
|
+
data = dict(
|
|
31
|
+
name=name,
|
|
32
|
+
copy_credentials=copy_credentials,
|
|
33
|
+
)
|
|
31
34
|
payload = {k: v for k, v in data.items() if v is not None}
|
|
32
35
|
logging.info(f"Creating Project {name}")
|
|
33
36
|
resp = await self.trainml._query("/project", "POST", None, payload)
|
|
@@ -51,7 +54,7 @@ class Project:
|
|
|
51
54
|
self.datastores = ProjectDatastores(self.trainml, self._id)
|
|
52
55
|
self.data_connectors = ProjectDataConnectors(self.trainml, self._id)
|
|
53
56
|
self.services = ProjectServices(self.trainml, self._id)
|
|
54
|
-
self.
|
|
57
|
+
self.credentials = ProjectCredentials(self.trainml, self._id)
|
|
55
58
|
self.secrets = ProjectSecrets(self.trainml, self._id)
|
|
56
59
|
|
|
57
60
|
@property
|
trainml/projects/secrets.py
CHANGED
|
@@ -24,7 +24,7 @@ class ProjectSecrets(object):
|
|
|
24
24
|
f"/project/{self.project_id}/secret/{name}", "PUT", None, payload
|
|
25
25
|
)
|
|
26
26
|
secret = ProjectSecret(self.trainml, **resp)
|
|
27
|
-
logging.info(f"Created Project
|
|
27
|
+
logging.info(f"Created Project Secret {name} in project {self.project_id}")
|
|
28
28
|
return secret
|
|
29
29
|
|
|
30
30
|
async def remove(self, name, **kwargs):
|
trainml/volumes.py
CHANGED
|
@@ -26,14 +26,26 @@ class Volumes(object):
|
|
|
26
26
|
volumes = [Volume(self.trainml, **volume) for volume in resp]
|
|
27
27
|
return volumes
|
|
28
28
|
|
|
29
|
-
async def create(
|
|
29
|
+
async def create(
|
|
30
|
+
self,
|
|
31
|
+
name,
|
|
32
|
+
source_type,
|
|
33
|
+
source_uri,
|
|
34
|
+
capacity,
|
|
35
|
+
type="evefs",
|
|
36
|
+
project_uuid=None,
|
|
37
|
+
**kwargs,
|
|
38
|
+
):
|
|
39
|
+
if not project_uuid:
|
|
40
|
+
project_uuid = self.trainml.active_project
|
|
30
41
|
data = dict(
|
|
31
42
|
name=name,
|
|
32
43
|
source_type=source_type,
|
|
33
44
|
source_uri=source_uri,
|
|
34
45
|
capacity=capacity,
|
|
35
|
-
|
|
36
|
-
|
|
46
|
+
project_uuid=project_uuid,
|
|
47
|
+
type=type,
|
|
48
|
+
**kwargs,
|
|
37
49
|
)
|
|
38
50
|
payload = {k: v for k, v in data.items() if v is not None}
|
|
39
51
|
logging.info(f"Creating Volume {name}")
|
|
@@ -4,37 +4,37 @@ examples/local_storage.py,sha256=w8iAeqr5CLOCOkNrqGzEDtybjDGGY7SQUqeE0ibMUrM,174
|
|
|
4
4
|
examples/training_inference_pipeline.py,sha256=SNr4RFT9y69F9G9tMD8ONUbJmXRFrq1yxynq-FbfEf8,2334
|
|
5
5
|
tests/integration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
tests/integration/conftest.py,sha256=VWWTfofsFcBOdSCXQxNYbMcDEEaErDi2wFFMn--LE4Y,1134
|
|
7
|
-
tests/integration/test_checkpoints_integration.py,sha256=
|
|
7
|
+
tests/integration/test_checkpoints_integration.py,sha256=Giy5Z6WyselfXzskDGR7Z0ks2KK2U7WGQBDPfyqQ6dk,3206
|
|
8
8
|
tests/integration/test_datasets_integration.py,sha256=zdHOevduuMUWvVxaHBslpmH8AdvPdqEJ95MdqCC5_rw,3499
|
|
9
9
|
tests/integration/test_environments_integration.py,sha256=0IckhJvQhd8j4Ouiu0hMq2b7iA1dbZpZYmknyfWjsFM,1403
|
|
10
10
|
tests/integration/test_gpu_types_integration.py,sha256=V2OncokZWWVq_l5FSmKEDM4EsWrmpB-zKiVPt-we0aY,1256
|
|
11
11
|
tests/integration/test_jobs_integration.py,sha256=N2peEQGYHteGMd0J7NK4gJaaTyps5jjuiKq2ENnD8SY,25117
|
|
12
|
-
tests/integration/test_models_integration.py,sha256=
|
|
13
|
-
tests/integration/test_projects_integration.py,sha256=BX-LqLfzawTQUhtx--5dw7QqR8kl_CJvwSCyNXDUQTw,1446
|
|
12
|
+
tests/integration/test_models_integration.py,sha256=u6KVnX-F00TqwiU-gEoZJP1oKfAblqnyRptOc9vNGJ4,2878
|
|
14
13
|
tests/integration/test_volumes_integration.py,sha256=gOmZpwwFxqeOAVmfKWSTmuyshx8nb2zu_0xv1RUEepM,3270
|
|
15
14
|
tests/integration/cloudbender/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
15
|
tests/integration/cloudbender/test_providers_integration.py,sha256=oV8ydFsosDZ_Z1Dkg2IN-ZhWuIl5e_HkHAORMsOsAJc,1473
|
|
17
16
|
tests/integration/projects/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
-
tests/integration/projects/conftest.py,sha256=
|
|
17
|
+
tests/integration/projects/conftest.py,sha256=sNN1Svq2IO63Yx3DC7-5ZnksaEifGpDZU-3ti9sZhIU,249
|
|
18
|
+
tests/integration/projects/test_projects_credentials_integration.py,sha256=3PnpxNEsedXmyyhqjSb8T4JzupB1Kmwu--3stNTBlN8,1636
|
|
19
|
+
tests/integration/projects/test_projects_data_connectors_integration.py,sha256=R90v7HVN4i9k-AOEl17AvnbWIwnD9Fl1OK9IGOV847o,1630
|
|
20
|
+
tests/integration/projects/test_projects_datastores_integration.py,sha256=S9aSvryVjrcoEDezr33x4T5aPjEhUwL9O1-1eyzhQ-s,1469
|
|
19
21
|
tests/integration/projects/test_projects_integration.py,sha256=HP4jPAyTqGt7pwk42bxQsqGp0olgai6sI-S1XXcXoJs,1241
|
|
20
22
|
tests/integration/projects/test_projects_keys_integration.py,sha256=O-a9OwBxIM2l0vi__GMlWP8ncNswxGBJvEhgo8PoalQ,1423
|
|
21
|
-
tests/integration/projects/test_projects_secrets_integration.py,sha256=
|
|
23
|
+
tests/integration/projects/test_projects_secrets_integration.py,sha256=bagLLfSUP805gOOPbn_xCQyifflNzIs8DGUBeUwOhO0,1481
|
|
24
|
+
tests/integration/projects/test_projects_services_integration.py,sha256=lBnrqFpjsL3zfaJJmFh2rCWfNmmX-TjyOPCR3KobDAc,1530
|
|
22
25
|
tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
|
-
tests/unit/conftest.py,sha256=
|
|
24
|
-
tests/unit/test_auth.py,sha256=nfhlOCR7rUsn_MaD8QQtBc2v0k8pIxqbzGgRAZK1WGc,858
|
|
26
|
+
tests/unit/conftest.py,sha256=hLfECgT0w4pVZABrpK4UUUeaX1aDzQvj8-erWTGBjHA,35588
|
|
25
27
|
tests/unit/test_auth_unit.py,sha256=nfhlOCR7rUsn_MaD8QQtBc2v0k8pIxqbzGgRAZK1WGc,858
|
|
26
|
-
tests/unit/test_checkpoints_unit.py,sha256=
|
|
28
|
+
tests/unit/test_checkpoints_unit.py,sha256=7bgpEnjkfETgbEHmYApyD_htEWAUVZdposyYVClU3tQ,15965
|
|
27
29
|
tests/unit/test_connections_unit.py,sha256=FzN2ddQxNpjxzNGUsXhjTk0HnD24wSPelPTL4o_r-Ho,5507
|
|
28
|
-
tests/unit/test_datasets_unit.py,sha256=
|
|
30
|
+
tests/unit/test_datasets_unit.py,sha256=YL_wU-NiXvPFOK_jM8l9q5cZGztsMkgQorggYaLt6Lc,15910
|
|
29
31
|
tests/unit/test_environments_unit.py,sha256=1QFGf1xwM0yKCyVHT_Xi0DX8g0Aelr0mcqAImEXJfQU,1882
|
|
30
32
|
tests/unit/test_exceptions.py,sha256=3tAok6kAU1QRjN7qTNVYuSGWDg7IEoK__OXFLyzLr7k,906
|
|
31
33
|
tests/unit/test_gpu_types_unit.py,sha256=c9ie6YSYT5onBnlmHvHWON9WgQiJ1eO2C-4Tk-UPQHg,2054
|
|
32
34
|
tests/unit/test_jobs_unit.py,sha256=bZxN9HUfHCyQCjZCZGn6WFIhu8S5FU1z5ZG9sgH2XEg,26835
|
|
33
|
-
tests/unit/test_models_unit.py,sha256=
|
|
34
|
-
tests/unit/test_projects_unit.py,sha256=uqMs3v4mNevUSh5QgP54_R88ctqOXdD73t0AgjTWXbg,10743
|
|
35
|
-
tests/unit/test_trainml.py,sha256=8vAKvFD1xYsx_VY4HFVa0b1MUlMoNApY6TO8r7vI-UQ,1701
|
|
35
|
+
tests/unit/test_models_unit.py,sha256=Wg2QsoKqtSFSVf-1tt4sA6OcwMTkSHYPcUBQQOmZCgY,15091
|
|
36
36
|
tests/unit/test_trainml_unit.py,sha256=8vAKvFD1xYsx_VY4HFVa0b1MUlMoNApY6TO8r7vI-UQ,1701
|
|
37
|
-
tests/unit/test_volumes_unit.py,sha256=
|
|
37
|
+
tests/unit/test_volumes_unit.py,sha256=DF3kFtkIfuZjwacBRpdmMGlPvV7vxaxUAhlstWj2V4w,15382
|
|
38
38
|
tests/unit/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
39
|
tests/unit/cli/conftest.py,sha256=w6p_2URicywJKUCtY79tSD_mx8cwJtxHbK_Lu3grOYs,236
|
|
40
40
|
tests/unit/cli/test_cli_checkpoint_unit.py,sha256=6gO6PWWxNJiL520mhTFkSUJT7p5-dptLwUgDjPeHNrA,702
|
|
@@ -43,7 +43,6 @@ tests/unit/cli/test_cli_environment_unit.py,sha256=7FFKFPVa6yqJqujTXD_tsSUDruW5K
|
|
|
43
43
|
tests/unit/cli/test_cli_gpu_unit.py,sha256=FIq3tQIDmeD-pvxkhJKMykfnlWcVxho2vRkoCMXgQxE,650
|
|
44
44
|
tests/unit/cli/test_cli_job_unit.py,sha256=xUqkLFDIyI1ExiVVgr-218gQSlFSYCm4RRX_eyipJhY,611
|
|
45
45
|
tests/unit/cli/test_cli_model_unit.py,sha256=fE-CRVg8gbtDlwrKBkf-hc9x7EhFlYeE3jlum1E27EA,629
|
|
46
|
-
tests/unit/cli/test_cli_project_unit.py,sha256=pi0N-XVH5wsJQ6idFcRsIofWSAdj8KtK1gwf1J3l2JY,1688
|
|
47
46
|
tests/unit/cli/test_cli_volume_unit.py,sha256=oggGL2eLiaExP6rSdFmQevxLp6nw5o7SKUEqMKBmy_A,644
|
|
48
47
|
tests/unit/cli/cloudbender/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
49
48
|
tests/unit/cli/cloudbender/test_cli_datastore_unit.py,sha256=DQWDjqg4viBZRONi00nVzqF9rJ5qKOKRub9pKbTmMWU,1381
|
|
@@ -51,39 +50,45 @@ tests/unit/cli/cloudbender/test_cli_device_unit.py,sha256=2BSMyXQ8fOzNKh_-pa_tx7
|
|
|
51
50
|
tests/unit/cli/cloudbender/test_cli_node_unit.py,sha256=KbK7axJ1L4y4sN7KQRpOVIqphnNpi0aFW4-HlYLtwnI,1316
|
|
52
51
|
tests/unit/cli/cloudbender/test_cli_provider_unit.py,sha256=Rm-tRNPbTTB7ZzkkIpLfDp_pEYfqihjB0ZYk_EPQUfs,781
|
|
53
52
|
tests/unit/cli/cloudbender/test_cli_region_unit.py,sha256=iH5AbrzZ-R2EJ-Bd2HFN7FN2lTpkr3-pCLR59ZVvdQU,1262
|
|
54
|
-
tests/unit/cli/cloudbender/test_cli_reservation_unit.py,sha256=4LDOJDXygMuho2cdI2K59eq4oyiry9hNaG0avEr0_tw,1311
|
|
55
53
|
tests/unit/cli/cloudbender/test_cli_service_unit.py,sha256=4LDOJDXygMuho2cdI2K59eq4oyiry9hNaG0avEr0_tw,1311
|
|
54
|
+
tests/unit/cli/projects/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
55
|
+
tests/unit/cli/projects/test_cli_project_credential_unit.py,sha256=gnmEpNbpEG5S9cYQUjSGty2e8mqeC_cCKmIUAJCgRXg,943
|
|
56
|
+
tests/unit/cli/projects/test_cli_project_data_connector_unit.py,sha256=_NgnxV8zTIycpHKe7dyL6EXq774puFHQjvgCKsiEMO0,993
|
|
57
|
+
tests/unit/cli/projects/test_cli_project_datastore_unit.py,sha256=E_kLoIZ5U92LQaPcYAKDyUqpjM1Xe6PVPvofU1Yn6Yk,936
|
|
58
|
+
tests/unit/cli/projects/test_cli_project_key_unit.py,sha256=Ma5HjsZt2RaHKgmMdGY59EIc2WdAgbWKWn2LvlYeDqQ,894
|
|
59
|
+
tests/unit/cli/projects/test_cli_project_secret_unit.py,sha256=QBkq1gVqkjGUni2xCihL994bvseNcA-dyUWaJVU9GjI,915
|
|
60
|
+
tests/unit/cli/projects/test_cli_project_service_unit.py,sha256=TRNOwK3RUCtktYdCGzfhQE3fE_mn8LweCN5E4gRn1h4,922
|
|
61
|
+
tests/unit/cli/projects/test_cli_project_unit.py,sha256=0IynsMwFsXBZn-u0gX2iir7AjPsNraHe68PuAe-Lkaw,627
|
|
56
62
|
tests/unit/cloudbender/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
57
63
|
tests/unit/cloudbender/test_data_connectors_unit.py,sha256=qy97mNAcy_xEkh8obBobHt16B3e1N3QcBSyfV9xJwPI,5783
|
|
58
|
-
tests/unit/cloudbender/test_datastores_unit.py,sha256=
|
|
64
|
+
tests/unit/cloudbender/test_datastores_unit.py,sha256=5XUczUrOQ2Zgfb2IbJeEtYxbBWRltEVJ1KIC_UeQjEY,5281
|
|
59
65
|
tests/unit/cloudbender/test_device_configs_unit.py,sha256=lzyCuF7MRoQrtJVTQFL27lqPnRwQFv25htPgJqDuQI8,5714
|
|
60
66
|
tests/unit/cloudbender/test_devices_unit.py,sha256=QBWnlOe1tw_XNA_i-yDHkmpGvtK36f2u1HhoXquoVaE,9103
|
|
61
67
|
tests/unit/cloudbender/test_nodes_unit.py,sha256=BDpfJXCBNNpLt5rhJMk2BVXDQ_4QSmxoVrO_YPs6xBU,6231
|
|
62
68
|
tests/unit/cloudbender/test_providers_unit.py,sha256=OgxifgC1IqLH8DNMKXy1Ne9_7a75ea6kHEOfRSRoQuQ,4373
|
|
63
69
|
tests/unit/cloudbender/test_regions_unit.py,sha256=BbJICLIQmlotpA1UmLD0KTW_H9g2UW0J8ZYzQk1_Xjc,6299
|
|
64
|
-
tests/unit/cloudbender/test_reservations_unit.py,sha256=nWEZ_p9EF2C49nbgL7Dt4NG2Irmyt94ZqJJQDyNfGFI,5624
|
|
65
70
|
tests/unit/cloudbender/test_services_unit.py,sha256=fYJx-W89HD-EYkO32_v33X40VxipUfWQCy13FZO2fcA,5220
|
|
66
71
|
tests/unit/projects/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
72
|
+
tests/unit/projects/test_project_credentials_unit.py,sha256=ObTaJ7_g0MP5N-0qHWdeYips0in1j_4UkOhXXI2FFwo,3480
|
|
67
73
|
tests/unit/projects/test_project_data_connectors_unit.py,sha256=uQPFx6rwYMWZz1IJkns_LdM5gccyHSIaKb3k8zmfSkY,3385
|
|
68
74
|
tests/unit/projects/test_project_datastores_unit.py,sha256=kcoaSs54gGqJ9gwPMpP6KHAPRvDJtdJpm49s4aYYt3E,3129
|
|
69
75
|
tests/unit/projects/test_project_keys_unit.py,sha256=2-w_VwmWxWHoLWBCoBAfg5WozyeYJHV361ZndlA0xk4,3161
|
|
70
76
|
tests/unit/projects/test_project_secrets_unit.py,sha256=StVlY-ZR3CKxXAt9NL8hTkXUEdgGESH0m6foEPXKE-4,3276
|
|
71
77
|
tests/unit/projects/test_project_services_unit.py,sha256=ZK5nz78RAmmaCrAwYBd34t87dh6etU-7snLB_xukZHM,3331
|
|
72
|
-
tests/unit/projects/test_projects_unit.py,sha256=
|
|
73
|
-
trainml/__init__.py,sha256=
|
|
78
|
+
tests/unit/projects/test_projects_unit.py,sha256=8rJ40bJ7YszEsoL6D02Muey-sgRjqFmMoR-R3IiP_Ig,3810
|
|
79
|
+
trainml/__init__.py,sha256=d6QltDwIOAM07aLFV02nUTwJs2OHntDpB_2JTwimxPM,433
|
|
74
80
|
trainml/__main__.py,sha256=JgErYkiskih8Y6oRwowALtR-rwQhAAdqOYWjQraRIPI,59
|
|
75
81
|
trainml/auth.py,sha256=gruZv27nhttrCbhcVQTH9kZkF2uMm1E06SwA_2pQAHQ,26565
|
|
76
|
-
trainml/checkpoints.py,sha256=
|
|
82
|
+
trainml/checkpoints.py,sha256=Hg3_Si7ohzsv4_8JIjoj9pMRpHNZRWKC5R2gtgmp01s,8790
|
|
77
83
|
trainml/connections.py,sha256=h-S1NZbOkaXpIlpRStA6q-3eXc_OMlFWOLzF8R9SVG8,20029
|
|
78
|
-
trainml/datasets.py,sha256=
|
|
84
|
+
trainml/datasets.py,sha256=dxTZbK-cnr8eoq48KAx2TZNK1ndcFveTVBtaNK2QyJ0,8600
|
|
79
85
|
trainml/environments.py,sha256=OH4o08zXZ7IJ2CiA1rPnys2Fl45r8qvQHfM2mCBRAIc,1507
|
|
80
|
-
trainml/exceptions.py,sha256=
|
|
86
|
+
trainml/exceptions.py,sha256=Qdof2fKRvbMiwarX1VSw1XJXXJjY71H4U3v05nE7-7g,5468
|
|
81
87
|
trainml/gpu_types.py,sha256=mm-dwfYc02192bmYPIJmzesndyBcoOdkKYBaYZXOUwU,1901
|
|
82
|
-
trainml/jobs.py,sha256=
|
|
83
|
-
trainml/models.py,sha256=
|
|
84
|
-
trainml/projects.py,sha256=ZVsVJtUPTYsQAkCLimjYF3DAwFwQV4ucLila-N-jSJo,6585
|
|
88
|
+
trainml/jobs.py,sha256=5wHiEmHfri1btgIn6zbFp9kIO6EU5FCOVkNMP0-WuYM,17632
|
|
89
|
+
trainml/models.py,sha256=SpVNt9oZMu70m_3VjO9j_QYexw_z-yRqMhIuJXPs4Vg,8284
|
|
85
90
|
trainml/trainml.py,sha256=EBnqQ3Q291xrPKYuN6xKm5yt0mJQOJ3b7GAlR-fl8NI,10864
|
|
86
|
-
trainml/volumes.py,sha256=
|
|
91
|
+
trainml/volumes.py,sha256=7T0ZN_Xq3qk4yzw7YYxC0rxH3KqlqADd6HOZCkAfCR4,8443
|
|
87
92
|
trainml/cli/__init__.py,sha256=Gvj6oGSEtgpb40ACtiVeMD93GM-uy15MG6VlX6rwdwA,4346
|
|
88
93
|
trainml/cli/checkpoint.py,sha256=8Rh4bmFwJ4DKlIjHK-FLTeRynABqKCgIUGRtbQhAsX4,7170
|
|
89
94
|
trainml/cli/connection.py,sha256=ELV6bPL30dzttFNxDU7Fb74R8oPL_E70k7TcJEzbwtQ,1700
|
|
@@ -91,43 +96,45 @@ trainml/cli/dataset.py,sha256=Pc00M6t7hGoRzCxznmmkijsWhG4PhIfG7UkrwtwykTY,6871
|
|
|
91
96
|
trainml/cli/environment.py,sha256=dfm_T8OlCM5M8dLyOQBapJl3eFuVIku2P4JO6V0cYVQ,1019
|
|
92
97
|
trainml/cli/gpu.py,sha256=CMcQyl2qbUgc2bc-gvUVT6X7bq2-sgiCHl3hyZ6kFWM,883
|
|
93
98
|
trainml/cli/model.py,sha256=hR23E6ttRXcLk-RofkPK6wUXMO7OU6sT6jTEHTmUg9Q,6111
|
|
94
|
-
trainml/cli/project.py,sha256=f772bHs68AVRY60l7dbVKgeDmDC3u2bZjqrz7zm7xvQ,3314
|
|
95
99
|
trainml/cli/volume.py,sha256=kDUss93N78DT-YlLjC6I3jEq5nBWfRNNR5M4tY_F_Zg,6246
|
|
96
100
|
trainml/cli/cloudbender/__init__.py,sha256=tKkL8TzD9nEeRtf1OEYM4XZJWb0-rGMPTmLIdA5G_SY,592
|
|
97
101
|
trainml/cli/cloudbender/data_connector.py,sha256=q0Hqeh5w00Zkmh61fzO3pNR6EmQfoLQ2DbgJ5ZBx1UM,3606
|
|
98
|
-
trainml/cli/cloudbender/datastore.py,sha256=
|
|
102
|
+
trainml/cli/cloudbender/datastore.py,sha256=j67VUoYZOFWP0F7WK8V7fft8HlT4uqauAu0WH-9Dkes,3323
|
|
99
103
|
trainml/cli/cloudbender/device.py,sha256=KGZCFwwvS4tWsWuudrhlvquu_IFtV7LCUAOmCajicic,3453
|
|
100
104
|
trainml/cli/cloudbender/node.py,sha256=iN_WaPCxOhtgDtnSsIFAEMGADG4MKiLjWoez6YSYwZI,3843
|
|
101
105
|
trainml/cli/cloudbender/provider.py,sha256=oFjZWKfFQjNY7OtDu7nUdfv-RTmQc_Huuug963D3BdA,1726
|
|
102
106
|
trainml/cli/cloudbender/region.py,sha256=X6-FYOb-pGpOEazn-NbsYSwa9ergB7FGATFkTe4a8Pk,2892
|
|
103
|
-
trainml/cli/cloudbender/reservation.py,sha256=z2oMYwp-w_Keo1DepKUtuRnwiGz2VscVHDYWEFap1gs,3569
|
|
104
107
|
trainml/cli/cloudbender/service.py,sha256=Wh6ycEuECiKL7qpFhc4IyO1rR5lvLtIHk3S475_R6pk,3147
|
|
105
108
|
trainml/cli/job/__init__.py,sha256=ljY-ELeXhXQ7txASbJEKGBom7OXfNyy7sWILz3nxRAE,6545
|
|
106
|
-
trainml/cli/job/create.py,sha256=
|
|
107
|
-
trainml/cli/project/__init__.py,sha256=
|
|
109
|
+
trainml/cli/job/create.py,sha256=1YGHgl0bN0LC7EtMStukHT6RvnBheaaOnkqoKsAxuco,34380
|
|
110
|
+
trainml/cli/project/__init__.py,sha256=HDcJUbKMHhz4Thrvpst5hnywFqzsv0XWmvfKNRi8zuo,1918
|
|
111
|
+
trainml/cli/project/credential.py,sha256=gByXKiYf5sJeNRtuXWcercWv8P2IzO5TjT8Ypp4mCR8,3443
|
|
112
|
+
trainml/cli/project/data_connector.py,sha256=KLDhpNJfwcJkcmyuJRgcVH70Jf73619O9ddYP8vhMvk,1411
|
|
113
|
+
trainml/cli/project/datastore.py,sha256=IwF0LqsSFn7DrKPRdxQs6kturk9MCI52A1aoWeb7ClA,1336
|
|
108
114
|
trainml/cli/project/key.py,sha256=kQlCs_N-5c27hOyGkmT22_J47x8U6CZaSardsaPYGbw,3203
|
|
109
|
-
trainml/cli/project/secret.py,sha256=
|
|
115
|
+
trainml/cli/project/secret.py,sha256=tHt7bYDt0MNkLTTePTIJFUh9Mn9ogebPcaSCiNRJFNQ,1927
|
|
116
|
+
trainml/cli/project/service.py,sha256=FzcyGI9MN-UvnjdKW7GmXLTXLUIXtuTFAISR_FmCmJo,1310
|
|
110
117
|
trainml/cloudbender/__init__.py,sha256=iE29obtC0_9f0IhRvHQcG5aY58fVhVYipTakpjAhdss,64
|
|
111
118
|
trainml/cloudbender/cloudbender.py,sha256=ekJZHSQ1F4HF8y0sAJ3MDB_hiC8QxPv9-O7U24z_RR4,717
|
|
112
|
-
trainml/cloudbender/data_connectors.py,sha256=
|
|
113
|
-
trainml/cloudbender/datastores.py,sha256=
|
|
119
|
+
trainml/cloudbender/data_connectors.py,sha256=e0KAkKtcOcxW-UFHHUdF6deAYtP1SFv2PH9VyvizHek,3420
|
|
120
|
+
trainml/cloudbender/datastores.py,sha256=HGD0SLd0KYxkwl_r9NpnkcfKmQJ0q86BaxWwwyQT9W0,3255
|
|
114
121
|
trainml/cloudbender/device_configs.py,sha256=DJWiGFaOE4C4xLE1BLDAiEjeL4T00R3FA_pb1xnSOr4,3399
|
|
115
122
|
trainml/cloudbender/devices.py,sha256=QORNmKdLJoqGZmeWXRnivC1JmNBIw-ebvf4bsoem3r8,5660
|
|
116
|
-
trainml/cloudbender/nodes.py,sha256=
|
|
117
|
-
trainml/cloudbender/providers.py,sha256
|
|
118
|
-
trainml/cloudbender/regions.py,sha256=
|
|
119
|
-
trainml/cloudbender/reservations.py,sha256=rOrGXWIUHON4ad2aufEcvK4Yv_Mv3dDoScUtLJE8LWw,3586
|
|
123
|
+
trainml/cloudbender/nodes.py,sha256=U2sTIL2fuBVsNFPsJrvB2JbBcuLULF1-AwJ4dp5ChmM,5924
|
|
124
|
+
trainml/cloudbender/providers.py,sha256=22ymUl1KLC8UlyoWMsIrOKhUDOwnhklhHQ3EZ_V6eWA,3738
|
|
125
|
+
trainml/cloudbender/regions.py,sha256=nfSY9fIWp_AaRE_1Y0qwXX6WVSyPKxpji-zUfM3BNUo,5157
|
|
120
126
|
trainml/cloudbender/services.py,sha256=KC3VcyljvnazUUG-Tzwm6Ab6d0--yuccXjOaMgYB5uA,5126
|
|
121
127
|
trainml/projects/__init__.py,sha256=6NKCcHtQMeGB1IyU-djANphfnDX6MEkrXUM5Fyq9fWg,75
|
|
128
|
+
trainml/projects/credentials.py,sha256=6WqHy_-SZZwqE4rULLF8gSyeRVmfsUxqZBuCjBXyxKw,2255
|
|
122
129
|
trainml/projects/data_connectors.py,sha256=Y8lJNF9K5JZlwfKTtN9gh7eSRAivgiPWe_lx05pGM2U,1662
|
|
123
130
|
trainml/projects/datastores.py,sha256=oyRffW8L7Z1tdqspl58Zf1ces0p-Stk0EbnMRaenkUw,1560
|
|
124
131
|
trainml/projects/keys.py,sha256=qcQAdysTbfVW19tzzxZDvBBWjU9DG0dkViLmG_S0SyM,2157
|
|
125
|
-
trainml/projects/projects.py,sha256=
|
|
126
|
-
trainml/projects/secrets.py,sha256=
|
|
132
|
+
trainml/projects/projects.py,sha256=0ZghShqjbs5swfn3BsLrMW2NzrdBXpf_M-nyzwYPjpM,2792
|
|
133
|
+
trainml/projects/secrets.py,sha256=TIvBd3rAvd4lF3pm5qR98UslHjldzlnzn_n9yvpmLgg,2160
|
|
127
134
|
trainml/projects/services.py,sha256=ZP-6CDXktIe6p89Hshgs91HLWXQPNWeU7VFtoKUPHXo,1679
|
|
128
|
-
trainml-0.5.
|
|
129
|
-
trainml-0.5.
|
|
130
|
-
trainml-0.5.
|
|
131
|
-
trainml-0.5.
|
|
132
|
-
trainml-0.5.
|
|
133
|
-
trainml-0.5.
|
|
135
|
+
trainml-0.5.12.dist-info/LICENSE,sha256=s0lpBxhSSUEpMavwde-Vb6K_K7xDCTTvSpNznVqVGR0,1069
|
|
136
|
+
trainml-0.5.12.dist-info/METADATA,sha256=mSnptclEuyJVSgkesMzkAYxYITGsfkzwZXM-PkyYzPk,7346
|
|
137
|
+
trainml-0.5.12.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
|
|
138
|
+
trainml-0.5.12.dist-info/entry_points.txt,sha256=OzBDm2wXby1bSGF02jTVxzRFZLejnbFiLHXhKdW3Bds,63
|
|
139
|
+
trainml-0.5.12.dist-info/top_level.txt,sha256=Y1kLFRWKUW7RG8BX7cvejHF_yW8wBOaRYF1JQHENY4w,23
|
|
140
|
+
trainml-0.5.12.dist-info/RECORD,,
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import re
|
|
2
|
-
import sys
|
|
3
|
-
import asyncio
|
|
4
|
-
from pytest import mark, fixture
|
|
5
|
-
|
|
6
|
-
pytestmark = [mark.sdk, mark.integration, mark.projects]
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
@mark.create
|
|
10
|
-
@mark.asyncio
|
|
11
|
-
class GetProjectsTests:
|
|
12
|
-
@fixture(scope="class")
|
|
13
|
-
async def project(self, trainml):
|
|
14
|
-
project = await trainml.projects.create(name="New Project", copy_keys=False)
|
|
15
|
-
yield project
|
|
16
|
-
await project.remove()
|
|
17
|
-
|
|
18
|
-
async def test_get_projects(self, trainml):
|
|
19
|
-
projects = await trainml.projects.list()
|
|
20
|
-
assert len(projects) > 0
|
|
21
|
-
|
|
22
|
-
async def test_get_project(self, trainml, project):
|
|
23
|
-
response = await trainml.projects.get(project.id)
|
|
24
|
-
assert response.id == project.id
|
|
25
|
-
|
|
26
|
-
async def test_project_properties(self, project):
|
|
27
|
-
assert isinstance(project.id, str)
|
|
28
|
-
assert isinstance(project.name, str)
|
|
29
|
-
assert isinstance(project.owner_name, str)
|
|
30
|
-
assert isinstance(project.is_owner, bool)
|
|
31
|
-
assert project.name == "New Project"
|
|
32
|
-
assert project.is_owner
|
|
33
|
-
|
|
34
|
-
async def test_project_str(self, project):
|
|
35
|
-
string = str(project)
|
|
36
|
-
regex = r"^{.*\"id\": \"" + project.id + r"\".*}$"
|
|
37
|
-
assert isinstance(string, str)
|
|
38
|
-
assert re.match(regex, string)
|
|
39
|
-
|
|
40
|
-
async def test_project_repr(self, project):
|
|
41
|
-
string = repr(project)
|
|
42
|
-
regex = r"^Project\( trainml , \*\*{.*'id': '" + project.id + r"'.*}\)$"
|
|
43
|
-
assert isinstance(string, str)
|
|
44
|
-
assert re.match(regex, string)
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import re
|
|
2
|
-
import json
|
|
3
|
-
import click
|
|
4
|
-
from unittest.mock import AsyncMock, patch
|
|
5
|
-
from pytest import mark, fixture, raises
|
|
6
|
-
|
|
7
|
-
pytestmark = [mark.cli, mark.unit, mark.cloudbender, mark.services]
|
|
8
|
-
|
|
9
|
-
from trainml.cli.cloudbender import service as specimen
|
|
10
|
-
from trainml.cloudbender.services import Service
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def test_list(runner, mock_services):
|
|
14
|
-
with patch("trainml.cli.TrainML", new=AsyncMock) as mock_trainml:
|
|
15
|
-
mock_trainml.cloudbender = AsyncMock()
|
|
16
|
-
mock_trainml.cloudbender.services = AsyncMock()
|
|
17
|
-
mock_trainml.cloudbender.services.list = AsyncMock(return_value=mock_services)
|
|
18
|
-
result = runner.invoke(
|
|
19
|
-
specimen,
|
|
20
|
-
args=["list", "--provider=prov-id-1", "--region=reg-id-1"],
|
|
21
|
-
)
|
|
22
|
-
assert result.exit_code == 0
|
|
23
|
-
mock_trainml.cloudbender.services.list.assert_called_once_with(
|
|
24
|
-
provider_uuid="prov-id-1", region_uuid="reg-id-1"
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def test_list_no_provider(runner, mock_services):
|
|
29
|
-
with patch("trainml.cli.TrainML", new=AsyncMock) as mock_trainml:
|
|
30
|
-
mock_trainml.cloudbender = AsyncMock()
|
|
31
|
-
mock_trainml.cloudbender.services = AsyncMock()
|
|
32
|
-
mock_trainml.cloudbender.services.list = AsyncMock(return_value=mock_services)
|
|
33
|
-
result = runner.invoke(specimen, ["list"])
|
|
34
|
-
assert result.exit_code != 0
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import re
|
|
2
|
-
import json
|
|
3
|
-
import click
|
|
4
|
-
from unittest.mock import AsyncMock, patch, create_autospec
|
|
5
|
-
from pytest import mark, fixture, raises
|
|
6
|
-
|
|
7
|
-
pytestmark = [mark.cli, mark.unit, mark.projects]
|
|
8
|
-
|
|
9
|
-
from trainml.cli import project as specimen
|
|
10
|
-
from trainml.projects import Project
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def test_list(runner, mock_projects):
|
|
14
|
-
with patch("trainml.cli.TrainML", new=AsyncMock) as mock_trainml:
|
|
15
|
-
mock_trainml.projects = AsyncMock()
|
|
16
|
-
mock_trainml.projects.list = AsyncMock(return_value=mock_projects)
|
|
17
|
-
result = runner.invoke(specimen, ["list"])
|
|
18
|
-
print(result)
|
|
19
|
-
assert result.exit_code == 0
|
|
20
|
-
mock_trainml.projects.list.assert_called_once()
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def test_list_datastores(runner, mock_project_datastores):
|
|
24
|
-
with patch("trainml.cli.TrainML", new=AsyncMock) as mock_trainml:
|
|
25
|
-
mock_project = create_autospec(Project)
|
|
26
|
-
mock_project.list_datastores = AsyncMock(return_value=mock_project_datastores)
|
|
27
|
-
mock_trainml.projects.get = AsyncMock(return_value=mock_project)
|
|
28
|
-
result = runner.invoke(specimen, ["list-datastores"])
|
|
29
|
-
print(result)
|
|
30
|
-
assert result.exit_code == 0
|
|
31
|
-
mock_project.list_datastores.assert_called_once()
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def test_list_services(runner, mock_project_services):
|
|
35
|
-
with patch("trainml.cli.TrainML", new=AsyncMock) as mock_trainml:
|
|
36
|
-
mock_project = create_autospec(Project)
|
|
37
|
-
mock_project.list_services = AsyncMock(return_value=mock_project_services)
|
|
38
|
-
mock_trainml.projects.get = AsyncMock(return_value=mock_project)
|
|
39
|
-
result = runner.invoke(specimen, ["list-services"])
|
|
40
|
-
print(result)
|
|
41
|
-
assert result.exit_code == 0
|
|
42
|
-
mock_project.list_services.assert_called_once()
|