qwak-core 0.4.278__py3-none-any.whl → 0.5.19__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.

Potentially problematic release.


This version of qwak-core might be problematic. Click here for more details.

Files changed (361) hide show
  1. _qwak_proto/jfml/hosting_gateway/v1/build_upload_url_pb2.py +8 -23
  2. _qwak_proto/jfml/hosting_gateway/v1/hosting_gateway_service_pb2.py +10 -27
  3. _qwak_proto/qwak/administration/account/v1/account_pb2.py +25 -88
  4. _qwak_proto/qwak/administration/account/v1/account_pb2.pyi +21 -2
  5. _qwak_proto/qwak/administration/account/v1/account_service_pb2.py +42 -187
  6. _qwak_proto/qwak/administration/account/v1/jfrog_tenant_details_pb2.py +26 -114
  7. _qwak_proto/qwak/administration/account/v1/personalization_pb2.py +8 -24
  8. _qwak_proto/qwak/administration/account/v1/preferences_pb2.py +6 -14
  9. _qwak_proto/qwak/administration/account/v1/terms_pb2.py +14 -54
  10. _qwak_proto/qwak/administration/authenticated_user/v1/authenticated_user_service_pb2.py +18 -67
  11. _qwak_proto/qwak/administration/authenticated_user/v1/credentials_pb2.py +8 -24
  12. _qwak_proto/qwak/administration/authenticated_user/v1/credentials_pb2.pyi +1 -1
  13. _qwak_proto/qwak/administration/authenticated_user/v1/details_pb2.py +14 -54
  14. _qwak_proto/qwak/administration/cluster/v2/cluster_pb2.py +38 -173
  15. _qwak_proto/qwak/administration/runtime_configuration/v0/container_registry_config_pb2.py +32 -0
  16. _qwak_proto/qwak/administration/runtime_configuration/v0/container_registry_config_pb2.pyi +65 -0
  17. _qwak_proto/qwak/administration/runtime_configuration/v0/container_registry_config_pb2_grpc.py +4 -0
  18. _qwak_proto/qwak/administration/runtime_configuration/v0/creds/auth_pb2.py +6 -14
  19. _qwak_proto/qwak/administration/runtime_configuration/v0/creds/secret_pb2.py +8 -24
  20. _qwak_proto/qwak/administration/runtime_configuration/v0/data_catalog_config_pb2.py +13 -35
  21. _qwak_proto/qwak/administration/runtime_configuration/v0/data_catalog_config_pb2.pyi +24 -3
  22. _qwak_proto/qwak/administration/runtime_configuration/v0/external/databricks/auth_pb2.py +34 -0
  23. _qwak_proto/qwak/administration/runtime_configuration/v0/external/databricks/auth_pb2.pyi +97 -0
  24. _qwak_proto/qwak/administration/runtime_configuration/v0/external/databricks/auth_pb2_grpc.py +4 -0
  25. _qwak_proto/qwak/administration/runtime_configuration/v0/external/elasticsearch_config_pb2.py +6 -14
  26. _qwak_proto/qwak/administration/runtime_configuration/v0/external/kafka_config_pb2.py +12 -44
  27. _qwak_proto/qwak/administration/runtime_configuration/v0/external/prometheus_config_pb2.py +9 -15
  28. _qwak_proto/qwak/administration/runtime_configuration/v0/external/prometheus_config_pb2.pyi +29 -0
  29. _qwak_proto/qwak/administration/runtime_configuration/v0/external/redis_config_pb2.py +6 -14
  30. _qwak_proto/qwak/administration/runtime_configuration/v0/external/victoriametrics_config_pb2.py +8 -15
  31. _qwak_proto/qwak/administration/runtime_configuration/v0/external/victoriametrics_config_pb2.pyi +16 -0
  32. _qwak_proto/qwak/administration/runtime_configuration/v0/feature_store_config_pb2.py +10 -34
  33. _qwak_proto/qwak/administration/runtime_configuration/v0/hosting/aws/auth_pb2.py +42 -0
  34. _qwak_proto/qwak/administration/runtime_configuration/v0/hosting/aws/auth_pb2.pyi +159 -0
  35. _qwak_proto/qwak/administration/runtime_configuration/v0/hosting/aws/auth_pb2_grpc.py +4 -0
  36. _qwak_proto/qwak/administration/runtime_configuration/v0/hosting/azure/auth_pb2.py +39 -0
  37. _qwak_proto/qwak/administration/runtime_configuration/v0/hosting/azure/auth_pb2.pyi +126 -0
  38. _qwak_proto/qwak/administration/runtime_configuration/v0/hosting/azure/auth_pb2_grpc.py +4 -0
  39. _qwak_proto/qwak/administration/runtime_configuration/v0/hosting_config_pb2.py +19 -55
  40. _qwak_proto/qwak/administration/runtime_configuration/v0/hosting_config_pb2.pyi +38 -6
  41. _qwak_proto/qwak/administration/runtime_configuration/v0/logs_storage_config_pb2.py +6 -14
  42. _qwak_proto/qwak/administration/runtime_configuration/v0/model_analytics_storage_config_pb2.py +6 -14
  43. _qwak_proto/qwak/administration/runtime_configuration/v0/network_config_pb2.py +14 -54
  44. _qwak_proto/qwak/administration/runtime_configuration/v0/object_storage_config_pb2.py +13 -35
  45. _qwak_proto/qwak/administration/runtime_configuration/v0/object_storage_config_pb2.pyi +26 -3
  46. _qwak_proto/qwak/administration/runtime_configuration/v0/observability_config_pb2.py +10 -34
  47. _qwak_proto/qwak/administration/runtime_configuration/v0/runtime_config_pb2.py +8 -15
  48. _qwak_proto/qwak/administration/runtime_configuration/v0/runtime_config_pb2.pyi +7 -2
  49. _qwak_proto/qwak/administration/runtime_configuration/v0/sql_engine_config_pb2.py +13 -35
  50. _qwak_proto/qwak/administration/runtime_configuration/v0/sql_engine_config_pb2.pyi +24 -3
  51. _qwak_proto/qwak/administration/v0/authentication/authentication_service_pb2.py +14 -47
  52. _qwak_proto/qwak/administration/v0/environments/configuration_pb2.py +20 -82
  53. _qwak_proto/qwak/administration/v0/environments/environment_pb2.py +12 -40
  54. _qwak_proto/qwak/administration/v0/environments/environment_service_pb2.py +36 -158
  55. _qwak_proto/qwak/administration/v0/environments/personalization_pb2.py +8 -24
  56. _qwak_proto/qwak/administration/v0/users/user_pb2.py +18 -71
  57. _qwak_proto/qwak/admiral/secret/v0/secret_pb2.py +29 -116
  58. _qwak_proto/qwak/admiral/secret/v0/secret_pb2.pyi +21 -2
  59. _qwak_proto/qwak/admiral/secret/v0/secret_service_pb2.py +18 -67
  60. _qwak_proto/qwak/admiral/secret/v0/system_secret_service_pb2.py +18 -67
  61. _qwak_proto/qwak/admiral/user_application_instance/v0/user_application_instance_pb2.py +38 -174
  62. _qwak_proto/qwak/admiral/user_application_instance/v0/user_application_instance_service_pb2.py +22 -87
  63. _qwak_proto/qwak/analytics/analytics_pb2.py +26 -121
  64. _qwak_proto/qwak/analytics/analytics_service_pb2.py +46 -207
  65. _qwak_proto/qwak/artifactory_settings/artifactory_settings_pb2.py +8 -24
  66. _qwak_proto/qwak/audience/v1/audience_api_pb2.py +30 -127
  67. _qwak_proto/qwak/audience/v1/audience_pb2.py +26 -113
  68. _qwak_proto/qwak/auto_scaling/v1/auto_scaling_pb2.py +18 -79
  69. _qwak_proto/qwak/auto_scaling/v1/auto_scaling_service_pb2.py +10 -27
  70. _qwak_proto/qwak/automation/v1/action_pb2.py +40 -180
  71. _qwak_proto/qwak/automation/v1/auto_scaling_pb2.py +18 -79
  72. _qwak_proto/qwak/automation/v1/automation_execution_pb2.py +12 -43
  73. _qwak_proto/qwak/automation/v1/automation_management_service_pb2.py +56 -258
  74. _qwak_proto/qwak/automation/v1/automation_pb2.py +11 -35
  75. _qwak_proto/qwak/automation/v1/automation_pb2.pyi +5 -1
  76. _qwak_proto/qwak/automation/v1/common_pb2.py +10 -35
  77. _qwak_proto/qwak/automation/v1/notification_pb2.py +16 -68
  78. _qwak_proto/qwak/automation/v1/trigger_pb2.py +14 -54
  79. _qwak_proto/qwak/batch_job/v1/batch_job_events_pb2.py +26 -116
  80. _qwak_proto/qwak/batch_job/v1/batch_job_resources_pb2.py +8 -26
  81. _qwak_proto/qwak/batch_job/v1/batch_job_service_pb2.py +119 -562
  82. _qwak_proto/qwak/batch_job/v1/batch_job_service_pb2.pyi +5 -1
  83. _qwak_proto/qwak/build/v1/build_api_pb2.py +86 -407
  84. _qwak_proto/qwak/build/v1/build_pb2.py +114 -549
  85. _qwak_proto/qwak/build_settings/build_settings_api_pb2.py +18 -67
  86. _qwak_proto/qwak/build_settings/build_settings_pb2.py +18 -74
  87. _qwak_proto/qwak/builds/build_pb2.py +46 -207
  88. _qwak_proto/qwak/builds/build_pb2.pyi +48 -3
  89. _qwak_proto/qwak/builds/build_url_pb2.py +26 -113
  90. _qwak_proto/qwak/builds/build_values_pb2.py +82 -0
  91. _qwak_proto/qwak/builds/build_values_pb2.pyi +559 -0
  92. _qwak_proto/qwak/builds/build_values_pb2_grpc.py +4 -0
  93. _qwak_proto/qwak/builds/builds_orchestrator_service_pb2.py +87 -270
  94. _qwak_proto/qwak/builds/builds_orchestrator_service_pb2.pyi +173 -0
  95. _qwak_proto/qwak/builds/builds_orchestrator_service_pb2_grpc.py +66 -0
  96. _qwak_proto/qwak/builds/builds_pb2.py +87 -528
  97. _qwak_proto/qwak/builds/builds_pb2.pyi +0 -191
  98. _qwak_proto/qwak/builds/builds_pb2_grpc.py +0 -233
  99. _qwak_proto/qwak/builds/internal_builds_orchestrator_service_pb2.py +12 -37
  100. _qwak_proto/qwak/data_versioning/data_versioning_pb2.py +8 -24
  101. _qwak_proto/qwak/data_versioning/data_versioning_service_pb2.py +14 -47
  102. _qwak_proto/qwak/deployment/alert_pb2.py +24 -108
  103. _qwak_proto/qwak/deployment/alert_service_pb2.py +30 -127
  104. _qwak_proto/qwak/deployment/deployment_messages_pb2.py +6 -14
  105. _qwak_proto/qwak/deployment/deployment_pb2.py +124 -588
  106. _qwak_proto/qwak/deployment/deployment_service_pb2.py +86 -419
  107. _qwak_proto/qwak/ecosystem/jfrog/v0/token_pb2.py +47 -165
  108. _qwak_proto/qwak/ecosystem/jfrog/v0/token_pb2.pyi +102 -3
  109. _qwak_proto/qwak/ecosystem/jfrog/v0/token_service_pb2.py +22 -87
  110. _qwak_proto/qwak/ecosystem/v0/auth_pb2.py +28 -0
  111. _qwak_proto/qwak/ecosystem/v0/auth_pb2.pyi +37 -0
  112. _qwak_proto/qwak/ecosystem/v0/auth_pb2_grpc.py +4 -0
  113. _qwak_proto/qwak/ecosystem/v0/azure_credentials_pb2.py +37 -0
  114. _qwak_proto/qwak/ecosystem/v0/azure_credentials_pb2.pyi +117 -0
  115. _qwak_proto/qwak/ecosystem/v0/azure_credentials_pb2_grpc.py +4 -0
  116. _qwak_proto/qwak/ecosystem/v0/credentials_pb2.py +12 -35
  117. _qwak_proto/qwak/ecosystem/v0/credentials_pb2.pyi +8 -3
  118. _qwak_proto/qwak/ecosystem/v0/ecosystem_pb2.py +30 -138
  119. _qwak_proto/qwak/ecosystem/v0/ecosystem_runtime_service_pb2.py +52 -237
  120. _qwak_proto/qwak/execution/v1/backfill_pb2.py +18 -74
  121. _qwak_proto/qwak/execution/v1/batch_pb2.py +10 -34
  122. _qwak_proto/qwak/execution/v1/deletion_pb2.py +12 -44
  123. _qwak_proto/qwak/execution/v1/execution_pb2.py +16 -69
  124. _qwak_proto/qwak/execution/v1/execution_service_pb2.py +64 -298
  125. _qwak_proto/qwak/execution/v1/internal/deployment/platform_details_pb2.py +6 -14
  126. _qwak_proto/qwak/execution/v1/jobs/job_pb2.py +18 -76
  127. _qwak_proto/qwak/execution/v1/jobs/job_service_pb2.py +54 -247
  128. _qwak_proto/qwak/execution/v1/jobs/reports/report_pb2.py +20 -84
  129. _qwak_proto/qwak/execution/v1/state/execution_state_pb2.py +6 -14
  130. _qwak_proto/qwak/execution/v1/state/execution_state_service_pb2.py +30 -127
  131. _qwak_proto/qwak/execution/v1/state/featureset_state_pb2.py +6 -14
  132. _qwak_proto/qwak/execution/v1/state/spark_execution_state_pb2.py +14 -68
  133. _qwak_proto/qwak/execution/v1/streaming_aggregation_pb2.py +22 -55
  134. _qwak_proto/qwak/execution/v1/streaming_aggregation_pb2.pyi +71 -1
  135. _qwak_proto/qwak/execution/v1/streaming_pb2.py +12 -44
  136. _qwak_proto/qwak/feature_store/entities/entity_pb2.py +16 -57
  137. _qwak_proto/qwak/feature_store/entities/entity_service_pb2.py +30 -127
  138. _qwak_proto/qwak/feature_store/features/aggregation_pb2.py +38 -175
  139. _qwak_proto/qwak/feature_store/features/deployment_pb2.py +36 -167
  140. _qwak_proto/qwak/feature_store/features/deployment_service_pb2.py +10 -27
  141. _qwak_proto/qwak/feature_store/features/execution_pb2.py +14 -56
  142. _qwak_proto/qwak/feature_store/features/feature_set_attribute_pb2.py +6 -14
  143. _qwak_proto/qwak/feature_store/features/feature_set_pb2.py +35 -156
  144. _qwak_proto/qwak/feature_store/features/feature_set_pb2.pyi +9 -1
  145. _qwak_proto/qwak/feature_store/features/feature_set_service_pb2.py +97 -440
  146. _qwak_proto/qwak/feature_store/features/feature_set_service_pb2.pyi +25 -0
  147. _qwak_proto/qwak/feature_store/features/feature_set_service_pb2_grpc.py +34 -0
  148. _qwak_proto/qwak/feature_store/features/feature_set_state_pb2.py +38 -181
  149. _qwak_proto/qwak/feature_store/features/feature_set_state_service_pb2.py +26 -107
  150. _qwak_proto/qwak/feature_store/features/feature_set_types_pb2.py +77 -347
  151. _qwak_proto/qwak/feature_store/features/feature_set_types_pb2.pyi +7 -2
  152. _qwak_proto/qwak/feature_store/features/monitoring_pb2.py +10 -34
  153. _qwak_proto/qwak/feature_store/features/real_time_feature_extractor_pb2.py +32 -143
  154. _qwak_proto/qwak/feature_store/jobs/job_pb2.py +12 -46
  155. _qwak_proto/qwak/feature_store/jobs/job_service_pb2.py +30 -127
  156. _qwak_proto/qwak/feature_store/jobs/v1/job_pb2.py +12 -45
  157. _qwak_proto/qwak/feature_store/jobs/v1/job_service_pb2.py +42 -187
  158. _qwak_proto/qwak/feature_store/platform/platform_details_pb2.py +8 -24
  159. _qwak_proto/qwak/feature_store/reports/report_pb2.py +14 -53
  160. _qwak_proto/qwak/feature_store/repository/common/platform_pb2.py +10 -34
  161. _qwak_proto/qwak/feature_store/serving/management_pb2.py +14 -47
  162. _qwak_proto/qwak/feature_store/serving/metadata_pb2.py +12 -44
  163. _qwak_proto/qwak/feature_store/serving/serving_pb2.py +50 -222
  164. _qwak_proto/qwak/feature_store/serving/v1/value_pb2.py +8 -24
  165. _qwak_proto/qwak/feature_store/sinks/sink_pb2.py +14 -54
  166. _qwak_proto/qwak/feature_store/sources/batch_pb2.py +79 -335
  167. _qwak_proto/qwak/feature_store/sources/batch_pb2.pyi +99 -7
  168. _qwak_proto/qwak/feature_store/sources/data_source_attribute_pb2.py +6 -14
  169. _qwak_proto/qwak/feature_store/sources/data_source_pb2.py +15 -55
  170. _qwak_proto/qwak/feature_store/sources/data_source_pb2.pyi +5 -1
  171. _qwak_proto/qwak/feature_store/sources/data_source_service_pb2.py +39 -148
  172. _qwak_proto/qwak/feature_store/sources/data_source_service_pb2.pyi +25 -0
  173. _qwak_proto/qwak/feature_store/sources/data_source_service_pb2_grpc.py +34 -0
  174. _qwak_proto/qwak/feature_store/sources/streaming_pb2.py +34 -146
  175. _qwak_proto/qwak/feature_store/v1/common/jfrog_artifact/jfrog_artifact_pb2.py +6 -14
  176. _qwak_proto/qwak/feature_store/v1/common/source_code/source_code_pb2.py +10 -34
  177. _qwak_proto/qwak/feature_store/v1/internal/data_source/data_source_service_pb2.py +16 -58
  178. _qwak_proto/qwak/feature_store/v1/internal/featureset/featureset_token_service_pb2.py +10 -27
  179. _qwak_proto/qwak/features_operator/v1/features_operator_pb2.py +14 -54
  180. _qwak_proto/qwak/features_operator/v1/features_operator_service_pb2.py +14 -47
  181. _qwak_proto/qwak/features_operator/v2/features_operator_pb2.py +16 -64
  182. _qwak_proto/qwak/features_operator/v2/features_operator_service_pb2.py +12 -37
  183. _qwak_proto/qwak/features_operator/v3/features_operator_async_service_pb2.py +26 -107
  184. _qwak_proto/qwak/features_operator/v3/features_operator_pb2.py +16 -64
  185. _qwak_proto/qwak/file_versioning/file_versioning_pb2.py +10 -33
  186. _qwak_proto/qwak/file_versioning/file_versioning_service_pb2.py +14 -47
  187. _qwak_proto/qwak/fitness_service/constructs_pb2.py +23 -100
  188. _qwak_proto/qwak/fitness_service/constructs_pb2.pyi +24 -0
  189. _qwak_proto/qwak/fitness_service/fitness_pb2.py +7 -34
  190. _qwak_proto/qwak/fitness_service/fitness_pb2.pyi +0 -93
  191. _qwak_proto/qwak/fitness_service/status_pb2.py +17 -108
  192. _qwak_proto/qwak/fitness_service/status_pb2.pyi +1 -121
  193. _qwak_proto/qwak/inference/feedback/feedback_pb2.py +28 -96
  194. _qwak_proto/qwak/instance_template/instance_template_pb2.py +13 -41
  195. _qwak_proto/qwak/instance_template/instance_template_pb2.pyi +4 -1
  196. _qwak_proto/qwak/instance_template/instance_template_service_pb2.py +14 -47
  197. _qwak_proto/qwak/integration/hugging_face_integration_pb2.py +16 -64
  198. _qwak_proto/qwak/integration/integration_pb2.py +28 -126
  199. _qwak_proto/qwak/integration/integration_service_pb2.py +34 -147
  200. _qwak_proto/qwak/integration/open_a_i_integration_pb2.py +16 -64
  201. _qwak_proto/qwak/integration/opsgenie_integration_pb2.py +20 -82
  202. _qwak_proto/qwak/integration/pagerduty_integration_pb2.py +24 -104
  203. _qwak_proto/qwak/integration/slack_app_integration_pb2.py +24 -104
  204. _qwak_proto/qwak/kube_deployment_captain/alert_pb2.py +22 -97
  205. _qwak_proto/qwak/kube_deployment_captain/alerting_pb2.py +12 -44
  206. _qwak_proto/qwak/kube_deployment_captain/batch_job_pb2.py +70 -323
  207. _qwak_proto/qwak/kube_deployment_captain/batch_job_pb2.pyi +20 -5
  208. _qwak_proto/qwak/kube_deployment_captain/deployment_pb2.py +44 -167
  209. _qwak_proto/qwak/kube_deployment_captain/feature_set_deployment_pb2.py +32 -144
  210. _qwak_proto/qwak/kube_deployment_captain/kube_deployment_captain_service_pb2.py +108 -519
  211. _qwak_proto/qwak/kube_deployment_captain/traffic_mapping_pb2.py +8 -24
  212. _qwak_proto/qwak/logging/log_filter_pb2.py +12 -44
  213. _qwak_proto/qwak/logging/log_line_pb2.py +8 -25
  214. _qwak_proto/qwak/logging/log_reader_service_pb2.py +10 -27
  215. _qwak_proto/qwak/logging/log_source_pb2.py +30 -134
  216. _qwak_proto/qwak/model_descriptor/open_ai_descriptor_pb2.py +18 -74
  217. _qwak_proto/qwak/model_group/model_group_pb2.py +25 -48
  218. _qwak_proto/qwak/model_group/model_group_pb2.pyi +88 -0
  219. _qwak_proto/qwak/model_group/model_group_pb2_grpc.py +70 -0
  220. _qwak_proto/qwak/model_group/model_group_repository_details_pb2.py +23 -75
  221. _qwak_proto/qwak/model_group/model_group_repository_details_pb2.pyi +44 -6
  222. _qwak_proto/qwak/models/models_pb2.py +99 -406
  223. _qwak_proto/qwak/models/models_pb2.pyi +86 -0
  224. _qwak_proto/qwak/models/models_pb2_grpc.py +34 -0
  225. _qwak_proto/qwak/models/models_query_pb2.py +16 -56
  226. _qwak_proto/qwak/models/models_query_pb2.pyi +4 -4
  227. _qwak_proto/qwak/monitoring/v0/alerting_channel_management_service_pb2.py +30 -127
  228. _qwak_proto/qwak/monitoring/v0/alerting_channel_pb2.py +34 -152
  229. _qwak_proto/qwak/monitoring/v0/alerting_channel_sync_service_pb2.py +14 -47
  230. _qwak_proto/qwak/offline/serving/v1/feature_values_pb2.py +6 -14
  231. _qwak_proto/qwak/offline/serving/v1/offline_serving_async_service_pb2.py +30 -123
  232. _qwak_proto/qwak/offline/serving/v1/options_pb2.py +6 -14
  233. _qwak_proto/qwak/offline/serving/v1/population_pb2.py +14 -54
  234. _qwak_proto/qwak/projects/jfrog_project_spec_pb2.py +6 -14
  235. _qwak_proto/qwak/projects/projects_pb2.py +50 -192
  236. _qwak_proto/qwak/projects/projects_pb2.pyi +35 -0
  237. _qwak_proto/qwak/prompt/v1/prompt/prompt_manager_service_pb2.py +54 -247
  238. _qwak_proto/qwak/prompt/v1/prompt/prompt_pb2.py +46 -214
  239. _qwak_proto/qwak/secret_service/secret_service_pb2.py +18 -67
  240. _qwak_proto/qwak/secret_service/secret_service_pb2.pyi +1 -1
  241. _qwak_proto/qwak/self_service/account/v0/account_membership_pb2.py +24 -106
  242. _qwak_proto/qwak/self_service/account/v0/account_membership_service_pb2.py +50 -227
  243. _qwak_proto/qwak/self_service/account/v0/account_status_pb2.py +16 -65
  244. _qwak_proto/qwak/self_service/account/v0/managing_account_pb2.py +37 -132
  245. _qwak_proto/qwak/self_service/account/v0/managing_account_pb2.pyi +40 -2
  246. _qwak_proto/qwak/self_service/account/v0/managing_account_service_pb2.py +22 -87
  247. _qwak_proto/qwak/self_service/user/v1/api_key_pb2.py +6 -14
  248. _qwak_proto/qwak/self_service/user/v1/user_pb2.py +6 -14
  249. _qwak_proto/qwak/self_service/user/v1/user_service_pb2.py +30 -121
  250. _qwak_proto/qwak/service_discovery/service_discovery_location_pb2.py +12 -44
  251. _qwak_proto/qwak/service_discovery/service_discovery_location_service_pb2.py +10 -27
  252. _qwak_proto/qwak/traffic/v1/traffic_api_pb2.py +22 -87
  253. _qwak_proto/qwak/traffic/v1/traffic_pb2.py +26 -113
  254. _qwak_proto/qwak/user_application/common/v0/resources_pb2.py +31 -139
  255. _qwak_proto/qwak/user_application/common/v0/resources_pb2.pyi +24 -0
  256. _qwak_proto/qwak/user_application/v0/user_application_pb2.py +11 -44
  257. _qwak_proto/qwak/user_application/v0/user_application_pb2.pyi +6 -0
  258. _qwak_proto/qwak/vectors/v1/collection/collection_pb2.py +24 -106
  259. _qwak_proto/qwak/vectors/v1/collection/collection_service_pb2.py +38 -167
  260. _qwak_proto/qwak/vectors/v1/collection/event/collection_event_pb2.py +6 -14
  261. _qwak_proto/qwak/vectors/v1/filters_pb2.py +30 -134
  262. _qwak_proto/qwak/vectors/v1/vector_pb2.py +14 -54
  263. _qwak_proto/qwak/vectors/v1/vector_service_pb2.py +26 -107
  264. _qwak_proto/qwak/workspace/workspace_pb2.py +22 -107
  265. _qwak_proto/qwak/workspace/workspace_service_pb2.py +62 -287
  266. qwak/__init__.py +1 -1
  267. qwak/automations/automations.py +3 -0
  268. qwak/clients/feature_store/execution_management_client.py +28 -0
  269. qwak/clients/feature_store/management_client.py +156 -206
  270. qwak/clients/feature_store/operator_client.py +19 -1
  271. qwak/clients/logging_client/client.py +13 -18
  272. qwak/clients/model_management/client.py +0 -5
  273. qwak/clients/project/client.py +0 -7
  274. qwak/exceptions/__init__.py +1 -0
  275. qwak/exceptions/qwak_grpc_address_exception.py +9 -0
  276. qwak/feature_store/_common/artifact_utils.py +10 -8
  277. qwak/feature_store/_common/packaging.py +39 -21
  278. qwak/feature_store/_common/source_code_spec.py +61 -11
  279. qwak/feature_store/_common/source_code_spec_factory.py +63 -10
  280. qwak/feature_store/data_sources/__init__.py +2 -0
  281. qwak/feature_store/data_sources/base.py +11 -7
  282. qwak/feature_store/data_sources/batch/snowflake.py +34 -8
  283. qwak/feature_store/data_sources/batch/unity_catalog.py +107 -0
  284. qwak/feature_store/execution/streaming_backfill.py +48 -0
  285. qwak/feature_store/feature_sets/base_feature_set.py +1 -0
  286. qwak/feature_store/feature_sets/streaming.py +84 -63
  287. qwak/feature_store/feature_sets/streaming_backfill.py +88 -124
  288. qwak/feature_store/online/client.py +20 -4
  289. qwak/feature_store/validations/validation_decorators.py +70 -0
  290. qwak/feature_store/validations/validation_response.py +3 -1
  291. qwak/feature_store/validations/validator.py +11 -3
  292. qwak/inner/build_logic/interface/context_interface.py +4 -0
  293. qwak/inner/build_logic/phases/phase_010_fetch_model/post_fetch_validation_step.py +1 -1
  294. qwak/inner/const.py +2 -6
  295. qwak/inner/di_configuration/__init__.py +1 -69
  296. qwak/inner/di_configuration/account.py +18 -63
  297. qwak/inner/di_configuration/containers.py +5 -1
  298. qwak/inner/di_configuration/dependency_wiring.py +98 -0
  299. qwak/inner/tool/auth.py +10 -80
  300. qwak/inner/tool/grpc/grpc_auth.py +0 -32
  301. qwak/inner/tool/grpc/grpc_tools.py +125 -11
  302. qwak/inner/tool/grpc/grpc_try_wrapping.py +140 -3
  303. qwak/llmops/generation/chat/openai/types/chat/chat_completion.py +24 -6
  304. qwak/llmops/generation/chat/openai/types/chat/chat_completion_chunk.py +44 -8
  305. qwak/llmops/generation/chat/openai/types/chat/chat_completion_message.py +6 -3
  306. qwak/qwak_client/client.py +2 -13
  307. qwak/vector_store/rest_helpers.py +4 -16
  308. qwak_core-0.5.19.dist-info/METADATA +48 -0
  309. {qwak_core-0.4.278.dist-info → qwak_core-0.5.19.dist-info}/RECORD +316 -334
  310. qwak_services_mock/mocks/execution_management_service.py +9 -1
  311. qwak_services_mock/mocks/feature_store_data_sources_manager_api.py +55 -13
  312. qwak_services_mock/mocks/feature_store_entities_manager_api.py +31 -29
  313. qwak_services_mock/mocks/features_operator_v3_service.py +20 -0
  314. qwak_services_mock/mocks/qwak_mocks.py +0 -2
  315. qwak_services_mock/services_mock.py +1 -11
  316. _qwak_proto/qwak/fitness_service/fitness_service_pb2.py +0 -110
  317. _qwak_proto/qwak/fitness_service/fitness_service_pb2.pyi +0 -121
  318. _qwak_proto/qwak/fitness_service/fitness_service_pb2_grpc.py +0 -169
  319. frogml_storage/__init__.py +0 -1
  320. frogml_storage/artifactory/__init__.py +0 -1
  321. frogml_storage/artifactory/_artifactory_api.py +0 -315
  322. frogml_storage/authentication/login/__init__.py +0 -1
  323. frogml_storage/authentication/login/_login_cli.py +0 -239
  324. frogml_storage/authentication/login/_login_command.py +0 -74
  325. frogml_storage/authentication/models/__init__.py +0 -3
  326. frogml_storage/authentication/models/_auth.py +0 -24
  327. frogml_storage/authentication/models/_auth_config.py +0 -70
  328. frogml_storage/authentication/models/_login.py +0 -22
  329. frogml_storage/authentication/utils/__init__.py +0 -17
  330. frogml_storage/authentication/utils/_authentication_utils.py +0 -281
  331. frogml_storage/authentication/utils/_login_checks_utils.py +0 -114
  332. frogml_storage/base_storage.py +0 -140
  333. frogml_storage/constants.py +0 -56
  334. frogml_storage/exceptions/checksum_verification_error.py +0 -3
  335. frogml_storage/exceptions/validation_error.py +0 -4
  336. frogml_storage/frog_ml.py +0 -668
  337. frogml_storage/http/__init__.py +0 -1
  338. frogml_storage/http/http_client.py +0 -83
  339. frogml_storage/logging/__init__.py +0 -1
  340. frogml_storage/logging/_log_config.py +0 -45
  341. frogml_storage/logging/log_utils.py +0 -21
  342. frogml_storage/models/__init__.py +0 -1
  343. frogml_storage/models/_download_context.py +0 -54
  344. frogml_storage/models/dataset_manifest.py +0 -13
  345. frogml_storage/models/entity_manifest.py +0 -93
  346. frogml_storage/models/frogml_dataset_version.py +0 -21
  347. frogml_storage/models/frogml_entity_type_info.py +0 -50
  348. frogml_storage/models/frogml_entity_version.py +0 -34
  349. frogml_storage/models/frogml_model_version.py +0 -21
  350. frogml_storage/models/model_manifest.py +0 -60
  351. frogml_storage/models/serialization_metadata.py +0 -15
  352. frogml_storage/utils/__init__.py +0 -12
  353. frogml_storage/utils/_environment.py +0 -21
  354. frogml_storage/utils/_input_checks_utility.py +0 -104
  355. frogml_storage/utils/_storage_utils.py +0 -15
  356. frogml_storage/utils/_url_utils.py +0 -27
  357. qwak/clients/build_management/__init__.py +0 -1
  358. qwak/clients/build_management/client.py +0 -114
  359. qwak_core-0.4.278.dist-info/METADATA +0 -415
  360. qwak_services_mock/mocks/build_management.py +0 -100
  361. {qwak_core-0.4.278.dist-info → qwak_core-0.5.19.dist-info}/WHEEL +0 -0
