trainml 0.5.8__tar.gz → 0.5.9__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 (131) hide show
  1. {trainml-0.5.8 → trainml-0.5.9}/PKG-INFO +1 -1
  2. trainml-0.5.9/tests/integration/projects/conftest.py +8 -0
  3. {trainml-0.5.8/tests/integration → trainml-0.5.9/tests/integration/projects}/test_projects_integration.py +0 -6
  4. trainml-0.5.9/tests/integration/projects/test_projects_keys_integration.py +43 -0
  5. trainml-0.5.9/tests/integration/projects/test_projects_secrets_integration.py +44 -0
  6. trainml-0.5.9/tests/unit/cloudbender/__init__.py +0 -0
  7. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/conftest.py +72 -2
  8. trainml-0.5.9/tests/unit/projects/__init__.py +0 -0
  9. trainml-0.5.9/tests/unit/projects/test_project_data_connectors_unit.py +102 -0
  10. trainml-0.5.9/tests/unit/projects/test_project_datastores_unit.py +96 -0
  11. trainml-0.5.9/tests/unit/projects/test_project_keys_unit.py +96 -0
  12. trainml-0.5.9/tests/unit/projects/test_project_secrets_unit.py +101 -0
  13. trainml-0.5.9/tests/unit/projects/test_project_services_unit.py +102 -0
  14. trainml-0.5.9/tests/unit/projects/test_projects_unit.py +128 -0
  15. {trainml-0.5.8 → trainml-0.5.9}/trainml/__init__.py +1 -1
  16. trainml-0.5.8/trainml/cli/project.py → trainml-0.5.9/trainml/cli/project/__init__.py +4 -0
  17. trainml-0.5.9/trainml/cli/project/key.py +124 -0
  18. trainml-0.5.9/trainml/cli/project/secret.py +71 -0
  19. trainml-0.5.9/trainml/projects/__init__.py +3 -0
  20. trainml-0.5.9/trainml/projects/data_connectors.py +63 -0
  21. trainml-0.5.9/trainml/projects/datastores.py +58 -0
  22. trainml-0.5.9/trainml/projects/keys.py +71 -0
  23. trainml-0.5.9/trainml/projects/projects.py +83 -0
  24. trainml-0.5.9/trainml/projects/secrets.py +70 -0
  25. trainml-0.5.9/trainml/projects/services.py +63 -0
  26. {trainml-0.5.8 → trainml-0.5.9}/trainml.egg-info/PKG-INFO +1 -1
  27. {trainml-0.5.8 → trainml-0.5.9}/trainml.egg-info/SOURCES.txt +25 -7
  28. trainml-0.5.8/tests/unit/test_projects_unit.py +0 -320
  29. trainml-0.5.8/trainml/projects.py +0 -228
  30. {trainml-0.5.8 → trainml-0.5.9}/LICENSE +0 -0
  31. {trainml-0.5.8 → trainml-0.5.9}/README.md +0 -0
  32. {trainml-0.5.8 → trainml-0.5.9}/examples/__init__.py +0 -0
  33. {trainml-0.5.8 → trainml-0.5.9}/examples/create_dataset_and_training_job.py +0 -0
  34. {trainml-0.5.8 → trainml-0.5.9}/examples/local_storage.py +0 -0
  35. {trainml-0.5.8 → trainml-0.5.9}/examples/training_inference_pipeline.py +0 -0
  36. {trainml-0.5.8 → trainml-0.5.9}/pyproject.toml +0 -0
  37. {trainml-0.5.8 → trainml-0.5.9}/setup.cfg +0 -0
  38. {trainml-0.5.8 → trainml-0.5.9}/setup.py +0 -0
  39. {trainml-0.5.8 → trainml-0.5.9}/tests/integration/__init__.py +0 -0
  40. {trainml-0.5.8 → trainml-0.5.9}/tests/integration/cloudbender/__init__.py +0 -0
  41. {trainml-0.5.8 → trainml-0.5.9}/tests/integration/cloudbender/test_providers_integration.py +0 -0
  42. {trainml-0.5.8 → trainml-0.5.9}/tests/integration/conftest.py +0 -0
  43. {trainml-0.5.8/tests/unit → trainml-0.5.9/tests/integration/projects}/__init__.py +0 -0
  44. {trainml-0.5.8 → trainml-0.5.9}/tests/integration/test_checkpoints_integration.py +0 -0
  45. {trainml-0.5.8 → trainml-0.5.9}/tests/integration/test_datasets_integration.py +0 -0
  46. {trainml-0.5.8 → trainml-0.5.9}/tests/integration/test_environments_integration.py +0 -0
  47. {trainml-0.5.8 → trainml-0.5.9}/tests/integration/test_gpu_types_integration.py +0 -0
  48. {trainml-0.5.8 → trainml-0.5.9}/tests/integration/test_jobs_integration.py +0 -0
  49. {trainml-0.5.8 → trainml-0.5.9}/tests/integration/test_models_integration.py +0 -0
  50. {trainml-0.5.8 → trainml-0.5.9}/tests/integration/test_volumes_integration.py +0 -0
  51. {trainml-0.5.8/tests/unit/cli → trainml-0.5.9/tests/unit}/__init__.py +0 -0
  52. {trainml-0.5.8/tests/unit/cli/cloudbender → trainml-0.5.9/tests/unit/cli}/__init__.py +0 -0
  53. {trainml-0.5.8/tests/unit → trainml-0.5.9/tests/unit/cli}/cloudbender/__init__.py +0 -0
  54. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/cli/cloudbender/test_cli_datastore_unit.py +0 -0
  55. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/cli/cloudbender/test_cli_device_unit.py +0 -0
  56. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/cli/cloudbender/test_cli_node_unit.py +0 -0
  57. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/cli/cloudbender/test_cli_provider_unit.py +0 -0
  58. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/cli/cloudbender/test_cli_region_unit.py +0 -0
  59. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/cli/cloudbender/test_cli_service_unit.py +0 -0
  60. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/cli/conftest.py +0 -0
  61. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/cli/test_cli_checkpoint_unit.py +0 -0
  62. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/cli/test_cli_datasets_unit.py +0 -0
  63. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/cli/test_cli_environment_unit.py +0 -0
  64. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/cli/test_cli_gpu_unit.py +0 -0
  65. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/cli/test_cli_job_unit.py +0 -0
  66. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/cli/test_cli_model_unit.py +0 -0
  67. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/cli/test_cli_project_unit.py +0 -0
  68. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/cli/test_cli_volume_unit.py +0 -0
  69. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/cloudbender/test_data_connectors_unit.py +0 -0
  70. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/cloudbender/test_datastores_unit.py +0 -0
  71. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/cloudbender/test_device_configs_unit.py +0 -0
  72. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/cloudbender/test_devices_unit.py +0 -0
  73. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/cloudbender/test_nodes_unit.py +0 -0
  74. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/cloudbender/test_providers_unit.py +0 -0
  75. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/cloudbender/test_regions_unit.py +0 -0
  76. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/cloudbender/test_services_unit.py +0 -0
  77. /trainml-0.5.8/tests/unit/test_auth.py → /trainml-0.5.9/tests/unit/test_auth_unit.py +0 -0
  78. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/test_checkpoints_unit.py +0 -0
  79. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/test_connections_unit.py +0 -0
  80. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/test_datasets_unit.py +0 -0
  81. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/test_environments_unit.py +0 -0
  82. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/test_exceptions.py +0 -0
  83. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/test_gpu_types_unit.py +0 -0
  84. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/test_jobs_unit.py +0 -0
  85. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/test_models_unit.py +0 -0
  86. /trainml-0.5.8/tests/unit/test_trainml.py → /trainml-0.5.9/tests/unit/test_trainml_unit.py +0 -0
  87. {trainml-0.5.8 → trainml-0.5.9}/tests/unit/test_volumes_unit.py +0 -0
  88. {trainml-0.5.8 → trainml-0.5.9}/trainml/__main__.py +0 -0
  89. {trainml-0.5.8 → trainml-0.5.9}/trainml/auth.py +0 -0
  90. {trainml-0.5.8 → trainml-0.5.9}/trainml/checkpoints.py +0 -0
  91. {trainml-0.5.8 → trainml-0.5.9}/trainml/cli/__init__.py +0 -0
  92. {trainml-0.5.8 → trainml-0.5.9}/trainml/cli/checkpoint.py +0 -0
  93. {trainml-0.5.8 → trainml-0.5.9}/trainml/cli/cloudbender/__init__.py +0 -0
  94. {trainml-0.5.8 → trainml-0.5.9}/trainml/cli/cloudbender/data_connector.py +0 -0
  95. {trainml-0.5.8 → trainml-0.5.9}/trainml/cli/cloudbender/datastore.py +0 -0
  96. {trainml-0.5.8 → trainml-0.5.9}/trainml/cli/cloudbender/device.py +0 -0
  97. {trainml-0.5.8 → trainml-0.5.9}/trainml/cli/cloudbender/node.py +0 -0
  98. {trainml-0.5.8 → trainml-0.5.9}/trainml/cli/cloudbender/provider.py +0 -0
  99. {trainml-0.5.8 → trainml-0.5.9}/trainml/cli/cloudbender/region.py +0 -0
  100. {trainml-0.5.8 → trainml-0.5.9}/trainml/cli/cloudbender/service.py +0 -0
  101. {trainml-0.5.8 → trainml-0.5.9}/trainml/cli/connection.py +0 -0
  102. {trainml-0.5.8 → trainml-0.5.9}/trainml/cli/dataset.py +0 -0
  103. {trainml-0.5.8 → trainml-0.5.9}/trainml/cli/environment.py +0 -0
  104. {trainml-0.5.8 → trainml-0.5.9}/trainml/cli/gpu.py +0 -0
  105. {trainml-0.5.8 → trainml-0.5.9}/trainml/cli/job/__init__.py +0 -0
  106. {trainml-0.5.8 → trainml-0.5.9}/trainml/cli/job/create.py +0 -0
  107. {trainml-0.5.8 → trainml-0.5.9}/trainml/cli/model.py +0 -0
  108. {trainml-0.5.8 → trainml-0.5.9}/trainml/cli/volume.py +0 -0
  109. {trainml-0.5.8 → trainml-0.5.9}/trainml/cloudbender/__init__.py +0 -0
  110. {trainml-0.5.8 → trainml-0.5.9}/trainml/cloudbender/cloudbender.py +0 -0
  111. {trainml-0.5.8 → trainml-0.5.9}/trainml/cloudbender/data_connectors.py +0 -0
  112. {trainml-0.5.8 → trainml-0.5.9}/trainml/cloudbender/datastores.py +0 -0
  113. {trainml-0.5.8 → trainml-0.5.9}/trainml/cloudbender/device_configs.py +0 -0
  114. {trainml-0.5.8 → trainml-0.5.9}/trainml/cloudbender/devices.py +0 -0
  115. {trainml-0.5.8 → trainml-0.5.9}/trainml/cloudbender/nodes.py +0 -0
  116. {trainml-0.5.8 → trainml-0.5.9}/trainml/cloudbender/providers.py +0 -0
  117. {trainml-0.5.8 → trainml-0.5.9}/trainml/cloudbender/regions.py +0 -0
  118. {trainml-0.5.8 → trainml-0.5.9}/trainml/cloudbender/services.py +0 -0
  119. {trainml-0.5.8 → trainml-0.5.9}/trainml/connections.py +0 -0
  120. {trainml-0.5.8 → trainml-0.5.9}/trainml/datasets.py +0 -0
  121. {trainml-0.5.8 → trainml-0.5.9}/trainml/environments.py +0 -0
  122. {trainml-0.5.8 → trainml-0.5.9}/trainml/exceptions.py +0 -0
  123. {trainml-0.5.8 → trainml-0.5.9}/trainml/gpu_types.py +0 -0
  124. {trainml-0.5.8 → trainml-0.5.9}/trainml/jobs.py +0 -0
  125. {trainml-0.5.8 → trainml-0.5.9}/trainml/models.py +0 -0
  126. {trainml-0.5.8 → trainml-0.5.9}/trainml/trainml.py +0 -0
  127. {trainml-0.5.8 → trainml-0.5.9}/trainml/volumes.py +0 -0
  128. {trainml-0.5.8 → trainml-0.5.9}/trainml.egg-info/dependency_links.txt +0 -0
  129. {trainml-0.5.8 → trainml-0.5.9}/trainml.egg-info/entry_points.txt +0 -0
  130. {trainml-0.5.8 → trainml-0.5.9}/trainml.egg-info/requires.txt +0 -0
  131. {trainml-0.5.8 → trainml-0.5.9}/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.8
