trainml 0.5.4__tar.gz → 0.5.5__tar.gz

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 (108) hide show
  1. {trainml-0.5.4/trainml.egg-info → trainml-0.5.5}/PKG-INFO +1 -1
  2. {trainml-0.5.4 → trainml-0.5.5}/pyproject.toml +4 -5
  3. {trainml-0.5.4 → trainml-0.5.5}/tests/integration/test_checkpoints_integration.py +7 -5
  4. {trainml-0.5.4 → trainml-0.5.5}/tests/integration/test_datasets_integration.py +4 -5
  5. {trainml-0.5.4 → trainml-0.5.5}/tests/integration/test_jobs_integration.py +40 -2
  6. {trainml-0.5.4 → trainml-0.5.5}/tests/integration/test_models_integration.py +8 -10
  7. {trainml-0.5.4 → trainml-0.5.5}/tests/integration/test_projects_integration.py +2 -6
  8. trainml-0.5.5/tests/integration/test_volumes_integration.py +100 -0
  9. trainml-0.5.5/tests/unit/cli/test_cli_volume_unit.py +20 -0
  10. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/conftest.py +82 -9
  11. trainml-0.5.5/tests/unit/test_volumes_unit.py +447 -0
  12. {trainml-0.5.4 → trainml-0.5.5}/trainml/__init__.py +1 -1
  13. {trainml-0.5.4 → trainml-0.5.5}/trainml/cli/__init__.py +3 -6
  14. trainml-0.5.5/trainml/cli/volume.py +235 -0
  15. {trainml-0.5.4 → trainml-0.5.5}/trainml/exceptions.py +21 -12
  16. {trainml-0.5.4 → trainml-0.5.5}/trainml/jobs.py +36 -39
  17. {trainml-0.5.4 → trainml-0.5.5}/trainml/trainml.py +7 -15
  18. trainml-0.5.5/trainml/volumes.py +255 -0
  19. {trainml-0.5.4 → trainml-0.5.5/trainml.egg-info}/PKG-INFO +1 -1
  20. {trainml-0.5.4 → trainml-0.5.5}/trainml.egg-info/SOURCES.txt +5 -0
  21. {trainml-0.5.4 → trainml-0.5.5}/LICENSE +0 -0
  22. {trainml-0.5.4 → trainml-0.5.5}/README.md +0 -0
  23. {trainml-0.5.4 → trainml-0.5.5}/examples/__init__.py +0 -0
  24. {trainml-0.5.4 → trainml-0.5.5}/examples/create_dataset_and_training_job.py +0 -0
  25. {trainml-0.5.4 → trainml-0.5.5}/examples/local_storage.py +0 -0
  26. {trainml-0.5.4 → trainml-0.5.5}/examples/training_inference_pipeline.py +0 -0
  27. {trainml-0.5.4 → trainml-0.5.5}/setup.cfg +0 -0
  28. {trainml-0.5.4 → trainml-0.5.5}/setup.py +0 -0
  29. {trainml-0.5.4 → trainml-0.5.5}/tests/integration/__init__.py +0 -0
  30. {trainml-0.5.4 → trainml-0.5.5}/tests/integration/cloudbender/__init__.py +0 -0
  31. {trainml-0.5.4 → trainml-0.5.5}/tests/integration/cloudbender/test_providers_integration.py +0 -0
  32. {trainml-0.5.4 → trainml-0.5.5}/tests/integration/conftest.py +0 -0
  33. {trainml-0.5.4 → trainml-0.5.5}/tests/integration/test_environments_integration.py +0 -0
  34. {trainml-0.5.4 → trainml-0.5.5}/tests/integration/test_gpu_types_integration.py +0 -0
  35. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/__init__.py +0 -0
  36. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cli/__init__.py +0 -0
  37. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cli/cloudbender/__init__.py +0 -0
  38. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cli/cloudbender/test_cli_datastore_unit.py +0 -0
  39. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cli/cloudbender/test_cli_device_unit.py +0 -0
  40. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cli/cloudbender/test_cli_node_unit.py +0 -0
  41. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cli/cloudbender/test_cli_provider_unit.py +0 -0
  42. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cli/cloudbender/test_cli_region_unit.py +0 -0
  43. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cli/cloudbender/test_cli_reservation_unit.py +0 -0
  44. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cli/conftest.py +0 -0
  45. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cli/test_cli_checkpoint_unit.py +0 -0
  46. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cli/test_cli_datasets_unit.py +0 -0
  47. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cli/test_cli_environment_unit.py +0 -0
  48. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cli/test_cli_gpu_unit.py +0 -0
  49. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cli/test_cli_job_unit.py +0 -0
  50. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cli/test_cli_model_unit.py +0 -0
  51. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cli/test_cli_project_unit.py +0 -0
  52. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cloudbender/__init__.py +0 -0
  53. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cloudbender/test_datastores_unit.py +0 -0
  54. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cloudbender/test_device_configs_unit.py +0 -0
  55. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cloudbender/test_devices_unit.py +0 -0
  56. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cloudbender/test_nodes_unit.py +0 -0
  57. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cloudbender/test_providers_unit.py +0 -0
  58. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cloudbender/test_regions_unit.py +0 -0
  59. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/cloudbender/test_reservations_unit.py +0 -0
  60. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/test_auth.py +0 -0
  61. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/test_checkpoints_unit.py +0 -0
  62. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/test_connections_unit.py +0 -0
  63. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/test_datasets_unit.py +0 -0
  64. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/test_environments_unit.py +0 -0
  65. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/test_exceptions.py +0 -0
  66. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/test_gpu_types_unit.py +0 -0
  67. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/test_jobs_unit.py +0 -0
  68. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/test_models_unit.py +0 -0
  69. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/test_projects_unit.py +0 -0
  70. {trainml-0.5.4 → trainml-0.5.5}/tests/unit/test_trainml.py +0 -0
  71. {trainml-0.5.4 → trainml-0.5.5}/trainml/__main__.py +0 -0
  72. {trainml-0.5.4 → trainml-0.5.5}/trainml/auth.py +0 -0
  73. {trainml-0.5.4 → trainml-0.5.5}/trainml/checkpoints.py +0 -0
  74. {trainml-0.5.4 → trainml-0.5.5}/trainml/cli/checkpoint.py +0 -0
  75. {trainml-0.5.4 → trainml-0.5.5}/trainml/cli/cloudbender/__init__.py +0 -0
  76. {trainml-0.5.4 → trainml-0.5.5}/trainml/cli/cloudbender/datastore.py +0 -0
  77. {trainml-0.5.4 → trainml-0.5.5}/trainml/cli/cloudbender/device.py +0 -0
  78. {trainml-0.5.4 → trainml-0.5.5}/trainml/cli/cloudbender/node.py +0 -0
  79. {trainml-0.5.4 → trainml-0.5.5}/trainml/cli/cloudbender/provider.py +0 -0
  80. {trainml-0.5.4 → trainml-0.5.5}/trainml/cli/cloudbender/region.py +0 -0
  81. {trainml-0.5.4 → trainml-0.5.5}/trainml/cli/cloudbender/reservation.py +0 -0
  82. {trainml-0.5.4 → trainml-0.5.5}/trainml/cli/connection.py +0 -0
  83. {trainml-0.5.4 → trainml-0.5.5}/trainml/cli/dataset.py +0 -0
  84. {trainml-0.5.4 → trainml-0.5.5}/trainml/cli/environment.py +0 -0
  85. {trainml-0.5.4 → trainml-0.5.5}/trainml/cli/gpu.py +0 -0
  86. {trainml-0.5.4 → trainml-0.5.5}/trainml/cli/job/__init__.py +0 -0
  87. {trainml-0.5.4 → trainml-0.5.5}/trainml/cli/job/create.py +0 -0
  88. {trainml-0.5.4 → trainml-0.5.5}/trainml/cli/model.py +0 -0
  89. {trainml-0.5.4 → trainml-0.5.5}/trainml/cli/project.py +0 -0
  90. {trainml-0.5.4 → trainml-0.5.5}/trainml/cloudbender/__init__.py +0 -0
  91. {trainml-0.5.4 → trainml-0.5.5}/trainml/cloudbender/cloudbender.py +0 -0
  92. {trainml-0.5.4 → trainml-0.5.5}/trainml/cloudbender/datastores.py +0 -0
  93. {trainml-0.5.4 → trainml-0.5.5}/trainml/cloudbender/device_configs.py +0 -0
  94. {trainml-0.5.4 → trainml-0.5.5}/trainml/cloudbender/devices.py +0 -0
  95. {trainml-0.5.4 → trainml-0.5.5}/trainml/cloudbender/nodes.py +0 -0
  96. {trainml-0.5.4 → trainml-0.5.5}/trainml/cloudbender/providers.py +0 -0
  97. {trainml-0.5.4 → trainml-0.5.5}/trainml/cloudbender/regions.py +0 -0
  98. {trainml-0.5.4 → trainml-0.5.5}/trainml/cloudbender/reservations.py +0 -0
  99. {trainml-0.5.4 → trainml-0.5.5}/trainml/connections.py +0 -0
  100. {trainml-0.5.4 → trainml-0.5.5}/trainml/datasets.py +0 -0
  101. {trainml-0.5.4 → trainml-0.5.5}/trainml/environments.py +0 -0
  102. {trainml-0.5.4 → trainml-0.5.5}/trainml/gpu_types.py +0 -0
  103. {trainml-0.5.4 → trainml-0.5.5}/trainml/models.py +0 -0
  104. {trainml-0.5.4 → trainml-0.5.5}/trainml/projects.py +0 -0
  105. {trainml-0.5.4 → trainml-0.5.5}/trainml.egg-info/dependency_links.txt +0 -0
  106. {trainml-0.5.4 → trainml-0.5.5}/trainml.egg-info/entry_points.txt +0 -0
  107. {trainml-0.5.4 → trainml-0.5.5}/trainml.egg-info/requires.txt +0 -0
  108. {trainml-0.5.4 → trainml-0.5.5}/trainml.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: trainml