@@ -1,5 +1,3 @@
1
- from typing import Optional
2
-
3
1
  import grpc
4
2
  from _qwak_proto.qwak.projects.projects_pb2 import (
5
3
  CreateProjectRequest,
@@ -8,7 +6,6 @@ from _qwak_proto.qwak.projects.projects_pb2 import (
8
6
  ListProjectsRequest,
9
7
  )
10
8
  from _qwak_proto.qwak.projects.projects_pb2_grpc import ProjectsManagementServiceStub
11
- from _qwak_proto.qwak.projects.jfrog_project_spec_pb2 import ModelRepositoryJFrogSpec
12
9
  from dependency_injector.wiring import Provide, inject
13
10
  from qwak.exceptions import QwakException
14
11
  from qwak.inner.di_configuration import QwakContainer
@@ -34,16 +31,12 @@ class ProjectsManagementClient:
34
31
  self,
35
32
  project_name,
36
33
  project_description,
37
- jfrog_project_key: Optional[str] = None,
38
34
  ):
39
35
  try:
40
36
  return self._projects_management_service.CreateProject(
41
37
  CreateProjectRequest(
42
38
  project_name=project_name,
43
39
  project_description=project_description,
44
- jfrog_spec=ModelRepositoryJFrogSpec(
45
- jfrog_project_key=jfrog_project_key
46
- ),
47
40
  )
48
41
  )
