lightning-sdk 0.1.46__py3-none-any.whl → 0.1.48__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. lightning_sdk/__init__.py +1 -1
  2. lightning_sdk/api/job_api.py +37 -6
  3. lightning_sdk/api/lit_container_api.py +19 -0
  4. lightning_sdk/api/mmt_api.py +18 -1
  5. lightning_sdk/api/teamspace_api.py +19 -1
  6. lightning_sdk/api/utils.py +1 -1
  7. lightning_sdk/cli/delete.py +58 -0
  8. lightning_sdk/cli/entrypoint.py +8 -0
  9. lightning_sdk/cli/inspect.py +31 -0
  10. lightning_sdk/cli/job_and_mmt_action.py +37 -0
  11. lightning_sdk/cli/jobs_menu.py +57 -0
  12. lightning_sdk/cli/list.py +54 -0
  13. lightning_sdk/cli/mmts_menu.py +57 -0
  14. lightning_sdk/cli/run.py +12 -0
  15. lightning_sdk/cli/stop.py +37 -0
  16. lightning_sdk/cli/teamspace_menu.py +94 -0
  17. lightning_sdk/job/base.py +70 -2
  18. lightning_sdk/job/job.py +59 -9
  19. lightning_sdk/job/v1.py +28 -0
  20. lightning_sdk/job/v2.py +40 -4
  21. lightning_sdk/job/work.py +10 -1
  22. lightning_sdk/lightning_cloud/openapi/__init__.py +3 -0
  23. lightning_sdk/lightning_cloud/openapi/api/lit_registry_service_api.py +202 -0
  24. lightning_sdk/lightning_cloud/openapi/api/models_store_api.py +250 -8
  25. lightning_sdk/lightning_cloud/openapi/models/__init__.py +3 -0
  26. lightning_sdk/lightning_cloud/openapi/models/v1_aws_direct_v1.py +27 -1
  27. lightning_sdk/lightning_cloud/openapi/models/v1_delete_lit_repository_response.py +97 -0
  28. lightning_sdk/lightning_cloud/openapi/models/v1_deployment_api.py +27 -1
  29. lightning_sdk/lightning_cloud/openapi/models/v1_deployment_state.py +1 -0
  30. lightning_sdk/lightning_cloud/openapi/models/v1_google_cloud_direct_v1.py +29 -27
  31. lightning_sdk/lightning_cloud/openapi/models/v1_job.py +27 -1
  32. lightning_sdk/lightning_cloud/openapi/models/v1_model.py +27 -1
  33. lightning_sdk/lightning_cloud/openapi/models/v1_resource_visibility.py +29 -3
  34. lightning_sdk/lightning_cloud/openapi/models/v1_user_features.py +27 -53
  35. lightning_sdk/lightning_cloud/openapi/models/v1_vultr_direct_v1.py +55 -3
  36. lightning_sdk/lightning_cloud/openapi/models/version_default_body.py +149 -0
  37. lightning_sdk/lightning_cloud/openapi/models/versions_version_body.py +123 -0
  38. lightning_sdk/lightning_cloud/utils/data_connection.py +1 -1
  39. lightning_sdk/lit_container.py +57 -0
  40. lightning_sdk/machine.py +4 -0
  41. lightning_sdk/mmt/base.py +39 -1
  42. lightning_sdk/mmt/mmt.py +59 -14
  43. lightning_sdk/mmt/v1.py +30 -2
  44. lightning_sdk/mmt/v2.py +31 -2
  45. lightning_sdk/status.py +11 -7
  46. lightning_sdk/teamspace.py +51 -1
  47. {lightning_sdk-0.1.46.dist-info → lightning_sdk-0.1.48.dist-info}/METADATA +1 -1
  48. {lightning_sdk-0.1.46.dist-info → lightning_sdk-0.1.48.dist-info}/RECORD +52 -39
  49. {lightning_sdk-0.1.46.dist-info → lightning_sdk-0.1.48.dist-info}/LICENSE +0 -0
  50. {lightning_sdk-0.1.46.dist-info → lightning_sdk-0.1.48.dist-info}/WHEEL +0 -0
  51. {lightning_sdk-0.1.46.dist-info → lightning_sdk-0.1.48.dist-info}/entry_points.txt +0 -0
  52. {lightning_sdk-0.1.46.dist-info → lightning_sdk-0.1.48.dist-info}/top_level.txt +0 -0
