lightning-sdk 2025.12.2__py3-none-any.whl → 2025.12.5__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.
@@ -1,3 +1,3 @@
1
1
  """Version information for lightning_sdk."""
2
2
 
3
- __version__ = "2025.12.02"
3
+ __version__ = "2025.12.05"
@@ -21,6 +21,7 @@ from lightning_sdk.cli.groups import (
21
21
  from lightning_sdk.cli.utils import CustomHelpFormatter
22
22
  from lightning_sdk.cli.utils.logging import CommandLoggingGroup, logging_excepthook
23
23
  from lightning_sdk.lightning_cloud.login import Auth
24
+ from lightning_sdk.utils.resolve import _get_authed_user, in_studio
24
25
 
25
26
 
26
27
  @click.group(
@@ -39,13 +40,22 @@ main_cli.context_class.formatter_class = CustomHelpFormatter
39
40
  @main_cli.command
40
41
  def login() -> None:
41
42
  """Login to Lightning AI Studios."""
42
- auth = Auth()
43
- auth.clear()
44
-
45
- try:
46
- auth.authenticate()
47
- except ConnectionError:
48
- raise RuntimeError(f"Unable to connect to {_cloud_url()}. Please check your internet connection.") from None
43
+ if in_studio():
44
+ # if inside a Studio, no need to run login command
45
+ try:
46
+ auth_user = _get_authed_user()
47
+ except Exception:
48
+ raise RuntimeError("Unable to identify user within a Studio") from None
49
+
50
+ click.echo(f'You are currently logged in as "{auth_user.name}"')
51
+ click.echo('"lightning login" is not required within a Studio')
52
+ else:
53
+ auth = Auth()
54
+ auth.clear()
55
+ try:
56
+ auth.authenticate()
57
+ except ConnectionError:
58
+ raise RuntimeError(f"Unable to connect to {_cloud_url()}. Please check your internet connection.") from None
49
59
 
50
60
 
51
61
  @main_cli.command
@@ -1,5 +1,6 @@
1
1
  """Studio cp command."""
2
2
 
3
+ import os
3
4
  from pathlib import Path
4
5
  from typing import Optional, TypedDict
5
6
 
@@ -7,7 +8,6 @@ import click
7
8
  from rich.console import Console
8
9
 
9
10
  from lightning_sdk.api.utils import _get_cloud_url
10
- from lightning_sdk.cli.legacy.exceptions import StudioCliError
11
11
  from lightning_sdk.cli.utils.owner_selection import OwnerMenu
12
12
  from lightning_sdk.cli.utils.studio_selection import StudiosMenu
13
13
  from lightning_sdk.cli.utils.teamspace_selection import TeamspacesMenu
@@ -38,7 +38,7 @@ def cp_impl(source: str, destination: str) -> None:
38
38
  raise ValueError("Either source or destination must be a Studio file.")
39
39
  elif "lit://" in source:
40
40
  # Download from Studio to local
41
- cp_download(studio_file_path=source, local_file_path=destination)
41
+ cp_download(studio_path=source, local_path=destination)
42
42
  else:
43
43
  # Upload from local to Studio
44
44
  cp_upload(local_file_path=source, studio_file_path=destination)
@@ -92,12 +92,8 @@ def cp_upload(
92
92
  studio_file_path: str,
93
93
  ) -> None:
94
94
  console = Console()
95
- if Path(local_file_path).is_dir():
96
- raise StudioCliError(
97
- f"The provided path is a folder: {local_file_path}. Use `lightning upload folder` instead."
98
- )
99
95
  if not Path(local_file_path).exists():
100
- raise FileNotFoundError(f"The provided path does not exist: {local_file_path}.")
96
+ raise FileNotFoundError(f"The provided path does not exist: {local_file_path}")
101
97
 
102
98
  studio_path_result = parse_studio_path(studio_file_path)
103
99
 
@@ -106,7 +102,14 @@ def cp_upload(
106
102
  )
107
103
  console.print(f"Uploading to {selected_studio.teamspace.name}/{selected_studio.name}")
108
104
 
109
- selected_studio.upload_file(local_file_path, studio_path_result["destination"])
105
+ if Path(local_file_path).is_dir():
106
+ selected_studio.upload_folder(local_file_path, studio_path_result["destination"])
107
+ else:
108
+ if studio_file_path.endswith(("/", "\\")):
109
+ # if destination ends with / or \, treat it as a directory
110
+ file_name = os.path.basename(local_file_path)
111
+ studio_path_result["destination"] = os.path.join(studio_path_result["destination"], file_name)
112
+ selected_studio.upload_file(local_file_path, studio_path_result["destination"])
110
113
 
111
114
  studio_url = (
112
115
  _get_cloud_url().replace(":443", "")
@@ -121,10 +124,43 @@ def cp_upload(
121
124
 
122
125
 
123
126
  def cp_download(
124
- studio_file_path: str,
125
- local_file_path: str,
127
+ studio_path: str,
128
+ local_path: str,
126
129
  ) -> None:
127
- raise NotImplementedError("Download functionality is not implemented yet.")
130
+ console = Console()
131
+ studio_path_result = parse_studio_path(studio_path)
132
+
133
+ selected_studio = resolve_studio(
134
+ studio_path_result["studio"], studio_path_result["teamspace"], studio_path_result["owner"]
135
+ )
136
+
137
+ # check if file/folder exists
138
+ path_info = selected_studio._studio_api.get_path_info(
139
+ selected_studio._studio.id, selected_studio._teamspace.id, path=studio_path_result["destination"]
140
+ )
141
+ if not path_info["exists"]:
142
+ raise FileNotFoundError(
143
+ f"The provided path does not exist in the studio: {studio_path_result['destination']} "
144
+ "Note that empty folders may not be detected as existing."
145
+ )
146
+
147
+ console.print(f"Downloading from {selected_studio.teamspace.name}/{selected_studio.name}")
148
+ if path_info["type"] == "directory":
149
+ folder_name = os.path.basename(studio_path_result["destination"].rstrip("/"))
150
+ target_path = os.path.join(local_path, folder_name)
151
+
152
+ selected_studio.download_folder(studio_path_result["destination"], target_path)
153
+ console.print(f"See your folder at {target_path}")
154
+ else:
155
+ if os.path.isdir(local_path) or local_path.endswith(("/", "\\")):
156
+ # if local_path ends with / or \ or is a directory, treat it as a directory
157
+ file_name = os.path.basename(studio_path_result["destination"])
158
+ target_path = os.path.join(local_path, file_name)
159
+ else:
160
+ target_path = local_path
161
+ os.makedirs(os.path.dirname(target_path), exist_ok=True)
162
+ selected_studio.download_file(studio_path_result["destination"], target_path)
163
+ console.print(f"See your file at {target_path}")
128
164
 
129
165
 
130
166
  def resolve_studio(studio_name: Optional[str], teamspace: Optional[str], owner: Optional[str]) -> Studio:
@@ -498,7 +498,9 @@ class Teamspace(metaclass=TrackCallsMeta):
498
498
  )
499
499
  return self._teamspace_api.list_model_versions(teamspace_id=self.id, model_name=name)
500
500
 
501
- def upload_file(self, file_path: str, remote_path: Optional[str] = None, progress_bar: bool = True) -> None:
501
+ def upload_file(
502
+ self, file_path: Union[Path, str], remote_path: Optional[str] = None, progress_bar: bool = True
503
+ ) -> None:
502
504
  """Uploads file to given remote path in the Teamspace drive."""
503
505
  if remote_path is None:
504
506
  remote_path = os.path.split(file_path)[1]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lightning_sdk
3
- Version: 2025.12.2
3
+ Version: 2025.12.5
4
4
  Summary: SDK to develop using Lightning AI Studios
5
5
  Author-email: Lightning-AI <justus@lightning.ai>
6
6
  License: MIT License
@@ -46,7 +46,7 @@ Requires-Dist: rich
46
46
  Requires-Dist: simple-term-menu
47
47
  Requires-Dist: six
48
48
  Requires-Dist: tqdm
49
- Requires-Dist: urllib3
49
+ Requires-Dist: urllib3<=2.5.0
50
50
  Requires-Dist: uvicorn
51
51
  Requires-Dist: websocket-client
52
52
  Requires-Dist: wget
@@ -1,6 +1,6 @@
1
1
  docs/source/conf.py,sha256=r8yX20eC-4mHhMTd0SbQb5TlSWHhO6wnJ0VJ_FBFpag,13249
2
2
  lightning_sdk/__init__.py,sha256=ym1mOWljHxiO4oijOrmtcjf-eIcwYJVFXkDvLduL4FA,1368
3
- lightning_sdk/__version__.py,sha256=mY7vyA2HBdHarQMNRbuD6EwG9ApvXSIPOttfDRj1rfk,73
3
+ lightning_sdk/__version__.py,sha256=xyg__GnThH4g-rLWswr2bg7RmNEA67sg5iBKzDfb9do,73
4
4
  lightning_sdk/agents.py,sha256=Uqsdu4PgswhpeXZzDSbp3hu30MMOhSlCnp8D56MaS_c,1658
5
5
  lightning_sdk/ai_hub.py,sha256=QzCfmX0h2CLn7r0DQyjWg6RnNw26Ey6akiP2Wffl9Ls,7006
6
6
  lightning_sdk/base_studio.py,sha256=yMvZ1dDq_avW3iu98CLEo9W9UL54mx4C6FC43IKLWAE,4691
@@ -18,7 +18,7 @@ lightning_sdk/sandbox.py,sha256=_NvnWotEXW2rBiVFZZ4krKXxVjuAqfNh04qELSM0-Pg,5786
18
18
  lightning_sdk/serve.py,sha256=XbllHwmOAOHjQJ0AQukwYe3OtspEwhmf5-_HXhL-mpc,11908
19
19
  lightning_sdk/status.py,sha256=lLGAuSvXBoXQFEEsEYwdCi0RcSNatUn5OPjJVjDtoM0,386
20
20
  lightning_sdk/studio.py,sha256=Yx8vw_-SPmr0UzWQ7Kq_IXDFtuk-j0UhM95-Fyaexjc,37609
21
- lightning_sdk/teamspace.py,sha256=pskDJWe3OGKFeXCKr-QZbzgor2AOQwdzgxqlS8Ahj_o,27558
21
+ lightning_sdk/teamspace.py,sha256=_6zrKLgoOjNdrDARt9aAvFG_oTZmZJclM4uTGVAj_0o,27585
22
22
  lightning_sdk/user.py,sha256=TSYh38rxoi7qKOfrK2JYh_Nknya2Kbz2ngDIY85fFOY,1778
23
23
  lightning_sdk/api/__init__.py,sha256=8boDRZ0LMl7G_IbpqHS2q3efeX_Y897_gsJ3iBF58M4,538
24
24
  lightning_sdk/api/agents_api.py,sha256=G47TbFo9kYqnBMqdw2RW-lfS1VAUBSXDmzs6fpIEMUs,4059
@@ -39,7 +39,7 @@ lightning_sdk/api/teamspace_api.py,sha256=wuwW4YbhloFqI9rS_5mbgsS6Dk3zYONLv9M6Oo
39
39
  lightning_sdk/api/user_api.py,sha256=o9gZmtvqNfj4kdSpo2fyyRuFAP7bM5w7mx0Oj9__Ads,4702
40
40
  lightning_sdk/api/utils.py,sha256=mB8ZPjxj8jjXMWRBtG-g0ZvR7NayZnGhMtEZfQMHtqA,29734
41
41
  lightning_sdk/cli/__init__.py,sha256=lksw08t_ZIuHOH47LCIqSVHeZ8cUXI2aJWHYhyujYHM,32
42
- lightning_sdk/cli/entrypoint.py,sha256=WsHbYB-rGIbXwz_Un6UiuOFdVPwXGTOs7GC5Zh4Y_B4,3467
42
+ lightning_sdk/cli/entrypoint.py,sha256=X6yWMfC5wSvO5L8g2JVKlral9r5TlAeEPfQ3ySbyp2g,3959
43
43
  lightning_sdk/cli/groups.py,sha256=umtnKZm4xrIEtY-SWrC1KcKzYGvArr08qeP2zGPkyTk,1609
44
44
  lightning_sdk/cli/base_studio/__init__.py,sha256=npBEmXWNVuiawm98TFVNHZf038kD4aW3gzVHsjbUPNI,272
45
45
  lightning_sdk/cli/base_studio/list.py,sha256=-psOgNpJY7_x5iGRw8UeK4r3jxryVidy4zl6UrnFWx8,1157
@@ -84,7 +84,7 @@ lightning_sdk/cli/license/set.py,sha256=uGjFgq-3jkMF0IstMIIRjKn8GDzg9TIe1OZcRkDT
84
84
  lightning_sdk/cli/mmt/__init__.py,sha256=CLgr-ZHHLS6Db_JGqpxbn4G2pYrKi4Qn-uhi8e0kFNc,145
85
85
  lightning_sdk/cli/studio/__init__.py,sha256=wREPAmPJdN4b51r6RRD1o4aE212KN7xI88Z0O6HTzEU,1022
86
86
  lightning_sdk/cli/studio/connect.py,sha256=RLi5VumsVlVDlyiGbST7lDuHAntOj_-99KsNr8J3knE,5057
87
- lightning_sdk/cli/studio/cp.py,sha256=qQn803KmK6AR4dIjLgLuOKU8VbC8_FW7eMxAB_lwgno,4765
87
+ lightning_sdk/cli/studio/cp.py,sha256=KZWpS_-eeQQGIvMWL1d8W-u9T1v-zWZmgTPzjguQO48,6534
88
88
  lightning_sdk/cli/studio/create.py,sha256=eVkuP1qg1aQSe2jyDgbIg-si5xPl8CwDIPcyvkUEFnQ,3179
89
89
  lightning_sdk/cli/studio/delete.py,sha256=Gi1KLCrSgjTiyoQe9NRvF4ZpsNyeM07KHnBxfdJg2FE,1483
90
90
  lightning_sdk/cli/studio/list.py,sha256=ieLiHRIfAb7E5e_r48BeTC03ib8RY6maeF7nkmrqaek,3301
@@ -1281,9 +1281,9 @@ lightning_sdk/utils/logging.py,sha256=WPyOx7KAn8OpRKqoDDlB7MkORtLDryJsj1WVXLYNqy
1281
1281
  lightning_sdk/utils/names.py,sha256=1EuXbIh7wldkDp1FG10oz9vIOyWrpGWeFFVy-DQBgzA,18162
1282
1282
  lightning_sdk/utils/progress.py,sha256=bLWw39fzq29PMWoFXaPIVfoS3Ug245950oWOFJ2ZaiU,12596
1283
1283
  lightning_sdk/utils/resolve.py,sha256=ukC-Zn35gNZV-fQ-ZyUgZkRPFb8nwsFh_aN7YcJ0sl8,10613
1284
- lightning_sdk-2025.12.2.dist-info/LICENSE,sha256=uFIuZwj5z-4TeF2UuacPZ1o17HkvKObT8fY50qN84sg,1064
1285
- lightning_sdk-2025.12.2.dist-info/METADATA,sha256=x8WV1oEbZWPehEeHjIxUzdQI0mmKcXMG6-JXsbxRDwE,4152
1286
- lightning_sdk-2025.12.2.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
1287
- lightning_sdk-2025.12.2.dist-info/entry_points.txt,sha256=OoZa4Fc8NMs6GSN0cdA1J8e6couzAcL82CbM1yo4f_M,122
1288
- lightning_sdk-2025.12.2.dist-info/top_level.txt,sha256=ps8doKILFXmN7F1mHncShmnQoTxKBRPIcchC8TpoBw4,19
1289
- lightning_sdk-2025.12.2.dist-info/RECORD,,
1284
+ lightning_sdk-2025.12.5.dist-info/LICENSE,sha256=uFIuZwj5z-4TeF2UuacPZ1o17HkvKObT8fY50qN84sg,1064
1285
+ lightning_sdk-2025.12.5.dist-info/METADATA,sha256=t88SaZclJyHWhv-FJKf3XYreHtzb8iVZz91lPxMw5qk,4159
1286
+ lightning_sdk-2025.12.5.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
1287
+ lightning_sdk-2025.12.5.dist-info/entry_points.txt,sha256=OoZa4Fc8NMs6GSN0cdA1J8e6couzAcL82CbM1yo4f_M,122
1288
+ lightning_sdk-2025.12.5.dist-info/top_level.txt,sha256=ps8doKILFXmN7F1mHncShmnQoTxKBRPIcchC8TpoBw4,19
1289
+ lightning_sdk-2025.12.5.dist-info/RECORD,,