3
+ Version: 0.5.9
4
4
  Summary: trainML client SDK and command line utilities
5
5
  Home-page: https://github.com/trainML/trainml-cli
6
6
  Author: trainML
@@ -0,0 +1,8 @@
1
+ from pytest import fixture
2
+
3
+
4
+ @fixture(scope="module")
5
+ async def project(trainml):
6
+ project = await trainml.projects.create(name="New Project", copy_keys=False)
7
+ yield project
8
+ await project.remove()
@@ -9,12 +9,6 @@ pytestmark = [mark.sdk, mark.integration, mark.projects]
9
9
  @mark.create
10
10
  @mark.asyncio
11
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
12
  async def test_get_projects(self, trainml):
19
13
  projects = await trainml.projects.list()
20
14
  assert len(projects) > 0
@@ -0,0 +1,43 @@
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 ProjectKeysTests:
12
+ @fixture(scope="class")
13
+ async def project_key(self, project):
14
+ project_key = await project.keys.put(
15
+ type="aws", key_id="ASFHALKF", secret="IUHKLHKAHF"
16
+ )
17
+ yield project_key
18
+ await project.keys.remove(type="aws")
19
+
20
+ async def test_list_project_keys(self, project, project_key):
21
+ keys = await project.keys.list()
22
+ assert len(keys) > 0
23
+
24
+ async def test_project_key_properties(self, project, project_key):
25
+ assert isinstance(project_key.project_uuid, str)
26
+ assert isinstance(project_key.type, str)
27
+ assert isinstance(project_key.key_id, str)
28
+ assert project_key.type == "aws"
29
+ assert project.id == project_key.project_uuid
30
+
31
+ async def test_project_key_str(self, project_key):
32
+ string = str(project_key)
33
+ regex = r"^{.*\"type\": \"" + project_key.type + r"\".*}$"
34
+ assert isinstance(string, str)
35
+ assert re.match(regex, string)
36
+
37
+ async def test_project_key_repr(self, project_key):
38
+ string = repr(project_key)
39
+ regex = (
40
+ r"^ProjectKey\( trainml , \*\*{.*'type': '" + project_key.type + r"'.*}\)$"
41
+ )
42
+ assert isinstance(string, str)
43
+ assert re.match(regex, string)
@@ -0,0 +1,44 @@
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 ProjectSecretsTests:
12
+ @fixture(scope="class")
13
+ async def project_secret(self, project):
14
+ project_secret = await project.secrets.put(
15
+ name="secret_value", value="IUHKLHKAHF"
16
+ )
17
+ yield project_secret
18
+ await project.secrets.remove(name="secret_value")
19
+
20
+ async def test_list_project_keys(self, project, project_secret):
21
+ secrets = await project.secrets.list()
22
+ assert len(secrets) > 0
23
+
24
+ async def test_project_secret_properties(self, project, project_secret):
25
+ assert isinstance(project_secret.project_uuid, str)
26
+ assert isinstance(project_secret.name, str)
27
+ assert project_secret.name == "secret_value"
28
+ assert project.id == project_secret.project_uuid
29
+
30
+ async def test_project_secret_str(self, project_secret):
31
+ string = str(project_secret)
32
+ regex = r"^{.*\"name\": \"" + project_secret.name + r"\".*}$"
33
+ assert isinstance(string, str)
34
+ assert re.match(regex, string)
35
+
36
+ async def test_project_secret_repr(self, project_secret):
37
+ string = repr(project_secret)
38
+ regex = (
39
+ r"^ProjectSecret\( trainml , \*\*{.*'name': '"
40
+ + project_secret.name
41
+ + r"'.*}\)$"
42
+ )
43
+ assert isinstance(string, str)
44
+ assert re.match(regex, string)
File without changes
@@ -16,9 +16,11 @@ from trainml.connections import Connections
16
16
  from trainml.projects import (
17
17
  Projects,
18
18
  Project,
19
- ProjectDatastore,
20
- ProjectService,
21
19
  )