lightning_sdk/mmt/base.py CHANGED
@@ -1,7 +1,8 @@
1
1
  from abc import abstractmethod
2
- from typing import TYPE_CHECKING, Dict, Optional, Protocol, Tuple, Union
2
+ from typing import TYPE_CHECKING, Dict, List, Optional, Protocol, Tuple, Union
3
3
 
4
4
  if TYPE_CHECKING:
5
+ from lightning_sdk.job.base import MachineDict
5
6
  from lightning_sdk.machine import Machine
6
7
  from lightning_sdk.organization import Organization
7
8
  from lightning_sdk.status import Status
@@ -41,6 +42,10 @@ class MMTMachine(Protocol):
41
42
  """The logs of the given machine."""
42
43
  ...
43
44
 
45
+ def dict(self) -> "MachineDict":
46
+ """Dict representation of the given machine."""
47
+ ...
48
+
44
49
 
45
50
  class _BaseMMT(_BaseJob):
46
51
  """Base interface to all job types."""
@@ -64,6 +69,7 @@ class _BaseMMT(_BaseJob):
64
69
  cloud_account_auth: bool = False,
65
70
  artifacts_local: Optional[str] = None,
66
71
  artifacts_remote: Optional[str] = None,
72
+ entrypoint: str = "sh -c",
67
73
  cluster: Optional[str] = None, # deprecated in favor of cloud_account
68
74
  ) -> "_BaseMMT":
69
75
  """Run async workloads using a docker image across multiple machines.
@@ -98,6 +104,10 @@ class _BaseMMT(_BaseJob):
98
104
  within it.
99
105
  Note that the connection needs to be added to the teamspace already in order for it to be found.
100
106
  Only supported for jobs with a docker image compute environment.
107
+ entrypoint: The entrypoint of your docker container. Defaults to `sh -c` which
108
+ just runs the provided command in a standard shell.
109
+ To use the pre-defined entrypoint of the provided image, set this to an empty string.
110
+ Only applicable when submitting docker jobs.
101
111
  """
102
112
  from lightning_sdk.studio import Studio
103
113
 
@@ -148,6 +158,9 @@ class _BaseMMT(_BaseJob):
148
158
  "Other jobs will automatically persist artifacts to the teamspace distributed filesystem."
149
159
  )
150
160
 
161
+ if entrypoint != "sh -c":
162
+ raise ValueError("Specifying the entrypoint has no effect for jobs with Studio envs.")
163
+
151
164
  else:
152
165
  if studio is not None:
153
166
  raise RuntimeError(
@@ -178,6 +191,7 @@ class _BaseMMT(_BaseJob):
178
191
  cloud_account_auth=cloud_account_auth,
179
192
  artifacts_local=artifacts_local,
180
193
  artifacts_remote=artifacts_remote,
194
+ entrypoint=entrypoint,
181
195
  )
182
196
  return inst
183
197
 
@@ -196,6 +210,7 @@ class _BaseMMT(_BaseJob):
196
210
  cloud_account_auth: bool = False,
197
211
  artifacts_local: Optional[str] = None,
198
212
  artifacts_remote: Optional[str] = None,
213
+ entrypoint: str = "sh -c",
199
214
  ) -> None:
200
215
  """Submit a new multi-machine job to the Lightning AI platform.
201
216
 
@@ -225,6 +240,9 @@ class _BaseMMT(_BaseJob):
225
240
  within it.
226
241
  Note that the connection needs to be added to the teamspace already in order for it to be found.
227
242
  Only supported for jobs with a docker image compute environment.
243
+ entrypoint: The entrypoint of your docker container. Defaults to sh -c.
244
+ To use the pre-defined entrypoint of the provided image, set this to an empty string.
245
+ Only applicable when submitting docker jobs.
228
246
  """
229
247
 
230
248
  @property
@@ -283,6 +301,26 @@ class _BaseMMT(_BaseJob):
283
301
  """Logs of the rank 0 machine."""
284
302
  return self.machines[0].logs
