proximl 0.5.8__tar.gz → 0.5.10__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. {proximl-0.5.8/proximl.egg-info → proximl-0.5.10}/PKG-INFO +1 -1
  2. {proximl-0.5.8 → proximl-0.5.10}/proximl/__init__.py +1 -1
  3. {proximl-0.5.8 → proximl-0.5.10}/proximl/checkpoints.py +14 -3
  4. {proximl-0.5.8 → proximl-0.5.10}/proximl/cli/cloudbender/datastore.py +2 -7
  5. proximl-0.5.8/proximl/cli/project.py → proximl-0.5.10/proximl/cli/project/__init__.py +4 -0
  6. proximl-0.5.10/proximl/cli/project/key.py +124 -0
  7. proximl-0.5.10/proximl/cli/project/secret.py +71 -0
  8. {proximl-0.5.8 → proximl-0.5.10}/proximl/cloudbender/data_connectors.py +8 -0
  9. {proximl-0.5.8 → proximl-0.5.10}/proximl/cloudbender/datastores.py +9 -19
  10. {proximl-0.5.8 → proximl-0.5.10}/proximl/cloudbender/nodes.py +45 -0
  11. {proximl-0.5.8 → proximl-0.5.10}/proximl/datasets.py +14 -3
  12. {proximl-0.5.8 → proximl-0.5.10}/proximl/jobs.py +2 -13
  13. {proximl-0.5.8 → proximl-0.5.10}/proximl/models.py +14 -3
  14. proximl-0.5.10/proximl/projects/__init__.py +3 -0
  15. proximl-0.5.10/proximl/projects/data_connectors.py +63 -0
  16. proximl-0.5.10/proximl/projects/datastores.py +58 -0
  17. proximl-0.5.10/proximl/projects/keys.py +71 -0
  18. proximl-0.5.10/proximl/projects/projects.py +83 -0
  19. proximl-0.5.10/proximl/projects/secrets.py +70 -0
  20. proximl-0.5.10/proximl/projects/services.py +63 -0
  21. {proximl-0.5.8 → proximl-0.5.10}/proximl/volumes.py +15 -3
  22. {proximl-0.5.8 → proximl-0.5.10/proximl.egg-info}/PKG-INFO +1 -1
  23. {proximl-0.5.8 → proximl-0.5.10}/proximl.egg-info/SOURCES.txt +25 -7
  24. proximl-0.5.10/tests/integration/projects/conftest.py +8 -0
  25. {proximl-0.5.8/tests/integration → proximl-0.5.10/tests/integration/projects}/test_projects_integration.py +0 -6
  26. proximl-0.5.10/tests/integration/projects/test_projects_keys_integration.py +43 -0
  27. proximl-0.5.10/tests/integration/projects/test_projects_secrets_integration.py +44 -0
  28. {proximl-0.5.8 → proximl-0.5.10}/tests/integration/test_checkpoints_integration.py +0 -1
  29. {proximl-0.5.8 → proximl-0.5.10}/tests/integration/test_models_integration.py +0 -1
  30. proximl-0.5.10/tests/unit/cloudbender/__init__.py +0 -0
  31. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/cloudbender/test_datastores_unit.py +1 -5
  32. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/conftest.py +72 -2
  33. proximl-0.5.10/tests/unit/projects/__init__.py +0 -0
  34. proximl-0.5.10/tests/unit/projects/test_project_data_connectors_unit.py +102 -0
  35. proximl-0.5.10/tests/unit/projects/test_project_datastores_unit.py +96 -0
  36. proximl-0.5.10/tests/unit/projects/test_project_keys_unit.py +96 -0
  37. proximl-0.5.10/tests/unit/projects/test_project_secrets_unit.py +101 -0
  38. proximl-0.5.10/tests/unit/projects/test_project_services_unit.py +102 -0
  39. proximl-0.5.10/tests/unit/projects/test_projects_unit.py +128 -0
  40. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/test_checkpoints_unit.py +15 -23
  41. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/test_datasets_unit.py +15 -20
  42. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/test_models_unit.py +13 -16
  43. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/test_volumes_unit.py +3 -0
  44. proximl-0.5.8/proximl/projects.py +0 -228
  45. proximl-0.5.8/tests/unit/test_projects_unit.py +0 -320
  46. {proximl-0.5.8 → proximl-0.5.10}/LICENSE +0 -0
  47. {proximl-0.5.8 → proximl-0.5.10}/README.md +0 -0
  48. {proximl-0.5.8 → proximl-0.5.10}/examples/__init__.py +0 -0
  49. {proximl-0.5.8 → proximl-0.5.10}/examples/create_dataset_and_training_job.py +0 -0
  50. {proximl-0.5.8 → proximl-0.5.10}/examples/local_storage.py +0 -0
  51. {proximl-0.5.8 → proximl-0.5.10}/examples/training_inference_pipeline.py +0 -0
  52. {proximl-0.5.8 → proximl-0.5.10}/proximl/__main__.py +0 -0
  53. {proximl-0.5.8 → proximl-0.5.10}/proximl/auth.py +0 -0
  54. {proximl-0.5.8 → proximl-0.5.10}/proximl/cli/__init__.py +0 -0
  55. {proximl-0.5.8 → proximl-0.5.10}/proximl/cli/checkpoint.py +0 -0
  56. {proximl-0.5.8 → proximl-0.5.10}/proximl/cli/cloudbender/__init__.py +0 -0
  57. {proximl-0.5.8 → proximl-0.5.10}/proximl/cli/cloudbender/data_connector.py +0 -0
  58. {proximl-0.5.8 → proximl-0.5.10}/proximl/cli/cloudbender/device.py +0 -0
  59. {proximl-0.5.8 → proximl-0.5.10}/proximl/cli/cloudbender/node.py +0 -0
  60. {proximl-0.5.8 → proximl-0.5.10}/proximl/cli/cloudbender/provider.py +0 -0
  61. {proximl-0.5.8 → proximl-0.5.10}/proximl/cli/cloudbender/region.py +0 -0
  62. {proximl-0.5.8 → proximl-0.5.10}/proximl/cli/cloudbender/service.py +0 -0
  63. {proximl-0.5.8 → proximl-0.5.10}/proximl/cli/connection.py +0 -0
  64. {proximl-0.5.8 → proximl-0.5.10}/proximl/cli/dataset.py +0 -0
  65. {proximl-0.5.8 → proximl-0.5.10}/proximl/cli/environment.py +0 -0
  66. {proximl-0.5.8 → proximl-0.5.10}/proximl/cli/gpu.py +0 -0
  67. {proximl-0.5.8 → proximl-0.5.10}/proximl/cli/job/__init__.py +0 -0
  68. {proximl-0.5.8 → proximl-0.5.10}/proximl/cli/job/create.py +0 -0
  69. {proximl-0.5.8 → proximl-0.5.10}/proximl/cli/model.py +0 -0
  70. {proximl-0.5.8 → proximl-0.5.10}/proximl/cli/volume.py +0 -0
  71. {proximl-0.5.8 → proximl-0.5.10}/proximl/cloudbender/__init__.py +0 -0
  72. {proximl-0.5.8 → proximl-0.5.10}/proximl/cloudbender/cloudbender.py +0 -0
  73. {proximl-0.5.8 → proximl-0.5.10}/proximl/cloudbender/device_configs.py +0 -0
  74. {proximl-0.5.8 → proximl-0.5.10}/proximl/cloudbender/devices.py +0 -0
  75. {proximl-0.5.8 → proximl-0.5.10}/proximl/cloudbender/providers.py +0 -0
  76. {proximl-0.5.8 → proximl-0.5.10}/proximl/cloudbender/regions.py +0 -0
  77. {proximl-0.5.8 → proximl-0.5.10}/proximl/cloudbender/services.py +0 -0
  78. {proximl-0.5.8 → proximl-0.5.10}/proximl/connections.py +0 -0
  79. {proximl-0.5.8 → proximl-0.5.10}/proximl/environments.py +0 -0
  80. {proximl-0.5.8 → proximl-0.5.10}/proximl/exceptions.py +0 -0
  81. {proximl-0.5.8 → proximl-0.5.10}/proximl/gpu_types.py +0 -0
  82. {proximl-0.5.8 → proximl-0.5.10}/proximl/proximl.py +0 -0
  83. {proximl-0.5.8 → proximl-0.5.10}/proximl.egg-info/dependency_links.txt +0 -0
  84. {proximl-0.5.8 → proximl-0.5.10}/proximl.egg-info/entry_points.txt +0 -0
  85. {proximl-0.5.8 → proximl-0.5.10}/proximl.egg-info/requires.txt +0 -0
  86. {proximl-0.5.8 → proximl-0.5.10}/proximl.egg-info/top_level.txt +0 -0
  87. {proximl-0.5.8 → proximl-0.5.10}/pyproject.toml +0 -0
  88. {proximl-0.5.8 → proximl-0.5.10}/setup.cfg +0 -0
  89. {proximl-0.5.8 → proximl-0.5.10}/setup.py +0 -0
  90. {proximl-0.5.8 → proximl-0.5.10}/tests/integration/__init__.py +0 -0
  91. {proximl-0.5.8 → proximl-0.5.10}/tests/integration/cloudbender/__init__.py +0 -0
  92. {proximl-0.5.8 → proximl-0.5.10}/tests/integration/cloudbender/test_providers_integration.py +0 -0
  93. {proximl-0.5.8 → proximl-0.5.10}/tests/integration/conftest.py +0 -0
  94. {proximl-0.5.8/tests/unit → proximl-0.5.10/tests/integration/projects}/__init__.py +0 -0
  95. {proximl-0.5.8 → proximl-0.5.10}/tests/integration/test_datasets_integration.py +0 -0
  96. {proximl-0.5.8 → proximl-0.5.10}/tests/integration/test_environments_integration.py +0 -0
  97. {proximl-0.5.8 → proximl-0.5.10}/tests/integration/test_gpu_types_integration.py +0 -0
  98. {proximl-0.5.8 → proximl-0.5.10}/tests/integration/test_jobs_integration.py +0 -0
  99. {proximl-0.5.8 → proximl-0.5.10}/tests/integration/test_volumes_integration.py +0 -0
  100. {proximl-0.5.8/tests/unit/cli → proximl-0.5.10/tests/unit}/__init__.py +0 -0
  101. {proximl-0.5.8/tests/unit/cli/cloudbender → proximl-0.5.10/tests/unit/cli}/__init__.py +0 -0
  102. {proximl-0.5.8/tests/unit → proximl-0.5.10/tests/unit/cli}/cloudbender/__init__.py +0 -0
  103. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/cli/cloudbender/test_cli_datastore_unit.py +0 -0
  104. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/cli/cloudbender/test_cli_device_unit.py +0 -0
  105. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/cli/cloudbender/test_cli_node_unit.py +0 -0
  106. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/cli/cloudbender/test_cli_provider_unit.py +0 -0
  107. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/cli/cloudbender/test_cli_region_unit.py +0 -0
  108. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/cli/cloudbender/test_cli_service_unit.py +0 -0
  109. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/cli/conftest.py +0 -0
  110. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/cli/test_cli_checkpoint_unit.py +0 -0
  111. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/cli/test_cli_datasets_unit.py +0 -0
  112. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/cli/test_cli_environment_unit.py +0 -0
  113. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/cli/test_cli_gpu_unit.py +0 -0
  114. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/cli/test_cli_job_unit.py +0 -0
  115. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/cli/test_cli_model_unit.py +0 -0
  116. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/cli/test_cli_project_unit.py +0 -0
  117. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/cli/test_cli_volume_unit.py +0 -0
  118. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/cloudbender/test_data_connectors_unit.py +0 -0
  119. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/cloudbender/test_device_configs_unit.py +0 -0
  120. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/cloudbender/test_devices_unit.py +0 -0
  121. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/cloudbender/test_nodes_unit.py +0 -0
  122. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/cloudbender/test_providers_unit.py +0 -0
  123. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/cloudbender/test_regions_unit.py +0 -0
  124. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/cloudbender/test_services_unit.py +0 -0
  125. /proximl-0.5.8/tests/unit/test_auth.py → /proximl-0.5.10/tests/unit/test_auth_unit.py +0 -0
  126. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/test_connections_unit.py +0 -0
  127. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/test_environments_unit.py +0 -0
  128. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/test_exceptions.py +0 -0
  129. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/test_gpu_types_unit.py +0 -0
  130. {proximl-0.5.8 → proximl-0.5.10}/tests/unit/test_jobs_unit.py +0 -0
  131. /proximl-0.5.8/tests/unit/test_proximl.py → /proximl-0.5.10/tests/unit/test_proximl_unit.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: proximl
