zenml-nightly 0.63.0.dev20240801__py3-none-any.whl → 0.64.0.dev20240811__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 (198) hide show
  1. README.md +2 -2
  2. RELEASE_NOTES.md +79 -0
  3. zenml/VERSION +1 -1
  4. zenml/__init__.py +0 -4
  5. zenml/analytics/enums.py +0 -6
  6. zenml/cli/__init__.py +0 -61
  7. zenml/cli/base.py +1 -1
  8. zenml/cli/web_login.py +8 -0
  9. zenml/client.py +0 -4
  10. zenml/config/build_configuration.py +43 -17
  11. zenml/config/docker_settings.py +80 -57
  12. zenml/config/source.py +58 -0
  13. zenml/constants.py +9 -2
  14. zenml/entrypoints/base_entrypoint_configuration.py +53 -8
  15. zenml/enums.py +1 -1
  16. zenml/environment.py +25 -9
  17. zenml/image_builders/base_image_builder.py +1 -1
  18. zenml/image_builders/build_context.py +25 -72
  19. zenml/integrations/azure/__init__.py +4 -0
  20. zenml/integrations/azure/flavors/__init__.py +11 -0
  21. zenml/integrations/azure/flavors/azureml_orchestrator_flavor.py +263 -0
  22. zenml/{_hub → integrations/azure/orchestrators}/__init__.py +7 -2
  23. zenml/integrations/azure/orchestrators/azureml_orchestrator.py +544 -0
  24. zenml/integrations/azure/orchestrators/azureml_orchestrator_entrypoint_config.py +86 -0
  25. zenml/integrations/azure/step_operators/azureml_step_operator.py +3 -0
  26. zenml/integrations/databricks/flavors/databricks_orchestrator_flavor.py +9 -0
  27. zenml/integrations/gcp/orchestrators/vertex_orchestrator.py +7 -2
  28. zenml/integrations/gcp/service_connectors/gcp_service_connector.py +123 -6
  29. zenml/integrations/kaniko/image_builders/kaniko_image_builder.py +1 -1
  30. zenml/integrations/mlflow/__init__.py +1 -1
  31. zenml/integrations/mlflow/experiment_trackers/mlflow_experiment_tracker.py +3 -1
  32. zenml/integrations/mlflow/flavors/mlflow_experiment_tracker_flavor.py +3 -0
  33. zenml/logger.py +13 -0
  34. zenml/models/__init__.py +0 -12
  35. zenml/models/v2/core/pipeline_deployment.py +21 -29
  36. zenml/models/v2/core/pipeline_run.py +13 -0
  37. zenml/models/v2/core/server_settings.py +12 -0
  38. zenml/models/v2/core/user.py +0 -21
  39. zenml/models/v2/misc/server_models.py +7 -1
  40. zenml/models/v2/misc/user_auth.py +0 -7
  41. zenml/new/pipelines/build_utils.py +193 -38
  42. zenml/new/pipelines/code_archive.py +157 -0
  43. zenml/new/pipelines/pipeline.py +29 -2
  44. zenml/new/pipelines/run_utils.py +67 -1
  45. zenml/service_connectors/service_connector_utils.py +14 -0
  46. zenml/stack_deployments/aws_stack_deployment.py +26 -3
  47. zenml/stack_deployments/azure_stack_deployment.py +11 -6
  48. zenml/stack_deployments/gcp_stack_deployment.py +24 -2
  49. zenml/stack_deployments/stack_deployment.py +17 -2
  50. zenml/steps/base_step.py +3 -0
  51. zenml/utils/archivable.py +149 -0
  52. zenml/utils/code_utils.py +244 -0
  53. zenml/utils/notebook_utils.py +122 -0
  54. zenml/utils/pipeline_docker_image_builder.py +3 -96
  55. zenml/utils/source_utils.py +109 -1
  56. zenml/zen_server/dashboard/assets/{404-CI13wQp4.js → 404-CRAA_Lew.js} +1 -1
  57. zenml/zen_server/dashboard/assets/@radix-BXWm7HOa.js +85 -0
  58. zenml/zen_server/dashboard/assets/{@react-router-CO-OsFwI.js → @react-router-l3lMcXA2.js} +1 -1
  59. zenml/zen_server/dashboard/assets/{@reactflow-DIYUhKYX.js → @reactflow-CeVxyqYT.js} +2 -2
  60. zenml/zen_server/dashboard/assets/{@tanstack-k96lU_C-.js → @tanstack-FmcYZMuX.js} +4 -4
  61. zenml/zen_server/dashboard/assets/AlertDialogDropdownItem-ErO9aOgK.js +1 -0
  62. zenml/zen_server/dashboard/assets/{AwarenessChannel-BNg5uWgI.js → AwarenessChannel-CLXo5rKM.js} +1 -1
  63. zenml/zen_server/dashboard/assets/{CodeSnippet-Cyp7f4dM.js → CodeSnippet-D0VLxT2A.js} +1 -1
  64. zenml/zen_server/dashboard/assets/{CollapsibleCard-Cu_A9W57.js → CollapsibleCard-BaUPiVg0.js} +1 -1
  65. zenml/zen_server/dashboard/assets/{Commands-DmQwTXjj.js → Commands-JrcZK-3j.js} +1 -1
  66. zenml/zen_server/dashboard/assets/CopyButton-Dbo52T1K.js +2 -0
  67. zenml/zen_server/dashboard/assets/{CsvVizualization-BvqItd-O.js → CsvVizualization-D3kAypDj.js} +3 -3
  68. zenml/zen_server/dashboard/assets/DisplayDate-DizbSeT-.js +1 -0
  69. zenml/zen_server/dashboard/assets/EditSecretDialog-Bd7mFLS4.js +1 -0
  70. zenml/zen_server/dashboard/assets/{EmptyState-BMLnFVlB.js → EmptyState-BHblM39I.js} +1 -1
  71. zenml/zen_server/dashboard/assets/{Error-DbXCTGua.js → Error-C6LeJSER.js} +1 -1
  72. zenml/zen_server/dashboard/assets/{ExecutionStatus-9zM7eaLh.js → ExecutionStatus-jH4OrWBq.js} +1 -1
  73. zenml/zen_server/dashboard/assets/{Helpbox-BIiNc-uH.js → Helpbox-aAB2XP-z.js} +1 -1
  74. zenml/zen_server/dashboard/assets/{Infobox-iv1Nu1A0.js → Infobox-BQ0aty32.js} +1 -1
  75. zenml/zen_server/dashboard/assets/{InlineAvatar-BvBtO2Dp.js → InlineAvatar-DpTLgM3Q.js} +1 -1
  76. zenml/zen_server/dashboard/assets/Lock-CNyJvf2r.js +1 -0
  77. zenml/zen_server/dashboard/assets/{MarkdownVisualization-xp3hhULl.js → MarkdownVisualization-Bajxn0HY.js} +1 -1
  78. zenml/zen_server/dashboard/assets/NumberBox-BmKE0qnO.js +1 -0
  79. zenml/zen_server/dashboard/assets/{PasswordChecker-DUveqlva.js → PasswordChecker-yGGoJSB-.js} +1 -1
  80. zenml/zen_server/dashboard/assets/{ProviderRadio-pSAvrGRS.js → ProviderRadio-BBqkIuTd.js} +1 -1
  81. zenml/zen_server/dashboard/assets/RadioItem-xLhXoiFV.js +1 -0
  82. zenml/zen_server/dashboard/assets/SearchField-C9R0mdaX.js +1 -0
  83. zenml/zen_server/dashboard/assets/{SetPassword-BOxpgh6N.js → SetPassword-52sNxNiO.js} +1 -1
  84. zenml/zen_server/dashboard/assets/{SuccessStep-CTSKN2lp.js → SuccessStep-DlkItqYG.js} +1 -1
  85. zenml/zen_server/dashboard/assets/{Tick-Bnr2TpW6.js → Tick-uxv80Q6a.js} +1 -1
  86. zenml/zen_server/dashboard/assets/{UpdatePasswordSchemas-BeCeaRW5.js → UpdatePasswordSchemas-oN4G3sKz.js} +1 -1
  87. zenml/zen_server/dashboard/assets/{aws-BgKTfTfx.js → aws-0_3UsPif.js} +1 -1
  88. zenml/zen_server/dashboard/assets/{check-circle-i56092KI.js → check-circle-1_I207rW.js} +1 -1
  89. zenml/zen_server/dashboard/assets/{chevron-down-D_ZlKMqH.js → chevron-down-BpaF8JqM.js} +1 -1
  90. zenml/zen_server/dashboard/assets/{chevron-right-double-CZBOf6JM.js → chevron-right-double-Dk8e2L99.js} +1 -1
  91. zenml/zen_server/dashboard/assets/{cloud-only-qelmY92E.js → cloud-only-BkUuI0lZ.js} +1 -1
  92. zenml/zen_server/dashboard/assets/components-Br2ezRib.js +1 -0
  93. zenml/zen_server/dashboard/assets/{copy-BXNk6BjL.js → copy-f3XGPPxt.js} +1 -1
  94. zenml/zen_server/dashboard/assets/{database-1xWSgZfO.js → database-cXYNX9tt.js} +1 -1
  95. zenml/zen_server/dashboard/assets/{docker-CQMVm_4d.js → docker-8uj__HHK.js} +1 -1
  96. zenml/zen_server/dashboard/assets/{dots-horizontal-BObFzD5l.js → dots-horizontal-sKQlWEni.js} +1 -1
  97. zenml/zen_server/dashboard/assets/edit-C0MVvPD2.js +1 -0
  98. zenml/zen_server/dashboard/assets/{file-text-CqD_iu6l.js → file-text-B9JibxTs.js} +1 -1
  99. zenml/zen_server/dashboard/assets/{help-bu_DgLKI.js → help-FuHlZwn0.js} +1 -1
  100. zenml/zen_server/dashboard/assets/index-Bd1xgUQG.js +1 -0
  101. zenml/zen_server/dashboard/assets/index-DaGknux4.css +1 -0
  102. zenml/zen_server/dashboard/assets/{index-KsTz2dHG.js → index-DhIZtpxB.js} +5 -5
  103. zenml/zen_server/dashboard/assets/{index.esm-CbHNSeVw.js → index.esm-DT4uyn2i.js} +1 -1
  104. zenml/zen_server/dashboard/assets/layout-D6oiSbfd.js +1 -0
  105. zenml/zen_server/dashboard/assets/{login-mutation-DRpbESS7.js → login-mutation-13A_JSVA.js} +1 -1
  106. zenml/zen_server/dashboard/assets/{logs-D8k8BVFf.js → logs-CgeE2vZP.js} +1 -1
  107. zenml/zen_server/dashboard/assets/{not-found-Dfx9hfkf.js → not-found-B0Mmb90p.js} +1 -1
  108. zenml/zen_server/dashboard/assets/{package-ClbU3KUi.js → package-DdkziX79.js} +1 -1
  109. zenml/zen_server/dashboard/assets/page-7-v2OBm-.js +1 -0
  110. zenml/zen_server/dashboard/assets/{page-f3jBVI5Z.js → page-B3ozwdD1.js} +1 -1
  111. zenml/zen_server/dashboard/assets/{page-DYBNGxJt.js → page-BGwA9B1M.js} +1 -1
  112. zenml/zen_server/dashboard/assets/{page-C176KxyB.js → page-BkjAUyTA.js} +1 -1
  113. zenml/zen_server/dashboard/assets/page-BnacgBiy.js +1 -0
  114. zenml/zen_server/dashboard/assets/{page-CzucfYPo.js → page-BxF_KMQ3.js} +2 -2
  115. zenml/zen_server/dashboard/assets/page-C4POHC0K.js +1 -0
  116. zenml/zen_server/dashboard/assets/page-C9kudd44.js +9 -0
  117. zenml/zen_server/dashboard/assets/page-CA1j3GpJ.js +1 -0
  118. zenml/zen_server/dashboard/assets/page-CCY6yfmu.js +1 -0
  119. zenml/zen_server/dashboard/assets/page-CgTe7Bme.js +1 -0
  120. zenml/zen_server/dashboard/assets/{page-DtpwnNXq.js → page-Cgn-6v2Y.js} +1 -1
  121. zenml/zen_server/dashboard/assets/page-CxQmQqDw.js +1 -0
  122. zenml/zen_server/dashboard/assets/page-D2Goey3H.js +1 -0
  123. zenml/zen_server/dashboard/assets/page-DLpOnf7u.js +1 -0
  124. zenml/zen_server/dashboard/assets/{page-DVPxY5fT.js → page-DSTQnBk-.js} +1 -1
  125. zenml/zen_server/dashboard/assets/{page-BoFtUD9H.js → page-DTysUGOy.js} +1 -1
  126. zenml/zen_server/dashboard/assets/{page-p2hLJdS2.js → page-D_EXUFJb.js} +1 -1
  127. zenml/zen_server/dashboard/assets/page-Db15QzsM.js +1 -0
  128. zenml/zen_server/dashboard/assets/{page-Btu39x7k.js → page-DugsjcQ_.js} +1 -1
  129. zenml/zen_server/dashboard/assets/{page-CZe9GEBF.js → page-OFKSPyN7.js} +1 -1
  130. zenml/zen_server/dashboard/assets/{page-CDgZmwxP.js → page-RnG-qhv9.js} +1 -1
  131. zenml/zen_server/dashboard/assets/{page-Cjn97HMv.js → page-T2BtjwPl.js} +1 -1
  132. zenml/zen_server/dashboard/assets/page-TXe1Eo3Z.js +1 -0
  133. zenml/zen_server/dashboard/assets/{page-BxiWdeyg.js → page-YiF_fNbe.js} +1 -1
  134. zenml/zen_server/dashboard/assets/{page-399pVZHU.js → page-hQaiQXfg.js} +1 -1
  135. zenml/zen_server/dashboard/assets/persist-3-5nOJ6m.js +1 -0
  136. zenml/zen_server/dashboard/assets/{play-circle-CNtZKDnW.js → play-circle-XSkLR12B.js} +1 -1
  137. zenml/zen_server/dashboard/assets/{plus-DOeLmm7C.js → plus-FB9-lEq_.js} +1 -1
  138. zenml/zen_server/dashboard/assets/refresh-COb6KYDi.js +1 -0
  139. zenml/zen_server/dashboard/assets/sharedSchema-BoYx_B_L.js +14 -0
  140. zenml/zen_server/dashboard/assets/{stack-detail-query-Ck7j7BP_.js → stack-detail-query-B-US_-wa.js} +1 -1
  141. zenml/zen_server/dashboard/assets/{terminal-By9cErXc.js → terminal-grtjrIEJ.js} +1 -1
  142. zenml/zen_server/dashboard/assets/trash-Cd5CSFqA.js +1 -0
  143. zenml/zen_server/dashboard/assets/{update-server-settings-mutation-f3ZT7psb.js → update-server-settings-mutation-B8GB_ubU.js} +1 -1
  144. zenml/zen_server/dashboard/assets/{url-rGEp5Umh.js → url-hcMJkz8p.js} +1 -1
  145. zenml/zen_server/dashboard/assets/{zod-BtSyGx4C.js → zod-CnykDKJj.js} +1 -1
  146. zenml/zen_server/dashboard/index.html +7 -7
  147. zenml/zen_server/dashboard_legacy/asset-manifest.json +4 -4
  148. zenml/zen_server/dashboard_legacy/index.html +1 -1
  149. zenml/zen_server/dashboard_legacy/{precache-manifest.2fa6e528a6e7447caaf35dadfe7514bb.js → precache-manifest.9c473c96a43298343a7ce1256183123b.js} +4 -4
  150. zenml/zen_server/dashboard_legacy/service-worker.js +1 -1
  151. zenml/zen_server/dashboard_legacy/static/js/{main.4aab7e98.chunk.js → main.463c90b9.chunk.js} +2 -2
  152. zenml/zen_server/dashboard_legacy/static/js/{main.4aab7e98.chunk.js.map → main.463c90b9.chunk.js.map} +1 -1
  153. zenml/zen_server/deploy/helm/Chart.yaml +1 -1
  154. zenml/zen_server/deploy/helm/README.md +2 -2
  155. zenml/zen_server/routers/stack_deployment_endpoints.py +6 -0
  156. zenml/zen_server/routers/users_endpoints.py +0 -7
  157. zenml/zen_server/utils.py +75 -0
  158. zenml/zen_server/zen_server_api.py +52 -1
  159. zenml/zen_stores/base_zen_store.py +7 -1
  160. zenml/zen_stores/migrations/versions/0.64.0_release.py +23 -0
  161. zenml/zen_stores/migrations/versions/026d4577b6a0_add_code_path.py +39 -0
  162. zenml/zen_stores/migrations/versions/3dcc5d20e82f_add_last_user_activity.py +51 -0
  163. zenml/zen_stores/migrations/versions/909550c7c4da_remove_user_hub_token.py +36 -0
  164. zenml/zen_stores/rest_zen_store.py +5 -3
  165. zenml/zen_stores/schemas/pipeline_deployment_schemas.py +3 -0
  166. zenml/zen_stores/schemas/pipeline_run_schemas.py +3 -0
  167. zenml/zen_stores/schemas/server_settings_schemas.py +2 -0
  168. zenml/zen_stores/schemas/user_schemas.py +0 -2
  169. zenml/zen_stores/sql_zen_store.py +25 -1
  170. {zenml_nightly-0.63.0.dev20240801.dist-info → zenml_nightly-0.64.0.dev20240811.dist-info}/METADATA +3 -3
  171. {zenml_nightly-0.63.0.dev20240801.dist-info → zenml_nightly-0.64.0.dev20240811.dist-info}/RECORD +174 -157
  172. zenml/_hub/client.py +0 -289
  173. zenml/_hub/constants.py +0 -21
  174. zenml/_hub/utils.py +0 -79
  175. zenml/cli/hub.py +0 -1116
  176. zenml/models/v2/misc/hub_plugin_models.py +0 -79
  177. zenml/zen_server/dashboard/assets/@radix-CFOkMR_E.js +0 -85
  178. zenml/zen_server/dashboard/assets/CopyButton-B3sWVJ4Z.js +0 -2
  179. zenml/zen_server/dashboard/assets/DisplayDate-DYgIjlDF.js +0 -1
  180. zenml/zen_server/dashboard/assets/SearchField-CXoBknpt.js +0 -1
  181. zenml/zen_server/dashboard/assets/components-DWe4cTjS.js +0 -1
  182. zenml/zen_server/dashboard/assets/index-vfjX_fJV.css +0 -1
  183. zenml/zen_server/dashboard/assets/page-C6tXXjnK.js +0 -1
  184. zenml/zen_server/dashboard/assets/page-CP9obrnG.js +0 -1
  185. zenml/zen_server/dashboard/assets/page-CaTOsNNw.js +0 -1
  186. zenml/zen_server/dashboard/assets/page-CmXmB_5i.js +0 -1
  187. zenml/zen_server/dashboard/assets/page-CvGAOfad.js +0 -1
  188. zenml/zen_server/dashboard/assets/page-D0bbc-qr.js +0 -5
  189. zenml/zen_server/dashboard/assets/page-DLEtD2ex.js +0 -1
  190. zenml/zen_server/dashboard/assets/page-DupV0aBd.js +0 -1
  191. zenml/zen_server/dashboard/assets/page-EweAR81y.js +0 -1
  192. zenml/zen_server/dashboard/assets/page-w-YaL77M.js +0 -9
  193. zenml/zen_server/dashboard/assets/persist-BReKApOc.js +0 -14
  194. zenml/zen_server/dashboard/assets/secrets-video-OBJ6irhH.svg +0 -21
  195. zenml/zen_server/dashboard/assets/stacks-video-7gfxpAq4.svg +0 -21
  196. {zenml_nightly-0.63.0.dev20240801.dist-info → zenml_nightly-0.64.0.dev20240811.dist-info}/LICENSE +0 -0
  197. {zenml_nightly-0.63.0.dev20240801.dist-info → zenml_nightly-0.64.0.dev20240811.dist-info}/WHEEL +0 -0
  198. {zenml_nightly-0.63.0.dev20240801.dist-info → zenml_nightly-0.64.0.dev20240811.dist-info}/entry_points.txt +0 -0