3
- Version: 0.5.4
3
+ Version: 0.5.5
4
4
  Summary: trainML client SDK and command line utilities
5
5
  Home-page: https://github.com/trainML/trainml-cli
6
6
  Author: trainML
@@ -3,9 +3,7 @@ python_files = "test_*"
3
3
  python_classes = "*Tests"
4
4
  python_functions = "test_*"
5
5
  asyncio_mode = "auto"
6
- testpaths = [
7
- "tests",
8
- ]
6
+ testpaths = ["tests"]
9
7
  markers = [
10
8
  "create: Tests that create resources on the trainml platform",
11
9
  "gpu_types: Gpu Type tests",
@@ -13,6 +11,7 @@ markers = [
13
11
  "datasets: Datasets tests",
14
12
  "models: Models tests",
15
13
  "checkpoints: Checkpoints tests",
14
+ "volumes: Volumes tests",
16
15
  "jobs: Jobs tests",
17
16
  "connections: Connections tests",
18
17
  "projects: Projects tests",
@@ -27,5 +26,5 @@ markers = [
27
26
  "unit: All unit tests (no trainML environment required)",
28
27
  "integration: All integration tests (trainML environment required)",
29
28
  "sdk: All tests of the SDK",
30
- "cli: All test of the cli"
31
- ]
29
+ "cli: All test of the cli",
30
+ ]
@@ -54,18 +54,20 @@ class GetCheckpointTests:
54
54
 
55
55
  @mark.create
56
56
  @mark.asyncio
57
- async def test_checkpoint_aws(trainml, capsys):
57
+ async def test_checkpoint_wasabi(trainml, capsys):
58
58
  checkpoint = await trainml.checkpoints.create(
59
- name="CLI Automated AWS",
60
- source_type="aws",
61
- source_uri="s3://trainml-examples/models/mxnet-model.zip",
59
+ name="CLI Automated Wasabi",
60
+ source_type="wasabi",
61
+ source_uri="s3://trainml-example/models/trainml-examples",
62
+ capacity="10G",
63
+ source_options=dict(endpoint_url="https://s3.wasabisys.com"),
62
64
  )
63
65
  checkpoint = await checkpoint.wait_for("ready", 300)
64
66
  status = checkpoint.status
65
67
  size = checkpoint.size
66
68
  await checkpoint.remove()
67
69
  assert status == "ready"
68
- assert size >= 1000000
70
+ assert size >= 500000
69
71
 
70
72
 
71
73
  @mark.create
@@ -13,8 +13,9 @@ class GetDatasetTests:
13
13
  async def dataset(self, trainml):
14
14
  dataset = await trainml.datasets.create(
15
15
  name="CLI Automated",
16
- source_type="aws",
17
- source_uri="s3://trainml-examples/data/cifar10",
16
+ source_type="wasabi",
17
+ source_uri="s3://trainml-example/input/cifar-10/cifar-10-batches-bin",
18
+ source_options=dict(endpoint_url="https://s3.wasabisys.com"),
18
19
  )
19
20
  dataset = await dataset.wait_for("ready", 300)
20
21
  yield dataset
@@ -48,9 +49,7 @@ class GetDatasetTests:
48
49
  async def test_dataset_repr(self, dataset):
49
50
  string = repr(dataset)
50
51
  regex = (
51
- r"^Dataset\( trainml , \*\*{.*'dataset_uuid': '"
52
- + dataset.id
53
- + r"'.*}\)$"
52
+ r"^Dataset\( trainml , \*\*{.*'dataset_uuid': '" + dataset.id + r"'.*}\)$"
54
53
  )
55
54
  assert isinstance(string, str)
56
55
  assert re.match(regex, string)
@@ -269,7 +269,7 @@ class JobAPIDataValidationTests:
269
269
  ),
