zenml-nightly 0.58.2.dev20240618__py3-none-any.whl → 0.58.2.dev20240620__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 (300) hide show
  1. zenml/VERSION +1 -1
  2. zenml/_hub/client.py +8 -5
  3. zenml/actions/base_action.py +8 -10
  4. zenml/artifact_stores/base_artifact_store.py +20 -15
  5. zenml/artifact_stores/local_artifact_store.py +3 -2
  6. zenml/artifacts/artifact_config.py +34 -19
  7. zenml/artifacts/external_artifact.py +18 -8
  8. zenml/artifacts/external_artifact_config.py +14 -6
  9. zenml/artifacts/unmaterialized_artifact.py +2 -11
  10. zenml/cli/__init__.py +6 -0
  11. zenml/cli/artifact.py +20 -2
  12. zenml/cli/served_model.py +0 -1
  13. zenml/cli/server.py +3 -3
  14. zenml/cli/utils.py +36 -40
  15. zenml/cli/web_login.py +2 -2
  16. zenml/client.py +198 -24
  17. zenml/client_lazy_loader.py +20 -14
  18. zenml/config/base_settings.py +5 -6
  19. zenml/config/build_configuration.py +1 -1
  20. zenml/config/compiler.py +3 -3
  21. zenml/config/docker_settings.py +27 -28
  22. zenml/config/global_config.py +33 -37
  23. zenml/config/pipeline_configurations.py +8 -11
  24. zenml/config/pipeline_run_configuration.py +6 -2
  25. zenml/config/pipeline_spec.py +3 -4
  26. zenml/config/resource_settings.py +8 -9
  27. zenml/config/schedule.py +16 -20
  28. zenml/config/secret_reference_mixin.py +6 -3
  29. zenml/config/secrets_store_config.py +16 -23
  30. zenml/config/server_config.py +50 -46
  31. zenml/config/settings_resolver.py +1 -1
  32. zenml/config/source.py +45 -35
  33. zenml/config/step_configurations.py +53 -31
  34. zenml/config/store_config.py +20 -19
  35. zenml/config/strict_base_model.py +2 -6
  36. zenml/constants.py +26 -2
  37. zenml/container_registries/base_container_registry.py +3 -2
  38. zenml/container_registries/default_container_registry.py +3 -3
  39. zenml/event_hub/base_event_hub.py +1 -1
  40. zenml/event_sources/base_event_source.py +11 -16
  41. zenml/exceptions.py +4 -0
  42. zenml/integrations/airflow/__init__.py +2 -10
  43. zenml/integrations/airflow/flavors/airflow_orchestrator_flavor.py +6 -7
  44. zenml/integrations/airflow/orchestrators/airflow_orchestrator.py +13 -249
  45. zenml/integrations/airflow/orchestrators/dag_generator.py +5 -3
  46. zenml/integrations/argilla/flavors/argilla_annotator_flavor.py +5 -4
  47. zenml/integrations/aws/__init__.py +1 -1
  48. zenml/integrations/aws/flavors/aws_container_registry_flavor.py +3 -2
  49. zenml/integrations/aws/flavors/sagemaker_orchestrator_flavor.py +11 -5
  50. zenml/integrations/aws/flavors/sagemaker_step_operator_flavor.py +6 -2
  51. zenml/integrations/aws/service_connectors/aws_service_connector.py +5 -4
  52. zenml/integrations/azure/flavors/azureml_step_operator_flavor.py +4 -4
  53. zenml/integrations/azure/service_connectors/azure_service_connector.py +4 -3
  54. zenml/integrations/azure/step_operators/azureml_step_operator.py +1 -1
  55. zenml/integrations/bentoml/steps/bentoml_deployer.py +1 -1
  56. zenml/integrations/bitbucket/plugins/event_sources/bitbucket_webhook_event_source.py +8 -12
  57. zenml/integrations/comet/flavors/comet_experiment_tracker_flavor.py +1 -1
  58. zenml/integrations/evidently/__init__.py +3 -4
  59. zenml/integrations/evidently/column_mapping.py +11 -3
  60. zenml/integrations/evidently/data_validators/evidently_data_validator.py +21 -3
  61. zenml/integrations/evidently/metrics.py +5 -6
  62. zenml/integrations/evidently/tests.py +5 -6
  63. zenml/integrations/facets/models.py +2 -6
  64. zenml/integrations/feast/__init__.py +3 -1
  65. zenml/integrations/feast/feature_stores/feast_feature_store.py +0 -23
  66. zenml/integrations/gcp/__init__.py +1 -1
  67. zenml/integrations/gcp/flavors/vertex_orchestrator_flavor.py +1 -1
  68. zenml/integrations/gcp/flavors/vertex_step_operator_flavor.py +1 -1
  69. zenml/integrations/gcp/orchestrators/vertex_orchestrator.py +234 -103
  70. zenml/integrations/gcp/service_connectors/gcp_service_connector.py +57 -42
  71. zenml/integrations/github/code_repositories/github_code_repository.py +1 -1
  72. zenml/integrations/github/plugins/event_sources/github_webhook_event_source.py +9 -13
  73. zenml/integrations/great_expectations/__init__.py +1 -1
  74. zenml/integrations/great_expectations/data_validators/ge_data_validator.py +44 -44
  75. zenml/integrations/great_expectations/flavors/great_expectations_data_validator_flavor.py +35 -2
  76. zenml/integrations/great_expectations/ge_store_backend.py +24 -11
  77. zenml/integrations/great_expectations/materializers/ge_materializer.py +3 -3
  78. zenml/integrations/great_expectations/utils.py +5 -5
  79. zenml/integrations/huggingface/__init__.py +3 -0
  80. zenml/integrations/huggingface/flavors/huggingface_model_deployer_flavor.py +1 -1
  81. zenml/integrations/huggingface/steps/__init__.py +3 -0
  82. zenml/integrations/huggingface/steps/accelerate_runner.py +149 -0
  83. zenml/integrations/huggingface/steps/huggingface_deployer.py +2 -2
  84. zenml/integrations/hyperai/flavors/hyperai_orchestrator_flavor.py +1 -1
  85. zenml/integrations/hyperai/service_connectors/hyperai_service_connector.py +4 -3
  86. zenml/integrations/kubeflow/__init__.py +1 -1
  87. zenml/integrations/kubeflow/flavors/kubeflow_orchestrator_flavor.py +48 -81
  88. zenml/integrations/kubeflow/orchestrators/kubeflow_orchestrator.py +295 -245
  89. zenml/integrations/kubernetes/flavors/kubernetes_orchestrator_flavor.py +1 -1
  90. zenml/integrations/kubernetes/orchestrators/kubernetes_orchestrator_entrypoint.py +11 -2
  91. zenml/integrations/kubernetes/pod_settings.py +17 -31
  92. zenml/integrations/kubernetes/service_connectors/kubernetes_service_connector.py +8 -7
  93. zenml/integrations/label_studio/__init__.py +1 -3
  94. zenml/integrations/label_studio/annotators/label_studio_annotator.py +3 -4
  95. zenml/integrations/label_studio/flavors/label_studio_annotator_flavor.py +2 -2
  96. zenml/integrations/langchain/materializers/document_materializer.py +44 -8
  97. zenml/integrations/mlflow/__init__.py +9 -3
  98. zenml/integrations/mlflow/experiment_trackers/mlflow_experiment_tracker.py +1 -1
  99. zenml/integrations/mlflow/flavors/mlflow_experiment_tracker_flavor.py +29 -37
  100. zenml/integrations/mlflow/model_registries/mlflow_model_registry.py +4 -4
  101. zenml/integrations/mlflow/steps/mlflow_deployer.py +1 -1
  102. zenml/integrations/neptune/flavors/neptune_experiment_tracker_flavor.py +1 -1
  103. zenml/integrations/pigeon/flavors/pigeon_annotator_flavor.py +1 -1
  104. zenml/integrations/s3/flavors/s3_artifact_store_flavor.py +9 -8
  105. zenml/integrations/seldon/seldon_client.py +52 -67
  106. zenml/integrations/seldon/services/seldon_deployment.py +3 -3
  107. zenml/integrations/seldon/steps/seldon_deployer.py +4 -4
  108. zenml/integrations/skypilot/flavors/skypilot_orchestrator_base_vm_config.py +15 -5
  109. zenml/integrations/skypilot_aws/__init__.py +1 -1
  110. zenml/integrations/skypilot_aws/flavors/skypilot_orchestrator_aws_vm_flavor.py +1 -1
  111. zenml/integrations/skypilot_azure/__init__.py +1 -1
  112. zenml/integrations/skypilot_azure/flavors/skypilot_orchestrator_azure_vm_flavor.py +1 -1
  113. zenml/integrations/skypilot_gcp/__init__.py +2 -1
  114. zenml/integrations/skypilot_gcp/flavors/skypilot_orchestrator_gcp_vm_flavor.py +1 -1
  115. zenml/integrations/skypilot_lambda/flavors/skypilot_orchestrator_lambda_vm_flavor.py +2 -2
  116. zenml/integrations/spark/flavors/spark_step_operator_flavor.py +1 -1
  117. zenml/integrations/tekton/__init__.py +1 -1
  118. zenml/integrations/tekton/flavors/tekton_orchestrator_flavor.py +66 -23
  119. zenml/integrations/tekton/orchestrators/tekton_orchestrator.py +547 -233
  120. zenml/integrations/tensorboard/__init__.py +1 -12
  121. zenml/integrations/tensorboard/services/tensorboard_service.py +3 -5
  122. zenml/integrations/tensorboard/visualizers/tensorboard_visualizer.py +6 -6
  123. zenml/integrations/tensorflow/__init__.py +2 -10
  124. zenml/integrations/tensorflow/materializers/keras_materializer.py +17 -9
  125. zenml/integrations/wandb/flavors/wandb_experiment_tracker_flavor.py +9 -14
  126. zenml/integrations/whylogs/flavors/whylogs_data_validator_flavor.py +1 -1
  127. zenml/lineage_graph/lineage_graph.py +1 -1
  128. zenml/materializers/built_in_materializer.py +3 -3
  129. zenml/materializers/pydantic_materializer.py +2 -2
  130. zenml/metadata/lazy_load.py +4 -4
  131. zenml/metadata/metadata_types.py +64 -4
  132. zenml/model/model.py +79 -54
  133. zenml/model_deployers/base_model_deployer.py +14 -12
  134. zenml/model_registries/base_model_registry.py +17 -15
  135. zenml/models/__init__.py +79 -206
  136. zenml/models/v2/base/base.py +54 -41
  137. zenml/models/v2/base/base_plugin_flavor.py +2 -6
  138. zenml/models/v2/base/filter.py +91 -76
  139. zenml/models/v2/base/page.py +2 -12
  140. zenml/models/v2/base/scoped.py +4 -7
  141. zenml/models/v2/core/api_key.py +22 -8
  142. zenml/models/v2/core/artifact.py +2 -2
  143. zenml/models/v2/core/artifact_version.py +74 -40
  144. zenml/models/v2/core/code_repository.py +37 -10
  145. zenml/models/v2/core/component.py +65 -16
  146. zenml/models/v2/core/device.py +14 -4
  147. zenml/models/v2/core/event_source.py +1 -2
  148. zenml/models/v2/core/flavor.py +74 -8
  149. zenml/models/v2/core/logs.py +68 -8
  150. zenml/models/v2/core/model.py +8 -4
  151. zenml/models/v2/core/model_version.py +25 -6
  152. zenml/models/v2/core/model_version_artifact.py +51 -21
  153. zenml/models/v2/core/model_version_pipeline_run.py +45 -13
  154. zenml/models/v2/core/pipeline.py +37 -72
  155. zenml/models/v2/core/pipeline_build.py +29 -17
  156. zenml/models/v2/core/pipeline_deployment.py +18 -6
  157. zenml/models/v2/core/pipeline_namespace.py +113 -0
  158. zenml/models/v2/core/pipeline_run.py +50 -22
  159. zenml/models/v2/core/run_metadata.py +59 -36
  160. zenml/models/v2/core/schedule.py +37 -24
  161. zenml/models/v2/core/secret.py +31 -12
  162. zenml/models/v2/core/service.py +64 -36
  163. zenml/models/v2/core/service_account.py +24 -11
  164. zenml/models/v2/core/service_connector.py +219 -44
  165. zenml/models/v2/core/stack.py +45 -17
  166. zenml/models/v2/core/step_run.py +28 -8
  167. zenml/models/v2/core/tag.py +8 -4
  168. zenml/models/v2/core/trigger.py +2 -2
  169. zenml/models/v2/core/trigger_execution.py +1 -0
  170. zenml/models/v2/core/user.py +18 -21
  171. zenml/models/v2/core/workspace.py +13 -3
  172. zenml/models/v2/misc/build_item.py +3 -3
  173. zenml/models/v2/misc/external_user.py +2 -6
  174. zenml/models/v2/misc/hub_plugin_models.py +9 -9
  175. zenml/models/v2/misc/loaded_visualization.py +2 -2
  176. zenml/models/v2/misc/service_connector_type.py +8 -17
  177. zenml/models/v2/misc/user_auth.py +7 -2
  178. zenml/new/pipelines/build_utils.py +3 -3
  179. zenml/new/pipelines/pipeline.py +17 -13
  180. zenml/new/pipelines/run_utils.py +103 -1
  181. zenml/orchestrators/base_orchestrator.py +10 -7
  182. zenml/orchestrators/local_docker/local_docker_orchestrator.py +1 -1
  183. zenml/orchestrators/step_runner.py +3 -6
  184. zenml/orchestrators/utils.py +1 -1
  185. zenml/plugins/base_plugin_flavor.py +6 -10
  186. zenml/plugins/plugin_flavor_registry.py +3 -7
  187. zenml/secret/base_secret.py +7 -8
  188. zenml/service_connectors/docker_service_connector.py +4 -3
  189. zenml/service_connectors/service_connector.py +5 -12
  190. zenml/service_connectors/service_connector_registry.py +2 -4
  191. zenml/services/container/container_service.py +1 -1
  192. zenml/services/container/container_service_endpoint.py +1 -1
  193. zenml/services/local/local_service.py +1 -1
  194. zenml/services/local/local_service_endpoint.py +1 -1
  195. zenml/services/service.py +16 -10
  196. zenml/services/service_type.py +4 -5
  197. zenml/services/terraform/terraform_service.py +1 -1
  198. zenml/stack/flavor.py +1 -5
  199. zenml/stack/flavor_registry.py +4 -4
  200. zenml/stack/stack.py +4 -1
  201. zenml/stack/stack_component.py +55 -31
  202. zenml/steps/base_step.py +34 -28
  203. zenml/steps/entrypoint_function_utils.py +3 -5
  204. zenml/steps/utils.py +12 -14
  205. zenml/utils/cuda_utils.py +50 -0
  206. zenml/utils/deprecation_utils.py +18 -20
  207. zenml/utils/dict_utils.py +1 -1
  208. zenml/utils/filesync_model.py +65 -28
  209. zenml/utils/function_utils.py +260 -0
  210. zenml/utils/json_utils.py +131 -0
  211. zenml/utils/mlstacks_utils.py +2 -2
  212. zenml/utils/pydantic_utils.py +270 -62
  213. zenml/utils/secret_utils.py +65 -12
  214. zenml/utils/source_utils.py +2 -2
  215. zenml/utils/typed_model.py +5 -3
  216. zenml/utils/typing_utils.py +243 -0
  217. zenml/utils/yaml_utils.py +1 -1
  218. zenml/zen_server/auth.py +2 -2
  219. zenml/zen_server/cloud_utils.py +6 -6
  220. zenml/zen_server/deploy/base_provider.py +1 -1
  221. zenml/zen_server/deploy/deployment.py +6 -8
  222. zenml/zen_server/deploy/docker/docker_zen_server.py +3 -4
  223. zenml/zen_server/deploy/local/local_provider.py +0 -1
  224. zenml/zen_server/deploy/local/local_zen_server.py +6 -6
  225. zenml/zen_server/deploy/terraform/terraform_zen_server.py +4 -6
  226. zenml/zen_server/exceptions.py +4 -1
  227. zenml/zen_server/feature_gate/zenml_cloud_feature_gate.py +1 -1
  228. zenml/zen_server/pipeline_deployment/utils.py +48 -68
  229. zenml/zen_server/rbac/models.py +2 -5
  230. zenml/zen_server/rbac/utils.py +11 -14
  231. zenml/zen_server/routers/auth_endpoints.py +2 -2
  232. zenml/zen_server/routers/pipeline_builds_endpoints.py +1 -1
  233. zenml/zen_server/routers/runs_endpoints.py +1 -1
  234. zenml/zen_server/routers/secrets_endpoints.py +3 -2
  235. zenml/zen_server/routers/server_endpoints.py +1 -1
  236. zenml/zen_server/routers/steps_endpoints.py +1 -1
  237. zenml/zen_server/routers/workspaces_endpoints.py +1 -1
  238. zenml/zen_stores/base_zen_store.py +46 -9
  239. zenml/zen_stores/migrations/utils.py +42 -46
  240. zenml/zen_stores/migrations/versions/0701da9951a0_added_service_table.py +1 -1
  241. zenml/zen_stores/migrations/versions/1041bc644e0d_remove_secrets_manager.py +5 -3
  242. zenml/zen_stores/migrations/versions/10a907dad202_delete_mlmd_tables.py +1 -1
  243. zenml/zen_stores/migrations/versions/26b776ad583e_redesign_artifacts.py +8 -10
  244. zenml/zen_stores/migrations/versions/37835ce041d2_optimizing_database.py +3 -3
  245. zenml/zen_stores/migrations/versions/46506f72f0ed_add_server_settings.py +10 -12
  246. zenml/zen_stores/migrations/versions/5994f9ad0489_introduce_role_permissions.py +3 -2
  247. zenml/zen_stores/migrations/versions/6917bce75069_add_pipeline_run_unique_constraint.py +4 -4
  248. zenml/zen_stores/migrations/versions/728c6369cfaa_add_name_column_to_input_artifact_pk.py +3 -2
  249. zenml/zen_stores/migrations/versions/743ec82b1b3c_update_size_of_build_images.py +2 -2
  250. zenml/zen_stores/migrations/versions/7500f434b71c_remove_shared_columns.py +3 -2
  251. zenml/zen_stores/migrations/versions/7834208cc3f6_artifact_project_scoping.py +8 -7
  252. zenml/zen_stores/migrations/versions/7b651bf6822e_track_secrets_in_db.py +6 -4
  253. zenml/zen_stores/migrations/versions/7e4a481d17f7_add_identity_table.py +2 -2
  254. zenml/zen_stores/migrations/versions/7f603e583dd7_fixed_migration.py +1 -1
  255. zenml/zen_stores/migrations/versions/a39c4184c8ce_remove_secrets_manager_flavors.py +2 -2
  256. zenml/zen_stores/migrations/versions/a91762e6be36_artifact_version_table.py +4 -4
  257. zenml/zen_stores/migrations/versions/alembic_start.py +1 -1
  258. zenml/zen_stores/migrations/versions/fbd7f18ced1e_increase_step_run_field_lengths.py +4 -4
  259. zenml/zen_stores/rest_zen_store.py +109 -49
  260. zenml/zen_stores/schemas/api_key_schemas.py +1 -1
  261. zenml/zen_stores/schemas/artifact_schemas.py +8 -8
  262. zenml/zen_stores/schemas/artifact_visualization_schemas.py +3 -3
  263. zenml/zen_stores/schemas/code_repository_schemas.py +1 -1
  264. zenml/zen_stores/schemas/component_schemas.py +8 -3
  265. zenml/zen_stores/schemas/device_schemas.py +8 -6
  266. zenml/zen_stores/schemas/event_source_schemas.py +3 -4
  267. zenml/zen_stores/schemas/flavor_schemas.py +5 -3
  268. zenml/zen_stores/schemas/model_schemas.py +26 -1
  269. zenml/zen_stores/schemas/pipeline_build_schemas.py +1 -1
  270. zenml/zen_stores/schemas/pipeline_deployment_schemas.py +4 -4
  271. zenml/zen_stores/schemas/pipeline_run_schemas.py +6 -6
  272. zenml/zen_stores/schemas/pipeline_schemas.py +5 -2
  273. zenml/zen_stores/schemas/run_metadata_schemas.py +2 -2
  274. zenml/zen_stores/schemas/secret_schemas.py +8 -5
  275. zenml/zen_stores/schemas/server_settings_schemas.py +3 -1
  276. zenml/zen_stores/schemas/service_connector_schemas.py +1 -1
  277. zenml/zen_stores/schemas/service_schemas.py +11 -2
  278. zenml/zen_stores/schemas/stack_schemas.py +1 -1
  279. zenml/zen_stores/schemas/step_run_schemas.py +11 -11
  280. zenml/zen_stores/schemas/tag_schemas.py +6 -2
  281. zenml/zen_stores/schemas/trigger_schemas.py +2 -2
  282. zenml/zen_stores/schemas/user_schemas.py +2 -2
  283. zenml/zen_stores/schemas/workspace_schemas.py +3 -1
  284. zenml/zen_stores/secrets_stores/aws_secrets_store.py +19 -20
  285. zenml/zen_stores/secrets_stores/azure_secrets_store.py +17 -20
  286. zenml/zen_stores/secrets_stores/base_secrets_store.py +79 -12
  287. zenml/zen_stores/secrets_stores/gcp_secrets_store.py +17 -20
  288. zenml/zen_stores/secrets_stores/hashicorp_secrets_store.py +4 -8
  289. zenml/zen_stores/secrets_stores/service_connector_secrets_store.py +10 -7
  290. zenml/zen_stores/secrets_stores/sql_secrets_store.py +5 -6
  291. zenml/zen_stores/sql_zen_store.py +196 -120
  292. zenml/zen_stores/zen_store_interface.py +33 -0
  293. {zenml_nightly-0.58.2.dev20240618.dist-info → zenml_nightly-0.58.2.dev20240620.dist-info}/METADATA +8 -7
  294. {zenml_nightly-0.58.2.dev20240618.dist-info → zenml_nightly-0.58.2.dev20240620.dist-info}/RECORD +297 -294
  295. zenml/integrations/kubeflow/utils.py +0 -95
  296. zenml/models/v2/base/internal.py +0 -37
  297. zenml/models/v2/base/update.py +0 -44
  298. {zenml_nightly-0.58.2.dev20240618.dist-info → zenml_nightly-0.58.2.dev20240620.dist-info}/LICENSE +0 -0
  299. {zenml_nightly-0.58.2.dev20240618.dist-info → zenml_nightly-0.58.2.dev20240620.dist-info}/WHEEL +0 -0
  300. {zenml_nightly-0.58.2.dev20240618.dist-info → zenml_nightly-0.58.2.dev20240620.dist-info}/entry_points.txt +0 -0