zenml/config/source.py CHANGED
@@ -42,6 +42,7 @@ class SourceType(Enum):
42
42
  INTERNAL = "internal"
43
43
  DISTRIBUTION_PACKAGE = "distribution_package"
44
44
  CODE_REPOSITORY = "code_repository"
45
+ NOTEBOOK = "notebook"
45
46
  UNKNOWN = "unknown"
46
47
 
47
48
 
@@ -229,6 +230,63 @@ class CodeRepositorySource(Source):
229
230
  return value
230
231
 
231
232
 
233
+ class NotebookSource(Source):
234
+ """Source representing an object defined in a notebook.
235
+
236
+ Attributes:
237
+ code_path: Path where the notebook cell code for this source is
238
+ uploaded.
239
+ replacement_module: Name of the module from which this source should
240
+ be loaded in case the code is not running in a notebook.
241
+ """
242
+
243
+ code_path: Optional[str] = None
244
+ replacement_module: Optional[str] = None
245
+ type: SourceType = SourceType.NOTEBOOK
246
+
247
+ # Private attribute that is used to store the code but should not be
248
+ # serialized
249
+ _cell_code: Optional[str] = None
250
+
251
+ @field_validator("type")
252
+ @classmethod
253
+ def _validate_type(cls, value: SourceType) -> SourceType:
254
+ """Validate the source type.
255
+
256
+ Args:
257
+ value: The source type.
258
+
259
+ Raises:
260
+ ValueError: If the source type is not `NOTEBOOK`.
261
+
262
+ Returns:
263
+ The source type.
264
+ """
265
+ if value != SourceType.NOTEBOOK:
266
+ raise ValueError("Invalid source type.")
267
+
268
+ return value
269
+
270
+ @field_validator("module")
271
+ @classmethod
272
+ def _validate_module(cls, value: str) -> str:
273
+ """Validate the module.
274
+
275
+ Args:
276
+ value: The module.
277
+
278
+ Raises:
279
+ ValueError: If the module is not `__main__`.
280
+
281
+ Returns:
282
+ The module.
283
+ """
284
+ if value != "__main__":
285
+ raise ValueError("Invalid module for notebook source.")
286
+
287
+ return value
288
+
289
+
232
290
  def convert_source(source: Any) -> Any:
