lightning-sdk 2025.8.6rc2__py3-none-any.whl → 2025.11.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.
Files changed (330) hide show
  1. lightning_sdk/__init__.py +13 -7
  2. lightning_sdk/__version__.py +3 -0
  3. lightning_sdk/agents.py +2 -1
  4. lightning_sdk/ai_hub.py +2 -1
  5. lightning_sdk/api/__init__.py +2 -0
  6. lightning_sdk/api/base_studio_api.py +13 -9
  7. lightning_sdk/api/cloud_account_api.py +31 -10
  8. lightning_sdk/api/deployment_api.py +27 -1
  9. lightning_sdk/api/job_api.py +16 -12
  10. lightning_sdk/api/license_api.py +26 -59
  11. lightning_sdk/api/llm_api.py +25 -2
  12. lightning_sdk/api/mmt_api.py +5 -2
  13. lightning_sdk/api/studio_api.py +252 -55
  14. lightning_sdk/api/teamspace_api.py +106 -30
  15. lightning_sdk/api/user_api.py +56 -2
  16. lightning_sdk/api/utils.py +108 -18
  17. lightning_sdk/base_studio.py +51 -27
  18. lightning_sdk/cli/__init__.py +1 -0
  19. lightning_sdk/cli/base_studio/__init__.py +10 -0
  20. lightning_sdk/cli/base_studio/list.py +43 -0
  21. lightning_sdk/cli/config/__init__.py +14 -0
  22. lightning_sdk/cli/config/get.py +57 -0
  23. lightning_sdk/cli/config/set.py +92 -0
  24. lightning_sdk/cli/config/show.py +9 -0
  25. lightning_sdk/cli/entrypoint.py +71 -71
  26. lightning_sdk/cli/groups.py +56 -0
  27. lightning_sdk/cli/job/__init__.py +7 -0
  28. lightning_sdk/cli/{clusters_menu.py → legacy/clusters_menu.py} +9 -6
  29. lightning_sdk/cli/{configure.py → legacy/configure.py} +2 -2
  30. lightning_sdk/cli/{connect.py → legacy/connect.py} +2 -2
  31. lightning_sdk/cli/{create.py → legacy/create.py} +12 -14
  32. lightning_sdk/cli/{delete.py → legacy/delete.py} +5 -5
  33. lightning_sdk/cli/legacy/deploy/__init__.py +0 -0
  34. lightning_sdk/cli/{deploy → legacy/deploy}/_auth.py +5 -6
  35. lightning_sdk/cli/{deploy → legacy/deploy}/devbox.py +8 -2
  36. lightning_sdk/cli/{deploy → legacy/deploy}/serve.py +19 -8
  37. lightning_sdk/cli/{download.py → legacy/download.py} +14 -15
  38. lightning_sdk/cli/legacy/entrypoint.py +110 -0
  39. lightning_sdk/cli/{generate.py → legacy/generate.py} +1 -1
  40. lightning_sdk/cli/{inspection.py → legacy/inspection.py} +1 -1
  41. lightning_sdk/cli/{job_and_mmt_action.py → legacy/job_and_mmt_action.py} +6 -6
  42. lightning_sdk/cli/{jobs_menu.py → legacy/jobs_menu.py} +1 -1
  43. lightning_sdk/cli/{list.py → legacy/list.py} +12 -13
  44. lightning_sdk/cli/{mmts_menu.py → legacy/mmts_menu.py} +1 -1
  45. lightning_sdk/cli/{open.py → legacy/open.py} +4 -4
  46. lightning_sdk/cli/{start.py → legacy/start.py} +1 -0
  47. lightning_sdk/cli/{stop.py → legacy/stop.py} +1 -1
  48. lightning_sdk/cli/{switch.py → legacy/switch.py} +1 -0
  49. lightning_sdk/cli/{teamspace_menu.py → legacy/teamspace_menu.py} +1 -1
  50. lightning_sdk/cli/{upload.py → legacy/upload.py} +7 -8
  51. lightning_sdk/cli/license/__init__.py +14 -0
  52. lightning_sdk/cli/license/get.py +15 -0
  53. lightning_sdk/cli/license/list.py +45 -0
  54. lightning_sdk/cli/license/set.py +13 -0
  55. lightning_sdk/cli/mmt/__init__.py +7 -0
  56. lightning_sdk/cli/studio/__init__.py +24 -0
  57. lightning_sdk/cli/studio/connect.py +139 -0
  58. lightning_sdk/cli/studio/create.py +96 -0
  59. lightning_sdk/cli/studio/delete.py +49 -0
  60. lightning_sdk/cli/studio/list.py +85 -0
  61. lightning_sdk/cli/studio/ssh.py +64 -0
  62. lightning_sdk/cli/studio/start.py +115 -0
  63. lightning_sdk/cli/studio/stop.py +45 -0
  64. lightning_sdk/cli/studio/switch.py +66 -0
  65. lightning_sdk/cli/utils/__init__.py +7 -0
  66. lightning_sdk/cli/utils/cloud_account_map.py +10 -0
  67. lightning_sdk/cli/utils/get_base_studio.py +24 -0
  68. lightning_sdk/cli/utils/handle_machine_and_gpus_args.py +69 -0
  69. lightning_sdk/cli/utils/logging.py +122 -0
  70. lightning_sdk/cli/utils/owner_selection.py +110 -0
  71. lightning_sdk/cli/utils/resolve.py +28 -0
  72. lightning_sdk/cli/utils/richt_print.py +35 -0
  73. lightning_sdk/cli/utils/save_to_config.py +27 -0
  74. lightning_sdk/cli/utils/ssh_connection.py +59 -0
  75. lightning_sdk/cli/utils/studio_selection.py +113 -0
  76. lightning_sdk/cli/utils/teamspace_selection.py +125 -0
  77. lightning_sdk/cli/vm/__init__.py +20 -0
  78. lightning_sdk/cli/vm/create.py +33 -0
  79. lightning_sdk/cli/vm/delete.py +25 -0
  80. lightning_sdk/cli/vm/list.py +30 -0
  81. lightning_sdk/cli/vm/ssh.py +31 -0
  82. lightning_sdk/cli/vm/start.py +60 -0
  83. lightning_sdk/cli/vm/stop.py +25 -0
  84. lightning_sdk/cli/vm/switch.py +38 -0
  85. lightning_sdk/constants.py +1 -0
  86. lightning_sdk/deployment/__init__.py +2 -0
  87. lightning_sdk/deployment/deployment.py +17 -2
  88. lightning_sdk/helpers.py +56 -37
  89. lightning_sdk/job/base.py +21 -6
  90. lightning_sdk/job/job.py +13 -0
  91. lightning_sdk/job/v1.py +11 -0
  92. lightning_sdk/job/v2.py +12 -0
  93. lightning_sdk/lightning_cloud/login.py +320 -10
  94. lightning_sdk/lightning_cloud/openapi/__init__.py +113 -3
  95. lightning_sdk/lightning_cloud/openapi/api/__init__.py +3 -0
  96. lightning_sdk/lightning_cloud/openapi/api/assistants_service_api.py +713 -75
  97. lightning_sdk/lightning_cloud/openapi/api/auth_service_api.py +376 -0
  98. lightning_sdk/lightning_cloud/openapi/api/billing_service_api.py +191 -1
  99. lightning_sdk/lightning_cloud/openapi/api/cloud_space_environment_template_service_api.py +5 -1
  100. lightning_sdk/lightning_cloud/openapi/api/cloud_space_service_api.py +420 -0
  101. lightning_sdk/lightning_cloud/openapi/api/cloudy_service_api.py +0 -97
  102. lightning_sdk/lightning_cloud/openapi/api/cluster_service_api.py +420 -0
  103. lightning_sdk/lightning_cloud/openapi/api/data_connection_service_api.py +101 -0
  104. lightning_sdk/lightning_cloud/openapi/api/incidents_service_api.py +1058 -0
  105. lightning_sdk/lightning_cloud/openapi/api/jobs_service_api.py +121 -0
  106. lightning_sdk/lightning_cloud/openapi/api/k8_s_cluster_service_api.py +1742 -94
  107. lightning_sdk/lightning_cloud/openapi/api/markets_service_api.py +145 -0
  108. lightning_sdk/lightning_cloud/openapi/api/models_store_api.py +4 -4
  109. lightning_sdk/lightning_cloud/openapi/api/product_license_service_api.py +108 -108
  110. lightning_sdk/lightning_cloud/openapi/api/projects_service_api.py +105 -0
  111. lightning_sdk/lightning_cloud/openapi/api/schedules_service_api.py +347 -0
  112. lightning_sdk/lightning_cloud/openapi/api/sdk_command_history_service_api.py +141 -0
  113. lightning_sdk/lightning_cloud/openapi/api/storage_service_api.py +761 -1
  114. lightning_sdk/lightning_cloud/openapi/configuration.py +3 -19
  115. lightning_sdk/lightning_cloud/openapi/models/__init__.py +110 -3
  116. lightning_sdk/lightning_cloud/openapi/models/assistant_id_conversations_body.py +15 -15
  117. lightning_sdk/lightning_cloud/openapi/models/cloudspace_id_visibility_body.py +27 -1
  118. lightning_sdk/lightning_cloud/openapi/models/cluster_id_kubernetestemplates_body.py +201 -0
  119. lightning_sdk/lightning_cloud/openapi/models/cluster_id_metrics_body.py +131 -1
  120. lightning_sdk/lightning_cloud/openapi/models/create.py +27 -1
  121. lightning_sdk/lightning_cloud/openapi/models/create_machine_request_represents_the_request_to_create_a_machine.py +461 -0
  122. lightning_sdk/lightning_cloud/openapi/models/deployments_id_body.py +27 -1
  123. lightning_sdk/lightning_cloud/openapi/models/externalv1_cloud_space_instance_status.py +105 -1
  124. lightning_sdk/lightning_cloud/openapi/models/externalv1_user_status.py +27 -1
  125. lightning_sdk/lightning_cloud/openapi/models/id_codeconfig_body.py +3 -81
  126. lightning_sdk/lightning_cloud/openapi/models/id_fork_body1.py +27 -1
  127. lightning_sdk/lightning_cloud/openapi/models/id_render_body.py +123 -0
  128. lightning_sdk/lightning_cloud/openapi/models/id_sleepconfig_body.py +175 -0
  129. lightning_sdk/lightning_cloud/openapi/models/id_transfer_body.py +53 -1
  130. lightning_sdk/lightning_cloud/openapi/models/incident_id_messages_body.py +123 -0
  131. lightning_sdk/lightning_cloud/openapi/models/incidents_id_body.py +279 -0
  132. lightning_sdk/lightning_cloud/openapi/models/job_id_reportroutingtelemetry_body.py +123 -0
  133. lightning_sdk/lightning_cloud/openapi/models/kubernetestemplates_id_body.py +201 -0
  134. lightning_sdk/lightning_cloud/openapi/models/license_key_validate_body.py +123 -0
  135. lightning_sdk/lightning_cloud/openapi/models/message_id_actions_body.py +201 -0
  136. lightning_sdk/lightning_cloud/openapi/models/messages_message_id_body.py +123 -0
  137. lightning_sdk/lightning_cloud/openapi/models/metricsstream_create_body.py +27 -1
  138. lightning_sdk/lightning_cloud/openapi/models/models_model_id_body.py +109 -31
  139. lightning_sdk/lightning_cloud/openapi/models/models_model_id_body1.py +149 -0
  140. lightning_sdk/lightning_cloud/openapi/models/orgs_id_body.py +53 -1
  141. lightning_sdk/lightning_cloud/openapi/models/project_id_storage_body.py +27 -1
  142. lightning_sdk/lightning_cloud/openapi/models/project_id_storagetransfers_body.py +175 -0
  143. lightning_sdk/lightning_cloud/openapi/models/project_tab_management_messages.py +123 -0
  144. lightning_sdk/lightning_cloud/openapi/models/projects_id_body.py +79 -1
  145. lightning_sdk/lightning_cloud/openapi/models/storage_complete_body.py +41 -15
  146. lightning_sdk/lightning_cloud/openapi/models/storagetransfers_validate_body.py +149 -0
  147. lightning_sdk/lightning_cloud/openapi/models/update1.py +27 -1
  148. lightning_sdk/lightning_cloud/openapi/models/uploads_upload_id_body1.py +27 -1
  149. lightning_sdk/lightning_cloud/openapi/models/user_id_affiliatelinks_body.py +107 -3
  150. lightning_sdk/lightning_cloud/openapi/models/v1_abort_storage_transfer_response.py +97 -0
  151. lightning_sdk/lightning_cloud/openapi/models/v1_aggregated_pod_metrics.py +799 -0
  152. lightning_sdk/lightning_cloud/openapi/models/v1_ai_pod_v1.py +53 -1
  153. lightning_sdk/lightning_cloud/openapi/models/v1_assistant_session_daily_aggregated.py +27 -1
  154. lightning_sdk/lightning_cloud/openapi/models/v1_billing_tier.py +0 -1
  155. lightning_sdk/lightning_cloud/openapi/models/v1_cancel_running_cloud_space_instance_transfer_response.py +97 -0
  156. lightning_sdk/lightning_cloud/openapi/models/v1_cloud_provider.py +2 -0
  157. lightning_sdk/lightning_cloud/openapi/models/v1_cloud_space_environment_template_config.py +27 -1
  158. lightning_sdk/lightning_cloud/openapi/models/v1_cloud_space_specialized_view.py +1 -0
  159. lightning_sdk/lightning_cloud/openapi/models/v1_cloud_space_transfer_metadata.py +147 -17
  160. lightning_sdk/lightning_cloud/openapi/models/v1_cloudflare_v1.py +3 -29
  161. lightning_sdk/lightning_cloud/openapi/models/v1_cluster_accelerator.py +53 -1
  162. lightning_sdk/lightning_cloud/openapi/models/v1_cluster_capacity_reservation.py +27 -1
  163. lightning_sdk/lightning_cloud/openapi/models/v1_cluster_metrics.py +1527 -0
  164. lightning_sdk/lightning_cloud/openapi/models/v1_cluster_security_options.py +27 -1
  165. lightning_sdk/lightning_cloud/openapi/models/v1_cluster_spec.py +53 -1
  166. lightning_sdk/lightning_cloud/openapi/models/v1_cluster_type.py +1 -0
  167. lightning_sdk/lightning_cloud/openapi/models/v1_container_metrics.py +21 -21
  168. lightning_sdk/lightning_cloud/openapi/models/v1_create_incident_request.py +305 -0
  169. lightning_sdk/lightning_cloud/openapi/models/v1_create_license_request.py +175 -0
  170. lightning_sdk/lightning_cloud/openapi/models/v1_create_machine_response.py +123 -0
  171. lightning_sdk/lightning_cloud/openapi/models/v1_create_model_metrics_response.py +97 -0
  172. lightning_sdk/lightning_cloud/openapi/models/v1_create_project_request.py +79 -1
  173. lightning_sdk/lightning_cloud/openapi/models/v1_create_sdk_command_history_request.py +253 -0
  174. lightning_sdk/lightning_cloud/openapi/models/v1_create_sdk_command_history_response.py +97 -0
  175. lightning_sdk/lightning_cloud/openapi/models/v1_daily_model_metrics.py +149 -0
  176. lightning_sdk/lightning_cloud/openapi/models/v1_data_connection.py +53 -1
  177. lightning_sdk/lightning_cloud/openapi/models/v1_delete_incident_message_response.py +97 -0
  178. lightning_sdk/lightning_cloud/openapi/models/v1_delete_incident_response.py +97 -0
  179. lightning_sdk/lightning_cloud/openapi/models/v1_delete_kubernetes_template_response.py +97 -0
  180. lightning_sdk/lightning_cloud/openapi/models/v1_delete_license_response.py +97 -0
  181. lightning_sdk/lightning_cloud/openapi/models/v1_delete_machine_response.py +97 -0
  182. lightning_sdk/lightning_cloud/openapi/models/v1_deployment.py +27 -1
  183. lightning_sdk/lightning_cloud/openapi/models/v1_external_cluster_spec.py +53 -1
  184. lightning_sdk/lightning_cloud/openapi/models/v1_external_search_user.py +27 -1
  185. lightning_sdk/lightning_cloud/openapi/models/v1_filestore_data_connection.py +27 -1
  186. lightning_sdk/lightning_cloud/openapi/models/v1_filesystem_metric.py +201 -0
  187. lightning_sdk/lightning_cloud/openapi/models/v1_firewall_rule.py +175 -0
  188. lightning_sdk/lightning_cloud/openapi/models/v1_get_cloud_space_required_balance_status_response.py +149 -0
  189. lightning_sdk/lightning_cloud/openapi/models/v1_get_cloud_space_transfer_estimate_response.py +149 -0
  190. lightning_sdk/lightning_cloud/openapi/models/v1_get_latest_model_metrics_response.py +123 -0
  191. lightning_sdk/lightning_cloud/openapi/models/v1_get_machine_response.py +123 -0
  192. lightning_sdk/lightning_cloud/openapi/models/v1_get_market_pricing_response.py +201 -0
  193. lightning_sdk/lightning_cloud/openapi/models/v1_get_model_metrics_response.py +123 -0
  194. lightning_sdk/lightning_cloud/openapi/models/v1_get_temp_bucket_credentials_response.py +201 -0
  195. lightning_sdk/lightning_cloud/openapi/models/v1_get_user_response.py +41 -15
  196. lightning_sdk/lightning_cloud/openapi/models/v1_google_cloud_direct_v1.py +27 -1
  197. lightning_sdk/lightning_cloud/openapi/models/v1_group_node_metrics.py +1215 -0
  198. lightning_sdk/lightning_cloud/openapi/models/v1_group_pod_metrics.py +1241 -0
  199. lightning_sdk/lightning_cloud/openapi/models/v1_guest_login_request.py +177 -0
  200. lightning_sdk/lightning_cloud/openapi/models/v1_guest_login_response.py +149 -0
  201. lightning_sdk/lightning_cloud/openapi/models/v1_guest_user.py +201 -0
  202. lightning_sdk/lightning_cloud/openapi/models/v1_incident.py +565 -0
  203. lightning_sdk/lightning_cloud/openapi/models/v1_incident_detail.py +149 -0
  204. lightning_sdk/lightning_cloud/openapi/models/v1_incident_event.py +591 -0
  205. lightning_sdk/lightning_cloud/openapi/models/v1_incident_message.py +253 -0
  206. lightning_sdk/lightning_cloud/openapi/models/v1_incident_severity.py +105 -0
  207. lightning_sdk/lightning_cloud/openapi/models/v1_incident_type.py +108 -0
  208. lightning_sdk/lightning_cloud/openapi/models/v1_job.py +53 -1
  209. lightning_sdk/lightning_cloud/openapi/models/v1_job_spec.py +27 -1
  210. lightning_sdk/lightning_cloud/openapi/models/v1_k8s_incident_indexes.py +149 -0
  211. lightning_sdk/lightning_cloud/openapi/models/v1_kai_scheduler_queue_metrics.py +627 -0
  212. lightning_sdk/lightning_cloud/openapi/models/v1_kubernetes_aws_config.py +279 -0
  213. lightning_sdk/lightning_cloud/openapi/models/v1_kubernetes_direct_settings_v1.py +253 -0
  214. lightning_sdk/lightning_cloud/openapi/models/v1_kubernetes_direct_v1.py +107 -3
  215. lightning_sdk/lightning_cloud/openapi/models/v1_kubernetes_template.py +357 -0
  216. lightning_sdk/lightning_cloud/openapi/models/v1_kubernetes_template_property.py +227 -0
  217. lightning_sdk/lightning_cloud/openapi/models/v1_lambda_labs_direct_v1.py +29 -3
  218. lightning_sdk/lightning_cloud/openapi/models/v1_license.py +227 -0
  219. lightning_sdk/lightning_cloud/openapi/models/v1_lightning_elastic_cluster_v1.py +97 -0
  220. lightning_sdk/lightning_cloud/openapi/models/v1_list_aggregated_pod_metrics_response.py +123 -0
  221. lightning_sdk/lightning_cloud/openapi/models/v1_list_cluster_metric_timestamps_response.py +123 -0
  222. lightning_sdk/lightning_cloud/openapi/models/v1_list_cluster_metrics_response.py +123 -0
  223. lightning_sdk/lightning_cloud/openapi/models/v1_list_cluster_namespace_metrics_response.py +123 -0
  224. lightning_sdk/lightning_cloud/openapi/models/v1_list_cluster_namespace_user_metrics_response.py +123 -0
  225. lightning_sdk/lightning_cloud/openapi/models/v1_list_conversation_message_actions_response.py +123 -0
  226. lightning_sdk/lightning_cloud/openapi/models/v1_list_filesystem_metrics_response.py +123 -0
  227. lightning_sdk/lightning_cloud/openapi/models/v1_list_group_pod_metrics_response.py +123 -0
  228. lightning_sdk/lightning_cloud/openapi/models/v1_list_incident_events_response.py +123 -0
  229. lightning_sdk/lightning_cloud/openapi/models/v1_list_incident_messages_response.py +149 -0
  230. lightning_sdk/lightning_cloud/openapi/models/v1_list_incidents_response.py +149 -0
  231. lightning_sdk/lightning_cloud/openapi/models/v1_list_kai_scheduler_queues_metrics_response.py +123 -0
  232. lightning_sdk/lightning_cloud/openapi/models/v1_list_kubernetes_templates_response.py +123 -0
  233. lightning_sdk/lightning_cloud/openapi/models/{v1_list_product_licenses_response.py → v1_list_license_response.py} +16 -16
  234. lightning_sdk/lightning_cloud/openapi/models/v1_list_machines_response.py +149 -0
  235. lightning_sdk/lightning_cloud/openapi/models/v1_list_platform_notifications_response.py +123 -0
  236. lightning_sdk/lightning_cloud/openapi/models/v1_list_schedule_runs_response.py +123 -0
  237. lightning_sdk/lightning_cloud/openapi/models/v1_list_storage_transfers_response.py +123 -0
  238. lightning_sdk/lightning_cloud/openapi/models/v1_lustre_data_connection.py +149 -0
  239. lightning_sdk/lightning_cloud/openapi/models/v1_machine.py +617 -0
  240. lightning_sdk/lightning_cloud/openapi/models/v1_machine_direct_v1.py +123 -0
  241. lightning_sdk/lightning_cloud/openapi/models/v1_magic_link_login_request.py +1 -27
  242. lightning_sdk/lightning_cloud/openapi/models/v1_magic_link_login_response.py +27 -1
  243. lightning_sdk/lightning_cloud/openapi/models/v1_managed_model.py +29 -3
  244. lightning_sdk/lightning_cloud/openapi/models/v1_market_price.py +149 -0
  245. lightning_sdk/lightning_cloud/openapi/models/v1_membership.py +53 -1
  246. lightning_sdk/lightning_cloud/openapi/models/v1_message_action.py +279 -0
  247. lightning_sdk/lightning_cloud/openapi/models/v1_metrics_stream.py +27 -1
  248. lightning_sdk/lightning_cloud/openapi/models/v1_model_metrics.py +175 -0
  249. lightning_sdk/lightning_cloud/openapi/models/v1_namespace_metrics.py +591 -0
  250. lightning_sdk/lightning_cloud/openapi/models/v1_namespace_user_metrics.py +435 -0
  251. lightning_sdk/lightning_cloud/openapi/models/v1_nebius_direct_v1.py +29 -3
  252. lightning_sdk/lightning_cloud/openapi/models/v1_node_metrics.py +361 -23
  253. lightning_sdk/lightning_cloud/openapi/models/v1_notification_type.py +1 -0
  254. lightning_sdk/lightning_cloud/openapi/models/v1_organization.py +53 -1
  255. lightning_sdk/lightning_cloud/openapi/models/v1_pause_storage_transfer_response.py +97 -0
  256. lightning_sdk/lightning_cloud/openapi/models/v1_platform_notification.py +279 -0
  257. lightning_sdk/lightning_cloud/openapi/models/v1_pod_metrics.py +335 -23
  258. lightning_sdk/lightning_cloud/openapi/models/v1_project.py +27 -1
  259. lightning_sdk/lightning_cloud/openapi/models/v1_project_cluster_binding.py +27 -1
  260. lightning_sdk/lightning_cloud/openapi/models/v1_project_membership.py +53 -1
  261. lightning_sdk/lightning_cloud/openapi/models/v1_project_settings.py +53 -1
  262. lightning_sdk/lightning_cloud/openapi/models/v1_project_tab.py +149 -0
  263. lightning_sdk/lightning_cloud/openapi/models/{v1_product_license_check_response.py → v1_purchase_annual_upsell_request.py} +23 -23
  264. lightning_sdk/lightning_cloud/openapi/models/v1_purchase_annual_upsell_response.py +123 -0
  265. lightning_sdk/lightning_cloud/openapi/models/v1_quote_annual_upsell_response.py +227 -0
  266. lightning_sdk/lightning_cloud/openapi/models/v1_render_kubernetes_template_response.py +123 -0
  267. lightning_sdk/lightning_cloud/openapi/models/v1_report_deployment_routing_telemetry_response.py +97 -0
  268. lightning_sdk/lightning_cloud/openapi/models/v1_required_balance_reason.py +107 -0
  269. lightning_sdk/lightning_cloud/openapi/models/v1_reset_api_key_request.py +97 -0
  270. lightning_sdk/lightning_cloud/openapi/models/v1_reset_api_key_response.py +123 -0
  271. lightning_sdk/lightning_cloud/openapi/models/v1_resource_visibility.py +1 -27
  272. lightning_sdk/lightning_cloud/openapi/models/v1_resume_storage_transfer_response.py +97 -0
  273. lightning_sdk/lightning_cloud/openapi/models/v1_routing_telemetry.py +79 -1
  274. lightning_sdk/lightning_cloud/openapi/models/v1_rule_resource.py +1 -0
  275. lightning_sdk/lightning_cloud/openapi/models/v1_schedule_run.py +357 -0
  276. lightning_sdk/lightning_cloud/openapi/models/v1_sdk_command_history_severity.py +104 -0
  277. lightning_sdk/lightning_cloud/openapi/models/v1_sdk_command_history_type.py +104 -0
  278. lightning_sdk/lightning_cloud/openapi/models/v1_secret_type.py +1 -0
  279. lightning_sdk/lightning_cloud/openapi/models/v1_server_alert_type.py +1 -0
  280. lightning_sdk/lightning_cloud/openapi/models/v1_slack_notifier.py +201 -0
  281. lightning_sdk/lightning_cloud/openapi/models/v1_slack_notifier_type.py +105 -0
  282. lightning_sdk/lightning_cloud/openapi/models/v1_storage_asset.py +133 -3
  283. lightning_sdk/lightning_cloud/openapi/models/v1_storage_transfer.py +435 -0
  284. lightning_sdk/lightning_cloud/openapi/models/v1_storage_transfer_status.py +108 -0
  285. lightning_sdk/lightning_cloud/openapi/models/v1_token_login_request.py +123 -0
  286. lightning_sdk/lightning_cloud/openapi/models/v1_token_login_response.py +123 -0
  287. lightning_sdk/lightning_cloud/openapi/models/v1_token_owner_type.py +104 -0
  288. lightning_sdk/lightning_cloud/openapi/models/v1_update_cloud_space_instance_config_request.py +3 -81
  289. lightning_sdk/lightning_cloud/openapi/models/v1_update_project_tab_order_response.py +123 -0
  290. lightning_sdk/lightning_cloud/openapi/models/v1_update_user_request.py +41 -15
  291. lightning_sdk/lightning_cloud/openapi/models/v1_user_features.py +444 -600
  292. lightning_sdk/lightning_cloud/openapi/models/v1_validate_license_response.py +123 -0
  293. lightning_sdk/lightning_cloud/openapi/models/v1_validate_storage_transfer_response.py +123 -0
  294. lightning_sdk/lightning_cloud/openapi/models/v1_voltage_park_direct_v1.py +29 -3
  295. lightning_sdk/lightning_cloud/rest_client.py +48 -45
  296. lightning_sdk/lightning_cloud/utils/data_connection.py +51 -1
  297. lightning_sdk/llm/llm.py +175 -56
  298. lightning_sdk/llm/public_assistants.py +44 -7
  299. lightning_sdk/machine.py +21 -2
  300. lightning_sdk/mmt/base.py +7 -0
  301. lightning_sdk/mmt/mmt.py +11 -3
  302. lightning_sdk/mmt/v1.py +3 -1
  303. lightning_sdk/mmt/v2.py +4 -0
  304. lightning_sdk/owner.py +2 -1
  305. lightning_sdk/pipeline/steps.py +6 -0
  306. lightning_sdk/plugin.py +6 -1
  307. lightning_sdk/studio.py +294 -53
  308. lightning_sdk/teamspace.py +167 -7
  309. lightning_sdk/user.py +19 -1
  310. lightning_sdk/utils/config.py +179 -0
  311. lightning_sdk/utils/license.py +13 -0
  312. lightning_sdk/utils/logging.py +79 -0
  313. lightning_sdk/utils/names.py +1179 -0
  314. lightning_sdk/utils/progress.py +283 -0
  315. lightning_sdk/utils/resolve.py +82 -7
  316. {lightning_sdk-2025.8.6rc2.dist-info → lightning_sdk-2025.11.5.dist-info}/METADATA +2 -1
  317. {lightning_sdk-2025.8.6rc2.dist-info → lightning_sdk-2025.11.5.dist-info}/RECORD +328 -169
  318. {lightning_sdk-2025.8.6rc2.dist-info → lightning_sdk-2025.11.5.dist-info}/entry_points.txt +1 -0
  319. lightning_sdk/lightning_cloud/openapi/models/v1_product_license.py +0 -435
  320. lightning_sdk/services/license.py +0 -363
  321. /lightning_sdk/cli/{deploy → legacy}/__init__.py +0 -0
  322. /lightning_sdk/cli/{ai_hub.py → legacy/ai_hub.py} +0 -0
  323. /lightning_sdk/cli/{docker_cli.py → legacy/docker_cli.py} +0 -0
  324. /lightning_sdk/cli/{exceptions.py → legacy/exceptions.py} +0 -0
  325. /lightning_sdk/cli/{run.py → legacy/run.py} +0 -0
  326. /lightning_sdk/cli/{studios_menu.py → legacy/studios_menu.py} +0 -0
  327. /lightning_sdk/cli/{coloring.py → utils/coloring.py} +0 -0
  328. {lightning_sdk-2025.8.6rc2.dist-info → lightning_sdk-2025.11.5.dist-info}/LICENSE +0 -0
  329. {lightning_sdk-2025.8.6rc2.dist-info → lightning_sdk-2025.11.5.dist-info}/WHEEL +0 -0
  330. {lightning_sdk-2025.8.6rc2.dist-info → lightning_sdk-2025.11.5.dist-info}/top_level.txt +0 -0