@@ -15,15 +15,28 @@
15
15
 
16
16
  import inspect
17
17
  import json
18
+ from json.decoder import JSONDecodeError
18
19
  from typing import Any, Callable, Dict, Optional, Type, TypeVar, Union, cast
19
20
 
20
21
  import yaml
21
- from pydantic import BaseModel
22
- from pydantic.decorator import ValidatedFunction
23
- from pydantic.json import pydantic_encoder
24
- from pydantic.utils import sequence_like
25
-
26
- from zenml.utils import dict_utils, yaml_utils
22
+ from pydantic import (
23
+ AfterValidator,
24
+ BaseModel,
25
+ BeforeValidator,
26
+ ConfigDict,
27
+ PlainValidator,
28
+ ValidationInfo,
29
+ WrapValidator,
30
+ validate_call,
31
+ )
32
+ from pydantic._internal import _repr as pydantic_repr
33
+ from pydantic.v1.utils import sequence_like
34
+
35
+ from zenml.logger import get_logger
36
+ from zenml.utils import dict_utils, typing_utils, yaml_utils
37
+ from zenml.utils.json_utils import pydantic_encoder
38
+
39
+ logger = get_logger(__name__)
27
40
 
28
41
  M = TypeVar("M", bound="BaseModel")
29
42
 