270
270
  )
271
271
  assert (
272
- "Invalid Request - Only regional datastore are allowed for Notebook and Endpoint output locations"
272
+ "Invalid Request - output_type invalid for Notebook and Endpoint jobs"
273
273
  in error.value.message
274
274
  )
275
275
 
@@ -298,7 +298,45 @@ class JobAPIDataValidationTests:
298
298
  ),
299
299
  )
300
300
  assert (
301
- "Invalid Request - Only regional datastore are allowed for Notebook and Endpoint output locations"
301
+ "Invalid Request - output_type invalid for Notebook and Endpoint jobs"
302
+ in error.value.message
303
+ )
304
+
305
+ async def test_invalid_volumes_for_training(self, trainml):
306
+ with raises(ApiError) as error:
307
+ await trainml.jobs.create(
308
+ name="Invalid Volumes for Training",
309
+ type="training",
310
+ gpu_types=["rtx3090"],
311
+ disk_size=10,
312
+ data=dict(
313
+ output_uri="s3://trainml-examples/output/resnet_cifar10",
314
+ output_type="aws",
315
+ volumes=["volume-id"],
316
+ ),
317
+ workers=["python train.py"],
318
+ )
319
+ assert (
320
+ "Invalid Request - Only Notebook and Endpoint job types can use writable volumes"
321
+ in error.value.message
322
+ )
323
+
324
+ async def test_invalid_volumes_for_inference(self, trainml):
325
+ with raises(ApiError) as error:
326
+ await trainml.jobs.create(
327
+ name="Invalid Volumes for Inference",
328
+ type="inference",
329
+ gpu_types=["rtx3090"],
330
+ disk_size=10,
331
+ data=dict(
332
+ output_uri="s3://trainml-examples/output/resnet_cifar10",
333
+ output_type="aws",
334
+ volumes=["volume-id"],
335
+ ),
336
+ workers=["python predict.py"],
337
+ )
338
+ assert (
339
+ "Invalid Request - Only Notebook and Endpoint job types can use writable volumes"
302
340
  in error.value.message
303
341
  )