3
- Version: 0.5.8
3
+ Version: 0.5.10
4
4
  Summary: proxiML client SDK and command line utilities
5
5
  Home-page: https://github.com/proxiML/python-sdk
6
6
  Author: proxiML
@@ -13,5 +13,5 @@ logging.basicConfig(
13
13
  logger = logging.getLogger(__name__)
14
14
 
15
15
 
16
- __version__ = "0.5.8"
16
+ __version__ = "0.5.10"
17
17
  __all__ = "ProxiML"
@@ -31,13 +31,24 @@ class Checkpoints(object):
31
31
  datasets = [Checkpoint(self.proximl, **dataset) for dataset in resp]
32
32
  return datasets
33
33
 
34
- async def create(self, name, source_type, source_uri, **kwargs):
34
+ async def create(
35
+ self,
36
+ name,
37
+ source_type,
38
+ source_uri,
39
+ type="evefs",
40
+ project_uuid=None,
41
+ **kwargs,
42
+ ):
43
+ if not project_uuid:
44
+ project_uuid = self.proximl.active_project
35
45
  data = dict(
36
46
  name=name,
37
47
  source_type=source_type,
38
48
  source_uri=source_uri,
39
- source_options=kwargs.get("source_options"),
40
- project_uuid=kwargs.get("project_uuid") or self.proximl.active_project,
49
+ project_uuid=project_uuid,
50
+ type=type,
51
+ **kwargs,
41
52
  )
42
53
  payload = {k: v for k, v in data.items() if v is not None}
43
54
  logging.info(f"Creating Checkpoint {name}")
@@ -29,13 +29,11 @@ def datastore(config):
29
29
  def list(config, provider, region):
30
30
  """List datastores."""
31
31
  data = [
32
- ["ID", "NAME", "TYPE", "URI", "ROOT"],
32
+ ["ID", "NAME", "TYPE"],
33
33
  [
34
34
  "-" * 80,
35
35
  "-" * 80,
36
36
  "-" * 80,
37
- "-" * 80,
38
- "-" * 80,
39
37
  ],
40
38
  ]
41
39
 
@@ -51,15 +49,12 @@ def list(config, provider, region):
51
49
  datastore.id,
52
50
  datastore.name,
53
51
  datastore.type,
54
- datastore.uri,
55
- datastore.root,
56
52
  ]