@@ -1,35 +1,59 @@
1
1
  import glob
2
2
  import os
3
3
  import warnings
4
+ from enum import Enum
4
5
  from pathlib import Path
5
- from typing import TYPE_CHECKING, List, Optional, Tuple, Union
6
+ from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Union
6
7
 
7
8
  from tqdm.auto import tqdm
8
9
 
9
10
  import lightning_sdk
10
11
  from lightning_sdk.agents import Agent
11
- from lightning_sdk.api import TeamspaceApi
12
- from lightning_sdk.lightning_cloud.openapi import V1Model, V1ModelVersionArchive, V1ProjectClusterBinding
13
- from lightning_sdk.machine import Machine
12
+ from lightning_sdk.api import CloudAccountApi, TeamspaceApi
13
+ from lightning_sdk.lightning_cloud.openapi import V1ClusterType, V1Model, V1ModelVersionArchive, V1ProjectClusterBinding
14
+ from lightning_sdk.machine import CloudProvider, Machine
14
15
  from lightning_sdk.models import UploadedModelInfo
15
16
  from lightning_sdk.organization import Organization
16
17
  from lightning_sdk.owner import Owner
17
18
  from lightning_sdk.user import User
19
+ from lightning_sdk.utils.logging import TrackCallsMeta
18
20
  from lightning_sdk.utils.resolve import (
19
21
  _get_organizations_for_authed_user,
20
22
  _parse_model_and_version,
21
23
  _resolve_org,
22
24
  _resolve_teamspace_name,
23
25
  _resolve_user,
26
+ skip_studio_init,
24
27
  )