304
342
 
@@ -43,29 +43,27 @@ class GetModelTests:
43
43
 
44
44
  async def test_model_repr(self, model):
45
45
  string = repr(model)
46
- regex = (
47
- r"^Model\( trainml , \*\*{.*'model_uuid': '"
48
- + model.id
49
- + r"'.*}\)$"
50
- )
46
+ regex = r"^Model\( trainml , \*\*{.*'model_uuid': '" + model.id + r"'.*}\)$"
51
47
  assert isinstance(string, str)
52
48
  assert re.match(regex, string)
53
49
 
54
50
 
55
51
  @mark.create
56
52
  @mark.asyncio
57
- async def test_model_aws(trainml, capsys):
53
+ async def test_model_wasabi(trainml, capsys):
58
54
  model = await trainml.models.create(
59
- name="CLI Automated AWS",
60
- source_type="aws",
61
- source_uri="s3://trainml-examples/models/mxnet-model.zip",
55
+ name="CLI Automated Wasabi",
56
+ source_type="wasabi",
57
+ source_uri="s3://trainml-example/models/trainml-examples",
58
+ capacity="10G",
59
+ source_options=dict(endpoint_url="https://s3.wasabisys.com"),
62
60
  )
63
61
  model = await model.wait_for("ready", 300)