57
53
  )
58
54
 
59
55
  for row in data:
60
56
  click.echo(
61
- "{: >37.36} {: >29.28} {: >9.8} {: >12.11} {: >12.11}"
62
- "".format(*row),
57
+ "{: >37.36} {: >29.28} {: >9.8} " "".format(*row),
63
58
  file=config.stdout,
64
59
  )
65
60
 
@@ -147,3 +147,7 @@ def list_services(config):
147
147
  "{: >38.36} {: >30.28} {: >30.28} {: >38.36}" "".format(*row),
148
148
  file=config.stdout,
149
149
  )
150
+
151
+
152
+ from proximl.cli.project.secret import secret
153
+ from proximl.cli.project.key import key
@@ -0,0 +1,124 @@
1
+ import click
2
+ import os
3
+ import json
4
+ import base64
5
+ from pathlib import Path
6
+ from proximl.cli import pass_config
7
+ from proximl.cli.project import project
8
+
9
+
10
+ @project.group()
11
+ @pass_config
12
+ def key(config):
13
+ """proxiML project key commands."""
14
+ pass
15
+
16
+
17
+ @key.command()
18
+ @pass_config
19
+ def list(config):
20
+ """List keys."""
21
+ data = [
22
+ ["TYPE", "KEY ID", "UPDATED AT"],
23
+ [
24
+ "-" * 80,
25
+ "-" * 80,
26
+ "-" * 80,
27
+ ],
28
+ ]
29
+ project = config.proximl.run(config.proximl.client.projects.get_current())
30
+ keys = config.proximl.run(project.keys.list())
31
+
32
+ for key in keys:
33
+ data.append(
34
+ [
35
+ key.type,
36
+ key.key_id,
37
+ key.updated_at.isoformat(timespec="seconds"),
38
+ ]
39
+ )
40
+
41
+ for row in data:
42
+ click.echo(
43
+ "{: >13.11} {: >37.35} {: >28.26}" "".format(*row),
44
+ file=config.stdout,
45
+ )
46
+
47
+
48
+ @key.command()
49
+ @click.argument(
50
+ "type",
51
+ type=click.Choice(
52
+ [
53
+ "aws",
54
+ "azure",
55
+ "docker",
56
+ "gcp",
57
+ "huggingface",
58
+ "kaggle",
59
+ "ngc",
60
+ "wasabi",
61
+ ],
62
+ case_sensitive=False,
63
+ ),
64
+ )
65
+ @pass_config
66
+ def put(config, type):
67
+ """
68
+ Set a key.
69
+
70
+ A key is uploaded.
71
+ """
72
+ project = config.proximl.run(config.proximl.client.projects.get_current())
73
+
74
+ tenant = None
75
+
76
+ if type in ["aws", "wasabi"]:
77
+ key_id = click.prompt("Enter the key ID", type=str, hide_input=False)
78
+ secret = click.prompt("Enter the secret key", type=str, hide_input=True)
79
+ elif type == "azure":
80
+ key_id = click.prompt(
81
+ "Enter the Application (client) ID", type=str, hide_input=False
82
+ )
83
+ tenant = click.prompt(
84
+ "Enter the Directory (tenant) ley", type=str, hide_input=False
85
+ )
86
+ secret = click.prompt("Enter the client secret", type=str, hide_input=True)
87
+ elif type in ["docker", "huggingface"]:
88
+ key_id = click.prompt("Enter the username", type=str, hide_input=False)
89
+ secret = click.prompt("Enter the access token", type=str, hide_input=True)
90
+ elif type in ["gcp", "kaggle"]:
91
+ file_name = click.prompt(
92
+ "Enter the path of the credentials file",
93
+ type=click.Path(
94
+ exists=True, file_okay=True, dir_okay=False, resolve_path=True
95
+ ),
96
+ hide_input=False,
97
+ )
98
+ key_id = os.path.basename(file_name)
99
+ with open(file_name) as f:
100
+ secret = json.load(f)
101
+ secret = json.dumps(secret)
102
+ elif type == "ngc":
103
+ key_id = "$oauthtoken"
104
+ secret = click.prompt("Enter the access token", type=str, hide_input=True)
105
+ else:
106
+ raise click.UsageError("Unsupported key type")
107
+
108
+ return config.proximl.run(
109
+ project.keys.put(type=type, key_id=key_id, secret=secret, tenant=tenant)
110
+ )
111
+
112
+
113
+ @key.command()
114
+ @click.argument("name", type=click.STRING)
115
+ @pass_config
116
+ def remove(config, name):
117
+ """
118
+ Remove a key.
119
+
120
+
121
+ """
122
+ project = config.proximl.run(config.proximl.client.projects.get_current())
123
+
124
+ return config.proximl.run(project.key.remove(name))
@@ -0,0 +1,71 @@
1
+ import click
2
+ from proximl.cli import pass_config
3
+ from proximl.cli.project import project
4
+
5
+
6
+ @project.group()
7
+ @pass_config
8
+ def secret(config):
9
+ """proxiML project secret commands."""
10
+ pass
11
+
12
+
13
+ @secret.command()
14
+ @pass_config
15
+ def list(config):
16
+ """List secrets."""
17
+ data = [
18
+ ["NAME", "CREATED BY", "UPDATED AT"],
19
+ [
20
+ "-" * 80,
21
+ "-" * 80,
22
+ "-" * 80,
23
+ ],
24
+ ]
25
+ project = config.proximl.run(config.proximl.client.projects.get_current())
26
+ secrets = config.proximl.run(project.secrets.list())
27
+
28
+ for secret in secrets:
29
+ data.append(
30
+ [
31
+ secret.name,
32
+ secret.created_by,
33
+ secret.updated_at.isoformat(timespec="seconds"),
34
+ ]
35
+ )
36
+
37
+ for row in data:
38
+ click.echo(
39
+ "{: >38.36} {: >30.28} {: >28.26}" "".format(*row),
40
+ file=config.stdout,
41
+ )
42
+
43
+
44
+ @secret.command()
45
+ @click.argument("name", type=click.STRING)
46
+ @pass_config
47
+ def put(config, name):
48
+ """
49
+ Set a secret value.
50
+
51
+ Secret is created with the specified NAME.
52
+ """
53
+ project = config.proximl.run(config.proximl.client.projects.get_current())
54
+
55
+ value = click.prompt("Enter the secret value", type=str, hide_input=True)
56
+
57
+ return config.proximl.run(project.secrets.put(name=name, value=value))
58
+
59
+
60
+ @secret.command()
61
+ @click.argument("name", type=click.STRING)
62
+ @pass_config
63
+ def remove(config, name):
64
+ """
65
+ Remove a secret.
66
+
67
+
68
+ """
69
+ project = config.proximl.run(config.proximl.client.projects.get_current())
70
+
71
+ return config.proximl.run(project.secret.remove(name))
@@ -1,5 +1,13 @@
1
1
  import json