49
42
 
@@ -1,6 +1,7 @@
1
1
  from .quiet_error import QuietError
2
2
  from .qwak_exception import QwakException
3
3
  from .qwak_general_build_exception import QwakGeneralBuildException
4
+ from .qwak_grpc_address_exception import QwakGrpcAddressException
4
5
  from .qwak_http_exception import QwakHTTPException
5
6
  from .qwak_inference_exception import QwakInferenceException
6
7
  from .qwak_load_configuration_exception import LoadConfigurationException
@@ -0,0 +1,9 @@
1
+ from typing import Union
2
+ from urllib.parse import ParseResult
3
+
4
+ from qwak.exceptions import QwakException
5
+
6
+
7
+ class QwakGrpcAddressException(QwakException):
8
+ def __init__(self, details: str, grpc_address: Union[str, ParseResult]):
9
+ self.message = f"Not a valid gRPC address: '{grpc_address}'. Details: {details}"
@@ -23,7 +23,7 @@ class ArtifactSpec:
23
23
  artifact_name: str
24
24
  root_module_path: Path
25
25
  artifact_object: Union["BaseTransformation", "Deserializer"]
26
- callables: List[Callable] = field(default_factory=lambda: list())
26
+ callables: List[Callable] = field(default_factory=list)
27
27
  suffix: str = ""