64
62
  status = model.status
65
63
  size = model.size
66
64
  await model.remove()
67
65
  assert status == "ready"
68
- assert size >= 1000000
66
+ assert size >= 500000
69
67
 
70
68
 
71
69
  @mark.create
@@ -11,9 +11,7 @@ pytestmark = [mark.sdk, mark.integration, mark.projects]
11
11
  class GetProjectsTests:
12
12
  @fixture(scope="class")
13
13
  async def project(self, trainml):
14
- project = await trainml.projects.create(
15
- name="New Project", copy_keys=False
16
- )
14
+ project = await trainml.projects.create(name="New Project", copy_keys=False)
17
15
  yield project
18
16
  await project.remove()
19
17
 
@@ -41,8 +39,6 @@ class GetProjectsTests:
41
39
 
42
40
  async def test_project_repr(self, project):
43
41
  string = repr(project)
44
- regex = (
45
- r"^Project\( trainml , \*\*{.*'id': '" + project.id + r"'.*}\)$"
46
- )
42
+ regex = r"^Project\( trainml , \*\*{.*'id': '" + project.id + r"'.*}\)$"
47
43
  assert isinstance(string, str)
48
44
  assert re.match(regex, string)
@@ -0,0 +1,100 @@
1
+ import re
2
+ import sys
3
+ import asyncio
4
+ from pytest import mark, fixture
5
+
6
+ pytestmark = [mark.sdk, mark.integration, mark.volumes]
7
+
8
+
9
+ @mark.create
10
+ @mark.asyncio
11
+ class GetVolumeTests:
12
+ @fixture(scope="class")
13
+ async def volume(self, trainml):
14
+ volume = await trainml.volumes.create(
15
+ name="CLI Automated",
16
+ source_type="git",
17
+ source_uri="git@github.com:trainML/environment-tests.git",
18
+ capacity="10G",
19
+ )
20
+ volume = await volume.wait_for("ready", 120)
21
+ yield volume
22
+ await volume.remove()
23
+ volume = await volume.wait_for("archived", 60)
24
+
25
+ async def test_get_volumes(self, trainml, volume):
26
+ volumes = await trainml.volumes.list()
27
+ assert len(volumes) > 0
28
+
29
+ async def test_get_volume(self, trainml, volume):
30
+ response = await trainml.volumes.get(volume.id)
31
+ assert response.id == volume.id
32
+
33
+ async def test_volume_properties(self, volume):
34
+ assert isinstance(volume.id, str)
35
+ assert isinstance(volume.status, str)
36
+ assert isinstance(volume.name, str)
37
+ assert isinstance(volume.capacity, str)
38
+ assert isinstance(volume.used_size, int)
39
+ assert isinstance(volume.billed_size, int)
40
+
41
+ async def test_volume_str(self, volume):
42
+ string = str(volume)
43
+ regex = r"^{.*\"id\": \"" + volume.id + r"\".*}$"
44
+ assert isinstance(string, str)
45
+ assert re.match(regex, string)
46
+
47
+ async def test_volume_repr(self, volume):
48
+ string = repr(volume)
49
+ regex = r"^Volume\( trainml , \*\*{.*'id': '" + volume.id + r"'.*}\)$"
50
+ assert isinstance(string, str)
51
+ assert re.match(regex, string)
52
+
53
+
54
+ @mark.create
55
+ @mark.asyncio
56
+ async def test_volume_wasabi(trainml, capsys):
57
+ volume = await trainml.volumes.create(
58
+ name="CLI Automated Wasabi",
59
+ source_type="wasabi",
60
+ source_uri="s3://trainml-example/models/trainml-examples",
61
+ capacity="10G",
62
+ source_options=dict(endpoint_url="https://s3.wasabisys.com"),
63
+ )
64
+ volume = await volume.wait_for("ready", 300)
65
+ status = volume.status
66
+ billed_size = volume.billed_size
67
+ used_size = volume.used_size
68
+ await volume.remove()
69
+ assert status == "ready"
70
+ assert billed_size >= 10000000
71
+ assert used_size >= 500000
72
+
73
+
74
+ @mark.create
75
+ @mark.asyncio
76
+ async def test_volume_local(trainml, capsys):
77
+ volume = await trainml.volumes.create(
78
+ name="CLI Automated Local",
79
+ source_type="local",
80
+ source_uri="~/tensorflow-model",
81
+ capacity="10G",
82
+ )
83
+ attach_task = asyncio.create_task(volume.attach())
84
+ connect_task = asyncio.create_task(volume.connect())
85
+ await asyncio.gather(attach_task, connect_task)
86
+ await volume.disconnect()
87
+ await volume.refresh()
88
+ status = volume.status
89
+ billed_size = volume.billed_size
90
+ used_size = volume.used_size
91
+ await volume.remove()
92
+ assert status == "ready"
93
+ assert billed_size >= 10000000
94
+ assert used_size >= 1000000
95
+ captured = capsys.readouterr()
96
+ sys.stdout.write(captured.out)
97
+ sys.stderr.write(captured.err)
98
+ assert "Starting data upload from local" in captured.out
99
+ assert "official/LICENSE 11456 bytes" in captured.out
100
+ assert "Upload complete" in captured.out
@@ -0,0 +1,20 @@
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.volumes]
8
+
9
+ from trainml.cli import volume as specimen
10
+ from trainml.volumes import Volume
11
+
12
+
13
+ def test_list(runner, mock_my_volumes):
14
+ with patch("trainml.cli.TrainML", new=AsyncMock) as mock_trainml:
15
+ mock_trainml.volumes = AsyncMock()
16
+ mock_trainml.volumes.list = AsyncMock(return_value=mock_my_volumes)
17
+ result = runner.invoke(specimen, ["list"])
18
+ print(result)
19
+ assert result.exit_code == 0
20
+ mock_trainml.volumes.list.assert_called_once()
@@ -7,6 +7,7 @@ from trainml.trainml import TrainML
7
7
  from trainml.auth import Auth