20
+ from trainml.projects.datastores import ProjectDatastore
21
+ from trainml.projects.services import ProjectService
22
+ from trainml.projects.data_connectors import ProjectDataConnector
23
+
22
24
  from trainml.cloudbender import Cloudbender
23
25
  from trainml.cloudbender.providers import Provider, Providers
24
26
  from trainml.cloudbender.regions import Region, Regions
@@ -26,6 +28,7 @@ from trainml.cloudbender.nodes import Node, Nodes
26
28
  from trainml.cloudbender.devices import Device, Devices
27
29
  from trainml.cloudbender.datastores import Datastore, Datastores
28
30
  from trainml.cloudbender.services import Service, Services
31
+ from trainml.cloudbender.data_connectors import DataConnector, DataConnectors
29
32
  from trainml.cloudbender.device_configs import DeviceConfig, DeviceConfigs
30
33
 
31
34
 
@@ -948,6 +951,68 @@ def mock_project_services():
948
951
  ]
949
952
 
950
953
 
954
+ @fixture(scope="session")
955
+ def mock_data_connectors():
956
+ trainml = Mock()
957
+ yield [
958
+ DataConnector(
959
+ trainml,
960
+ **{
961
+ "provider_uuid": "prov-id-1",
962
+ "region_uuid": "reg-id-1",
963
+ "connector_id": "con-id-1",
964
+ "type": "custom",
965
+ "name": "On-Prem Connection A",
966
+ "protocol": "TCP",
967
+ "port_range": "8000-8099",
968
+ "cidr": "10.0.3.0/24",
969
+ },
970
+ ),
971
+ DataConnector(
972
+ trainml,
973
+ **{
974
+ "provider_uuid": "prov-id-2",
975
+ "region_uuid": "reg-id-2",
976
+ "connector_id": "con-id-2",
977
+ "type": "custom",
978
+ "name": "Cloud Connection B",
979
+ "protocol": "UDP",
980
+ "port_range": "5000",
981
+ "cidr": "10.0.2.0/24",
982
+ },
983
+ ),
984
+ ]
985
+
986
+
987
+ @fixture(
988
+ scope="session",
989
+ )
990
+ def mock_project_data_connectors():
991
+ trainml = Mock()
992
+ yield [
993
+ ProjectDataConnector(
994
+ trainml,
995
+ **{
996
+ "project_uuid": "proj-id-1",
997
+ "region_uuid": "reg-id-1",
998
+ "id": "con-id-1",
999
+ "type": "custom",
1000
+ "name": "On-Prem Connection A",
1001
+ },
1002
+ ),
1003
+ ProjectDataConnector(
1004
+ trainml,
1005
+ **{
1006
+ "project_uuid": "proj-id-1",
1007
+ "region_uuid": "reg-id-2",
1008
+ "id": "con-id-2",
1009
+ "type": "custom",
1010
+ "name": "Cloud Connection B",
1011
+ },
1012
+ ),
1013
+ ]
1014
+
1015
+
951
1016
  @fixture(scope="session")