28
28
 
29
29
 
@@ -48,10 +48,12 @@ class ArtifactsUploader:
48
48
  transformation_functions: Optional[List[Callable[..., Any]]] = (
49
49
  transformation.get_functions()
50
50
  )
51
- if transformation_functions is not None and transformation_functions:
52
- return ArtifactSpec(
53
- artifact_name=featureset_name,
54
- root_module_path=Path(__instance_module_path__).parent,
55
- artifact_object=transformation,
56
- callables=transformation_functions,
57
- )
51
+ if not transformation_functions:
52
+ return None
53
+
54
+ return ArtifactSpec(
55
+ artifact_name=featureset_name,
56
+ root_module_path=Path(__instance_module_path__).parent,
57
+ artifact_object=transformation,
58
+ callables=transformation_functions,
59
+ )
@@ -6,16 +6,17 @@ import zipfile
6
6
  from io import BytesIO
7
7
  from pathlib import Path
8
8
  from shutil import make_archive
9
- from typing import TYPE_CHECKING, Callable, List, Union
9
+ from typing import TYPE_CHECKING, Callable, Dict, List, Optional, Union
10
10
  from uuid import uuid4
11
11
 
12
12
  import requests
13
-
14
13
  from qwak.clients.feature_store.management_client import FeatureRegistryClient