8
8
  from trainml.datasets import Dataset, Datasets
9
9
  from trainml.checkpoints import Checkpoint, Checkpoints
10
+ from trainml.volumes import Volume, Volumes
10
11
  from trainml.models import Model, Models
11
12
  from trainml.gpu_types import GpuType, GpuTypes
12
13
  from trainml.environments import Environment, Environments
@@ -258,6 +259,79 @@ def mock_models():
258
259
  ]
259
260
 
260
261
 
262
+ @fixture(scope="session")
263
+ def mock_my_volumes():
264
+ trainml = Mock()
265
+ yield [
266
+ Volume(
267
+ trainml,
268
+ id="1",
269
+ project_uuid="proj-id-1",
270
+ name="first one",
271
+ status="ready",
272
+ capacity="10G",
273
+ used_size=100000000,
274
+ billed_size=100000000,
275
+ createdAt="2020-12-31T23:59:59.000Z",
276
+ ),
277
+ Volume(
278
+ trainml,
279
+ id="2",
280
+ project_uuid="proj-id-1",
281
+ name="second one",
282
+ status="ready",
283
+ capacity="10G",
284
+ used_size=100000000,
285
+ billed_size=100000000,
286
+ createdAt="2021-01-01T00:00:01.000Z",
287
+ ),
288
+ Volume(
289
+ trainml,
290
+ id="3",
291
+ project_uuid="proj-id-1",
292
+ name="first one",
293
+ status="ready",
294
+ capacity="10G",
295
+ used_size=100000000,
296
+ billed_size=100000000,
297
+ createdAt="2021-01-01T00:00:01.000Z",
298
+ ),
299
+ Volume(
300
+ trainml,
301
+ id="4",
302
+ project_uuid="proj-id-1",
303
+ name="other one",
304
+ status="ready",
305
+ capacity="10G",
306
+ used_size=100000000,
307
+ billed_size=100000000,
308
+ createdAt="2020-12-31T23:59:59.000Z",
309
+ ),
310
+ Volume(
311
+ trainml,
312
+ id="5",
313
+ project_uuid="proj-id-1",
314
+ name="not ready",
315
+ status="new",
316
+ capacity="10G",
317
+ used_size=100000000,
318
+ billed_size=100000000,
319
+ createdAt="2021-01-01T00:00:01.000Z",
320
+ ),
321
+ Volume(
322
+ trainml,
323
+ id="6",
324
+ project_uuid="proj-id-1",
325
+ name="failed",
326
+ status="failed",
327
+ capacity="10G",
328
+ used_size=100000000,
329
+ billed_size=100000000,
330
+ createdAt="2021-01-01T00:00:01.000Z",
331
+ ),
332
+ ]
333
+
334
+
261
335
  @fixture(scope="session")