2
2
  import logging
3
+ import asyncio
4
+ import math
5
+
6
+ from proximl.exceptions import (
7
+ ApiError,
8
+ SpecificationError,
9
+ ProxiMLException,
10
+ )
3
11
 
4
12
 
5
13
  class DataConnectors(object):
@@ -1,5 +1,13 @@
1
1
  import json
2
2
  import logging
3
+ import asyncio
4
+ import math
5
+
6
+ from proximl.exceptions import (
7
+ ApiError,
8
+ SpecificationError,
9
+ ProxiMLException,
10
+ )
3
11
 
4
12
 
5
13
  class Datastores(object):
@@ -20,9 +28,7 @@ class Datastores(object):
20
28
  "GET",
21
29
  kwargs,
22
30
  )
23
- datastores = [
24
- Datastore(self.proximl, **datastore) for datastore in resp
25
- ]
31
+ datastores = [Datastore(self.proximl, **datastore) for datastore in resp]
26
32
  return datastores
27
33
 
28
34
  async def create(
@@ -31,18 +37,12 @@ class Datastores(object):
31
37
  region_uuid,
32
38
  name,
33
39
  type,
34
- uri,
35
- root,
36
- options=None,
37
40
  **kwargs,
38
41
  ):
39
42
  logging.info(f"Creating Datastore {name}")