285
303
 
304
+ def dict(
305
+ self
306
+ ) -> Dict[str, Union[str, "Studio", "Status", "Machine", None, List[Dict[str, Union[str, "Status", "Machine"]]]]]:
307
+ """Dict representation of this job."""
308
+ studio = self.studio
309
+
310
+ return {
311
+ "name": self.name,
312
+ "teamspace": f"{self.teamspace.owner.name}/{self.teamspace.name}",
313
+ "studio": studio.name if studio else None,
314
+ "image": self.image,
315
+ "command": self.command,
316
+ "status": self.status,
317
+ "machine": self.machine,
318
+ "machines": [
319
+ {"name": d["name"], "status": d["status"], "machine": d["machine"]}
320
+ for d in (x.dict() for x in self.machines)
321
+ ],
322
+ }
323
+
286
324
  @abstractmethod
287
325
  def _update_internal_job(self) -> None:
288
326
  pass
lightning_sdk/mmt/mmt.py CHANGED
@@ -1,4 +1,3 @@
1
- from contextlib import suppress
2
1
  from functools import lru_cache
3
2
  from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple, Union
4
3
 
@@ -58,15 +57,40 @@ class MMT(_BaseMMT):
58
57
  user: the name of the user owning the :param`teamspace`
59
58
  in case it is owned directly by a user instead of an org.
60
59
  """
61
- internal_mmt_cls = _MMTV2 if _has_mmt_v2() and not self._force_v1 else _MMTV1
62
-
63
- self._internal_mmt = internal_mmt_cls(
64
- name=name,
65
- teamspace=teamspace,
66
- org=org,
67
- user=user,
68
- _fetch_job=_fetch_job,
69
- )
60
+ from lightning_sdk.lightning_cloud.openapi.rest import ApiException
61
+
62
+ if _has_mmt_v2() and not self._force_v1:
63
+ # try with v2 and fall back to v1
64
+ try:
65
+ mmt = _MMTV2(
66
+ name=name,
67
+ teamspace=teamspace,
68
+ org=org,
69
+ user=user,
70
+ _fetch_job=_fetch_job,
71
+ )
72
+ except ApiException as e:
73
+ try:
74
+ mmt = _MMTV1(
75
+ name=name,
76
+ teamspace=teamspace,
77
+ org=org,
78
+ user=user,
79
+ _fetch_job=_fetch_job,
80
+ )
81
+ except ApiException:
82
+ raise e from e
83
+
84
+ else:
85
+ mmt = _MMTV1(
86
+ name=name,
87
+ teamspace=teamspace,
88
+ org=org,
89
+ user=user,
90
+ _fetch_job=_fetch_job,
91
+ )
92
+
93
+ self._internal_mmt = mmt
70
94
 
71
95
  @classmethod
72
96
  def run(
@@ -87,6 +111,7 @@ class MMT(_BaseMMT):
87
111
  cloud_account_auth: bool = False,
88
112
  artifacts_local: Optional[str] = None,
89
113
  artifacts_remote: Optional[str] = None,
114
+ entrypoint: str = "sh -c",
90
115
  cluster: Optional[str] = None, # deprecated in favor of cloud_account
91
116
  ) -> "MMT":
92
117
  """Run async workloads using a docker image across multiple machines.
@@ -121,6 +146,9 @@ class MMT(_BaseMMT):
121
146
  within it.
122
147
  Note that the connection needs to be added to the teamspace already in order for it to be found.
123
148
  Only supported for jobs with a docker image compute environment.
149
+ entrypoint: The entrypoint of your docker container. Defaults to sh -c.
150
+ To use the pre-defined entrypoint of the provided image, set this to an empty string.
151
+ Only applicable when submitting docker jobs.
124
152
  """
125
153
  ret_val = super().run(
126
154
  name=name,
@@ -144,10 +172,7 @@ class MMT(_BaseMMT):
144
172
  # required for typing with "MMT"
145
173
  assert isinstance(ret_val, cls)
146
174
 
147
- msg = "Multi-Machine Job was successfully launched."
148
-
149
- with suppress(NotImplementedError):
150
- msg += f" View it at {ret_val.link}"
175
+ msg = f"Multi-Machine Job was successfully launched. View it at {ret_val.link}"
151
176
 
152
177
  _logger.info(msg)
153
178
  return ret_val
@@ -166,6 +191,7 @@ class MMT(_BaseMMT):
166
191
  cloud_account_auth: bool = False,
167
192
  artifacts_local: Optional[str] = None,
168
193
  artifacts_remote: Optional[str] = None,
194
+ entrypoint: str = "sh -c",
169
195
  ) -> "MMT":
170
196
  """Submit a new multi-machine job to the Lightning AI platform.