262
336
  def mock_gpu_types():
263
337
  trainml = Mock()
@@ -903,6 +977,9 @@ def mock_device_configs():
903
977
  def mock_trainml(
904
978
  mock_my_datasets,
905
979
  mock_public_datasets,
980
+ mock_my_checkpoints,
981
+ mock_public_checkpoints,
982
+ mock_my_volumes,
906
983
  mock_models,
907
984
  mock_gpu_types,
908
985
  mock_environments,
@@ -921,6 +998,7 @@ def mock_trainml(
921
998
  trainml.project = "proj-id-1"
922
999
  trainml.datasets = create_autospec(Datasets)
923
1000
  trainml.checkpoints = create_autospec(Checkpoints)
1001
+ trainml.volumes = create_autospec(Volumes)
924
1002
  trainml.models = create_autospec(Models)
925
1003
  trainml.gpu_types = create_autospec(GpuTypes)
926
1004
  trainml.environments = create_autospec(Environments)
@@ -930,10 +1008,9 @@ def mock_trainml(
930
1008
  trainml.datasets.list = AsyncMock(return_value=mock_my_datasets)
931
1009
  trainml.datasets.list_public = AsyncMock(return_value=mock_public_datasets)
932
1010
  trainml.checkpoints.list = AsyncMock(return_value=mock_my_checkpoints)
933
- trainml.checkpoints.list_public = AsyncMock(
934
- return_value=mock_public_checkpoints
935
- )
1011
+ trainml.checkpoints.list_public = AsyncMock(return_value=mock_public_checkpoints)
936
1012
  trainml.models.list = AsyncMock(return_value=mock_models)
1013
+ trainml.volumes.list = AsyncMock(return_value=mock_my_volumes)
937
1014
  trainml.gpu_types.list = AsyncMock(return_value=mock_gpu_types)
938
1015
  trainml.environments.list = AsyncMock(return_value=mock_environments)
939
1016
  trainml.jobs.list = AsyncMock(return_value=mock_jobs)
@@ -950,13 +1027,9 @@ def mock_trainml(
950
1027
  trainml.cloudbender.devices = create_autospec(Nodes)
951
1028
  trainml.cloudbender.devices.list = AsyncMock(return_value=mock_devices)
952
1029
  trainml.cloudbender.datastores = create_autospec(Datastores)
953
- trainml.cloudbender.datastores.list = AsyncMock(
954
- return_value=mock_datastores
955
- )
1030
+ trainml.cloudbender.datastores.list = AsyncMock(return_value=mock_datastores)
956
1031
  trainml.cloudbender.reservations = create_autospec(Reservations)
957
- trainml.cloudbender.reservations.list = AsyncMock(
958
- return_value=mock_reservations
959
- )
1032
+ trainml.cloudbender.reservations.list = AsyncMock(return_value=mock_reservations)
960
1033
  trainml.cloudbender.device_configs = create_autospec(DeviceConfigs)
961
1034
  trainml.cloudbender.device_configs.list = AsyncMock(
962
1035
  return_value=mock_device_configs