@@ -54,9 +67,9 @@ def update_model(
54
67
  else:
55
68
  update_dict = update
56
69
  else:
57
- update_dict = update.dict(exclude_unset=True)
70
+ update_dict = update.model_dump(exclude_unset=True)
58
71
 
59
- original_dict = original.dict(exclude_unset=True)
72
+ original_dict = original.model_dump(exclude_unset=True)
60
73
  if recursive:
61
74
  values = dict_utils.recursive_update(original_dict, update_dict)
62
75
  else:
@@ -94,7 +107,7 @@ class TemplateGenerator:
94
107
  self.instance_or_class
95
108
  )
96
109
 
97
- # Convert to json in an intermediate step so we can leverage Pydantic's
110
+ # Convert to json in an intermediate step, so we can leverage Pydantic's
98
111
  # encoder to support types like UUID and datetime
99
112
  json_string = json.dumps(template, default=pydantic_encoder)
100
113
  return cast(Dict[str, Any], json.loads(json_string))
@@ -110,7 +123,7 @@ class TemplateGenerator:
110
123
  """
111
124
  template = self._generate_template_for_model_class(model.__class__)
112
125
 
113
- for name in model.__fields_set__:
126
+ for name in model.model_fields_set:
114
127
  value = getattr(model, name)
115
128
  template[name] = self._generate_template_for_value(value)
116
129
 
@@ -130,19 +143,25 @@ class TemplateGenerator:
130
143
  """
