qwak-core 0.4.245__py3-none-any.whl → 0.4.247__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.
- _qwak_proto/qwak/service_discovery/service_discovery_location_pb2.py +65 -0
- _qwak_proto/qwak/service_discovery/service_discovery_location_pb2.pyi +73 -0
- _qwak_proto/qwak/service_discovery/service_discovery_location_pb2_grpc.py +4 -0
- _qwak_proto/qwak/service_discovery/service_discovery_location_service_pb2.py +49 -0
- _qwak_proto/qwak/service_discovery/service_discovery_location_service_pb2.pyi +41 -0
- _qwak_proto/qwak/service_discovery/service_discovery_location_service_pb2_grpc.py +231 -0
- qwak/__init__.py +1 -1
- qwak/clients/feature_store/offline_serving_client.py +29 -4
- qwak/clients/location_discovery/__init__.py +1 -0
- qwak/clients/location_discovery/client.py +73 -0
- qwak/feature_store/_common/functions.py +0 -19
- qwak/feature_store/offline/__init__.py +1 -2
- qwak/inner/build_logic/phases/phase_020_remote_register_qwak_build/upload_step.py +20 -20
- {qwak_core-0.4.245.dist-info → qwak_core-0.4.247.dist-info}/METADATA +1 -1
- {qwak_core-0.4.245.dist-info → qwak_core-0.4.247.dist-info}/RECORD +19 -15
- qwak_services_mock/mocks/location_discovery_service_api.py +104 -0
- qwak_services_mock/mocks/qwak_mocks.py +4 -0
- qwak_services_mock/services_mock.py +13 -0
- qwak/feature_store/_common/featureset_asterisk_handler.py +0 -115
- qwak/feature_store/offline/_query_engine.py +0 -32
- qwak/feature_store/offline/athena/__init__.py +0 -0
- qwak/feature_store/offline/athena/athena_query_engine.py +0 -153
- qwak/feature_store/offline/client.py +0 -718
- {qwak_core-0.4.245.dist-info → qwak_core-0.4.247.dist-info}/WHEEL +0 -0
@@ -3,15 +3,14 @@ from __future__ import annotations
|
|
3
3
|
import re
|
4
4
|
from pathlib import Path
|
5
5
|
from typing import Any, List, Tuple, Union, Optional
|
6
|
-
from retrying import retry
|
7
6
|
|
8
7
|
import joblib
|
9
8
|
import requests
|
9
|
+
from retrying import retry
|
10
10
|
|
11
11
|
from _qwak_proto.qwak.builds.build_url_pb2 import BuildVersioningTagsType
|
12
12
|
from _qwak_proto.qwak.builds.builds_orchestrator_service_pb2 import (
|
13
13
|
GetBuildVersioningUploadURLResponse,
|
14
|
-
AuthenticationDetail,
|
15
14
|
)
|
16
15
|
from qwak.exceptions import QwakException
|
17
16
|
from qwak.exceptions import QwakGeneralBuildException
|
@@ -158,15 +157,17 @@ class UploadStep(Step):
|
|
158
157
|
):
|
159
158
|
self.build_logger.debug(f"Upload file {file}")
|
160
159
|
|
161
|
-
pre_signed_url_response =
|
162
|
-
|
160
|
+
pre_signed_url_response: GetBuildVersioningUploadURLResponse = (
|
161
|
+
self.get_pre_signed_upload_url(
|
162
|
+
tag=tag, tag_type=BuildVersioningTagsType.FILE_TAG_TYPE
|
163
|
+
)
|
163
164
|
)
|
164
165
|
self.upload_file_to_remote_storge(
|
165
166
|
upload_url=pre_signed_url_response.upload_url,
|
166
167
|
file=file,
|
167
168
|
all_files_size_to_upload=all_files_size_to_upload,
|
168
169
|
read_so_far=read_so_far,
|
169
|
-
|
170
|
+
headers=pre_signed_url_response.headers,
|
170
171
|
)
|
171
172
|
|
172
173
|
self.build_logger.debug(f"Upload file {file} completed")
|
@@ -179,7 +180,7 @@ class UploadStep(Step):
|
|
179
180
|
try:
|
180
181
|
self.build_logger.debug(f"Getting pre-signed url for upload - tag {tag}")
|
181
182
|
|
182
|
-
pre_signed_url_response = (
|
183
|
+
pre_signed_url_response: GetBuildVersioningUploadURLResponse = (
|
183
184
|
self.context.client_builds_orchestrator.get_build_versioning_upload_url(
|
184
185
|
build_id=self.context.build_id,
|
185
186
|
model_id=self.context.model_id,
|
@@ -203,22 +204,16 @@ class UploadStep(Step):
|
|
203
204
|
file: Path,
|
204
205
|
all_files_size_to_upload: int,
|
205
206
|
read_so_far: int,
|
206
|
-
|
207
|
+
headers: Optional[dict] = None,
|
207
208
|
):
|
209
|
+
if not headers:
|
210
|
+
headers = {}
|
211
|
+
|
208
212
|
try:
|
209
213
|
self.build_logger.debug(f"Upload file {file} to Qwak storage")
|
210
|
-
auth: Optional[Tuple[str, str]] = None
|
211
|
-
if (
|
212
|
-
authentication_details.WhichOneof("integration_type")
|
213
|
-
== "jfrog_authentication_detail"
|
214
|
-
):
|
215
|
-
auth = (
|
216
|
-
authentication_details.jfrog_authentication_detail.username,
|
217
|
-
authentication_details.jfrog_authentication_detail.token,
|
218
|
-
)
|
219
214
|
|
220
215
|
self.send_request(
|
221
|
-
upload_url, file, all_files_size_to_upload, read_so_far,
|
216
|
+
upload_url, file, all_files_size_to_upload, read_so_far, headers
|
222
217
|
)
|
223
218
|
self.build_logger.debug(
|
224
219
|
f"File {file} uploaded to Qwak storage successfully"
|
@@ -236,8 +231,14 @@ class UploadStep(Step):
|
|
236
231
|
file: Path,
|
237
232
|
all_files_size_to_upload: int,
|
238
233
|
read_so_far: int,
|
239
|
-
|
234
|
+
headers: Optional[dict],
|
240
235
|
):
|
236
|
+
if not headers:
|
237
|
+
headers = {}
|
238
|
+
|
239
|
+
# Adding to the current headers the content-type
|
240
|
+
headers["content-type"] = "text/plain"
|
241
|
+
|
241
242
|
http_response = requests.put( # nosec B113
|
242
243
|
url=upload_url,
|
243
244
|
data=UploadInChunks(
|
@@ -247,8 +248,7 @@ class UploadStep(Step):
|
|
247
248
|
all_files_size_to_upload=all_files_size_to_upload,
|
248
249
|
read_so_far=read_so_far,
|
249
250
|
),
|
250
|
-
|
251
|
-
headers={"content-type": "text/plain"},
|
251
|
+
headers=headers,
|
252
252
|
)
|
253
253
|
|
254
254
|
if http_response.status_code not in [200, 201]:
|
@@ -540,6 +540,12 @@ _qwak_proto/qwak/self_service/user/v1/user_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7E
|
|
540
540
|
_qwak_proto/qwak/self_service/user/v1/user_service_pb2.py,sha256=31GMuClpxHWHnFPXKxKlxLby-NofL9yHj4GULLJQ8ng,10389
|
541
541
|
_qwak_proto/qwak/self_service/user/v1/user_service_pb2.pyi,sha256=Y4BlejbLGPraMkujz9Du_uC4WwJdCUgWSPv1IEFTYKk,8148
|
542
542
|
_qwak_proto/qwak/self_service/user/v1/user_service_pb2_grpc.py,sha256=HPNgP5ejFRwdgF_eVoDqu2-wpG1odK_p5nyZ9iXTIL8,10512
|
543
|
+
_qwak_proto/qwak/service_discovery/service_discovery_location_pb2.py,sha256=KnfvXbH36EvzBtG0aWgYKy761JEsRkvgCdMhG5-Zq9Q,3329
|
544
|
+
_qwak_proto/qwak/service_discovery/service_discovery_location_pb2.pyi,sha256=33gciRiYabLn_gmN5Ksw5reequ4GkfUbGxFW4gionf4,2406
|
545
|
+
_qwak_proto/qwak/service_discovery/service_discovery_location_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
|
546
|
+
_qwak_proto/qwak/service_discovery/service_discovery_location_service_pb2.py,sha256=NkkenQmPrFSm9T9bji2vJtD5difVTdFE8pN5-2Z5gmM,3813
|
547
|
+
_qwak_proto/qwak/service_discovery/service_discovery_location_service_pb2.pyi,sha256=7lfas7n0SXrqcrjCjivcqPVEV8SOQhW8vEXbhvdVFeg,1357
|
548
|
+
_qwak_proto/qwak/service_discovery/service_discovery_location_service_pb2_grpc.py,sha256=LfpjLTdJ8lTJjErhDHgoM9ew-7c_FfXcnSqFEL2plVU,13684
|
543
549
|
_qwak_proto/qwak/traffic/v1/traffic_api_pb2.py,sha256=4KmYUxK7Gku8IddNOc7VCOjS89H5qtAv4eOMqAJ4v2o,6909
|
544
550
|
_qwak_proto/qwak/traffic/v1/traffic_api_pb2.pyi,sha256=tsh59fnAmLLsKzc5-dj9Jx8MDXJWukoNzJtvGjGQjfI,5186
|
545
551
|
_qwak_proto/qwak/traffic/v1/traffic_api_pb2_grpc.py,sha256=46oskdNbo8xUzu8QGNtqtvUL93zYuOsSHCVFY1e8TLM,8228
|
@@ -576,7 +582,7 @@ _qwak_proto/qwak/workspace/workspace_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXH
|
|
576
582
|
_qwak_proto/qwak/workspace/workspace_service_pb2.py,sha256=AB3C9S_AbOD7Nx1Ni4j1rW6PNtYTV1zjiqFQk-goQ74,21429
|
577
583
|
_qwak_proto/qwak/workspace/workspace_service_pb2.pyi,sha256=nKKCHwnovZhsy8TSVmdz-Vtl0nviOOoX56HD-41Xo08,13726
|
578
584
|
_qwak_proto/qwak/workspace/workspace_service_pb2_grpc.py,sha256=yKGuexxTBza99Ihe0DSTniV2ZSd_AG47inHenqfi890,27193
|
579
|
-
qwak/__init__.py,sha256=
|
585
|
+
qwak/__init__.py,sha256=J_KtOzJioSVXYmoJWJVbRcqfxi3x8qL7akMQxB_RlhQ,587
|
580
586
|
qwak/automations/__init__.py,sha256=qFZRvCxUUn8gcxkJR0v19ulHW2oJ0x6-Rif7HiheDP4,1522
|
581
587
|
qwak/automations/automation_executions.py,sha256=5MeH_epYYWb8NKXgAozwT_jPyyUDednBHG7izloi7RY,3228
|
582
588
|
qwak/automations/automations.py,sha256=3yx8e2v0uSKDnXbqyknasyEoQ5vxGni6K40Hbi1_zkk,12599
|
@@ -630,7 +636,7 @@ qwak/clients/feature_store/__init__.py,sha256=mMCPBHDga6Y7dtJfNoHvfOvCyjNUHrVDX5
|
|
630
636
|
qwak/clients/feature_store/execution_management_client.py,sha256=tKLIML8wsvgsl1hBfx74izFL0rHYdNM69sEstomDfYM,4051
|
631
637
|
qwak/clients/feature_store/job_registry_client.py,sha256=7VMtEj7aofKcABrYpldgdxyv8Vkdq_mocjns1O0uCqA,2635
|
632
638
|
qwak/clients/feature_store/management_client.py,sha256=UqFx_wVrDx0N7ArMmaLiBqAzpekqZgkmQlC9UHkze_M,20498
|
633
|
-
qwak/clients/feature_store/offline_serving_client.py,sha256=
|
639
|
+
qwak/clients/feature_store/offline_serving_client.py,sha256=gz8hqaboPA1Und8leOf1O0dXa9xorHDTU3b7-Ne9YSE,9344
|
634
640
|
qwak/clients/feature_store/operator_client.py,sha256=qChgvX8m7A_tffMIaRx22pLSt5YxAbWeHPO-67LrRKE,5811
|
635
641
|
qwak/clients/file_versioning/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
636
642
|
qwak/clients/file_versioning/client.py,sha256=ywOy9olB4mekjQQrKUufAbaC-3sWzQnqd3ChcwrAJzc,2505
|
@@ -644,6 +650,8 @@ qwak/clients/integration_management/openai/__init__.py,sha256=47DEQpj8HBSa-_TImW
|
|
644
650
|
qwak/clients/integration_management/openai/openai_system_secret.py,sha256=y7NT-F-S50ol7CUcnrSK522xZr7k0lD7bYo9VlyZ1j8,2119
|
645
651
|
qwak/clients/kube_deployment_captain/__init__.py,sha256=rJUEEy3zNH0aTFyuO_UBexzaUKdjvwU9P2vV1MDj684,41
|
646
652
|
qwak/clients/kube_deployment_captain/client.py,sha256=g5nLf4l7A4SFpdfF8Q5KwEincSFiWTHKKEFKztE5QVw,9308
|
653
|
+
qwak/clients/location_discovery/__init__.py,sha256=sqGQ75YHFE6nvOcir38fykUUmAa6cFEIze8PJYgYWRc,44
|
654
|
+
qwak/clients/location_discovery/client.py,sha256=O-wjMGiSTJ5qGjD0VhofE6Mv7NqvmwCpRnJgzyxKg6I,2867
|
647
655
|
qwak/clients/logging_client/__init__.py,sha256=1OCHnigQBYThBwGbxCreYA0BgP0HcuLFzNEWd3Yxh-c,34
|
648
656
|
qwak/clients/logging_client/client.py,sha256=IdPa93JjlVm0B_Gdc4lH9LYHoVn5DjT_gIPaZ-W3Hdw,4906
|
649
657
|
qwak/clients/model_management/__init__.py,sha256=vjWVP8MjmK4_A70WOgJqa6x24AeLK-ABjGJtogGzw9w,43
|
@@ -685,8 +693,7 @@ qwak/feature_store/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuF
|
|
685
693
|
qwak/feature_store/_common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
686
694
|
qwak/feature_store/_common/artifact_utils.py,sha256=iIdz6EfFuE_yub6g5KXlOOMt7TA7pEuuLwjlzVSRpO8,1977
|
687
695
|
qwak/feature_store/_common/feature_set_utils.py,sha256=dhtPWnwv1nB3h3EA8FAYklx1qGkO_Dj1jecaBGNNpew,8634
|
688
|
-
qwak/feature_store/_common/
|
689
|
-
qwak/feature_store/_common/functions.py,sha256=z033VNAqGZak2oB7pUSS9iJrh9aMRblVGP3iLWCChko,1298
|
696
|
+
qwak/feature_store/_common/functions.py,sha256=kSNYJ7dy48NN09HG9asm4ibQh0JaCGcZYsRDjRWlUHE,659
|
690
697
|
qwak/feature_store/_common/packaging.py,sha256=eyTyjIB_C6wGHcdU7xR5u7-N2Ld98s4LPU_iZtcbRO0,8122
|
691
698
|
qwak/feature_store/_common/source_code_spec.py,sha256=OqlrGVtLvZNtJjycEyC5v5VCIfD12JkYcM2JbnR-x_k,1804
|
692
699
|
qwak/feature_store/_common/source_code_spec_factory.py,sha256=zDif0nlWs43T87-k2VCUYyQyR6O3vbCHYCOtVfLUI8g,1760
|
@@ -748,12 +755,8 @@ qwak/feature_store/feature_sets/transformations/functions/qwak_pandas.py,sha256=
|
|
748
755
|
qwak/feature_store/feature_sets/transformations/functions/schema.py,sha256=kuu8MZ3d2Y9DkmgPZCRgDb0ecsc8isFHQG1lFLPBR3Y,1156
|
749
756
|
qwak/feature_store/feature_sets/transformations/transformations.py,sha256=k10Tg64XOfvpL9pQPMEfkuXtMT5EYxZ9-xkTOoD1fpM,15328
|
750
757
|
qwak/feature_store/feature_sets/transformations/validations/validations_util.py,sha256=Nr7MyWTLxe9J5VwQYCPRpaQdsv5VmWsWLwPC3C-cwOk,3179
|
751
|
-
qwak/feature_store/offline/__init__.py,sha256=
|
758
|
+
qwak/feature_store/offline/__init__.py,sha256=v6cf_Ne02UxZpsxPCWna0cZBLyF2czN_iL4eO3XIPOI,96
|
752
759
|
qwak/feature_store/offline/_offline_serving_validations.py,sha256=a3Ga9-IPTS0TPf_ghjuQ9qumBCMKFaQBkWxdoawUr-s,1216
|
753
|
-
qwak/feature_store/offline/_query_engine.py,sha256=LBVejISK9daYYWUYclXuMifezfsuzF4JgBhp2YlHZf0,738
|
754
|
-
qwak/feature_store/offline/athena/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
755
|
-
qwak/feature_store/offline/athena/athena_query_engine.py,sha256=Z8Y46nf9-_TI7AXpS5aO57UTDQFnFvARislMQcwQb8A,5182
|
756
|
-
qwak/feature_store/offline/client.py,sha256=dGtCnqlhuL4y5T7AtbTj1Pzu78-8JR_O1wnrnKmozHE,28651
|
757
760
|
qwak/feature_store/offline/client_v2.py,sha256=MKIlVGohW7aMmCpBUKE9wP9X6gtU_pLVfOgnBn2Bp98,14393
|
758
761
|
qwak/feature_store/offline/feature_set_features.py,sha256=Eh_rPz_m12cAQvrhIF-xtA-ZGVKy1HlgKJdjNvsmPoo,739
|
759
762
|
qwak/feature_store/online/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -810,7 +813,7 @@ qwak/inner/build_logic/phases/phase_010_fetch_model/set_version_step.py,sha256=M
|
|
810
813
|
qwak/inner/build_logic/phases/phase_020_remote_register_qwak_build/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
811
814
|
qwak/inner/build_logic/phases/phase_020_remote_register_qwak_build/cleanup_step.py,sha256=Nxv3wAbuCocvsC1V7-gGSTRLOEKdrlViME4_BUTedCY,618
|
812
815
|
qwak/inner/build_logic/phases/phase_020_remote_register_qwak_build/start_remote_build_step.py,sha256=3k8wLGh-tANo0AYJstPHIACpSul-h7gYbxGgFQZzRZQ,1673
|
813
|
-
qwak/inner/build_logic/phases/phase_020_remote_register_qwak_build/upload_step.py,sha256=
|
816
|
+
qwak/inner/build_logic/phases/phase_020_remote_register_qwak_build/upload_step.py,sha256=tj42f3h1uFl4FYiwp0uBxfRVqFyiGQLEIJ4iz1M_IJc,9323
|
814
817
|
qwak/inner/build_logic/phases/phases_pipeline.py,sha256=KveRNEYji1FbzP1tswJWReMqoCnuHfDLmYFeS4YBJpE,1244
|
815
818
|
qwak/inner/build_logic/run_handlers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
816
819
|
qwak/inner/build_logic/run_handlers/programmatic_phase_run_handler.py,sha256=nDR0e357sc-Lr-36uCUzxCK3LORzqYyoutHQ3rmXo1w,3484
|
@@ -1035,11 +1038,12 @@ qwak_services_mock/mocks/integration_management_service.py,sha256=j5ew7epeG0-n-q
|
|
1035
1038
|
qwak_services_mock/mocks/internal_build_orchestrator_service.py,sha256=deupu0eGAepqwh8bbebCY3i1BavrXv_mTpRdktaENPk,1046
|
1036
1039
|
qwak_services_mock/mocks/job_registry_service_api.py,sha256=BEU8eH9yE0_Jrc792rdp_M2KtrXO97uB3hklmQZsUtI,2696
|
1037
1040
|
qwak_services_mock/mocks/kube_captain_service_api.py,sha256=raZEWAP3aOk-DeM9qVHMGl97AK-8_smiCYCo0Euj0zg,1583
|
1041
|
+
qwak_services_mock/mocks/location_discovery_service_api.py,sha256=sEy-FEZg1rQnGqmNiewH4azkxbj-riaoiQ4h8XjeA2o,3679
|
1038
1042
|
qwak_services_mock/mocks/logging_service.py,sha256=rkOud7CFAvb0xfP6WXf3kP541eXdYJK5Lv_Q_2I1Fek,7381
|
1039
1043
|
qwak_services_mock/mocks/model_management_service.py,sha256=H3bMTr7VLrGjZjIrjgrjBk3kNDy1UjQXOeUyL5eAL_o,4153
|
1040
1044
|
qwak_services_mock/mocks/project_manager_service.py,sha256=WzcYzN3O04kSpvuTwX0QIF0HCh_ggsV9-gMel_vQVuc,3090
|
1041
1045
|
qwak_services_mock/mocks/prompt_manager_service.py,sha256=tEhVUVwkvRy68r7MNX9V3V8ZBZ1ynqzr6v1zREMm0_s,9895
|
1042
|
-
qwak_services_mock/mocks/qwak_mocks.py,sha256=
|
1046
|
+
qwak_services_mock/mocks/qwak_mocks.py,sha256=abayoevvX2gzUftDef_SYlL2t44P0r_7IaVh4GM0Hx0,6142
|
1043
1047
|
qwak_services_mock/mocks/secret_service.py,sha256=BwNyhNSTmxHDACzrr7NHjZ0YchX3wHWuJkl1ioi0Aig,1406
|
1044
1048
|
qwak_services_mock/mocks/self_service_user_service.py,sha256=UK22V-wAc0zHScXCE0QKDO0TdbrHf_uk7tEEIM47MpI,1205
|
1045
1049
|
qwak_services_mock/mocks/system_secret_service.py,sha256=S8MfGGEex7bs0AvnAf8SbPOzE-YDfCvePT1TxXWzHRQ,1896
|
@@ -1049,9 +1053,9 @@ qwak_services_mock/mocks/utils/exception_handlers.py,sha256=Fhi9cx_qNytDnl4BtZmE
|
|
1049
1053
|
qwak_services_mock/mocks/vector_serving_api.py,sha256=7ZSmDJVdw7_ne7BxLLrmy8eZkzVCeZ508gfL51wpKeY,5722
|
1050
1054
|
qwak_services_mock/mocks/vectors_management_api.py,sha256=ePh8l3MlDGzs7E4NuPZzF5xK-bC9AdMgDaNZrq3FkHc,3594
|
1051
1055
|
qwak_services_mock/mocks/workspace_manager_service_mock.py,sha256=O9ZSwln4T4kHVkR_usXnDQtarTeNfffSMON0P6wbT4g,7740
|
1052
|
-
qwak_services_mock/services_mock.py,sha256=
|
1056
|
+
qwak_services_mock/services_mock.py,sha256=zXtHcX8a_acz7ynxuCBxxVpHpde7aAGjIn6Uw52LY1s,19593
|
1053
1057
|
qwak_services_mock/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1054
1058
|
qwak_services_mock/utils/service_utils.py,sha256=ZlB0CnB1J6oBn6_m7fQO2U8tKoboHdUa6ljjkRMYNXU,265
|
1055
|
-
qwak_core-0.4.
|
1056
|
-
qwak_core-0.4.
|
1057
|
-
qwak_core-0.4.
|
1059
|
+
qwak_core-0.4.247.dist-info/METADATA,sha256=R1THTra1pOBCXCvAxwZkPPIov3RUG4-KODuL00yyLTk,2150
|
1060
|
+
qwak_core-0.4.247.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
1061
|
+
qwak_core-0.4.247.dist-info/RECORD,,
|
@@ -0,0 +1,104 @@
|
|
1
|
+
from typing import Dict, Optional
|
2
|
+
|
3
|
+
import grpc
|
4
|
+
from _qwak_proto.qwak.service_discovery.service_discovery_location_pb2 import (
|
5
|
+
ServiceLocationDescriptor,
|
6
|
+
)
|
7
|
+
from _qwak_proto.qwak.service_discovery.service_discovery_location_service_pb2 import (
|
8
|
+
GetServingUrlRequestResponse,
|
9
|
+
)
|
10
|
+
from _qwak_proto.qwak.service_discovery.service_discovery_location_service_pb2_grpc import (
|
11
|
+
LocationDiscoveryServiceServicer,
|
12
|
+
)
|
13
|
+
|
14
|
+
|
15
|
+
class LocationDiscoveryServiceApiMock(LocationDiscoveryServiceServicer):
|
16
|
+
"""
|
17
|
+
Mock implementation of the LocationDiscoveryService for testing SDK behavior.
|
18
|
+
Allows setting mock responses and optional error codes for each endpoint.
|
19
|
+
"""
|
20
|
+
|
21
|
+
def __init__(self):
|
22
|
+
super().__init__()
|
23
|
+
self._responses: Dict[str, Optional[ServiceLocationDescriptor]] = {}
|
24
|
+
self._error_codes: Dict[str, grpc.StatusCode] = {}
|
25
|
+
|
26
|
+
def _set_mock(
|
27
|
+
self,
|
28
|
+
key: str,
|
29
|
+
response: Optional[ServiceLocationDescriptor],
|
30
|
+
error_code: grpc.StatusCode = grpc.StatusCode.NOT_FOUND,
|
31
|
+
):
|
32
|
+
self._responses[key] = response
|
33
|
+
self._error_codes[key] = error_code
|
34
|
+
|
35
|
+
def _handle(
|
36
|
+
self, key: str, context: grpc.ServicerContext
|
37
|
+
) -> GetServingUrlRequestResponse:
|
38
|
+
response = self._responses.get(key)
|
39
|
+
if response:
|
40
|
+
return GetServingUrlRequestResponse(location=response)
|
41
|
+
context.set_code(self._error_codes.get(key, grpc.StatusCode.NOT_FOUND))
|
42
|
+
context.set_details(f"No mock response set for {key}")
|
43
|
+
return GetServingUrlRequestResponse()
|
44
|
+
|
45
|
+
# Setters
|
46
|
+
def set_get_offline_serving_url_response(
|
47
|
+
self,
|
48
|
+
response: Optional[ServiceLocationDescriptor],
|
49
|
+
error_code: grpc.StatusCode = grpc.StatusCode.NOT_FOUND,
|
50
|
+
):
|
51
|
+
self._set_mock("offline", response, error_code)
|
52
|
+
|
53
|
+
def set_get_distribution_manager_url_response(
|
54
|
+
self,
|
55
|
+
response: Optional[ServiceLocationDescriptor],
|
56
|
+
error_code: grpc.StatusCode = grpc.StatusCode.NOT_FOUND,
|
57
|
+
):
|
58
|
+
self._set_mock("distribution", response, error_code)
|
59
|
+
|
60
|
+
def set_get_analytics_engine_url_response(
|
61
|
+
self,
|
62
|
+
response: Optional[ServiceLocationDescriptor],
|
63
|
+
error_code: grpc.StatusCode = grpc.StatusCode.NOT_FOUND,
|
64
|
+
):
|
65
|
+
self._set_mock("analytics", response, error_code)
|
66
|
+
|
67
|
+
def set_get_metrics_gateway_url_response(
|
68
|
+
self,
|
69
|
+
response: Optional[ServiceLocationDescriptor],
|
70
|
+
error_code: grpc.StatusCode = grpc.StatusCode.NOT_FOUND,
|
71
|
+
):
|
72
|
+
self._set_mock("metrics", response, error_code)
|
73
|
+
|
74
|
+
def set_get_features_operator_url_response(
|
75
|
+
self,
|
76
|
+
response: Optional[ServiceLocationDescriptor],
|
77
|
+
error_code: grpc.StatusCode = grpc.StatusCode.NOT_FOUND,
|
78
|
+
):
|
79
|
+
self._set_mock("features", response, error_code)
|
80
|
+
|
81
|
+
def set_get_hosting_gateway_url_response(
|
82
|
+
self,
|
83
|
+
response: Optional[ServiceLocationDescriptor],
|
84
|
+
error_code: grpc.StatusCode = grpc.StatusCode.NOT_FOUND,
|
85
|
+
):
|
86
|
+
self._set_mock("hosting", response, error_code)
|
87
|
+
|
88
|
+
def GetOfflineServingUrl(self, request, context):
|
89
|
+
return self._handle("offline", context)
|
90
|
+
|
91
|
+
def GetDistributionManagerUrl(self, request, context):
|
92
|
+
return self._handle("distribution", context)
|
93
|
+
|
94
|
+
def GetAnalyticsEngineUrl(self, request, context):
|
95
|
+
return self._handle("analytics", context)
|
96
|
+
|
97
|
+
def GetMetricsGatewayUrl(self, request, context):
|
98
|
+
return self._handle("metrics", context)
|
99
|
+
|
100
|
+
def GetFeaturesOperatorUrl(self, request, context):
|
101
|
+
return self._handle("features", context)
|
102
|
+
|
103
|
+
def GetHostingGatewayUrl(self, request, context):
|
104
|
+
return self._handle("hosting", context)
|
@@ -60,6 +60,9 @@ from qwak_services_mock.mocks.internal_build_orchestrator_service import (
|
|
60
60
|
)
|
61
61
|
from qwak_services_mock.mocks.job_registry_service_api import JobRegistryServiceApiMock
|
62
62
|
from qwak_services_mock.mocks.kube_captain_service_api import KubeCaptainServiceApiMock
|
63
|
+
from qwak_services_mock.mocks.location_discovery_service_api import (
|
64
|
+
LocationDiscoveryServiceApiMock,
|
65
|
+
)
|
63
66
|
from qwak_services_mock.mocks.logging_service import LoggingServiceApiMock
|
64
67
|
from qwak_services_mock.mocks.model_management_service import (
|
65
68
|
ModelsManagementServiceMock,
|
@@ -121,3 +124,4 @@ class QwakMocks:
|
|
121
124
|
system_secret_service: SystemSecretServiceMock
|
122
125
|
integration_management_service: IntegrationManagementServiceMock
|
123
126
|
prompt_manager_service: PromptManagerServiceMock
|
127
|
+
location_discovery_service: LocationDiscoveryServiceApiMock
|
@@ -106,6 +106,9 @@ from _qwak_proto.qwak.secret_service.secret_service_pb2_grpc import (
|
|
106
106
|
from _qwak_proto.qwak.self_service.user.v1.user_service_pb2_grpc import (
|
107
107
|
add_UserServiceServicer_to_server,
|
108
108
|
)
|
109
|
+
from _qwak_proto.qwak.service_discovery.service_discovery_location_service_pb2_grpc import (
|
110
|
+
add_LocationDiscoveryServiceServicer_to_server,
|
111
|
+
)
|
109
112
|
from _qwak_proto.qwak.vectors.v1.collection.collection_service_pb2_grpc import (
|
110
113
|
add_VectorCollectionServiceServicer_to_server,
|
111
114
|
)
|
@@ -175,6 +178,9 @@ from qwak_services_mock.mocks.internal_build_orchestrator_service import (
|
|
175
178
|
)
|
176
179
|
from qwak_services_mock.mocks.job_registry_service_api import JobRegistryServiceApiMock
|
177
180
|
from qwak_services_mock.mocks.kube_captain_service_api import KubeCaptainServiceApiMock
|
181
|
+
from qwak_services_mock.mocks.location_discovery_service_api import (
|
182
|
+
LocationDiscoveryServiceApiMock,
|
183
|
+
)
|
178
184
|
from qwak_services_mock.mocks.logging_service import LoggingServiceApiMock
|
179
185
|
from qwak_services_mock.mocks.model_management_service import (
|
180
186
|
ModelsManagementServiceMock,
|
@@ -235,6 +241,7 @@ def qwak_container():
|
|
235
241
|
file_versioning,
|
236
242
|
instance_template,
|
237
243
|
kube_deployment_captain,
|
244
|
+
location_discovery,
|
238
245
|
logging_client,
|
239
246
|
model_management,
|
240
247
|
project,
|
@@ -280,6 +287,7 @@ def qwak_container():
|
|
280
287
|
integration_manager_client,
|
281
288
|
system_secret_client,
|
282
289
|
prompt_manager_client,
|
290
|
+
location_discovery,
|
283
291
|
]
|
284
292
|
)
|
285
293
|
|
@@ -492,6 +500,11 @@ def attach_servicers(free_port, server):
|
|
492
500
|
PromptManagerServiceMock,
|
493
501
|
add_PromptManagerServiceServicer_to_server,
|
494
502
|
),
|
503
|
+
(
|
504
|
+
"location_discovery_service",
|
505
|
+
LocationDiscoveryServiceApiMock,
|
506
|
+
add_LocationDiscoveryServiceServicer_to_server,
|
507
|
+
),
|
495
508
|
("port", free_port, None),
|
496
509
|
],
|
497
510
|
)
|
@@ -1,115 +0,0 @@
|
|
1
|
-
import dataclasses
|
2
|
-
import itertools
|
3
|
-
import re
|
4
|
-
from typing import Callable, Dict, List
|
5
|
-
|
6
|
-
from qwak.feature_store.offline import OfflineClient
|
7
|
-
from qwak.model.schema_entities import BaseFeature, Entity, FeatureStoreInput
|
8
|
-
|
9
|
-
|
10
|
-
def is_asterisk(feature: BaseFeature) -> bool:
|
11
|
-
"""
|
12
|
-
Checks whether the given Feature is a FeatureStoreInput with an '*'
|
13
|
-
Args:
|
14
|
-
feature: input feature
|
15
|
-
Return
|
16
|
-
"""
|
17
|
-
p = "^[^.]+.\\*$"
|
18
|
-
# if this is not a FeatureStoreInput, no need to check
|
19
|
-
if isinstance(feature, FeatureStoreInput):
|
20
|
-
return bool(re.match(p, feature.name))
|
21
|
-
return False
|
22
|
-
|
23
|
-
|
24
|
-
def inflate_feature(feature: BaseFeature, offline_fs: OfflineClient) -> List:
|
25
|
-
"""
|
26
|
-
Inflates a Feature into a list. if the feature contains an '*', a list
|
27
|
-
a feature for each feature in the associate FeatureSet is returned. else -
|
28
|
-
a list containing the original feature is returned.
|
29
|
-
Args:
|
30
|
-
feature: input feature
|
31
|
-
offline_fs: OfflineFeatureStore to query
|
32
|
-
Return:
|
33
|
-
if an '*' exists, returns a List of FeatureStoreInuput for each feature in the feature set
|
34
|
-
else returns a list containing the feature.
|
35
|
-
|
36
|
-
"""
|
37
|
-
if is_asterisk(feature):
|
38
|
-
featureset_name = feature.name.lower().split(".")[0]
|
39
|
-
|
40
|
-
p = f"^{featureset_name}+.*$"
|
41
|
-
feature_names = [
|
42
|
-
feature.lower()
|
43
|
-
for feature in offline_fs.get_columns_by_feature_set(featureset_name)
|
44
|
-
if re.match(p, feature.lower())
|
45
|
-
]
|
46
|
-
return [dataclasses.replace(feature, name=name) for name in feature_names]
|
47
|
-
|
48
|
-
return [feature]
|
49
|
-
|
50
|
-
|
51
|
-
def unpack_asterisk_features(
|
52
|
-
features: List[BaseFeature],
|
53
|
-
feature_store_generator: Callable[[], OfflineClient] = lambda: OfflineClient(),
|
54
|
-
) -> List[BaseFeature]:
|
55
|
-
"""
|
56
|
-
Handles features with an '*'.
|
57
|
-
If a feature of type FeatureStoreInput that matches '<featureset_name>.*' exists,
|
58
|
-
transforms this feature into the list of features actually present in the FeatureSet.
|
59
|
-
Other features remain unchanged.
|
60
|
-
the original order is maintained, and the internal order (inside a FeatureStoreInput
|
61
|
-
that has an '*') is inferred from the order of columns returned from
|
62
|
-
OfflineFeatureStore.get_columns_by_feature_set(...)
|
63
|
-
Args:
|
64
|
-
features: List of features
|
65
|
-
feature_store_generator: A function that generates an instance of OfflineFeatureStore
|
66
|
-
If no feature with an '*' is found, the function is not called.
|
67
|
-
|
68
|
-
Returns:
|
69
|
-
the unpacked features
|
70
|
-
"""
|
71
|
-
asterisk_found = any([is_asterisk(f) for f in features])
|
72
|
-
if asterisk_found:
|
73
|
-
# at least 1 feature contains an asterisk, map each feature to
|
74
|
-
# a list of features (features with no '*' are mapped to a list of size 1), then flatten it.
|
75
|
-
offline_feature_store = feature_store_generator()
|
76
|
-
inflated_features = [
|
77
|
-
inflate_feature(feature, offline_feature_store) for feature in features
|
78
|
-
]
|
79
|
-
return list(itertools.chain.from_iterable(inflated_features))
|
80
|
-
|
81
|
-
return features
|
82
|
-
|
83
|
-
|
84
|
-
def unpack_asterisk_features_from_key_mapping(
|
85
|
-
key_to_features: Dict[str, List[str]],
|
86
|
-
feature_store_generator: Callable[[], OfflineClient] = lambda: OfflineClient(),
|
87
|
-
) -> dict:
|
88
|
-
"""
|
89
|
-
Handles features with an '*'.
|
90
|
-
If a feature name that matches '<featureset_name>.*' exists in one of the lists,
|
91
|
-
transforms this feature into the list of feature names actually present in the FeatureSet.
|
92
|
-
Other features remain unchanged.
|
93
|
-
the original order is maintained, and the internal order (inside a feature
|
94
|
-
that has an '*') is inferred from the order of columns returned from
|
95
|
-
OfflineFeatureStore.get_columns_by_feature_set(...)
|
96
|
-
Args:
|
97
|
-
key_to_features: dictionary of entity keys to requested features (same as in the offline store)
|
98
|
-
>>> key_to_features = {'uuid': ['user_purchases.*',
|
99
|
-
>>> 'user_purchases.avg_purchase_amount']}
|
100
|
-
feature_store_generator: A function that generates an instance of OfflineFeatureStore
|
101
|
-
If no feature with an '*' is found, the function is not called.
|
102
|
-
Returns:
|
103
|
-
the unpacked features
|
104
|
-
"""
|
105
|
-
inflated_key_to_features = {}
|
106
|
-
|
107
|
-
for entity, features in key_to_features.items():
|
108
|
-
feature_inputs = [
|
109
|
-
FeatureStoreInput(name=feature, entity=Entity(name=entity, type=str))
|
110
|
-
for feature in features
|
111
|
-
]
|
112
|
-
unpacked = unpack_asterisk_features(feature_inputs, feature_store_generator)
|
113
|
-
feature_list = [feature.name for feature in unpacked]
|
114
|
-
inflated_key_to_features[entity] = feature_list
|
115
|
-
return inflated_key_to_features
|
@@ -1,32 +0,0 @@
|
|
1
|
-
import uuid
|
2
|
-
from abc import ABC, abstractmethod
|
3
|
-
|
4
|
-
import pandas as pd
|
5
|
-
|
6
|
-
|
7
|
-
class BaseQueryEngine(ABC):
|
8
|
-
@abstractmethod
|
9
|
-
def upload_table(self, df: pd.DataFrame):
|
10
|
-
pass
|
11
|
-
|
12
|
-
@abstractmethod
|
13
|
-
def cleanup(self):
|
14
|
-
pass
|
15
|
-
|
16
|
-
@abstractmethod
|
17
|
-
def run_query(self, query: str):
|
18
|
-
pass
|
19
|
-
|
20
|
-
@abstractmethod
|
21
|
-
def read_pandas_from_query(self, query: str, parse_dates=None):
|
22
|
-
pass
|
23
|
-
|
24
|
-
@staticmethod
|
25
|
-
@abstractmethod
|
26
|
-
def get_quotes():
|
27
|
-
pass
|
28
|
-
|
29
|
-
class JoinTableSpec:
|
30
|
-
def __init__(self, join_tables_db_name: str, quotes: str):
|
31
|
-
self.table_name = str(uuid.uuid4())
|
32
|
-
self.join_table_full_path = f"{quotes}{join_tables_db_name}{quotes}.{quotes}{self.table_name}{quotes}"
|
File without changes
|