233
291
  """Converts an old source string to a source object.
234
292
 
zenml/constants.py CHANGED
@@ -165,7 +165,6 @@ ENV_ZENML_SKIP_IMAGE_BUILDER_DEFAULT = "ZENML_SKIP_IMAGE_BUILDER_DEFAULT"
165
165
  ENV_ZENML_REQUIRES_CODE_DOWNLOAD = "ZENML_REQUIRES_CODE_DOWNLOAD"
166
166
  ENV_ZENML_SERVER = "ZENML_SERVER"
167
167
  ENV_ZENML_LOCAL_SERVER = "ZENML_LOCAL_SERVER"
168
- ENV_ZENML_HUB_URL = "ZENML_HUB_URL"
169
168
  ENV_ZENML_ENFORCE_TYPE_ANNOTATIONS = "ZENML_ENFORCE_TYPE_ANNOTATIONS"
170
169
  ENV_ZENML_ENABLE_IMPLICIT_AUTH_METHODS = "ZENML_ENABLE_IMPLICIT_AUTH_METHODS"
171
170
  ENV_ZENML_DISABLE_STEP_LOGS_STORAGE = "ZENML_DISABLE_STEP_LOGS_STORAGE"
@@ -279,7 +278,6 @@ DEFAULT_ZENML_SERVER_SECURE_HEADERS_CONTENT = "nosniff"
279
278
  _csp_script_src_urls = ["https://widgets-v3.featureos.app"]
280
279
  _csp_connect_src_urls = [
281
280
  "https://sdkdocs.zenml.io",
282
- "https://hubapi.zenml.io",
283
281
  "https://analytics.zenml.io",
284
282
  ]
285
283
  _csp_img_src_urls = [
@@ -315,6 +313,7 @@ DEFAULT_ZENML_SERVER_SECURE_HEADERS_PERMISSIONS = (
315
313
  )
316
314
  DEFAULT_ZENML_SERVER_SECURE_HEADERS_REPORT_TO = "default"
317
315
  DEFAULT_ZENML_SERVER_USE_LEGACY_DASHBOARD = False
316
+ DEFAULT_ZENML_SERVER_REPORT_USER_ACTIVITY_TO_DB_SECONDS = 30
318
317
 
319
318
  # Configurations to decide which resources report their usage and check for
320
319
  # entitlement in the case of a cloud deployment. Expected Format is this:
@@ -494,3 +493,11 @@ BANNED_NAME_CHARACTERS = "\t\n\r\v\f"
494
493
 
495
494
 
496
495
  STACK_DEPLOYMENT_API_TOKEN_EXPIRATION = 60 * 6 # 6 hours
496
+
497
+ # ZenML Pro
498
+ ZENML_PRO_CONNECTION_ISSUES_SUSPENDED_PAUSED_TENANT_HINT = (
499
+ "\nHINT: Since you are trying to communicate with the ZenML Pro Tenant, "
500
+ "please make sure that your tenant is in RUNNING state on your "
501
+ "Organization page. If the tenant is PAUSED you can `Resume` it via UI "
502
+ "and try again."
503
+ )
@@ -27,10 +27,15 @@ from zenml.constants import (
27
27
  handle_bool_env_var,
28
28
  )
29
29
  from zenml.logger import get_logger
30
- from zenml.utils import code_repository_utils, source_utils, uuid_utils
30
+ from zenml.utils import (
31
+ code_repository_utils,
32
+ code_utils,
33
+ source_utils,
34
+ uuid_utils,
35
+ )
31
36
 
32
37
  if TYPE_CHECKING:
33
- from zenml.models import PipelineDeploymentResponse
38
+ from zenml.models import CodeReferenceResponse, PipelineDeploymentResponse
34
39
 
35
40
  logger = get_logger(__name__)
36
41
  DEFAULT_ENTRYPOINT_COMMAND = [
@@ -198,7 +203,7 @@ class BaseEntrypointConfiguration(ABC):
198
203
 
199
204
  Raises:
200
205
  RuntimeError: If the current environment requires code download
201
- but the deployment does not have an associated code reference.
206
+ but the deployment does not have a reference to any code.
202
207
  """