171
197
 
@@ -195,6 +221,10 @@ class MMT(_BaseMMT):
195
221
  within it.
196
222
  Note that the connection needs to be added to the teamspace already in order for it to be found.
197
223
  Only supported for jobs with a docker image compute environment.
224
+ entrypoint: The entrypoint of your docker container. Defaults to `sh -c` which
225
+ just runs the provided command in a standard shell.
226
+ To use the pre-defined entrypoint of the provided image, set this to an empty string.
227
+ Only applicable when submitting docker jobs.
198
228
  """
199
229
  self._job = self._internal_mmt._submit(
200
230
  num_machines=num_machines,
@@ -270,6 +300,21 @@ class MMT(_BaseMMT):
270
300
  def link(self) -> str:
271
301
  return self._internal_mmt.link
272
302
 
303
+ @property
304
+ def studio(self) -> Optional["Studio"]:
305
+ """The studio used to submit the MMT."""
306
+ return self._internal_mmt.studio
307
+
308
+ @property
309
+ def image(self) -> Optional[str]:
310
+ """The image used to submit the MMT."""
311
+ return self._internal_mmt.image
312
+
313
+ @property
314
+ def command(self) -> str:
315
+ """The command the MMT is running."""
316
+ return self._internal_mmt.command
317
+
273
318
  def __getattr__(self, key: str) -> Any:
274
319
  """Forward the attribute lookup to the internal job implementation."""
275
320
  try:
lightning_sdk/mmt/v1.py CHANGED
@@ -1,6 +1,7 @@
1
1
  from typing import TYPE_CHECKING, Dict, Optional, Tuple, Union
2
2
 
3
3
  from lightning_sdk.api.mmt_api import MMTApiV1
4
+ from lightning_sdk.api.utils import _get_cloud_url
4
5
  from lightning_sdk.job.v1 import _internal_status_to_external_status
5
6
  from lightning_sdk.job.work import Work
6
7
 
@@ -53,6 +54,7 @@ class _MMTV1(_BaseMMT):
53
54
  cloud_account_auth: bool = False,
54
55
  artifacts_local: Optional[str] = None,
55
56
  artifacts_remote: Optional[str] = None,
57
+ entrypoint: str = "sh -c",
56
58
  ) -> "_MMTV1":
57
59
  """Submit a new multi-machine job to the Lightning AI platform.
58
60
 
@@ -82,10 +84,14 @@ class _MMTV1(_BaseMMT):
82
84
  within it.
83
85
  Note that the connection needs to be added to the teamspace already in order for it to be found.
84
86
  Only supported for jobs with a docker image compute environment.