952
1017
  def mock_device_configs():
953
1018
  trainml = Mock()
@@ -991,6 +1056,7 @@ def mock_trainml(
991
1056
  mock_devices,
992
1057
  mock_datastores,
993
1058
  mock_services,
1059
+ mock_data_connectors,
994
1060
  mock_device_configs,
995
1061
  ):
996
1062
  trainml = create_autospec(TrainML)
@@ -1030,6 +1096,10 @@ def mock_trainml(
1030
1096
  trainml.cloudbender.datastores.list = AsyncMock(return_value=mock_datastores)
1031
1097
  trainml.cloudbender.services = create_autospec(Services)
1032
1098
  trainml.cloudbender.services.list = AsyncMock(return_value=mock_services)
1099
+ trainml.cloudbender.data_connectors = create_autospec(DataConnectors)
1100
+ trainml.cloudbender.data_connectors.list = AsyncMock(
1101
+ return_value=mock_data_connectors
1102
+ )
1033
1103
  trainml.cloudbender.device_configs = create_autospec(DeviceConfigs)
1034
1104
  trainml.cloudbender.device_configs.list = AsyncMock(
1035
1105
  return_value=mock_device_configs
File without changes
@@ -0,0 +1,102 @@
1
+ import re
2
+ import json
3
+ import logging
4
+ from unittest.mock import AsyncMock, patch
5
+ from pytest import mark, fixture, raises
6
+ from aiohttp import WSMessage, WSMsgType
7
+
8
+ import trainml.projects.data_connectors as specimen
9
+ from trainml.exceptions import (
10
+ ApiError,
11
+ SpecificationError,
12
+ TrainMLException,
13
+ )
14
+
15
+ pytestmark = [mark.sdk, mark.unit, mark.projects]
16
+
17
+
18
+ @fixture
19
+ def project_data_connectors(mock_trainml):
20
+ yield specimen.ProjectDataConnectors(mock_trainml, project_id="1")
21
+
22
+
23
+ @fixture
24
+ def project_data_connector(mock_trainml):
25
+ yield specimen.ProjectDataConnector(
26
+ mock_trainml,
27
+ id="ds-id-1",
28
+ name="connector 1",
29
+ project_uuid="proj-id-1",
30
+ type="custom",
31
+ region_uuid="reg-id-1",
32
+ )
33
+
34
+
35
+ class ProjectDataConnectorsTests:
36
+ @mark.asyncio
37
+ async def test_project_data_connectors_refresh(
38
+ self, project_data_connectors, mock_trainml
39
+ ):
40
+ api_response = dict()
41
+ mock_trainml._query = AsyncMock(return_value=api_response)
42
+ await project_data_connectors.refresh()
43
+ mock_trainml._query.assert_called_once_with(
44
+ "/project/1/data_connectors", "PATCH"
45
+ )
46
+
47
+ @mark.asyncio
48
+ async def test_project_data_connectors_list(
49
+ self, project_data_connectors, mock_trainml
50
+ ):
51
+ api_response = [
52
+ {
53
+ "project_uuid": "proj-id-1",
54
+ "region_uuid": "reg-id-1",
55
+ "id": "store-id-1",
56
+ "type": "custom",
57
+ "name": "On-Prem Connection A",
58
+ },
59
+ {
60
+ "project_uuid": "proj-id-1",
61
+ "region_uuid": "reg-id-2",
62
+ "id": "store-id-2",
63
+ "type": "custom",
64
+ "name": "Cloud Connection B",
65
+ },
66
+ ]
67
+ mock_trainml._query = AsyncMock(return_value=api_response)
68
+ resp = await project_data_connectors.list()
69
+ mock_trainml._query.assert_called_once_with(
70
+ "/project/1/data_connectors", "GET", dict()
71
+ )
72
+ assert len(resp) == 2
73
+
74
+
75
+ class ProjectDataConnectorTests:
76
+ def test_project_data_connector_properties(self, project_data_connector):
77
+ assert isinstance(project_data_connector.id, str)
78
+ assert isinstance(project_data_connector.name, str)
79
+ assert isinstance(project_data_connector.project_uuid, str)
80
+ assert isinstance(project_data_connector.type, str)
81
+ assert isinstance(project_data_connector.region_uuid, str)
82
+
83
+ def test_project_data_connector_str(self, project_data_connector):
84
+ string = str(project_data_connector)
85
+ regex = r"^{.*\"id\": \"" + project_data_connector.id + r"\".*}$"
86
+ assert isinstance(string, str)
87
+ assert re.match(regex, string)
88
+
89
+ def test_project_data_connector_repr(self, project_data_connector):
90
+ string = repr(project_data_connector)
91
+ regex = (
92
+ r"^ProjectDataConnector\( trainml , \*\*{.*'id': '"
93
+ + project_data_connector.id
94
+ + r"'.*}\)$"
95
+ )
96
+ assert isinstance(string, str)
97
+ assert re.match(regex, string)
98
+
99
+ def test_project_data_connector_bool(self, project_data_connector, mock_trainml):
100
+ empty_project_data_connector = specimen.ProjectDataConnector(mock_trainml)
101
+ assert bool(project_data_connector)
102
+ assert not bool(empty_project_data_connector)
@@ -0,0 +1,96 @@
1
+ import re
2
+ import json
3
+ import logging
4
+ from unittest.mock import AsyncMock, patch
5
+ from pytest import mark, fixture, raises
6
+ from aiohttp import WSMessage, WSMsgType
7
+
8
+ import trainml.projects.datastores as specimen
9
+ from trainml.exceptions import (
10
+ ApiError,
11
+ SpecificationError,
12
+ TrainMLException,
13
+ )
14
+
15
+ pytestmark = [mark.sdk, mark.unit, mark.projects]
16
+
17
+
18
+ @fixture
19
+ def project_datastores(mock_trainml):
20
+ yield specimen.ProjectDatastores(mock_trainml, project_id="1")
21
+
22
+
23
+ @fixture
24
+ def project_datastore(mock_trainml):
25
+ yield specimen.ProjectDatastore(
26
+ mock_trainml,
27
+ id="ds-id-1",
28
+ name="datastore 1",
29
+ project_uuid="proj-id-1",
30
+ type="nfs",
31
+ region_uuid="reg-id-1",
32
+ )
33
+
34
+
35
+ class ProjectDatastoresTests:
36
+ @mark.asyncio
37
+ async def test_project_datastores_refresh(self, project_datastores, mock_trainml):
38
+ api_response = dict()
39
+ mock_trainml._query = AsyncMock(return_value=api_response)
40
+ await project_datastores.refresh()
41
+ mock_trainml._query.assert_called_once_with("/project/1/datastores", "PATCH")
42
+
43
+ @mark.asyncio
44
+ async def test_project_datastores_list(self, project_datastores, mock_trainml):
45
+ api_response = [
46
+ {
47
+ "project_uuid": "proj-id-1",
48
+ "region_uuid": "reg-id-1",
49
+ "id": "store-id-1",
50
+ "type": "nfs",
51
+ "name": "On-prem NFS",
52
+ },
53
+ {
54
+ "project_uuid": "proj-id-1",
55
+ "region_uuid": "reg-id-2",
56
+ "id": "store-id-2",
57
+ "type": "smb",
58
+ "name": "GCP Samba",
59
+ },
60
+ ]
61
+ mock_trainml._query = AsyncMock(return_value=api_response)
62
+ resp = await project_datastores.list()
63
+ mock_trainml._query.assert_called_once_with(
64
+ "/project/1/datastores", "GET", dict()
65
+ )
66
+ assert len(resp) == 2
67
+
68
+
69
+ class ProjectDatastoreTests:
70
+ def test_project_datastore_properties(self, project_datastore):
71
+ assert isinstance(project_datastore.id, str)
72
+ assert isinstance(project_datastore.name, str)
73
+ assert isinstance(project_datastore.project_uuid, str)
74
+ assert isinstance(project_datastore.type, str)
75
+ assert isinstance(project_datastore.region_uuid, str)
76
+
77
+ def test_project_datastore_str(self, project_datastore):
78
+ string = str(project_datastore)
79
+ regex = r"^{.*\"id\": \"" + project_datastore.id + r"\".*}$"
80
+ assert isinstance(string, str)
81
+ assert re.match(regex, string)
82
+
83
+ def test_project_datastore_repr(self, project_datastore):
84
+ string = repr(project_datastore)
85
+ regex = (
86
+ r"^ProjectDatastore\( trainml , \*\*{.*'id': '"
87
+ + project_datastore.id
88
+ + r"'.*}\)$"
89
+ )
90
+ assert isinstance(string, str)
91
+ assert re.match(regex, string)
92
+
93
+ def test_project_datastore_bool(self, project_datastore, mock_trainml):
94
+ empty_project_datastore = specimen.ProjectDatastore(mock_trainml)
95
+ assert bool(project_datastore)
96
+ assert not bool(empty_project_datastore)
@@ -0,0 +1,96 @@
1
+ import re
2
+ import json
3
+ import logging
4
+ from unittest.mock import AsyncMock, patch
5
+ from pytest import mark, fixture, raises
6
+ from aiohttp import WSMessage, WSMsgType
7
+
8
+ import trainml.projects.keys as specimen
9
+ from trainml.exceptions import (
10
+ ApiError,
11
+ SpecificationError,
12
+ TrainMLException,
13
+ )
14
+
15
+ pytestmark = [mark.sdk, mark.unit, mark.projects]
16
+
17
+
18
+ @fixture
19
+ def project_keys(mock_trainml):
20
+ yield specimen.ProjectKeys(mock_trainml, project_id="1")
21
+
22
+
23
+ @fixture
24
+ def project_key(mock_trainml):
25
+ yield specimen.ProjectKey(
26
+ mock_trainml, project_uuid="proj-id-1", type="aws", key_id="AIYHGFSDLK"
27
+ )
28
+
29
+
30
+ class ProjectKeysTests:
31
+ @mark.asyncio
32
+ async def test_project_keys_list(self, project_keys, mock_trainml):
33
+ api_response = [
34
+ {"project_uuid": "proj-id-1", "type": "aws", "key_id": "AIYHGFSDLK"},
35
+ {"project_uuid": "proj-id-1", "type": "gcp", "key_id": "credentials.json"},
36
+ ]
37
+ mock_trainml._query = AsyncMock(return_value=api_response)
38
+ resp = await project_keys.list()
39
+ mock_trainml._query.assert_called_once_with("/project/1/keys", "GET", dict())
40
+ assert len(resp) == 2
41
+
42
+ @mark.asyncio
43
+ async def test_remove_project_key(
44
+ self,
45
+ project_keys,
46
+ mock_trainml,
47
+ ):
48
+ api_response = dict()
49
+ mock_trainml._query = AsyncMock(return_value=api_response)
50
+ await project_keys.remove("aws")
51
+ mock_trainml._query.assert_called_once_with(
52
+ "/project/1/key/aws", "DELETE", dict()
53
+ )
54
+
55
+ @mark.asyncio
56
+ async def test_put_project_key(self, project_keys, mock_trainml):
57
+ requested_config = dict(type="aws", key_id="AIUDHADA", secret="ASKHJSLKF")
58
+ expected_payload = dict(key_id="AIUDHADA", secret="ASKHJSLKF")
59
+ api_response = {
60
+ "project_uuid": "project-id-1",
61
+ "type": "aws",
62
+ "key_id": "AIUDHADA",
63
+ }
64
+
65
+ mock_trainml._query = AsyncMock(return_value=api_response)
66
+ response = await project_keys.put(**requested_config)
67
+ mock_trainml._query.assert_called_once_with(
68
+ "/project/1/key/aws", "PUT", None, expected_payload
69
+ )
70
+ assert response.type == "aws"
71
+
72
+
73
+ class ProjectKeyTests:
74
+ def test_project_key_properties(self, project_key):
75
+ assert isinstance(project_key.type, str)
76
+ assert isinstance(project_key.key_id, str)
77
+ assert isinstance(project_key.project_uuid, str)
78
+
79
+ def test_project_key_str(self, project_key):
80
+ string = str(project_key)
81
+ regex = r"^{.*\"type\": \"" + project_key.type + r"\".*}$"
82
+ assert isinstance(string, str)
83
+ assert re.match(regex, string)
84
+
85
+ def test_project_key_repr(self, project_key):
86
+ string = repr(project_key)
87
+ regex = (
88
+ r"^ProjectKey\( trainml , \*\*{.*'type': '" + project_key.type + r"'.*}\)$"
89
+ )
90
+ assert isinstance(string, str)
91
+ assert re.match(regex, string)
92
+
93
+ def test_project_key_bool(self, project_key, mock_trainml):
94
+ empty_project_key = specimen.ProjectKey(mock_trainml)
95
+ assert bool(project_key)
96
+ assert not bool(empty_project_key)
@@ -0,0 +1,101 @@
1
+ import re
2
+ import json
3
+ import logging
4
+ from unittest.mock import AsyncMock, patch
5
+ from pytest import mark, fixture, raises
6
+ from aiohttp import WSMessage, WSMsgType
7
+
8
+ import trainml.projects.secrets as specimen
9
+ from trainml.exceptions import (
10
+ ApiError,
11
+ SpecificationError,
12
+ TrainMLException,
13
+ )
14
+
15
+ pytestmark = [mark.sdk, mark.unit, mark.projects]
16
+
17
+
18
+ @fixture
19
+ def project_secrets(mock_trainml):
20
+ yield specimen.ProjectSecrets(mock_trainml, project_id="1")
21
+
22
+
23
+ @fixture
24
+ def project_service(mock_trainml):
25
+ yield specimen.ProjectSecret(
26
+ mock_trainml,
27
+ project_uuid="proj-id-1",
28
+ name="secret_value",
29
+ )
30
+
31
+
32
+ class ProjectSecretsTests:
33
+ @mark.asyncio
34
+ async def test_project_secrets_list(self, project_secrets, mock_trainml):
35
+ api_response = [
36
+ {
37
+ "project_uuid": "proj-id-1",
38
+ "name": "secret_value",
39
+ },
40
+ {
41
+ "project_uuid": "proj-id-1",
42
+ "name": "secret_value_2",
43
+ },
44
+ ]
45
+ mock_trainml._query = AsyncMock(return_value=api_response)
46
+ resp = await project_secrets.list()
47
+ mock_trainml._query.assert_called_once_with("/project/1/secrets", "GET", dict())
48
+ assert len(resp) == 2
49
+
50
+ @mark.asyncio
51
+ async def test_remove_project_secret(
52
+ self,
53
+ project_secrets,
54
+ mock_trainml,
55
+ ):
56
+ api_response = dict()
57
+ mock_trainml._query = AsyncMock(return_value=api_response)
58
+ await project_secrets.remove("secret_value")
59
+ mock_trainml._query.assert_called_once_with(
60
+ "/project/1/secret/secret_value", "DELETE", dict()
61
+ )
62
+
63
+ @mark.asyncio
64
+ async def test_put_project_secret(self, project_secrets, mock_trainml):
65
+ requested_config = dict(name="secret_value", value="ASKHJSLKF")
66
+ expected_payload = dict(value="ASKHJSLKF")
67
+ api_response = {"project_uuid": "project-id-1", "name": "secret_value"}
68
+
69
+ mock_trainml._query = AsyncMock(return_value=api_response)
70
+ response = await project_secrets.put(**requested_config)
71
+ mock_trainml._query.assert_called_once_with(
72
+ "/project/1/secret/secret_value", "PUT", None, expected_payload
73
+ )
74
+ assert response.name == "secret_value"
75
+
76
+
77
+ class ProjectSecretTests:
78
+ def test_project_service_properties(self, project_service):
79
+ assert isinstance(project_service.name, str)
80
+ assert isinstance(project_service.project_uuid, str)
81
+
82
+ def test_project_service_str(self, project_service):
83
+ string = str(project_service)
84
+ regex = r"^{.*\"name\": \"" + project_service.name + r"\".*}$"
85
+ assert isinstance(string, str)
86
+ assert re.match(regex, string)
87
+
88
+ def test_project_service_repr(self, project_service):
89
+ string = repr(project_service)
90
+ regex = (
91
+ r"^ProjectSecret\( trainml , \*\*{.*'name': '"
92
+ + project_service.name
93
+ + r"'.*}\)$"
94
+ )
95
+ assert isinstance(string, str)
96
+ assert re.match(regex, string)
97
+
98
+ def test_project_service_bool(self, project_service, mock_trainml):
99
+ empty_project_service = specimen.ProjectSecret(mock_trainml)
100
+ assert bool(project_service)
101
+ assert not bool(empty_project_service)