131
144
  template: Dict[str, Any] = {}
132
145
 
133
- for name, field in model_class.__fields__.items():
134
- if self._is_model_class(field.outer_type_):
135
- template[name] = self._generate_template_for_model_class(
136
- field.outer_type_
137
- )
138
- elif field.outer_type_ is Optional and self._is_model_class(
139
- field.type_
140
- ):
141
- template[name] = self._generate_template_for_model_class(
142
- field.type_
143
- )
144
- else:
145
- template[name] = field._type_display()
146
+ for name, field in model_class.model_fields.items():
147
+ annotation = field.annotation
148
+
149
+ if annotation is not None:
150
+ if self._is_model_class(annotation):
151
+ template[name] = self._generate_template_for_model_class(
152
+ annotation
153
+ )
154
+
155
+ elif typing_utils.is_optional(
156
+ annotation
157
+ ) and self._is_model_class(
158
+ typing_utils.get_args(annotation)[0]
159
+ ):
160
+ template[name] = self._generate_template_for_model_class(
161
+ typing_utils.get_args(annotation)[0]
162
+ )
163
+ else:
164
+ template[name] = pydantic_repr.display_as_type(annotation)
146
165
 
147
166
  return template
148
167
 
@@ -188,12 +207,16 @@ class YAMLSerializationMixin(BaseModel):
188
207
 