87
+ entrypoint: The entrypoint of your docker container. Defaults to `sh -c` which
88
+ just runs the provided command in a standard shell.
89
+ To use the pre-defined entrypoint of the provided image, set this to an empty string.
90
+ Only applicable when submitting docker jobs.
85
91
  """
86
92
  if studio is None:
87
93
  raise ValueError("Studio is required for submitting jobs")
88
- if image is not None or image_credentials is not None or cloud_account_auth:
94
+ if image is not None or image_credentials is not None or cloud_account_auth or entrypoint != "sh -c":
89
95
  raise ValueError("Image is not supported for submitting jobs")
90
96
 
91
97
  if artifacts_local is not None or artifacts_remote is not None:
@@ -174,7 +180,29 @@ class _MMTV1(_BaseMMT):
174
180
 
175
181
  @property
176
182
  def link(self) -> str:
177
- return f"https://lightning.ai/{self.teamspace.owner.name}/{self.teamspace.name}/studios/{self._job_api.get_studio_name(self._guaranteed_job)}/app?app_id=mmt&app_tab=Runs&job_name={self.name}"
183
+ return (
184
+ f"{_get_cloud_url()}/{self.teamspace.owner.name}/{self.teamspace.name}/studios/{self._job_api.get_studio_name(self._guaranteed_job)}/"
185
+ f"app?app_id=mmt&app_tab=Runs&job_name={self.name}"
186
+ )
187
+
188
+ @property
189
+ def image(self) -> Optional[str]:
190
+ """The image used to submit the job."""
191
+ # mmtv1 don't support images, so return None here
192
+ return None
193
+
194
+ @property
195
+ def studio(self) -> Optional["Studio"]:
196
+ """The studio used to submit the job."""
197
+ from lightning_sdk.studio import Studio
198
+
199
+ studio_name = self._job_api.get_studio_name(self._guaranteed_job)
200
+ return Studio(studio_name, teamspace=self.teamspace)
201
+
202
+ @property
203
+ def command(self) -> str:
204
+ """The command the job is running."""
205
+ return self._job_api.get_command(self._guaranteed_job)
178
206
 
179
207
  # the following and functions are solely to make the Work class function
180
208
  @property
lightning_sdk/mmt/v2.py CHANGED
@@ -1,6 +1,7 @@
1
1
  from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple, Union
2
2
 
3
3
  from lightning_sdk.api.mmt_api import MMTApiV2
4
+ from lightning_sdk.api.utils import _get_cloud_url
4
5
 
5
6
  if TYPE_CHECKING:
6
7
  from lightning_sdk.job.job import Job
@@ -52,6 +53,7 @@ class _MMTV2(_BaseMMT):
52
53
  cloud_account_auth: bool = False,
53
54
  artifacts_local: Optional[str] = None,
54
55
  artifacts_remote: Optional[str] = None,
56
+ entrypoint: str = "sh -c",
55
57
  ) -> "_MMTV2":
56
58
  """Submit a new multi-machine job to the Lightning AI platform.
57
59
 
@@ -81,6 +83,10 @@ class _MMTV2(_BaseMMT):
81
83
  within it.
82
84
  Note that the connection needs to be added to the teamspace already in order for it to be found.
83
85
  Only supported for jobs with a docker image compute environment.