203
208
  requires_code_download = handle_bool_env_var(
204
209
  ENV_ZENML_REQUIRES_CODE_DOWNLOAD
@@ -207,17 +212,33 @@ class BaseEntrypointConfiguration(ABC):
207
212
  if not requires_code_download:
208
213
  return
209
214
 
210
- code_reference = deployment.code_reference
211
- if not code_reference:
215
+ if code_reference := deployment.code_reference:
216
+ self.download_code_from_code_repository(
217
+ code_reference=code_reference
218
+ )
219
+ elif code_path := deployment.code_path:
220
+ self.download_code_from_artifact_store(code_path=code_path)
221
+ else:
212
222
  raise RuntimeError(
213
- "Code download required but no code reference provided."
223
+ "Code download required but no code reference or path provided."
214
224
  )
215
225
 
226
+ logger.info("Code download finished.")
227
+
228
+ def download_code_from_code_repository(
229
+ self, code_reference: "CodeReferenceResponse"
230
+ ) -> None:
231
+ """Download code from a code repository.
232
+
233
+ Args:
234
+ code_reference: The reference to the code.
235
+ """
216
236
  logger.info(
217
237
  "Downloading code from code repository `%s` (commit `%s`).",
218
238
  code_reference.code_repository.name,
219
239
  code_reference.commit,
220
240
  )
241
+
221
242
  model = Client().get_code_repository(code_reference.code_repository.id)
222
243
  repo = BaseCodeRepository.from_model(model)
223
244
  code_repo_root = os.path.abspath("code")
@@ -234,10 +255,34 @@ class BaseEntrypointConfiguration(ABC):
234
255
  code_repository_utils.set_custom_local_repository(
235
256
  root=code_repo_root, commit=code_reference.commit, repo=repo
236
257
  )
237
- # Add downloaded file directory to python path
258
+
238
259
  sys.path.insert(0, download_dir)
260
+ os.chdir(download_dir)
239
261
 
240
- logger.info("Code download finished.")
262
+ def download_code_from_artifact_store(self, code_path: str) -> None:
263
+ """Download code from the artifact store.
264
+
265
+ Args:
266
+ code_path: Path where the code is stored.
267
+ """
268
+ logger.info(
269
+ "Downloading code from artifact store path `%s`.", code_path
270
+ )
271
+
272
+ # Do not remove this line, we need to instantiate the artifact store to
273
+ # register the filesystem needed for the file download
274
+ _ = Client().active_stack.artifact_store
275
+
276
+ extract_dir = os.path.abspath("code")
277
+ os.makedirs(extract_dir)
278
+
279
+ code_utils.download_and_extract_code(
280
+ code_path=code_path, extract_dir=extract_dir
281
+ )
282
+
283
+ source_utils.set_custom_source_root(extract_dir)
284
+ sys.path.insert(0, extract_dir)
285
+ os.chdir(extract_dir)
241
286
 
242
287
  @abstractmethod
243
288
  def run(self) -> None:
zenml/enums.py CHANGED
@@ -171,7 +171,6 @@ class CliCategories(StrEnum):
171
171
 
172
172
  STACK_COMPONENTS = "Stack Components"
173
173
  MODEL_DEPLOYMENT = "Model Deployment"
174
- HUB = "ZenML Hub"
175
174
  INTEGRATIONS = "Integrations"
176
175
  MANAGEMENT_TOOLS = "Management Tools"
177
176
  MODEL_CONTROL_PLANE = "Model Control Plane"
@@ -303,6 +302,7 @@ class EnvironmentType(StrEnum):
303
302
  NOTEBOOK = "notebook"
304
303
  PAPERSPACE = "paperspace"
305
304
  WSL = "wsl"
305
+ LIGHTNING_AI_STUDIO = "lightning_ai_studio"
306
306
 
307
307
 
308
308
  class ModelStages(StrEnum):
zenml/environment.py CHANGED
@@ -15,7 +15,6 @@
15
15
 
16
16
  import os
17
17
  import platform
18
- from importlib.util import find_spec
19
18
  from pathlib import Path
20
19
  from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple, Type, cast
21
20
 
@@ -70,6 +69,8 @@ def get_environment() -> str:
70
69
  return EnvironmentType.BITBUCKET_CI
71
70
  elif Environment.in_ci():
72
71
  return EnvironmentType.GENERIC_CI
72
+ elif Environment.in_lightning_ai_studio():
73
+ return EnvironmentType.LIGHTNING_AI_STUDIO
73
74
  elif Environment.in_docker():
74
75
  return EnvironmentType.DOCKER
75
76
  elif Environment.in_container():
@@ -257,15 +258,17 @@ class Environment(metaclass=SingletonMetaClass):
257
258
  if Environment.in_google_colab():
258
259
  return True
259
260
 
260
- if find_spec("IPython") is not None:
261
- from IPython import get_ipython
261
+ try:
262
+ ipython = get_ipython() # type: ignore[name-defined]
263
+ except NameError:
264
+ return False
262
265
 
263
- if get_ipython().__class__.__name__ in [
264
- "TerminalInteractiveShell",
265
- "ZMQInteractiveShell",
266
- "DatabricksShell",
267
- ]:
268
- return True
266
+ if ipython.__class__.__name__ in [
267
+ "TerminalInteractiveShell",
268
+ "ZMQInteractiveShell",
269
+ "DatabricksShell",
270
+ ]:
271
+ return True
269
272
  return False
270
273
 
271
274
  @staticmethod
@@ -339,6 +342,19 @@ class Environment(metaclass=SingletonMetaClass):
339
342
  """
340
343
  return "microsoft-standard" in platform.uname().release
341
344
 
345
+ @staticmethod
346
+ def in_lightning_ai_studio() -> bool:
347
+ """If the current Python process is running in Lightning.ai studios.
348
+
349
+ Returns:
350
+ `True` if the current Python process is running in Lightning.ai studios,
351
+ `False` otherwise.
352
+ """
353
+ return (
354
+ "LIGHTNING_CLOUD_URL" in os.environ
355
+ and "LIGHTNING_CLOUDSPACE_HOST" in os.environ
356
+ )
357
+
342
358
  def register_component(
343
359
  self, component: "BaseEnvironmentComponent"
344
360
  ) -> "BaseEnvironmentComponent":
@@ -119,7 +119,7 @@ class BaseImageBuilder(StackComponent, ABC):
119
119
 
120
120
  hash_ = hashlib.sha1() # nosec
121
121
  with tempfile.NamedTemporaryFile(mode="w+b", delete=False) as f:
122
- build_context.write_archive(f, gzip=True)
122
+ build_context.write_archive(f, use_gzip=True)
123
123
 
124
124
  while True:
125
125
  data = f.read(64 * 1024)
@@ -14,18 +14,18 @@
14
14
  """Image build context."""
15
15
 
16
16
  import os
17
- from pathlib import Path
18
- from typing import IO, Dict, List, Optional, Set, Tuple, cast
17
+ from typing import IO, Dict, List, Optional, Set, cast
19
18
 
20
19
  from zenml.constants import REPOSITORY_DIRECTORY_NAME
21
20
  from zenml.io import fileio
22
21
  from zenml.logger import get_logger
23
22
  from zenml.utils import io_utils, string_utils
23
+ from zenml.utils.archivable import Archivable
24
24
 
25
25
  logger = get_logger(__name__)
26
26
 
27
27
 
28
- class BuildContext:
28
+ class BuildContext(Archivable):
29
29
  """Image build context.
30
30
 
31
31
  This class is responsible for creating an archive of the files needed to
@@ -45,9 +45,9 @@ class BuildContext:
45
45
  given, a file called `.dockerignore` in the build context root
46
46
  directory will be used instead if it exists.
47
47
  """
48
+ super().__init__()
48
49
  self._root = root
49
50
  self._dockerignore_file = dockerignore_file
50
- self._extra_files: Dict[str, str] = {}
51
51
 
52
52
  @property
53
53
  def dockerignore_file(self) -> Optional[str]:
@@ -68,70 +68,26 @@ class BuildContext:
68
68
 
69
69
  return None
70
70
 
71
- def add_file(self, source: str, destination: str) -> None:
72
- """Adds a file to the build context.
73
-
74
- Args:
75
- source: The source of the file to add. This can either be a path
76
- or the file content.
77
- destination: The path inside the build context where the file
78
- should be added.
79
- """
80
- if fileio.exists(source):
81
- with fileio.open(source) as f:
82
- self._extra_files[destination] = f.read()
83
- else:
84
- self._extra_files[destination] = source
85
-
86
- def add_directory(self, source: str, destination: str) -> None:
87
- """Adds a directory to the build context.
88
-
89
- Args:
90
- source: Path to the directory.
91
- destination: The path inside the build context where the directory
92
- should be added.
93
-
94
- Raises:
95
- ValueError: If `source` does not point to a directory.
96
- """
97
- if not fileio.isdir(source):
98
- raise ValueError(
99
- f"Can't add directory {source} to the build context as it "
100
- "does not exist or is not a directory."
101
- )
102
-
103
- for dir, _, files in fileio.walk(source):
104
- dir_path = Path(fileio.convert_to_str(dir))
105
- for file_name in files:
106
- file_name = fileio.convert_to_str(file_name)
107
- file_source = dir_path / file_name
108
- file_destination = (
109
- Path(destination)
110
- / dir_path.relative_to(source)
111
- / file_name
112
- )
113
-
114
- with file_source.open("r") as f:
115
- self._extra_files[file_destination.as_posix()] = f.read()
116
-
117
- def write_archive(self, output_file: IO[bytes], gzip: bool = True) -> None:
71
+ def write_archive(
72
+ self, output_file: IO[bytes], use_gzip: bool = True
73
+ ) -> None:
118
74
  """Writes an archive of the build context to the given file.
119
75
 
120
76
  Args:
121
77
  output_file: The file to write the archive to.
122
- gzip: Whether to use `gzip` to compress the file.
78
+ use_gzip: Whether to use `gzip` to compress the file.
123
79
  """
124
80
  from docker.utils import build as docker_build_utils
125
81
 
126
- files = self._get_files()
127
- extra_files = self._get_extra_files()
82
+ files = self.get_files()
83
+ extra_files = self.get_extra_files()
128
84
 
129
85
  context_archive = docker_build_utils.create_archive(
130
86
  fileobj=output_file,
131
87
  root=self._root,
132
- files=sorted(files),
133
- gzip=gzip,
134
- extra_files=extra_files,
88
+ files=sorted(files.keys()),
89
+ gzip=use_gzip,
90
+ extra_files=list(extra_files.items()),
135
91
  )
136
92
 
137
93
  build_context_size = os.path.getsize(context_archive.name)
@@ -151,33 +107,30 @@ class BuildContext:
151
107
  os.path.join(self._root, ".dockerignore"),
152
108
  )
153
109
 
154
- def _get_files(self) -> Set[str]:
155
- """Gets all non-ignored files in the build context root directory.
110
+ def get_files(self) -> Dict[str, str]:
111
+ """Gets all regular files that should be included in the archive.
156
112
 
157
113
  Returns:
158
- All build context files.
114
+ A dict {path_in_archive: path_on_filesystem} for all regular files
115
+ in the archive.
159
116
  """
160
117
  if self._root:
161
- exclude_patterns = self._get_exclude_patterns()
162
118
  from docker.utils import build as docker_build_utils
163
119
 
164
- return cast(
120
+ exclude_patterns = self._get_exclude_patterns()
121
+
122
+ archive_paths = cast(
165
123
  Set[str],
166
124
  docker_build_utils.exclude_paths(
167
125
  self._root, patterns=exclude_patterns
168
126
  ),
169
127
  )
128
+ return {
129
+ archive_path: os.path.join(self._root, archive_path)
130
+ for archive_path in archive_paths
131
+ }
170
132
  else:
171
- return set()
172
-
173
- def _get_extra_files(self) -> List[Tuple[str, str]]:
174
- """Gets all extra files of the build context.
175
-
176
- Returns:
177
- A tuple (path, file_content) for all extra files in the build
178
- context.
179
- """
180
- return list(self._extra_files.items())
133
+ return {}
181
134
 
182
135
  def _get_exclude_patterns(self) -> List[str]:
183
136
  """Gets all exclude patterns from the dockerignore file.
@@ -27,6 +27,7 @@ from zenml.stack import Flavor
27
27
 
28
28
  AZURE_ARTIFACT_STORE_FLAVOR = "azure"
29
29
  AZUREML_STEP_OPERATOR_FLAVOR = "azureml"
30
+ AZUREML_ORCHESTRATOR_FLAVOR = "azureml"
30
31
 
31
32
  # Service connector constants
32
33
  AZURE_CONNECTOR_TYPE = "azure"
@@ -47,6 +48,7 @@ class AzureIntegration(Integration):
47
48
  "azure-mgmt-containerservice>=20.0.0",
48
49
  "azure-storage-blob==12.17.0", # temporary fix for https://github.com/Azure/azure-sdk-for-python/issues/32056
49
50
  "kubernetes",
51
+ "azure-ai-ml==1.18.0"
50
52
  ]
51
53
  REQUIREMENTS_IGNORED_ON_UNINSTALL = ["kubernetes"]
52
54
 
@@ -65,11 +67,13 @@ class AzureIntegration(Integration):
65
67
  from zenml.integrations.azure.flavors import (
66
68
  AzureArtifactStoreFlavor,
67
69
  AzureMLStepOperatorFlavor,
70
+ AzureMLOrchestratorFlavor,
68
71
  )
69
72
 
70
73
  return [
71
74
  AzureArtifactStoreFlavor,
72
75
  AzureMLStepOperatorFlavor,
76
+ AzureMLOrchestratorFlavor,
73
77
  ]
74
78
 
75
79
 
@@ -16,10 +16,17 @@
16
16
  from zenml.integrations.azure.flavors.azure_artifact_store_flavor import (
17
17
  AzureArtifactStoreConfig,
18
18
  AzureArtifactStoreFlavor,
19
+
19
20
  )
20
21
  from zenml.integrations.azure.flavors.azureml_step_operator_flavor import (
21
22
  AzureMLStepOperatorConfig,
22
23
  AzureMLStepOperatorFlavor,
24
+ AzureMLStepOperatorSettings,
25
+ )
26
+ from zenml.integrations.azure.flavors.azureml_orchestrator_flavor import (
27
+ AzureMLOrchestratorConfig,
28
+ AzureMLOrchestratorFlavor,
29
+ AzureMLOrchestratorSettings,
23
30
  )
24
31
 
25
32
  __all__ = [
@@ -27,4 +34,8 @@ __all__ = [
27
34
  "AzureArtifactStoreConfig",
28
35
  "AzureMLStepOperatorFlavor",
29
36
  "AzureMLStepOperatorConfig",
37
+ "AzureMLStepOperatorSettings",
38
+ "AzureMLOrchestratorFlavor",
39
+ "AzureMLOrchestratorConfig",
40
+ "AzureMLOrchestratorSettings",
30
41
  ]