189
208
  Args:
190
209
  sort_keys: Whether to sort the keys in the YAML representation.
191
- **kwargs: Kwargs to pass to the pydantic json(...) method.
210
+ **kwargs: Kwargs to pass to the pydantic model_dump(...) method.
192
211
 
193
212
  Returns:
194
213
  YAML string representation.
195
214
  """
196
- dict_ = json.loads(self.json(**kwargs, sort_keys=sort_keys))
215
+ dict_ = json.loads(
216
+ json.dumps(
217
+ self.model_dump(mode="json", **kwargs), sort_keys=sort_keys
218
+ )
219
+ )
197
220
  return yaml.dump(dict_, sort_keys=sort_keys)
198
221
 
199
222
  @classmethod
@@ -207,12 +230,12 @@ class YAMLSerializationMixin(BaseModel):
207
230
  The model instance.
208
231
  """
209
232
  dict_ = yaml_utils.read_yaml(path)
210
- return cls.parse_obj(dict_)
233
+ return cls.model_validate(dict_)
211
234
 
212
235
 
213
236
  def validate_function_args(
214
237
  __func: Callable[..., Any],
215
- __config: Dict[str, Any],
238
+ __config: Optional[ConfigDict],
216
239
  *args: Any,
217
240
  **kwargs: Any,
218
241
  ) -> Dict[str, Any]:
@@ -233,40 +256,225 @@ def validate_function_args(
233
256
  Returns:
234
257
  The validated arguments.
235
258
  """
236
- parameter_prefix = "zenml__"
237
-
238
259
  signature = inspect.signature(__func)
239
- parameters = [
240
- param.replace(name=f"{parameter_prefix}{param.name}")
241
- for param in signature.parameters.values()
242
- ]
243
- signature = signature.replace(parameters=parameters)
244
-
245
- def f() -> None:
246
- pass
247
-
248
- # We create a dummy function with the original function signature, but
249
- # add a prefix to all arguments to avoid potential clashes with pydantic
250
- # BaseModel attributes
260
+
261
+ validated_args = ()
262
+ validated_kwargs = {}
263
+
264
+ def f(*args: Any, **kwargs: Dict[Any, Any]) -> None:
265
+ nonlocal validated_args
266
+ nonlocal validated_kwargs
267
+
268
+ validated_args = args
269
+ validated_kwargs = kwargs
270
+
271
+ # We create a dummy function with the original function signature to run
272
+ # pydantic validation without actually running the function code
251
273
  f.__signature__ = signature # type: ignore[attr-defined]
252
- f.__annotations__ = {
253
- f"{parameter_prefix}{key}": annotation
254
- for key, annotation in __func.__annotations__.items()
255
- }
256
-
257
- validation_func = ValidatedFunction(f, config=__config)
258
-
259
- kwargs = {
260
- f"{parameter_prefix}{key}": value for key, value in kwargs.items()
261
- }
262
- model = validation_func.init_model_instance(*args, **kwargs)
263
-
264
- validated_args = {
265
- k[len(parameter_prefix) :]: v
266
- for k, v in model._iter()
267
- if k in model.__fields_set__
268
- or model.__fields__[k].default_factory
269
- or model.__fields__[k].default
270
- }
271
-
272
- return validated_args
274
+ f.__annotations__ = __func.__annotations__
275
+
276
+ validated_function = validate_call(config=__config, validate_return=False)(
277
+ f
278
+ )
279
+
280
+ # This raises a pydantic.ValidatonError in case the arguments are not valid
281
+ validated_function(*args, **kwargs)
282
+
283
+ return signature.bind(*validated_args, **validated_kwargs).arguments
284
+
285
+
286
+ def model_validator_data_handler(
287
+ raw_data: Any,
288
+ base_class: Type[BaseModel],
289
+ validation_info: ValidationInfo,
290
+ ) -> Dict[str, Any]:
291
+ """Utility function to parse raw input data of varying types to a dict.
292
+
293
+ With the change to pydantic v2, validators which operate with "before"
294
+ (or previously known as the "pre" parameter) are getting "Any" types of raw
295
+ input instead of a "Dict[str, Any]" as before. Depending on the use-case,
296
+ this can create conflicts after the migration and this function will be
297
+ used as a helper function to handle different types of raw input data.
298
+
299
+ A code snippet to showcase how the behaviour changes. The "before" validator
300
+ prints the type of the input:
301
+
302
+ class Base(BaseModel):
303
+ a: int = 3
304
+
305
+ class MyClass(Base):
306
+ @model_validator(mode="before")
307
+ @classmethod
308
+ def before_validator(cls, data: Any) -> Any:
309
+ print(type(data))
310
+ return {}
311
+
312
+ one = MyClass() # prints "<class 'dict'>"
313
+ MyClass.model_validate(one) # prints NOTHING, it is already validated
314
+ MyClass.model_validate("asdf") # prints "<class 'str'>", fails without the modified return.
315
+ MyClass.model_validate(RandomClass()) # prints "<class 'RandomClass'>", fails without the modified return.
316
+ MyClass.model_validate(Base()) # prints "<class 'Base'>", fails without the modified return.
317
+ MyClass.model_validate_json(json.dumps("aria")) # prints "<class 'str'>", fails without the modified return.
318
+ MyClass.model_validate_json(json.dumps([1])) # prints "<class 'list'>", fails without the modified return.
319
+ MyClass.model_validate_json(one.model_dump_json()) # prints "<class 'dict'>"
320
+
321
+ Args:
322
+ raw_data: The raw data passed to the validator, can be "Any" type.
323
+ base_class: The class that the validator belongs to
324
+ validation_info: Extra information about the validation process.
325
+
326
+ Raises:
327
+ TypeError: if the type of the data is not processable.
328
+ ValueError: in case of an unknown validation mode.
329
+
330
+ Returns:
331
+ A dictionary which will be passed to the eventual validator of pydantic.
332
+ """
333
+ if validation_info.mode == "python":
334
+ # This is mode is only active if people validate objects using pythonic
335
+ # raw data such as MyClass(...) or MyClass.model_validate()
336
+
337
+ if isinstance(raw_data, dict):
338
+ # In most cases, this is the behaviour as the raw input is a dict
339
+ return raw_data
340
+
341
+ elif isinstance(raw_data, base_class):
342
+ # In some cases, we pass the same object type to the validation
343
+ # in such cases, it is critical we keep the original structure of
344
+ # fields that are already set.
345
+ return dict(raw_data)
346
+
347
+ elif issubclass(base_class, raw_data.__class__):
348
+ # There are a few occurrences where the annotation of the field is
349
+ # denoted by a subclass, and we use the instance of its super class
350
+ # as the raw input. In such cases we will use the same approach as
351
+ # before, while raising a debug message.
352
+ logger.debug(
353
+ f"During the validation of a `{base_class}` object, an instance"
354
+ f"of `{raw_data.__class__}` (super class of `{base_class}`) "
355
+ f"has been passed as raw input. This might lead to unexpected "
356
+ f"behaviour in case `{base_class}` have features which can not"
357
+ f"be extracted from an instance of a `{raw_data.__class__}`."
358
+ )
359
+ return dict(raw_data)
360
+
361
+ elif isinstance(raw_data, str):
362
+ # If the raw input is a raw string, we can try to use the `json`
363
+ # module to parse it. The resulting data needs to be a proper
364
+ # dict for us to pass it to the validation process.
365
+ try:
366
+ json_data = json.loads(raw_data)
367
+
368
+ if isinstance(json_data, dict):
369
+ return json_data
370
+ else:
371
+ raise TypeError("The resulting json data is not a dict!")
372
+
373
+ except (TypeError, JSONDecodeError) as e:
374
+ raise TypeError(
375
+ "The raw json input string can not be converted to a "
376
+ f"dict: {e}"
377
+ )
378
+ else:
379
+ raise TypeError(
380
+ "Unsupported type of raw input data for the `python` validation"
381
+ "mode of the pydantic class. Please consider changing the way "
382
+ f"you are creating using the `{base_class}` or instead use"
383
+ f"`{base_class}.model_validate_json()`."
384
+ )
385
+
386
+ elif validation_info.mode == "json":
387
+ # This is mode is only active if people validate objects using json
388
+ # input data such as MyClass.model_validate_json()
389
+ if isinstance(raw_data, dict):
390
+ return raw_data
391
+ else:
392
+ raise TypeError(
393
+ f"The resulting JSON data {raw_data} is not a dict, therefore"
394
+ f"can not be used by the validation process."
395
+ )
396
+ else:
397
+ # Unknown validation mode
398
+ raise ValueError(f"Unknown validation mode. {validation_info.mode}")
399
+
400
+
401
+ def before_validator_handler(
402
+ method: Callable[..., Any],
403
+ ) -> Callable[[Any, Any, Any], Any]:
404
+ """Decorator to handle the raw input data for pydantic model validators.
405
+
406
+ Args:
407
+ method: the class method with the actual validation logic.
408
+
409
+ Returns:
410
+ the validator method
411
+ """
412
+
413
+ def before_validator(
414
+ cls: Type[BaseModel], data: Any, validation_info: ValidationInfo
415
+ ) -> Any:
416
+ """Wrapper method to handle the raw data.
417
+
418
+ Args:
419
+ cls: the class handler
420
+ data: the raw input data
421
+ validation_info: the context of the validation.
422
+
423
+ Returns:
424
+ the validated data
425
+ """
426
+ data = model_validator_data_handler(
427
+ raw_data=data, base_class=cls, validation_info=validation_info
428
+ )
429
+ return method(cls=cls, data=data)
430
+
431
+ return before_validator
432
+
433
+
434
+ def has_validators(
435
+ pydantic_class: Type[BaseModel],
436
+ field_name: Optional[str] = None,
437
+ ) -> bool:
438
+ """Function to check if a Pydantic model or a pydantic field has validators.
439
+
440
+ Args:
441
+ pydantic_class: The class defining the pydantic model.
442
+ field_name: Optional, field info. If specified, this function will focus
443
+ on a singular field within the class. If not specified, it will
444
+ check model validators.
445
+
446
+ Returns:
447
+ Whether the specified field or class has a validator or not.
448
+ """
449
+ # If field is not specified check model validators
450
+ if field_name is None:
451
+ if pydantic_class.__pydantic_decorators__.model_validators:
452
+ return True
453
+
454
+ # Else, check field validators
455
+ else:
456
+ # 1. Field validators can be defined through @field_validator decorators
457
+ f_validators = pydantic_class.__pydantic_decorators__.field_validators
458
+
459
+ for name, f_v in f_validators.items():
460
+ if field_name in f_v.info.fields:
461
+ return True
462
+
463
+ # 2. Field validators can be defined through the Annotation[.....]
464
+ field_info = pydantic_class.model_fields[field_name]
465
+ if metadata := field_info.metadata:
466
+ if any(
467
+ isinstance(
468
+ m,
469
+ (
470
+ AfterValidator,
471
+ BeforeValidator,
472
+ PlainValidator,
473
+ WrapValidator,
474
+ ),
475
+ )
476
+ for m in metadata
477
+ ):
478
+ return True
479
+
480
+ return False
@@ -16,16 +16,29 @@
16
16
  import re
17
17
  from typing import TYPE_CHECKING, Any, NamedTuple
18
18
 
19
- from pydantic import Field
19
+ from pydantic import Field, PlainSerializer, SecretStr
20
+ from typing_extensions import Annotated
21
+
22
+ from zenml.logger import get_logger
20
23
 
21
24
  if TYPE_CHECKING:
22
- from pydantic.fields import ModelField
25
+ from pydantic.fields import FieldInfo
23
26
 
24
27
  _secret_reference_expression = re.compile(r"\{\{\s*\S+?\.\S+\s*\}\}")
25
28
 
26
29
  PYDANTIC_SENSITIVE_FIELD_MARKER = "sensitive"
27
30
  PYDANTIC_CLEAR_TEXT_FIELD_MARKER = "prevent_secret_reference"
28
31
 
32
+ PlainSerializedSecretStr = Annotated[
33
+ SecretStr,
34
+ PlainSerializer(
35
+ lambda v: v.get_secret_value() if v is not None else None,
36
+ when_used="json",
37
+ ),
38
+ ]
39
+
40
+ logger = get_logger(__name__)
41
+
29
42
 
30
43
  def is_secret_reference(value: Any) -> bool:
31
44
  """Checks whether any value is a secret reference.
@@ -87,8 +100,9 @@ def SecretField(*args: Any, **kwargs: Any) -> Any:
87
100
  Returns:
88
101
  Pydantic field info.
89
102
  """
90
- kwargs[PYDANTIC_SENSITIVE_FIELD_MARKER] = True
91
- return Field(*args, **kwargs) # type: ignore[pydantic-field]
103
+ json_schema_extra = kwargs.get("json_schema_extra", {})
104
+ json_schema_extra.update({PYDANTIC_SENSITIVE_FIELD_MARKER: True})
105
+ return Field(json_schema_extra=json_schema_extra, *args, **kwargs) # type: ignore[pydantic-field]
92
106
 
93
107
 
94
108
  def ClearTextField(*args: Any, **kwargs: Any) -> Any:
@@ -103,11 +117,12 @@ def ClearTextField(*args: Any, **kwargs: Any) -> Any:
103
117
  Returns:
104
118
  Pydantic field info.
105
119
  """
106
- kwargs[PYDANTIC_CLEAR_TEXT_FIELD_MARKER] = True
107
- return Field(*args, **kwargs) # type: ignore[pydantic-field]
120
+ json_schema_extra = kwargs.get("json_schema_extra", {})
121
+ json_schema_extra.update({PYDANTIC_CLEAR_TEXT_FIELD_MARKER: True})
122
+ return Field(json_schema_extra=json_schema_extra, *args, **kwargs) # type: ignore[pydantic-field]
108
123
 
109
124
 
110
- def is_secret_field(field: "ModelField") -> bool:
125
+ def is_secret_field(field: "FieldInfo") -> bool:
111
126
  """Returns whether a pydantic field contains sensitive information or not.
112
127
 
113
128
  Args:
@@ -116,10 +131,29 @@ def is_secret_field(field: "ModelField") -> bool:
116
131
  Returns:
117
132
  `True` if the field contains sensitive information, `False` otherwise.
118
133
  """
119
- return field.field_info.extra.get(PYDANTIC_SENSITIVE_FIELD_MARKER, False) # type: ignore[no-any-return]
120
-
121
-
122
- def is_clear_text_field(field: "ModelField") -> bool:
134
+ if field.json_schema_extra is not None:
135
+ if isinstance(field.json_schema_extra, dict):
136
+ if marker := field.json_schema_extra.get(
137
+ PYDANTIC_SENSITIVE_FIELD_MARKER
138
+ ):
139
+ assert isinstance(marker, bool), (
140
+ f"The parameter `{PYDANTIC_SENSITIVE_FIELD_MARKER}` in the "
141
+ f"field definition can only be a boolean value."
142
+ )
143
+ return marker
144
+
145
+ else:
146
+ logger.warning(
147
+ f"The 'json_schema_extra' of the field '{field.title}' is "
148
+ "not defined as a dict. This might lead to unexpected "
149
+ "behaviour as we are checking it is a secret text field. "
150
+ "Returning 'False' as default..."
151
+ )
152
+
153
+ return False
154
+
155
+
156
+ def is_clear_text_field(field: "FieldInfo") -> bool:
123
157
  """Returns whether a pydantic field prevents secret references or not.
124
158
 
125
159
  Args:
@@ -128,4 +162,23 @@ def is_clear_text_field(field: "ModelField") -> bool:
128
162
  Returns:
129
163
  `True` if the field prevents secret references, `False` otherwise.
130
164
  """
131
- return field.field_info.extra.get(PYDANTIC_CLEAR_TEXT_FIELD_MARKER, False) # type: ignore[no-any-return]
165
+ if field.json_schema_extra is not None:
166
+ if isinstance(field.json_schema_extra, dict):
167
+ if marker := field.json_schema_extra.get(
168
+ PYDANTIC_CLEAR_TEXT_FIELD_MARKER
169
+ ):
170
+ assert isinstance(marker, bool), (
171
+ f"The parameter `{PYDANTIC_CLEAR_TEXT_FIELD_MARKER}` in the "
172
+ f"field definition can only be a boolean value."
173
+ )
174
+ return marker
175
+
176
+ else:
177
+ logger.warning(
178
+ f"The 'json_schema_extra' of the field '{field.title}' is "
179
+ "not defined as a dict. This might lead to unexpected "
180
+ "behaviour as we are checking it is a clear text field. "
181
+ "Returning 'False' as default..."
182
+ )
183
+
184
+ return False
@@ -83,11 +83,11 @@ def load(source: Union[Source, str]) -> Any:
83
83
 
84
84
  import_root = None
85
85
  if source.type == SourceType.CODE_REPOSITORY:
86
- source = CodeRepositorySource.parse_obj(source)
86
+ source = CodeRepositorySource.model_validate(dict(source))
87
87
  _warn_about_potential_source_loading_issues(source=source)
88
88
  import_root = get_source_root()
89
89
  elif source.type == SourceType.DISTRIBUTION_PACKAGE:
90
- source = DistributionPackageSource.parse_obj(source)
90
+ source = DistributionPackageSource.model_validate(dict(source))
91
91
  if source.version:
92
92
  current_package_version = _get_package_version(
93
93
  package_name=source.package_name
@@ -17,7 +17,9 @@ import json
17
17
  from typing import Any, Dict, Tuple, Type, cast
18
18
 
19
19
  from pydantic import BaseModel, Field
20
- from pydantic.main import ModelMetaclass
20
+
21
+ # TODO: Investigate if we can solve this import a different way.
22
+ from pydantic._internal._model_construction import ModelMetaclass
21
23
  from typing_extensions import Literal
22
24
 
23
25
  from zenml.utils import source_utils
@@ -85,7 +87,7 @@ class BaseTypedModel(BaseModel, metaclass=BaseTypedModelMeta):
85
87
 
86
88
  matrix = TheMatrix(choice=RedPill())
87
89
  d = matrix.dict()
88
- new_matrix = TheMatrix.parse_obj(d)
90
+ new_matrix = TheMatrix.model_validate(d)
89
91
  assert isinstance(new_matrix.choice, RedPill)
90
92
  ```
91
93
 
@@ -126,7 +128,7 @@ class BaseTypedModel(BaseModel, metaclass=BaseTypedModelMeta):
126
128
  f"Class `{cls}` is not a ZenML BaseTypedModel subclass."
127
129
  )
128
130
 
129
- return cls.parse_obj(model_dict)
131
+ return cls.model_validate(model_dict)
130
132
 
131
133
  @classmethod
132
134
  def from_json(