25
28
 
26
29
  if TYPE_CHECKING:
27
30
  from lightning_sdk.job import Job
28
31
  from lightning_sdk.mmt import MMT
29
- from lightning_sdk.studio import Studio
32
+ from lightning_sdk.studio import VM, Studio
30
33
 
31
34
 
32
- class Teamspace:
35
+ class FolderLocation(Enum):
36
+ AWS = "AWS"
37
+ GCP = "GCP"
38
+ CLOUD_AGNOSTIC = "CLOUD_AGNOSTIC"
39
+
40
+ def __str__(self) -> str:
41
+ """Converts the FolderLocation to a str."""
42
+ return self.value
43
+
44
+
45
+ class ConnectionType(Enum):
46
+ EFS = "EFS"
47
+ S3 = "S3"
48
+ GCS = "GCS"
49
+ FILESTORE = "FILESTORE"
50
+
51
+ def __str__(self) -> str:
52
+ """Converts the FolderLocation to a str."""
53
+ return self.value
54
+
55
+
56
+ class Teamspace(metaclass=TrackCallsMeta):
33
57
  """A teamspace is a collection of Studios, Clusters, Members and an associated Budget.
34
58
 
35
59
  Args:
@@ -53,6 +77,7 @@ class Teamspace:
53
77
  user: Optional[Union[str, User]] = None,
54
78
  ) -> None:
55
79
  self._teamspace_api = TeamspaceApi()
80
+ self._cloud_account_api = CloudAccountApi()
56
81
 
57
82
  name = _resolve_teamspace_name(name)
58
83
 
@@ -70,6 +95,20 @@ class Teamspace:
70
95
  self._user = _resolve_user(user)
71
96
  self._org = _resolve_org(org)
72
97
 
98
+ # If still no user or org resolved, try config defaults
99
+ if self._user is None and self._org is None:
100
+ from lightning_sdk.utils.config import Config, DefaultConfigKeys
101
+
102
+ config = Config()
103
+ owner_type = config.get_value(DefaultConfigKeys.teamspace_owner_type)
104
+ owner_name = config.get_value(DefaultConfigKeys.teamspace_owner)
105
+
106
+ if owner_type and owner_name:
107
+ if owner_type.lower() == "organization":
108
+ self._org = _resolve_org(owner_name)
109
+ elif owner_type.lower() == "user":
110
+ self._user = _resolve_user(owner_name)
111
+
73
112
  self._owner: Owner
74
113
  if self._user is None and self._org is None:
75
114
  raise RuntimeError(
@@ -106,12 +145,25 @@ class Teamspace:
106
145
  """All studios within that teamspace."""
107
146
  from lightning_sdk.studio import Studio
108
147
 
148
+ return self._get_studios(Studio)
149
+
150
+ @property
151
+ def vms(self) -> List["VM"]:
152
+ from lightning_sdk.studio import VM
153
+
154
+ return [x for x in self._get_studios(VM) if isinstance(x, VM)]
155
+
156
+ def _get_studios(self, target_cls: type) -> List[Union["Studio", "VM"]]:
109
157
  studios = []
110
158
  cloud_accounts = self._teamspace_api.list_cloud_accounts(teamspace_id=self.id)
111
159
  for cl in cloud_accounts:
112
160
  _studios = self._teamspace_api.list_studios(teamspace_id=self.id, cloud_account=cl.cluster_id)
113
161
  for s in _studios:
114
- studios.append(Studio(name=s.name, teamspace=self, cluster=cl.cluster_name, create_ok=False))
162
+ with skip_studio_init():
163
+ studio = target_cls(name=s.name, teamspace=self, cluster=cl.cluster_name, create_ok=False)
164
+ studio._studio = s
165
+ studio._teamspace = self
166
+ studios.append(studio)
115
167
 
116
168
  return studios
117
169
 
@@ -195,6 +247,24 @@ class Teamspace:
195
247
 
196
248
  return tuple(mmts)
197
249
 
250
+ @property
251
+ def secrets(self) -> Dict[str, str]:
252
+ """All (encrypted) secrets for the teamspace.
253
+
254
+ Note:
255
+ Once created, the secret values are encrypted and cannot be viewed here anymore.
256
+ """
257
+ return self._teamspace_api.get_secrets(self.id)
258
+
259
+ def set_secret(self, key: str, value: str) -> None:
260
+ """Set the (encrypted) secrets for the teamspace."""
261
+ if not self._teamspace_api.verify_secret_name(key):
262
+ raise ValueError(
263
+ "Secret keys must only contain alphanumeric characters and underscores and not begin with a number."
264
+ )
265
+
266
+ self._teamspace_api.set_secret(self.id, key, value)
267
+
198
268
  def list_machines(self, cloud_account: Optional[str] = None) -> List[Machine]:
199
269
  if cloud_account is None:
200
270
  cloud_account = os.getenv("LIGHTNING_CLUSTER_ID") or self.default_cloud_account
@@ -478,6 +548,96 @@ class Teamspace:
478
548
  cloud_account=self.default_cloud_account,
479
549
  )
480
550
 
551
+ def new_folder(
552
+ self, name: str, location: Optional[FolderLocation] = None, cloud_account: Optional[str] = None
553
+ ) -> None:
554
+ """Create a new folder in this Teamspace.
555
+
556
+ Args:
557
+ name: The name of the folder. Folders will be accesible under `/teamspace/folders/<name>`
558
+ location: The location of the folder. Defaults to cloud agnostic.
559
+ cloud_account: The cloud account to create the folder in. Not used for cloud agnostic folders.
560
+ """
561
+ if cloud_account is None:
562
+ cloud_account = self.default_cloud_account
563
+
564
+ cloud_accounts = self._cloud_account_api.list_cloud_accounts(self.id)
565
+ resolved_cloud_accounts = [
566
+ external_cloud for external_cloud in cloud_accounts if external_cloud.id == cloud_account
567
+ ]
568
+
569
+ if len(resolved_cloud_accounts) == 0:
570
+ raise ValueError(f"Cloud account not found: {cloud_account}")
571
+
572
+ resolved_cloud_account = resolved_cloud_accounts[0]
573
+
574
+ # if the cloud account is global, default to agnostic
575
+ if location is None and resolved_cloud_account.spec.cluster_type == V1ClusterType.GLOBAL:
576
+ location = FolderLocation.CLOUD_AGNOSTIC
577
+
578
+ # if it's global, then default to agnostic, and aws / gcp otherwise if set
579
+ if (
580
+ location is not None
581
+ and location != FolderLocation.CLOUD_AGNOSTIC
582
+ and resolved_cloud_account.spec.cluster_type == V1ClusterType.GLOBAL
583
+ ):
584
+ providers = self._cloud_account_api.get_cloud_account_provider_mapping(self.id)
585
+
586
+ if location == FolderLocation.AWS:
587
+ resolved_cloud_account = providers[CloudProvider.AWS]
588
+ elif location == FolderLocation.GCP:
589
+ resolved_cloud_account = providers[CloudProvider.GCP]
590
+
591
+ if location == FolderLocation.CLOUD_AGNOSTIC:
592
+ self._teamspace_api.new_folder(self.id, name, None)
593
+ else:
594
+ self._teamspace_api.new_folder(self.id, name, resolved_cloud_account)
595
+
596
+ return
597
+
598
+ def new_connection(
599
+ self,
600
+ name: str,
601
+ source: str,
602
+ connection_type: ConnectionType,
603
+ writable: bool = True,
604
+ cloud_account: Optional[str] = None,
605
+ region: Optional[str] = None,
606
+ ) -> None:
607
+ """Add an existing data source to this Teamspace.
608
+
609
+ Args:
610
+ name: the name under which your data will be available in this Teamspace
611
+ source: the source spec of your data. Format depends on the type of data to connect.
612
+ For EFS, this should be the filsystem id
613
+ connection_type: the kind of data to connect to this Teamspace
614
+ writable: whether to support write-back to this data source. If False, the data is connected as read-only
615
+ cloud_account: which cloud-account to connect to the data source to.
616
+ If not specified, will retrieve the cloud-account that matches the required provider type
617
+ starting with private cloud accounts and falling back to public if necessary.
618
+ region: which provider region this data is in. Required for some connection types only.
619
+ """
620
+ provider_for_connection = self._cloud_account_api.get_cloud_provider_for_connection_type(connection_type)
621
+
622
+ if connection_type == ConnectionType.EFS and region is None:
623
+ raise ValueError("Region must be specified")
624
+
625
+ cloud_account = self._cloud_account_api.resolve_cloud_account(
626
+ self.id, cloud_account, provider_for_connection, None
627
+ )
628
+
629
+ cloud_accounts = self._cloud_account_api.list_cloud_accounts(self.id)
630
+ resolved_cloud_accounts = [
631
+ external_cloud for external_cloud in cloud_accounts if external_cloud.id == cloud_account
632
+ ]
633
+
634
+ if len(resolved_cloud_accounts) == 0:
635
+ raise ValueError(f"Cloud account not found: {cloud_account}")
636
+
637
+ resolved_cloud_account = resolved_cloud_accounts[0]
638
+
639
+ self._teamspace_api.new_connection(self.id, name, source, resolved_cloud_account, writable, region or "")
640
+
481
641
 
482
642
  def _list_files(path: Union[str, Path]) -> Tuple[List[Path], List[str]]:
483
643
  """List all folders in a directory and return them as a list and relative path."""
lightning_sdk/user.py CHANGED
@@ -1,4 +1,4 @@
1
- from typing import Optional
1
+ from typing import Dict, Optional
2
2
 
3
3
  from lightning_sdk.api import UserApi
4
4
  from lightning_sdk.owner import Owner
@@ -37,6 +37,24 @@ class User(Owner):
37
37
  """The user's ID."""
