zenml-nightly 0.63.0.dev20240801__py3-none-any.whl → 0.64.0.dev20240809__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.dev20240809.dist-info}/METADATA +3 -3
  171. {zenml_nightly-0.63.0.dev20240801.dist-info → zenml_nightly-0.64.0.dev20240809.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.dev20240809.dist-info}/LICENSE +0 -0
  197. {zenml_nightly-0.63.0.dev20240801.dist-info → zenml_nightly-0.64.0.dev20240809.dist-info}/WHEEL +0 -0
  198. {zenml_nightly-0.63.0.dev20240801.dist-info → zenml_nightly-0.64.0.dev20240809.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,122 @@
1
+ # Copyright (c) ZenML GmbH 2024. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at:
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12
+ # or implied. See the License for the specific language governing
13
+ # permissions and limitations under the License.
14
+ """Notebook utilities."""
15
+
16
+ from typing import Any, Callable, Optional, TypeVar, Union
17
+
18
+ from zenml.environment import Environment
19
+ from zenml.logger import get_logger
20
+
21
+ ZENML_NOTEBOOK_CELL_CODE_ATTRIBUTE_NAME = "__zenml_notebook_cell_code__"
22
+
23
+ AnyObject = TypeVar("AnyObject", bound=Any)
24
+
25
+ logger = get_logger(__name__)
26
+
27
+
28
+ def is_defined_in_notebook_cell(obj: Any) -> bool:
29
+ """Check whether an object is defined in a notebook cell.
30
+
31
+ Args:
32
+ obj: The object to check.
33
+
34
+ Returns:
35
+ Whether the object is defined in a notebook cell.
36
+ """
37
+ if not Environment.in_notebook():
38
+ return False
39
+
40
+ module_name = getattr(obj, "__module__", None)
41
+ return module_name == "__main__"
42
+
43
+
44
+ def enable_notebook_code_extraction(
45
+ _obj: Optional["AnyObject"] = None,
46
+ ) -> Union["AnyObject", Callable[["AnyObject"], "AnyObject"]]:
47
+ """Decorator to enable code extraction from notebooks.
48
+
49
+ Args:
50
+ _obj: The class or function for which to enable code extraction.
51
+
52
+ Returns:
53
+ The decorated class or function.
54
+ """
55
+
56
+ def inner_decorator(obj: "AnyObject") -> "AnyObject":
57
+ try_to_save_notebook_cell_code(obj)
58
+ return obj
59
+
60
+ if _obj is None:
61
+ return inner_decorator
62
+ else:
63
+ return inner_decorator(_obj)
64
+
65
+
66
+ def get_active_notebook_cell_code() -> Optional[str]:
67
+ """Get the code of the currently active notebook cell.
68
+
69
+ Returns:
70
+ The code of the currently active notebook cell.
71
+ """
72
+ cell_code = None
73
+ try:
74
+ ipython = get_ipython() # type: ignore[name-defined]
75
+ cell_code = ipython.get_parent()["content"]["code"]
76
+ except (NameError, KeyError) as e:
77
+ logger.warning("Unable to extract cell code: %s.", str(e))
78
+
79
+ return cell_code
80
+
81
+
82
+ def try_to_save_notebook_cell_code(obj: Any) -> None:
83
+ """Try to save the notebook cell code for an object.
84
+
85
+ Args:
86
+ obj: The object for which to save the notebook cell code.
87
+ """
88
+ if is_defined_in_notebook_cell(obj):
89
+ if cell_code := get_active_notebook_cell_code():
90
+ setattr(
91
+ obj,
92
+ ZENML_NOTEBOOK_CELL_CODE_ATTRIBUTE_NAME,
93
+ cell_code,
94
+ )
95
+
96
+
97
+ def load_notebook_cell_code(obj: Any) -> Optional[str]:
98
+ """Load the notebook cell code for an object.
99
+
100
+ Args:
101
+ obj: The object for which to load the cell code.
102
+
103
+ Returns:
104
+ The notebook cell code if it was saved.
105
+ """
106
+ return getattr(obj, ZENML_NOTEBOOK_CELL_CODE_ATTRIBUTE_NAME, None)
107
+
108
+
109
+ def warn_about_notebook_cell_magic_commands(cell_code: str) -> None:
110
+ """Warn about magic commands in the cell code.
111
+
112
+ Args:
113
+ cell_code: The cell code.
114
+ """
115
+ if any(line.startswith(("%", "!")) for line in cell_code.splitlines()):
116
+ logger.warning(
117
+ "Some lines in your notebook cell start with a `!` or `%` "
118
+ "character. Running a ZenML step remotely from a notebook "
119
+ "only works if the cell only contains python code. If any "
120
+ "of these lines contain Jupyter notebook magic commands, "
121
+ "remove them and try again."
122
+ )
@@ -17,11 +17,9 @@ import itertools
17
17
  import os
18
18
  import subprocess
19
19
  import sys
20
- from collections import defaultdict
21
20
  from typing import (
22
21
  TYPE_CHECKING,
23
22
  Any,
24
- DefaultDict,
25
23
  Dict,
26
24
  List,
27
25
  Optional,
@@ -277,9 +275,7 @@ class PipelineDockerImageBuilder:
277
275
  requirements_files = self.gather_requirements_files(
278
276
  docker_settings=docker_settings,
279
277
  stack=stack,
280
- # Only pass code repo to include its dependencies if we actually
281
- # need to download code
282
- code_repository=code_repository if download_files else None,
278
+ code_repository=code_repository,
283
279
  )
284
280
 
285
281
  self._add_requirements_files(
@@ -444,8 +440,9 @@ class PipelineDockerImageBuilder:
444
440
  requirements files.
445
441
  The files will be in the following order:
446
442
  - Packages installed in the local Python environment
443
+ - Requirements defined by stack integrations
444
+ - Requirements defined by user integrations
447
445
  - User-defined requirements
448
- - Requirements defined by user-defined and/or stack integrations
449
446
  """
450
447
  requirements_files: List[Tuple[str, str, List[str]]] = []
451
448
 
@@ -481,43 +478,6 @@ class PipelineDockerImageBuilder:
481
478
  "- Including python packages from local environment"
482
479
  )
483
480
 
484
- # Generate requirements files for all ZenML Hub plugins
485
- if docker_settings.required_hub_plugins:
486
- (
487
- hub_internal_requirements,
488
- hub_pypi_requirements,
489
- ) = PipelineDockerImageBuilder._get_hub_requirements(
490
- docker_settings.required_hub_plugins
491
- )
492
-
493
- # Plugin packages themselves
494
- for i, (index, packages) in enumerate(
495
- hub_internal_requirements.items()
496
- ):
497
- file_name = f".zenml_hub_internal_requirements_{i}"
498
- file_lines = [f"-i {index}", *packages]
499
- file_contents = "\n".join(file_lines)
500
- requirements_files.append(
501
- (file_name, file_contents, ["--no-deps"])
502
- )
503
- if log:
504
- logger.info(
505
- "- Including internal hub packages from index `%s`: %s",
506
- index,
507
- ", ".join(f"`{r}`" for r in packages),
508
- )
509
-
510
- # PyPI requirements of plugin packages
511
- if hub_pypi_requirements:
512
- file_name = ".zenml_hub_pypi_requirements"
513
- file_contents = "\n".join(hub_pypi_requirements)
514
- requirements_files.append((file_name, file_contents, []))
515
- if log:
516
- logger.info(
517
- "- Including hub requirements from PyPI: %s",
518
- ", ".join(f"`{r}`" for r in hub_pypi_requirements),
519
- )
520
-
521
481
  if docker_settings.install_stack_requirements:
522
482
  stack_requirements = stack.requirements()
523
483
  if code_repository:
@@ -599,59 +559,6 @@ class PipelineDockerImageBuilder:
599
559
 
600
560
  return requirements_files
601
561
 
602
- @staticmethod
603
- def _get_hub_requirements(
604
- required_hub_plugins: List[str],
605
- ) -> Tuple[Dict[str, List[str]], List[str]]:
606
- """Get package requirements for ZenML Hub plugins.
607
-
608
- Args:
609
- required_hub_plugins: List of hub plugin names in the format
610
- `(<author_username>/)<plugin_name>(==<version>)`.
611
-
612
- Returns:
613
- - A dict of the hub plugin packages themselves (which need to be
614
- installed from a custom index, mapping index URLs to lists of
615
- package names.
616
- - A list of all unique dependencies of the required hub plugins
617
- (which can be installed from PyPI).
618
- """
619
- from zenml._hub.client import HubClient
620
- from zenml._hub.utils import parse_plugin_name, plugin_display_name
621
-
622
- client = HubClient()
623
-
624
- internal_requirements: DefaultDict[str, List[str]] = defaultdict(list)
625
- pypi_requirements: List[str] = []
626
-
627
- for plugin_str in required_hub_plugins:
628
- author, name, version = parse_plugin_name(
629
- plugin_str, version_separator="=="
630
- )
631
-
632
- plugin = client.get_plugin(
633
- name=name,
634
- version=version,
635
- author=author,
636
- )
637
-
638
- if plugin and plugin.index_url and plugin.package_name:
639
- internal_requirements[plugin.index_url].append(
640
- plugin.package_name
641
- )
642
- if plugin.requirements:
643
- pypi_requirements.extend(plugin.requirements)
644
- else:
645
- display_name = plugin_display_name(name, version, author)
646
- logger.warning(
647
- "Hub plugin `%s` does not exist or cannot be installed."
648
- "Skipping installation of this plugin.",
649
- display_name,
650
- )
651
-
652
- pypi_requirements = sorted(set(pypi_requirements))
653
- return dict(internal_requirements), pypi_requirements
654
-
655
562
  @staticmethod
656
563
  def _generate_zenml_pipeline_dockerfile(
657
564
  parent_image: str,
@@ -35,14 +35,19 @@ from typing import (
35
35
  from zenml.config.source import (
36
36
  CodeRepositorySource,
37
37
  DistributionPackageSource,
38
+ NotebookSource,
38
39
  Source,
39
40
  SourceType,
40
41
  )
41
42
  from zenml.constants import ENV_ZENML_CUSTOM_SOURCE_ROOT
42
43
  from zenml.environment import Environment
43
44
  from zenml.logger import get_logger
45
+ from zenml.utils import notebook_utils
44
46
 
45
47
  logger = get_logger(__name__)
48
+
49
+ ZENML_SOURCE_ATTRIBUTE_NAME = "__zenml_source__"
50
+
46
51
  NoneType = type(None)
47
52
  NoneTypeSource = Source(
48
53
  module=NoneType.__module__, attribute="NoneType", type=SourceType.BUILTIN
@@ -58,10 +63,13 @@ BuiltinFunctionTypeSource = Source(
58
63
  type=SourceType.BUILTIN,
59
64
  )
60
65
 
66
+
61
67
  _CUSTOM_SOURCE_ROOT: Optional[str] = os.getenv(
62
68
  ENV_ZENML_CUSTOM_SOURCE_ROOT, None
63
69
  )
64
70
 
71
+ _SHARED_TEMPDIR: Optional[str] = None
72
+
65
73
 
66
74
  def load(source: Union[Source, str]) -> Any:
67
75
  """Load a source or import path.
@@ -105,6 +113,14 @@ def load(source: Union[Source, str]) -> Any:
105
113
  source.version,
106
114
  source.import_path,
107
115
  )
116
+ elif source.type == SourceType.NOTEBOOK:
117
+ if Environment.in_notebook():
118
+ # If we're in a notebook, we don't need to do anything as the
119
+ # loading from the __main__ module should work just fine.
120
+ pass
121
+ else:
122
+ notebook_source = NotebookSource.model_validate(dict(source))
123
+ return _try_to_load_notebook_source(notebook_source)
108
124
  elif source.type in {SourceType.USER, SourceType.UNKNOWN}:
109
125
  # Unknown source might also refer to a user file, include source
110
126
  # root in python path just to be sure
@@ -152,6 +168,9 @@ def resolve(
152
168
  return FunctionTypeSource
153
169
  elif obj is BuiltinFunctionType:
154
170
  return BuiltinFunctionTypeSource
171
+ elif source := getattr(obj, ZENML_SOURCE_ATTRIBUTE_NAME, None):
172
+ assert isinstance(source, Source)
173
+ return source
155
174
  elif isinstance(obj, ModuleType):
156
175
  module = obj
157
176
  attribute_name = None
@@ -216,6 +235,16 @@ def resolve(
216
235
  else:
217
236
  # Fallback to an unknown source if we can't find the package
218
237
  source_type = SourceType.UNKNOWN
238
+ elif source_type == SourceType.NOTEBOOK:
239
+ source = NotebookSource(
240
+ module=module_name,
241
+ attribute=attribute_name,
242
+ type=source_type,
243
+ )
244
+ # Private attributes are ignored by pydantic if passed in the __init__
245
+ # method, so we set this afterwards
246
+ source._cell_code = notebook_utils.load_notebook_cell_code(obj)
247
+ return source
219
248
 
220
249
  return Source(
221
250
  module=module_name, attribute=attribute_name, type=source_type
@@ -362,7 +391,7 @@ def get_source_type(module: ModuleType) -> SourceType:
362
391
  file_path = inspect.getfile(module)
363
392
  except (TypeError, OSError):
364
393
  if module.__name__ == "__main__" and Environment.in_notebook():
365
- return SourceType.USER
394
+ return SourceType.NOTEBOOK
366
395
 
367
396
  return SourceType.BUILTIN
368
397
 
@@ -529,6 +558,85 @@ def _load_module(
529
558
  return importlib.import_module(module_name)
530
559
 
531
560
 
561
+ def _get_shared_temp_dir() -> str:
562
+ """Get path to a shared temporary directory.
563
+
564
+ Returns:
565
+ Path to a shared temporary directory.
566
+ """
567
+ global _SHARED_TEMPDIR
568
+
569
+ if not _SHARED_TEMPDIR:
570
+ import tempfile
571
+
572
+ _SHARED_TEMPDIR = tempfile.mkdtemp()
573
+
574
+ return _SHARED_TEMPDIR
575
+
576
+
577
+ def _try_to_load_notebook_source(source: NotebookSource) -> Any:
578
+ """Helper function to load a notebook source outside of a notebook.
579
+
580
+ Args:
581
+ source: The source to load.
582
+
583
+ Raises:
584
+ RuntimeError: If the source can't be loaded.
585
+
586
+ Returns:
587
+ The loaded object.
588
+ """
589
+ if not source.code_path or not source.replacement_module:
590
+ raise RuntimeError(
591
+ f"Failed to load {source.import_path}. This object was defined in "
592
+ "a notebook and you're trying to load it outside of a notebook. "
593
+ "This is currently only enabled for ZenML steps."
594
+ )
595
+
596
+ extract_dir = _get_shared_temp_dir()
597
+ file_path = os.path.join(extract_dir, f"{source.replacement_module}.py")
598
+
599
+ if not os.path.exists(file_path):
600
+ from zenml.utils import code_utils
601
+
602
+ logger.info(
603
+ "Downloading notebook cell content from `%s` to load `%s`.",
604
+ source.code_path,
605
+ source.import_path,
606
+ )
607
+
608
+ code_utils.download_and_extract_code(
609
+ code_path=source.code_path, extract_dir=extract_dir
610
+ )
611
+
612
+ try:
613
+ module = _load_module(
614
+ module_name=source.replacement_module, import_root=extract_dir
615
+ )
616
+ except ImportError:
617
+ raise RuntimeError(
618
+ f"Unable to load {source.import_path}. This object was defined in "
619
+ "a notebook and you're trying to load it outside of a notebook. "
620
+ "To enable this, ZenML extracts the code of your cell into a "
621
+ "python file. This means your cell code needs to be "
622
+ "self-contained:\n"
623
+ " * All required imports must be done in this cell, even if the "
624
+ "same imports already happen in previous notebook cells.\n"
625
+ " * The cell can't use any code defined in other notebook cells."
626
+ )
627
+
628
+ if source.attribute:
629
+ obj = getattr(module, source.attribute)
630
+ else:
631
+ obj = module
632
+
633
+ # Store the original notebook source so resolving this object works as
634
+ # expected
635
+ setattr(obj, ZENML_SOURCE_ATTRIBUTE_NAME, source)
636
+
637
+ return obj
638
+
639
+
532
640
  def _get_package_for_module(module_name: str) -> Optional[str]:
533
641
  """Get the package name for a module.
534
642
 
@@ -1 +1 @@
1
- import{j as e}from"./@radix-CFOkMR_E.js";import{h as s,r as t}from"./index-KsTz2dHG.js";import{E as r}from"./EmptyState-BMLnFVlB.js";import{H as a}from"./help-bu_DgLKI.js";import{L as o}from"./@react-router-CO-OsFwI.js";import"./@tanstack-k96lU_C-.js";import"./@reactflow-DIYUhKYX.js";function d(){return e.jsx("div",{className:"flex min-h-screen w-full flex-col",children:e.jsx(r,{icon:e.jsx(a,{className:"h-[120px] w-[120px] fill-neutral-300"}),children:e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{className:"mb-2 text-display-xs font-semibold",children:"We can't find the page you are looking for"}),e.jsx("p",{className:"text-lg text-theme-text-secondary",children:"You can try typing a different URL or we can bring you back to your Homepage."}),e.jsx("div",{className:"mt-5 flex justify-center",children:e.jsx(s,{size:"md",asChild:!0,children:e.jsx(o,{className:"w-min self-center whitespace-nowrap",to:t.home,children:e.jsx("span",{className:"px-0.5",children:"Go to Home"})})})})]})})})}export{d as default};
1
+ import{j as e}from"./@radix-BXWm7HOa.js";import{h as s,r as t}from"./index-DhIZtpxB.js";import{E as r}from"./EmptyState-BHblM39I.js";import{H as a}from"./help-FuHlZwn0.js";import{L as o}from"./@react-router-l3lMcXA2.js";import"./@tanstack-FmcYZMuX.js";import"./@reactflow-CeVxyqYT.js";function d(){return e.jsx("div",{className:"flex min-h-screen w-full flex-col",children:e.jsx(r,{icon:e.jsx(a,{className:"h-[120px] w-[120px] fill-neutral-300"}),children:e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{className:"mb-2 text-display-xs font-semibold",children:"We can't find the page you are looking for"}),e.jsx("p",{className:"text-lg text-theme-text-secondary",children:"You can try typing a different URL or we can bring you back to your Homepage."}),e.jsx("div",{className:"mt-5 flex justify-center",children:e.jsx(s,{size:"md",asChild:!0,children:e.jsx(o,{className:"w-min self-center whitespace-nowrap",to:t.home,children:e.jsx("span",{className:"px-0.5",children:"Go to Home"})})})})]})})})}export{d as default};