15
14
  from qwak.exceptions import QwakException
16
15
  from qwak.feature_store._common.value import (
17
16
  UPDATE_QWAK_SDK_WITH_FEATURE_STORE_EXTRA_MSG,
18
17
  )
18
+ from requests import HTTPError, Response
19
+ from urllib.parse import urlparse, ParseResult
19
20
 
20
21
  ZIP_FUNCTION_CONTENT_TYPE = "text/plain"
21
22
 
@@ -195,29 +196,47 @@ def upload_artifact(
195
196
  return uploaded_artifact_url
196
197
 
197
198
 
198
- def put_presigned_url(presign_url: str, content: bytes, content_type: str) -> None:
199
- http_response = requests.put(
200
- presign_url,
201
- headers={"content-type": content_type},
202
- data=content,
203
- timeout=600,
204
- )
205
- if 400 <= http_response.status_code < 600:
206
- raise QwakException(
207
- f"Error while uploading user function to s3. status code: {http_response.status_code}"
199
+ def put_files_content(
200
+ url: str,
201
+ content: bytes,
202
+ content_type: str,
203
+ extra_headers: Optional[Dict[str, str]] = None,
204
+ ) -> None:
205
+ """
206
+ uploads files content to s3 using presigned url or to jfrog artifactory using url and authentication headers
207
+ """
208
+ extra_headers = extra_headers or {}
209
+ try:
210
+ http_response: Response = requests.put(
211
+ url,
212
+ headers={"content-type": content_type, **extra_headers},
213
+ data=content,
214
+ timeout=300,
208
215
  )
216
+ http_response.raise_for_status()
217
+ except HTTPError as e:
218
+ raise QwakException(
219
+ f"Error while uploading artifact. status code: {e.response.status_code} with reason: {e.response.reason}"
220
+ ) from e
209
221
 
210
222
 
211
223
  def upload_to_s3(presign_url: str, in_memory_zip: bytes, content_type: str) -> str:
212
- put_presigned_url(
213
- presign_url=presign_url, content=in_memory_zip, content_type=content_type
224
+ parsed_url: ParseResult = urlparse(presign_url)
225
+ extra_headers: Dict[str, str] = (
226
+ {"x-ms-blob-type": "BlockBlob"}
227
+ if parsed_url.hostname.endswith(".blob.core.windows.net")
228
+ else None
229
+ )
230
+ put_files_content(
231
+ url=presign_url,
232
+ content=in_memory_zip,
233
+ content_type=content_type,
234
+ extra_headers=extra_headers,
214
235
  )
215
- from urllib.parse import urlparse
216
236
 
217
- parsed_url = urlparse(presign_url)
218
- postfix = parsed_url.path
219
- bucket = parsed_url.hostname.split(".s3.")[0]
220
- s3_path = f"s3://{bucket}{postfix}" # noqa: E231
237
+ postfix: str = parsed_url.path
238
+ bucket: str = parsed_url.hostname.split(".s3.")[0]
239
+ s3_path: str = f"s3://{bucket}{postfix}" # noqa: E231
221
240
  return s3_path
222
241
 
223
242
 
@@ -227,8 +246,7 @@ def base_upload_function_code(
227
246
  feature_module_dir: Path,
228
247
  ) -> str:
229
248
  """
230
- get presign url and prepare a zip file with the functions code
231
- and it's module and upload it to clients' s3 bucket
249
+ get presign url and prepare a zip file with the functions code and it's module than uploads it to clients' s3 bucket
232
250
  Args:
233
251
  presign_url: presign url
234
252
  functions: udf functions
@@ -1,48 +1,98 @@
1
1
  from abc import ABC, abstractmethod
2
- from dataclasses import dataclass, field
3
2
  from typing import Optional
4
3
 
4
+ from _qwak_proto.qwak.feature_store.v1.common.jfrog_artifact.jfrog_artifact_pb2 import (
5
+ JfrogArtifact as ProtoJfrogArtifact,
6
+ )
5
7
  from _qwak_proto.qwak.feature_store.v1.common.source_code.source_code_pb2 import (
6
- SourceCodeSpec as ProtoSourceCodeSpec,
7
8
  SourceCodeArtifact as ProtoSourceCodeArtifact,
9
+ SourceCodeSpec as ProtoSourceCodeSpec,
8
10
  ZipArtifact as ProtoZipArtifact,
9
11
  )
12
+ from pydantic import BaseModel, Field, model_validator
10
13
  from qwak.exceptions import QwakException
14
+ from typing_extensions import Self
15
+
16
+
17
+ class JfrogArtifact(BaseModel):
18
+ path: str
19
+
20
+ @classmethod
21
+ def from_proto(cls, proto: ProtoJfrogArtifact) -> "JfrogArtifact":
22
+ return cls(path=proto.path)
23
+
24
+ def to_proto(self) -> ProtoJfrogArtifact:
25
+ return ProtoJfrogArtifact(path=self.path)
11
26
 
12
27
 
13
- class SourceCodeArtifact(ABC):
28
+ class SourceCodeArtifact(BaseModel, ABC):
14
29
  @abstractmethod
15
30
  def _to_proto(self) -> ProtoSourceCodeArtifact:
16
31
  pass
17
32
 
18
33
 
19
- @dataclass
20
34
  class ZipArtifact(SourceCodeArtifact):
21
- artifact_path: str
22
35
  main_file: str
36
+ qwak_artifact_path: Optional[str] = None
37
+ jfrog_artifact_path: Optional[JfrogArtifact] = None
38
+
39
+ @model_validator(mode="after")
40
+ def validate_only_one_artifact_path_type_provided(self: Self) -> Self:
41
+ """
42
+ Ensures that either 'qwak_artifact_path' or 'jfrog_artifact_path' is provided,
43
+ but not both.
44
+ """
45
+ if (self.qwak_artifact_path is None) == (self.jfrog_artifact_path is None):
46
+ raise QwakException(
47
+ "Either `qwak_artifact_path` or `jfrog_artifact_path` must be provided."
48
+ )
49
+ return self
23
50
 
24
51
  @classmethod
25
52
  def _from_proto(cls, proto: ProtoSourceCodeArtifact) -> "ZipArtifact":
26
53
  artifact_type: str = proto.WhichOneof("type")
27
54
  if artifact_type != "zip_artifact":
28
- raise QwakException(f"Instead of `zip_artifact` got: {artifact_type}")
55
+ raise QwakException(
56
+ f"Instead of `zip_artifact` got: {artifact_type}" # noqa
57
+ )
58
+
59
+ artifact_path_type: str = proto.zip_artifact.WhichOneof("path_type")
60
+ jfrog_artifact_path: Optional[JfrogArtifact] = None
61
+ qwak_artifact_path: Optional[str] = None
62
+
63
+ if artifact_path_type == "jfrog_artifact_path":
64
+ jfrog_artifact_path = JfrogArtifact.from_proto(
65
+ proto.zip_artifact.jfrog_artifact_path
66
+ )
67
+ elif artifact_path_type == "path":
68
+ qwak_artifact_path = proto.zip_artifact.path
69
+ else:
70
+ raise QwakException(
71
+ "Either `path` or `jfrog_artifact_path` must be provided inside SourceCodeArtifact proto."
72
+ )
29
73
 
30
74
  return cls(
31
- artifact_path=proto.zip_artifact.path,
75
+ jfrog_artifact_path=jfrog_artifact_path,
76
+ qwak_artifact_path=qwak_artifact_path,
32
77
  main_file=proto.zip_artifact.main_file,
33
78
  )
34
79
 
35
80
  def _to_proto(self) -> ProtoSourceCodeArtifact:
36
81
  return ProtoSourceCodeArtifact(
37
82
  zip_artifact=ProtoZipArtifact(
38
- path=self.artifact_path, main_file=self.main_file
83
+ jfrog_artifact_path=(
84
+ self.jfrog_artifact_path.to_proto()
85
+ if self.jfrog_artifact_path
86
+ else None
87
+ ),
88
+ path=self.qwak_artifact_path,
89
+ main_file=self.main_file,
39
90
  )
40
91
  )
41
92
 
42
93
 
43
- @dataclass
44
- class SourceCodeSpec:
45
- artifact: Optional[SourceCodeArtifact] = field(default=None)
94
+ class SourceCodeSpec(BaseModel):
95
+ artifact: Optional[SourceCodeArtifact] = Field(default=None)
46
96
 
47
97
  @classmethod
48
98
  def _from_proto(cls, proto: ProtoSourceCodeSpec) -> "SourceCodeSpec":
@@ -1,23 +1,30 @@
1
1
  import os
2
2
  from pathlib import Path
3
- from typing import Optional
3
+ from typing import Any, Dict, Optional
4
4
 
5
5
  from qwak.exceptions import QwakException
6
6
  from qwak.feature_store._common import packaging
7
- from qwak.feature_store._common.source_code_spec import SourceCodeSpec, ZipArtifact
7
+ from qwak.feature_store._common.source_code_spec import (
8
+ JfrogArtifact,
9
+ SourceCodeSpec,
10
+ ZipArtifact,
11
+ )
8
12
 
9
13
 
10
14
  class SourceCodeSpecFactory:
11
15
  @staticmethod
12
- def _upload_source_code_dir(main_entity_path: Path, presign_url: str):
16
+ def _upload_source_code_dir(
17
+ main_entity_path: Path, url: str, extra_headers: Dict[str, Any]
18
+ ):
13
19
  zip_location: Optional[Path] = None
14
20
  try:
15
21
  zip_location = packaging.zip_source_code_dir(base_path=main_entity_path)
16
22
  with open(zip_location, "rb") as zip_file:
17
- packaging.put_presigned_url(
18
- presign_url=presign_url,
23
+ packaging.put_files_content(
24
+ url=url,
19
25
  content=zip_file.read(),
20
26
  content_type="application/octet-stream",
27
+ extra_headers=extra_headers,
21
28
  )
22
29
  except Exception as e:
23
30
  raise QwakException("Got an error while trying to upload file.") from e
@@ -25,25 +32,71 @@ class SourceCodeSpecFactory:
25
32
  if zip_location:
26
33
  os.remove(zip_location)
27
34
 
28
- @staticmethod
35
+ @classmethod
29
36
  def get_zip_source_code_spec(
30
- main_entity_path: Path, presign_url: str
37
+ cls,
38
+ main_entity_path: Path,
39
+ url: str,
40
+ extra_headers: Optional[Dict[str, str]] = None,
31
41
  ) -> SourceCodeSpec:
32
42
  """
33
43
  Zips and upload the artifact,
34
44
  the main "entity" relative path is set as the main_entity_path
35
45
  """
36
- SourceCodeSpecFactory._upload_source_code_dir(
37
- main_entity_path=main_entity_path, presign_url=presign_url
46
+ cls._upload_source_code_dir(
47
+ main_entity_path=main_entity_path,
48
+ url=url,
49
+ extra_headers=extra_headers or {},
38
50
  )
39
51
 
40
52
  parent_base_path = (
41
53
  main_entity_path.parent if main_entity_path.is_file() else main_entity_path
42
54
  )
43
55
 
56
+ if cls._is_artifactory_source_code(extra_headers):
57
+ return cls._build_artifactory_source_code_spec(
58
+ url=url,
59
+ parent_base_path=parent_base_path,
60
+ main_entity_path=main_entity_path,
61
+ )
62
+ else:
63
+ return cls._build_qwak_source_code_spec(
64
+ url=url,
65
+ parent_base_path=parent_base_path,
66
+ main_entity_path=main_entity_path,
67
+ )
68
+
69
+ @classmethod
70
+ def _is_artifactory_source_code(
71
+ cls, extra_headers: Optional[Dict[str, str]]
72
+ ) -> bool:
73
+ """
74
+ Check if the source code is from Artifactory by checking the extra headers.
75
+ """
76
+ if not extra_headers:
77
+ return False
78
+ return True
79
+
80
+ @classmethod
81
+ def _build_artifactory_source_code_spec(
82
+ cls, url: str, parent_base_path: Path, main_entity_path: Path
83
+ ) -> SourceCodeSpec:
84
+ return SourceCodeSpec(
85
+ artifact=ZipArtifact(
86
+ jfrog_artifact_path=JfrogArtifact(path=url),
87
+ main_file=str(
88
+ Path(parent_base_path.name) / Path(main_entity_path.name)
89
+ ),
90
+ )
91
+ )
92
+
93
+ @classmethod
94
+ def _build_qwak_source_code_spec(
95
+ cls, url: str, parent_base_path: Path, main_entity_path: Path
96
+ ) -> SourceCodeSpec:
44
97
  return SourceCodeSpec(
45
98
  artifact=ZipArtifact(
46
- artifact_path=presign_url,
99
+ qwak_artifact_path=url,
47
100
  main_file=str(
48
101
  Path(parent_base_path.name) / Path(main_entity_path.name)
49
102
  ),
@@ -2,6 +2,7 @@ from qwak.feature_store.data_sources.batch.athena import AthenaSource
2
2
  from qwak.feature_store.data_sources.batch.big_query import BigQuerySource
3
3
  from qwak.feature_store.data_sources.batch.clickhouse import ClickhouseSource
4
4
  from qwak.feature_store.data_sources.batch.csv import CsvSource
5
+ from qwak.feature_store.data_sources.batch.unity_catalog import UnityCatalogSource
5
6
  from qwak.feature_store.data_sources.batch.elastic_search import ElasticSearchSource
6
7
  from qwak.feature_store.data_sources.batch.filesystem.aws import (
7
8
  AnonymousS3Configuration,
@@ -52,6 +53,7 @@ __all__ = [
52
53
  "RedshiftSource",
53
54
  "SnowflakeSource",
54
55
  "VerticaSource",
56
+ "UnityCatalogSource",
55
57
  "KafkaSource",
56
58
  "Deserializer",
57
59
  "CustomDeserializer",
@@ -6,12 +6,13 @@ from typing import TYPE_CHECKING, Optional, Tuple
6
6
  from _qwak_proto.qwak.feature_store.sources.data_source_pb2 import (
7
7
  DataSourceSpec as ProtoDataSourceSpec,
8
8
  )
9
+ from _qwak_proto.qwak.feature_store.v1.internal.data_source.data_source_service_pb2 import (
10
+ GetDataSourceSourceCodeUploadResponse,
11
+ )
9
12
  from qwak.clients.feature_store import FeatureRegistryClient
10
13
  from qwak.exceptions import QwakException
11
14
  from qwak.feature_store._common.artifact_utils import ArtifactSpec, ArtifactsUploader
12
- from qwak.feature_store._common.source_code_spec import (
13
- SourceCodeSpec,
14
- )
15
+ from qwak.feature_store._common.source_code_spec import SourceCodeSpec
15
16
  from qwak.feature_store._common.source_code_spec_factory import SourceCodeSpecFactory
16
17
  from qwak.feature_store.data_sources.attributes import DataSourceAttributes
17
18
  from qwak.feature_store.validations.validation_options import (
@@ -63,14 +64,16 @@ class BaseSource(ABC):
63
64
  uploaded_artifact_url = self._upload_artifact()
64
65
 
65
66
  if source_definition_path:
66
- presign_url: (
67
- str
67
+ code_upload_args: (
68
+ GetDataSourceSourceCodeUploadResponse
68
69
  ) = FeatureRegistryClient().get_datasource_source_code_presign_url(
69
- ds_name=self.name
70
+ ds_name=self.name, repository_name=getattr(self, "repository")
70
71
  )
71
72
  source_code_spec: SourceCodeSpec = (
72
73
  SourceCodeSpecFactory.get_zip_source_code_spec(
73
- main_entity_path=source_definition_path, presign_url=presign_url
74
+ main_entity_path=source_definition_path,
75
+ url=code_upload_args.upload_url,
76
+ extra_headers=code_upload_args.extra_headers,
74
77
  )
75
78
  )
76
79
 
@@ -113,6 +116,7 @@ class BaseSource(ABC):
113
116
  data_source=self,
114
117
  sample_size=number_of_rows,
115
118
  validation_options=validation_options,
119
+ silence_specific_exceptions=False,
116
120
  )
117
121
 
118
122
  if isinstance(response, SuccessValidationResponse):
@@ -1,5 +1,6 @@
1
1
  from dataclasses import dataclass
2
2
  from typing import Optional
3
+ import warnings
3
4
 
4
5
  from _qwak_proto.qwak.feature_store.sources.batch_pb2 import (
5
6
  BatchSource as ProtoBatchSource,
@@ -11,15 +12,18 @@ from _qwak_proto.qwak.feature_store.sources.data_source_pb2 import (
11
12
  from qwak.exceptions import QwakException
12
13
  from qwak.feature_store.data_sources.batch._batch import BaseBatchSource
13
14
 
15
+ warnings.simplefilter("once", DeprecationWarning)
16
+
14
17
 
15
18
  @dataclass
16
19
  class SnowflakeSource(BaseBatchSource):
17
20
  host: str
18
21
  username_secret_name: str
19
- password_secret_name: str
20
22
  database: str
21
23
  schema: str
22
24
  warehouse: str
25
+ password_secret_name: Optional[str] = None
26
+ pem_private_key_secret_name: Optional[str] = None
23
27
  table: Optional[str] = None
24
28
  query: Optional[str] = None
25
29
  repository: Optional[str] = None
@@ -28,16 +32,36 @@ class SnowflakeSource(BaseBatchSource):
28
32
  self._validate()
29
33
 
30
34
  def _validate(self):
31
- if self.table and self.query:
32
- raise QwakException("Only one of query and table may be set")
33
- if not self.table and not self.query:
34
- raise QwakException("One of table or query must be set")
35
-
36
35
  if not self.username_secret_name:
37
36
  raise QwakException("username_secret_name must be set!")
38
37
 
39
- if not self.password_secret_name:
40
- raise QwakException("password_secret_name must be set!")
38
+ if not self.database:
39
+ raise QwakException("database must be set!")
40
+
41
+ if not self.schema:
42
+ raise QwakException("schema must be set!")
43
+
44
+ if self.password_secret_name:
45
+ warnings.warn(
46
+ "Snowflake basic authentication is deprecated and should not be used. Use key-pair authentication instead.",
47
+ DeprecationWarning,
48
+ )
49
+
50
+ no_unique_source_exception_message = "Only one of query or table may be set"
51
+ has_table = bool(self.table)
52
+ has_query = bool(self.query)
53
+ no_source_set = not (has_table or has_query)
54
+ both_source_set = has_table and has_query
55
+ if no_source_set or both_source_set:
56
+ raise QwakException(no_unique_source_exception_message)
57
+
58
+ no_unique_auth_exception_message = "Exactly one of 'password_secret_name' or 'pem_private_key_secret_name' must be set"
59
+ has_password_secret = bool(self.password_secret_name)
60
+ has_pem_private_key_secret = bool(self.pem_private_key_secret_name)
61
+ no_auth_set = not (has_password_secret or has_pem_private_key_secret)
62
+ both_auth_set = has_password_secret and has_pem_private_key_secret
63
+ if no_auth_set or both_auth_set:
64
+ raise QwakException(no_unique_auth_exception_message)
41
65
 
42
66
  def _to_proto(self, artifact_url: Optional[str] = None):
43
67
  return ProtoDataSourceSpec(
@@ -50,6 +74,7 @@ class SnowflakeSource(BaseBatchSource):
50
74
  host=self.host,
51
75
  username_secret_name=self.username_secret_name,
52
76
  password_secret_name=self.password_secret_name,
77
+ pem_private_key_secret_name=self.pem_private_key_secret_name,
53
78
  database=self.database,
54
79
  schema=self.schema,
55
80
  warehouse=self.warehouse,
@@ -69,6 +94,7 @@ class SnowflakeSource(BaseBatchSource):
69
94
  host=snowflake.host,
70
95
  username_secret_name=snowflake.username_secret_name,
71
96
  password_secret_name=snowflake.password_secret_name,
97
+ pem_private_key_secret_name=snowflake.pem_private_key_secret_name,
72
98
  database=snowflake.database,
73
99
  schema=snowflake.schema,
74
100
  warehouse=snowflake.warehouse,
@@ -0,0 +1,107 @@
1
+ from dataclasses import dataclass
2
+ from typing import Optional
3
+
4
+ from _qwak_proto.qwak.feature_store.sources.batch_pb2 import (
5
+ BatchSource as ProtoBatchSource,
6
+ CatalogSource as ProtoCatalogSource,
7
+ UnityCatalogSource as ProtoUnityCatalogSource,
8
+ )
9
+ from _qwak_proto.qwak.feature_store.sources.data_source_pb2 import (
10
+ DataSourceSpec as ProtoDataSourceSpec,
11
+ )
12
+ from qwak.exceptions import QwakException
13
+ from qwak.feature_store.data_sources.batch._batch import BaseBatchSource
14
+
15
+ RESERVED_CATALOG_NAME = "qwak_catalog"
16
+
17
+
18
+ @dataclass
19
+ class UnityCatalogSource(BaseBatchSource):
20
+ """Unity Catalog batch data source.
21
+
22
+ Attributes:
23
+ uri (str): Connection uri to Unity Catalog i.e https://<workspace-instance-name>.<domain-name>/api/2.1/unity-catalog
24
+
25
+ schema (str): The Unity Catalog schema name where the data is located.
26
+
27
+ catalog (str): The Unity Catalog catalog name.
28
+
29
+ personal_access_token_secret_name (Optional[str]): The name of the secret
30
+ containing the personal access token for authentication. e.g "my-pat-secret"
31
+
32
+ table (Optional[str]): The table name within the specified catalog and schema.
33
+ Either 'table' or 'query' must be provided, but not both. e.g "my_table"
34
+
35
+ query (Optional[str]): A SQL query to execute against the Unity Catalog.
36
+ Either 'query' or 'table' must be provided, but not both. e.g "select * from {catalog}.{schema}.{table}"
37
+
38
+ repository (Optional[str]): The data source group.
39
+
40
+ """
41
+
42
+ uri: str
43
+ schema: str
44
+ catalog: str
45
+ personal_access_token_secret_name: Optional[str] = None
46
+ table: Optional[str] = None
47
+ query: Optional[str] = None
48
+ repository: Optional[str] = None
49
+
50
+ def __post_init__(self):
51
+ self._validate()
52
+
53
+ def _validate(self):
54
+ if not self.uri:
55
+ raise QwakException("`uri` cannot be empty.")
56
+
57
+ if not self.schema:
58
+ raise QwakException("`schema` cannot be empty.")
59
+
60
+ if not self.catalog:
61
+ raise QwakException("`catalog` cannot be empty.")
62
+
63
+ if not self.personal_access_token_secret_name:
64
+ raise QwakException("`personal_access_token_secret_name` cannot be empty.")
65
+
66
+ if self.catalog == RESERVED_CATALOG_NAME:
67
+ raise QwakException(
68
+ f"`catalog` can not be set to `{RESERVED_CATALOG_NAME}`.",
69
+ )
70
+
71
+ if bool(self.query) == bool(self.table):
72
+ raise QwakException("Either `query` or `table` must be provided.")
73
+
74
+ def _to_proto(self, artifact_url: Optional[str] = None) -> ProtoDataSourceSpec:
75
+ return ProtoDataSourceSpec(
76
+ data_source_repository_name=self.repository,
77
+ batch_source=ProtoBatchSource(
78
+ name=self.name,
79
+ description=self.description,
80
+ date_created_column=self.date_created_column,
81
+ catalogSource=ProtoCatalogSource(
82
+ url=self.uri,
83
+ query=self.query,
84
+ table=self.table,
85
+ unityCatalogSource=ProtoUnityCatalogSource(
86
+ catalog=self.catalog,
87
+ schema=self.schema,
88
+ personal_access_token_secret_name=self.personal_access_token_secret_name,
89
+ ),
90
+ ),
91
+ ),
92
+ )
93
+
94
+ @classmethod
95
+ def _from_proto(cls, proto: ProtoBatchSource) -> "UnityCatalogSource":
96
+ catalog_source = proto.catalogSource
97
+ return cls(
98
+ name=proto.name,
99
+ date_created_column=proto.date_created_column,
100
+ description=proto.description,
101
+ uri=catalog_source.url,
102
+ schema=catalog_source.unityCatalogSource.schema,
103
+ catalog=catalog_source.unityCatalogSource.catalog,
104
+ personal_access_token_secret_name=catalog_source.unityCatalogSource.personal_access_token_secret_name,
105
+ table=catalog_source.table,
106
+ query=catalog_source.query,
107
+ )