40
43
  data = dict(
41
44
  name=name,
42
45
  type=type,
43
- uri=uri,
44
- root=root,
45
- options=options,
46
46
  **kwargs,
47
47
  )
48
48
  payload = {k: v for k, v in data.items() if v is not None}
@@ -73,8 +73,6 @@ class Datastore:
73
73
  self._region_uuid = self._datastore.get("region_uuid")
74
74
  self._type = self._datastore.get("type")
75
75
  self._name = self._datastore.get("name")
76
- self._uri = self._datastore.get("uri")
77
- self._root = self._datastore.get("root")
78
76
 
79
77
  @property
80
78
  def id(self) -> str:
@@ -96,14 +94,6 @@ class Datastore:
96
94
  def name(self) -> str:
97
95
  return self._name
98
96
 
99
- @property
100
- def uri(self) -> str:
101
- return self._uri
102
-
103
- @property
104
- def root(self) -> str:
105
- return self._root
106
-
107
97
  def __str__(self):
108
98
  return json.dumps({k: v for k, v in self._datastore.items()})
109
99
 
@@ -1,5 +1,13 @@
1
1
  import json
2
2
  import logging
3
+ import asyncio
4
+ import math
5
+
6
+ from proximl.exceptions import (
7
+ ApiError,
8
+ SpecificationError,
9
+ ProxiMLException,
10
+ )
3
11
 