38
38
  return self._user.id
39
39
 
40
+ @property
41
+ def secrets(self) -> Dict[str, str]:
42
+ """All (encrypted) secrets for the user.
43
+
44
+ Note:
45
+ Once created, the secret values are encrypted and cannot be viewed here anymore.
46
+ """
47
+ return self._user_api.get_secrets()
48
+
49
+ def set_secret(self, key: str, value: str) -> None:
50
+ """Set a (encrypted) secret for the user."""
51
+ if not self._user_api.verify_secret_name(key):
52
+ raise ValueError(
53
+ "Secret keys must only contain alphanumeric characters and underscores and not begin with a number."
54
+ )
55
+
56
+ self._user_api.set_secret(key, value)
57
+
40
58
  def __repr__(self) -> str:
41
59
  """Returns reader friendly representation."""
42
60
  return f"User(name={self.name})"
@@ -0,0 +1,179 @@
1
+ import os
2
+ from dataclasses import dataclass
3
+ from typing import Any, Dict, Mapping, Optional, Sequence
4
+
5
+ import yaml
6
+
7
+ _DEFAULT_CONFIG_FILE_PATH = "~/.lightning/config.yaml"
8
+
9
+
10
+ @dataclass(frozen=True)
11
+ class DefaultConfigKeys:
12
+ """Default configuration keys for the Lightning SDK."""
13
+
14
+ organization: str = "organization.name"
15
+ user: str = "user.name"
16
+
17
+ teamspace_name: str = "teamspace.name"
18
+ teamspace_owner: str = "teamspace.owner"
19
+ teamspace_owner_type: str = "teamspace.owner_type"
20
+
21
+ machine: str = "machine.name"
22
+
23
+ studio: str = "studio.name"
24
+
25
+ cloud_account: str = "cloud_account.name"
26
+ cloud_provider: str = "cloud_provider.name"
27
+
28
+ license: str = "license"
29
+
30
+
31
+ class ConfigProxy:
32
+ def __init__(self, root: "Config", *path: str) -> None:
33
+ self._root = root
34
+ self._path = path # list of keys from root
35
+
36
+ def __getattr__(self, name: str) -> "ConfigProxy":
37
+ """Returns a reference to a nested ConfigProxy object a level deeper in the config hierarchy.
38
+
39
+ Args:
40
+ name: the name of the attribute to access, which corresponds to a key in the config.
41
+
42
+ Returns:
43
+ ConfigProxy: the next ConfigProxy object for the attribute.
44
+ """
45
+ # Build a deeper path and return a new proxy
46
+ return ConfigProxy(self._root, *self._path, name)
47
+
48
+ def __setattr__(self, name: str, value: Any) -> None:
49
+ """Sets the name attribute to value at the current hierarchy level.
50
+
51
+ Args:
52
+ name: the attribute name to set, which corresponds to a key in the config.
53
+ value: the value to set for the given attribute name in the config.
54
+ """
55
+ if name in ("_root", "_path"): # internal attributes
56
+ super().__setattr__(name, value)
57
+ else:
58
+ # Assign a nested value in the root config
59
+ self._root._set_nested([*self._path, name], value)
60
+
61
+
62
+ class Config:
63
+ def __init__(self, config_file: Optional[str] = None) -> None:
64
+ """Config class to manage configuration settings for the lightning SDK and CLI.
65
+
66
+ Args:
67
+ config_file: the file path where the configuration is stored.
68
+ If None, defaults to "~/.lightning/config.yaml".
69
+ """
70
+ if config_file is None:
71
+ config_file = _DEFAULT_CONFIG_FILE_PATH
72
+ self._config_file = os.path.expanduser(config_file)
73
+
74
+ def _load_config(self) -> Dict[str, Any]:
75
+ if not os.path.exists(self._config_file):
76
+ return {} # Return empty dict if config doesn't exist
77
+ with open(self._config_file) as f:
78
+ return yaml.safe_load(f) or {}
79
+
80
+ def _save_config(self, config: Dict[str, Any]) -> None:
81
+ os.makedirs(os.path.dirname(self._config_file), exist_ok=True)
82
+ config = _unflatten_dict(config)
83
+ with open(self._config_file, "w") as f:
84
+ yaml.safe_dump(config, f, default_flow_style=False, sort_keys=True)
85
+
86
+ def _set_nested(self, keys: Sequence[str], value: str) -> None:
87
+ config = self._load_config()
88
+ curr = config
89
+ for k in keys[:-1]:
90
+ if k not in curr or not isinstance(curr[k], Dict):
91
+ curr[k] = {}
92
+ curr = curr[k]
93
+ curr[keys[-1]] = value
94
+ self._save_config(config)
95
+
96
+ def get_value(self, key_path: str) -> Optional[str]:
97
+ """Gets a value from the config using dot notation.
98
+
99
+ Args:
100
+ key_path: the dot-separated path to the config value (e.g. "teamspace.name")
101
+
102
+ Returns:
103
+ The config value if found, None otherwise
104
+ """
105
+ return self._get_value_type(key_path, str)
106
+
107
+ def get_sub_config(self, key_path: str) -> Optional[Mapping[str, Any]]:
108
+ """Gets a subconfig from the config using dot notation.
109
+
110
+ Args:
111
+ key_path: the dot-separated path to the subconfig (e.g. "license")
112
+
113
+ Returns:
114
+ The subconfig if found, None otherwise
115
+ """
116
+ return self._get_value_type(key_path, Mapping)
117
+
118
+ def _get_value_type(self, key_path: str, subtype: type) -> Optional[Any]:
119
+ config = self._load_config()
120
+ if not isinstance(config, Mapping):
121
+ return None
122
+
123
+ keys = key_path.split(".")
124
+ curr = config
125
+ for k in keys:
126
+ if not isinstance(curr, dict) or k not in curr:
127
+ return None
128
+ curr = curr[k]
129
+ return curr if isinstance(curr, subtype) else None
130
+
131
+ def __getattr__(self, name: str) -> ConfigProxy:
132
+ """Returns a proxy to the actual values to allow for nested access.
133
+
134
+ Args:
135
+ name: the name of the value to retrieve.
136
+
137
+ Returns:
138
+ ConfigProxy: a proxy object that allows nested access to the configuration.
139
+ """
140
+ return ConfigProxy(self, name)
141
+
142
+ def __setattr__(self, name: str, value: Any) -> None:
143
+ """Sets the name attribute to value at the root level."""
144
+ if name in ("_config_file",): # internal attributes
145
+ super().__setattr__(name, value)
146
+ else:
147
+ # Assign a value at the root level
148
+ self._set_nested([name], value)
149
+
150
+ def __repr__(self) -> str:
151
+ """Returns a string representation of the config."""
152
+ return str(self)
153
+
154
+ def __str__(self) -> str:
155
+ """Returns a string representation of the config."""
156
+ return yaml.dump(
157
+ {"Config": {"config_file": self._config_file, **self._load_config()}},
158
+ indent=4,
159
+ sort_keys=True,
160
+ )
161
+
162
+ def get(self, key: str) -> Optional[str]:
163
+ return self.get_value(key)
164
+
165
+ def set(self, key: str, value: str) -> None:
166
+ self._set_nested([key], value)
167
+
168
+
169
+ def _unflatten_dict(flat_dict: Dict[str, Any]) -> Dict[str, Any]:
170
+ unflattened_dict = {}
171
+ for key, value in flat_dict.items():
172
+ keys = key.split(".")
173
+ curr = unflattened_dict
174
+ for k in keys[:-1]:
175
+ if k not in curr:
176
+ curr[k] = {}
177
+ curr = curr[k]
178
+ curr[keys[-1]] = value
179
+ return unflattened_dict
@@ -0,0 +1,13 @@
1
+ from functools import lru_cache
2
+
3
+ from lightning_sdk.api.license_api import LicenseApi
4
+
5
+
6
+ class License:
7
+ def __init__(self, license_key: str, product_name: str) -> None:
8
+ self.license_key = license_key
9
+ self.product_name = product_name
10
+
11
+ @lru_cache(maxsize=1) # noqa: B019
12
+ def validate(self) -> bool:
13
+ return LicenseApi(self.license_key).validate_license(self.license_key, self.product_name)
@@ -0,0 +1,79 @@
1
+ import functools
2
+ import inspect
3
+ import time
4
+ import traceback
5
+ from abc import ABCMeta
6
+ from contextlib import suppress
7
+ from typing import Callable, Dict, Tuple
8
+
9
+ from lightning_sdk.__version__ import __version__
10
+ from lightning_sdk.lightning_cloud.openapi import V1CreateSDKCommandHistoryRequest, V1SDKCommandHistorySeverity
11
+ from lightning_sdk.lightning_cloud.openapi.models.v1_sdk_command_history_type import V1SDKCommandHistoryType
12
+ from lightning_sdk.lightning_cloud.rest_client import LightningClient
13
+
14
+
15
+ def track_calls() -> Callable[..., any]:
16
+ def decorator(func: Callable[..., any]) -> Callable[..., any]:
17
+ @functools.wraps(func)
18
+ def wrapper(*args: Tuple[any, ...], **kwargs: Dict[str, any]) -> any:
19
+ start_time = time.time()
20
+ sig = inspect.signature(func)
21
+ bound_args = sig.bind(*args, **kwargs)
22
+ bound_args.apply_defaults()
23
+
24
+ args_str = ", ".join(f"{k}: {v}" for k, v in bound_args.arguments.items() if k != "self")
25
+ message = f"VERSION: {__version__} | ARGS: {args_str} "
26
+
27
+ body = V1CreateSDKCommandHistoryRequest(
28
+ command=func.__qualname__,
29
+ message=message,
30
+ project_id=None,
31
+ severity=V1SDKCommandHistorySeverity.INFO,
32
+ type=V1SDKCommandHistoryType.SDK,
33
+ )
34
+
35
+ try:
36
+ return func(*args, **kwargs)
37
+
38
+ except Exception as e:
39
+ body.severity = V1SDKCommandHistorySeverity.ERROR
40
+ body.message += f" | Error: {type(e).__name__}: {e!s} | Traceback: {traceback.format_exc(limit=3)}"
41
+ body.duration = int(time.time() - start_time)
42
+ with suppress(Exception):
43
+ client = LightningClient(retry=False, max_tries=0)
44
+ client.s_dk_command_history_service_create_sdk_command_history(body=body)
45
+ raise
46
+
47
+ return wrapper
48
+
49
+ return decorator
50
+
51
+
52
+ class TrackCallsMeta(type):
53
+ def __new__(cls, name: any, bases: any, attrs: any) -> type.__new__:
54
+ for attr_name, attr_value in attrs.items():
55
+ if attr_name.startswith("__") and attr_name not in ("__init__", "__call__"):
56
+ attrs[attr_name] = attr_value
57
+ continue
58
+
59
+ # Noisy
60
+ if attr_name in ("_cls_name"):
61
+ attrs[attr_name] = attr_value
62
+ continue
63
+
64
+ if callable(attr_value):
65
+ attrs[attr_name] = track_calls()(attr_value)
66
+
67
+ elif isinstance(attr_value, property):
68
+ fget = track_calls()(attr_value.fget) if attr_value.fget else None
69
+ fset = track_calls()(attr_value.fset) if attr_value.fset else None
70
+ fdel = track_calls()(attr_value.fdel) if attr_value.fdel else None
71
+ attrs[attr_name] = property(fget, fset, fdel)
72
+
73
+ else:
74
+ attrs[attr_name] = attr_value
75
+ return super().__new__(cls, name, bases, attrs)
76
+
77
+
78
+ class TrackCallsABCMeta(ABCMeta, TrackCallsMeta):
79
+ """Combined metaclass for classes that need both ABC and TrackCalls functionality."""