86
+ entrypoint: The entrypoint of your docker container. Defaults to `sh -c` which
87
+ just runs the provided command in a standard shell.
88
+ To use the pre-defined entrypoint of the provided image, set this to an empty string.
89
+ Only applicable when submitting docker jobs.
84
90
  """
85
91
  # Command is required if Studio is provided to know what to run
86
92
  # Image is mutually exclusive with Studio
@@ -113,6 +119,7 @@ class _MMTV2(_BaseMMT):
113
119
  cloud_account_auth=cloud_account_auth,
114
120
  artifacts_local=artifacts_local,
115
121
  artifacts_remote=artifacts_remote,
122
+ entrypoint=entrypoint,
116
123
  )
117
124
  self._job = submitted
118
125
  self._name = submitted.name
@@ -189,5 +196,27 @@ class _MMTV2(_BaseMMT):
189
196
 
190
197
  @property
191
198
  def link(self) -> str:
192
- # TODO: Since we don't have a UI for this yet, we can't have a link
193
- raise NotImplementedError
199
+ # TODO: MMT env with studio -> go to studio plugin
200
+ return f"{_get_cloud_url()}/{self.teamspace.owner.name}/{self.teamspace.name}/jobs/{self.name}?app_id=mmt"
201
+
202
+ @property
203
+ def image(self) -> Optional[str]:
204
+ """The image used to submit the job."""
205
+ return self._job_api.get_image_name(self._guaranteed_job)
206
+
207
+ @property
208
+ def studio(self) -> Optional["Studio"]:
209
+ """The studio used to submit the job."""
210
+ from lightning_sdk.studio import Studio
211
+
212
+ studio_name = self._job_api.get_studio_name(self._guaranteed_job)
213
+
214
+ # if job was submitted with image, studio will be None
215
+ if not studio_name:
216
+ return None
217
+ return Studio(studio_name, teamspace=self.teamspace)
218
+
219
+ @property
220
+ def command(self) -> str:
221
+ """The command the job is running."""
222
+ return self._job_api.get_command(self._guaranteed_job)
lightning_sdk/status.py CHANGED
@@ -4,10 +4,14 @@ from enum import Enum
4
4
  class Status(Enum):
5
5
  """Enum holding all possible studio status types."""
6
6
 
7
- NotCreated = 1
8
- Pending = 2
9
- Running = 3
10
- Stopping = 4
11
- Stopped = 5
12
- Completed = 6
13
- Failed = 7
7
+ NotCreated = "NotCreated"
8
+ Pending = "Pending"
9
+ Running = "Running"
10
+ Stopping = "Stopping"
11
+ Stopped = "Stopped"
12
+ Completed = "Completed"
13
+ Failed = "Failed"
14
+
15
+ def __str__(self) -> str:
16
+ """String representation of the enum."""
17
+ return self.value
@@ -1,6 +1,6 @@
1
1
  import warnings
2
2
  from pathlib import Path
3
- from typing import TYPE_CHECKING, List, Optional, Union
3
+ from typing import TYPE_CHECKING, List, Optional, Tuple, Union
4
4
 
5
5
  from lightning_sdk.agents import Agent
6
6
  from lightning_sdk.api import TeamspaceApi
@@ -17,6 +17,8 @@ from lightning_sdk.utils.resolve import (
17
17
  )
18
18
 
19
19
  if TYPE_CHECKING:
20
+ from lightning_sdk.job import Job
21
+ from lightning_sdk.mmt import MMT
20
22
  from lightning_sdk.studio import Studio
21
23
 
22
24
 
@@ -126,6 +128,54 @@ class Teamspace:
126
128
  )
127
129
  return self.cloud_accounts
128
130
 
131
+ @property
132
+ def jobs(self) -> Tuple["Job", ...]:
133
+ from lightning_sdk.job import Job
134
+ from lightning_sdk.plugin import forced_v1
135
+
136
+ jobsv1, jobsv2 = self._teamspace_api.list_jobs(teamspace_id=self.id)
137
+
138
+ jobs = []
139
+
140
+ for j1 in jobsv1:
141
+ with forced_v1(Job):
142
+ # _fetch_job = False to prevent refetching on init since we already got it
143
+ job = Job(name=j1.name, teamspace=self, _fetch_job=False)
144
+ job._internal_job._job = j1
145
+ jobs.append(job)
146
+
147
+ for j2 in jobsv2:
148
+ # _fetch_job = False to prevent refetching on init since we already got it
149
+ job = Job(name=j2.name, teamspace=self, _fetch_job=False)
150
+ job._internal_job._job = j2
151
+ jobs.append(job)
152
+
153
+ return tuple(jobs)
154
+
155
+ @property
156
+ def multi_machine_jobs(self) -> Tuple["MMT", ...]:
157
+ from lightning_sdk.mmt import MMT
158
+ from lightning_sdk.plugin import forced_v1
159
+
160
+ mmtsv1, mmtsv2 = self._teamspace_api.list_mmts(teamspace_id=self.id)
161
+
162
+ mmts = []
163
+
164
+ for m1 in mmtsv1:
165
+ with forced_v1(MMT):
166
+ # _fetch_job = False to prevent refetching on init since we already got it
167
+ mmt = MMT(name=m1.name, teamspace=self, _fetch_job=False)
168
+ mmt._internal_mmt._job = m1
169
+ mmts.append(mmt)
170
+
171
+ for m2 in mmtsv2:
172
+ # _fetch_job = False to prevent refetching on init since we already got it
173
+ mmt = MMT(name=m2.name, teamspace=self, _fetch_job=False)
174
+ mmt._internal_mmt._job = m2
175
+ mmts.append(mmt)
176
+
177
+ return tuple(mmts)
178
+
129
179
  def __eq__(self, other: "Teamspace") -> bool:
130
180
  """Checks whether the provided other object is equal to this one."""
131
181
  return (
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lightning_sdk
3
- Version: 0.1.46
3
+ Version: 0.1.48
4
4
  Summary: SDK to develop using Lightning AI Studios
5
5
  Author-email: Lightning-AI <justus@lightning.ai>
6
6
  License: MIT License