4
12
 
5
13
  class Nodes(object):
@@ -153,3 +161,40 @@ class Node:
153
161
  None,
154
162
  dict(command=command),
155
163
  )
164
+
165
+ async def wait_for(self, status, timeout=300):
166
+ if self.status == status:
167
+ return
168
+ valid_statuses = ["active", "maintenance", "offline", "stopped", "archived"]
169
+ if not status in valid_statuses:
170
+ raise SpecificationError(
171
+ "status",
172
+ f"Invalid wait_for status {status}. Valid statuses are: {valid_statuses}",
173
+ )
174
+ MAX_TIMEOUT = 24 * 60 * 60
175
+ if timeout > MAX_TIMEOUT:
176
+ raise SpecificationError(
177
+ "timeout",
178
+ f"timeout must be less than {MAX_TIMEOUT} seconds.",
179
+ )
180
+
181
+ POLL_INTERVAL_MIN = 5
182
+ POLL_INTERVAL_MAX = 60
183
+ POLL_INTERVAL = max(min(timeout / 60, POLL_INTERVAL_MAX), POLL_INTERVAL_MIN)
184
+ retry_count = math.ceil(timeout / POLL_INTERVAL)
185
+ count = 0
186
+ while count < retry_count:
187
+ await asyncio.sleep(POLL_INTERVAL)
188
+ try:
189
+ await self.refresh()
190
+ except ApiError as e:
191
+ if status == "archived" and e.status == 404:
192
+ return
193
+ raise e
194
+ if self.status == status:
195
+ return self
196
+ else:
197
+ count += 1
198
+ logging.debug(f"self: {self}, retry count {count}")
199
+
200
+ raise ProxiMLException(f"Timeout waiting for {status}")
@@ -31,13 +31,24 @@ class Datasets(object):
31
31
  datasets = [Dataset(self.proximl, **dataset) for dataset in resp]
32
32
  return datasets
33
33
 
34
- async def create(self, name, source_type, source_uri, **kwargs):
34
+ async def create(
35
+ self,
36
+ name,
37
+ source_type,
38
+ source_uri,
39
+ type="evefs",
40
+ project_uuid=None,
41
+ **kwargs,
42
+ ):
43
+ if not project_uuid:
44
+ project_uuid = self.proximl.active_project
35
45
  data = dict(
36
46
  name=name,
37
47
  source_type=source_type,
38
48
  source_uri=source_uri,
39
- source_options=kwargs.get("source_options"),
40
- project_uuid=kwargs.get("project_uuid") or self.proximl.active_project,
49
+ project_uuid=project_uuid,
50
+ type=type,
51
+ **kwargs,
41
52
  )
42
53
  payload = {k: v for k, v in data.items() if v is not None}
43
54
  logging.info(f"Creating Dataset {name}")
@@ -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
- in [
527
- "waiting for GPUs",
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
  ]
@@ -26,13 +26,24 @@ class Models(object):
26
26
  models = [Model(self.proximl, **model) for model in resp]
27
27
  return models
28
28
 
29
- async def create(self, name, source_type, source_uri, **kwargs):
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.proximl.active_project
30
40
  data = dict(
31
41
  name=name,
32
42
  source_type=source_type,
33
43
  source_uri=source_uri,
34
- source_options=kwargs.get("source_options"),
35
- project_uuid=kwargs.get("project_uuid") or self.proximl.active_project,
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,3 @@
1
+ from .projects import Projects, Project
2
+
3
+ __all__ = ["Projects", "Project"]
@@ -0,0 +1,63 @@
1
+ import json
2
+ import logging
3
+
4
+
5
+ class ProjectDataConnectors(object):
6
+ def __init__(self, proximl, project_id):
7
+ self.proximl = proximl
8
+ self.project_id = project_id
9
+
10
+ async def list(self, **kwargs):
11
+ resp = await self.proximl._query(
12
+ f"/project/{self.project_id}/data_connectors", "GET", kwargs
13
+ )
14
+ data_connectors = [
15
+ ProjectDataConnector(self.proximl, **data_connector)
16
+ for data_connector in resp
17
+ ]
18
+ return data_connectors
19
+
20
+ async def refresh(self):
21
+ await self.proximl._query(
22
+ f"/project/{self.project_id}/data_connectors", "PATCH"
23
+ )
24
+
25
+
26
+ class ProjectDataConnector:
27
+ def __init__(self, proximl, **kwargs):
28
+ self.proximl = proximl
29
+ self._entity = kwargs
30
+ self._id = self._entity.get("id")
31
+ self._project_uuid = self._entity.get("project_uuid")
32
+ self._name = self._entity.get("name")
33
+ self._type = self._entity.get("type")
34
+ self._region_uuid = self._entity.get("region_uuid")
35
+
36
+ @property
37
+ def id(self) -> str:
38
+ return self._id
39
+
40
+ @property
41
+ def project_uuid(self) -> str:
42
+ return self._project_uuid
43
+
44
+ @property
45
+ def name(self) -> str:
46
+ return self._name
47
+
48
+ @property
49
+ def type(self) -> str:
50
+ return self._type
51
+
52
+ @property
53
+ def region_uuid(self) -> str:
54
+ return self._region_uuid
55
+
56
+ def __str__(self):
57
+ return json.dumps({k: v for k, v in self._entity.items()})
58
+
59
+ def __repr__(self):
60
+ return f"ProjectDataConnector( proximl , **{self._entity.__repr__()})"
61
+
62
+ def __bool__(self):
63
+ return bool(self._id)
@@ -0,0 +1,58 @@
1
+ import json
2
+ import logging
3
+
4
+
5
+ class ProjectDatastores(object):
6
+ def __init__(self, proximl, project_id):
7
+ self.proximl = proximl
8
+ self.project_id = project_id
9
+
10
+ async def list(self, **kwargs):
11
+ resp = await self.proximl._query(
12
+ f"/project/{self.project_id}/datastores", "GET", kwargs
13
+ )
14
+ datastores = [ProjectDatastore(self.proximl, **datastore) for datastore in resp]
15
+ return datastores
16
+
17
+ async def refresh(self):
18
+ await self.proximl._query(f"/project/{self.project_id}/datastores", "PATCH")
19
+
20
+
21
+ class ProjectDatastore:
22
+ def __init__(self, proximl, **kwargs):
23
+ self.proximl = proximl
24
+ self._entity = kwargs
25
+ self._id = self._entity.get("id")
26
+ self._project_uuid = self._entity.get("project_uuid")
27
+ self._name = self._entity.get("name")
28
+ self._type = self._entity.get("type")
29
+ self._region_uuid = self._entity.get("region_uuid")
30
+
31
+ @property
32
+ def id(self) -> str:
33
+ return self._id
34
+
35
+ @property
36
+ def project_uuid(self) -> str:
37
+ return self._project_uuid
38
+
39
+ @property
40
+ def name(self) -> str:
41
+ return self._name
42
+
43
+ @property
44
+ def type(self) -> str:
45
+ return self._type
46
+
47
+ @property
48
+ def region_uuid(self) -> str:
49
+ return self._region_uuid
50
+
51
+ def __str__(self):
52
+ return json.dumps({k: v for k, v in self._entity.items()})
53
+
54
+ def __repr__(self):
55
+ return f"ProjectDatastore( proximl , **{self._entity.__repr__()})"
56
+
57
+ def __bool__(self):
58
+ return bool(self._id)