qwak-core 0.4.246__py3-none-any.whl → 0.4.248__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 (26) hide show
  1. _qwak_proto/qwak/service_discovery/service_discovery_location_pb2.py +65 -0
  2. _qwak_proto/qwak/service_discovery/service_discovery_location_pb2.pyi +73 -0
  3. _qwak_proto/qwak/service_discovery/service_discovery_location_pb2_grpc.py +4 -0
  4. _qwak_proto/qwak/service_discovery/service_discovery_location_service_pb2.py +49 -0
  5. _qwak_proto/qwak/service_discovery/service_discovery_location_service_pb2.pyi +41 -0
  6. _qwak_proto/qwak/service_discovery/service_discovery_location_service_pb2_grpc.py +231 -0
  7. qwak/__init__.py +1 -1
  8. qwak/clients/feature_store/offline_serving_client.py +29 -4
  9. qwak/clients/location_discovery/__init__.py +1 -0
  10. qwak/clients/location_discovery/client.py +73 -0
  11. qwak/feature_store/_common/functions.py +0 -19
  12. qwak/feature_store/offline/__init__.py +1 -2
  13. qwak/inner/model_loggers_utils.py +8 -20
  14. qwak/model_loggers/artifact_logger.py +7 -2
  15. qwak/model_loggers/data_logger.py +11 -6
  16. {qwak_core-0.4.246.dist-info → qwak_core-0.4.248.dist-info}/METADATA +1 -1
  17. {qwak_core-0.4.246.dist-info → qwak_core-0.4.248.dist-info}/RECORD +21 -17
  18. qwak_services_mock/mocks/location_discovery_service_api.py +104 -0
  19. qwak_services_mock/mocks/qwak_mocks.py +4 -0
  20. qwak_services_mock/services_mock.py +13 -0
  21. qwak/feature_store/_common/featureset_asterisk_handler.py +0 -115
  22. qwak/feature_store/offline/_query_engine.py +0 -32
  23. qwak/feature_store/offline/athena/__init__.py +0 -0
  24. qwak/feature_store/offline/athena/athena_query_engine.py +0 -153
  25. qwak/feature_store/offline/client.py +0 -718
  26. {qwak_core-0.4.246.dist-info → qwak_core-0.4.248.dist-info}/WHEEL +0 -0
@@ -4,7 +4,6 @@ from typing import Optional
4
4
 
5
5
  import requests
6
6
 
7
- from _qwak_proto.qwak.builds.builds_orchestrator_service_pb2 import AuthenticationDetail
8
7
  from qwak.clients.model_management.client import ModelsManagementClient
9
8
  from qwak.exceptions import QwakException
10
9
 
@@ -69,33 +68,22 @@ def fetch_build_id() -> Optional[str]:
69
68
  def upload_data(
70
69
  upload_url: str,
71
70
  data: bytes,
72
- authentication_details: Optional[AuthenticationDetail],
71
+ headers: dict,
73
72
  content_type: str = "text/plain",
74
- ) -> None:
73
+ ):
75
74
  """
76
75
  Upload data
77
- Args:
78
- upload_url: the url to upload to.
79
- data: the data to upload
80
- authentication_details: authentication details for upload data
81
- content_type: Uploaded content-type
76
+ :param upload_url: the url to upload to.
77
+ :param data: the data to upload
78
+ :param headers: authentication details for upload data
79
+ :param content_type: Uploaded content-type
82
80
  """
83
81
  try:
84
- auth = None
85
- if (
86
- authentication_details.WhichOneof("integration_type")
87
- == "jfrog_authentication_detail"
88
- ):
89
- auth = (
90
- authentication_details.jfrog_authentication_detail.username,
91
- authentication_details.jfrog_authentication_detail.token,
92
- )
93
-
82
+ headers["Content-Type"] = content_type
94
83
  http_response = requests.put( # nosec B113
95
84
  upload_url,
96
85
  data=data,
97
- headers={"content-type": content_type},
98
- auth=auth,
86
+ headers=headers,
99
87
  )
100
88
 
101
89
  if http_response.status_code not in [200, 201]:
@@ -2,6 +2,9 @@ import urllib.request
2
2
  from typing import Optional
3
3
 
4
4
  from _qwak_proto.qwak.builds.build_url_pb2 import BuildVersioningTagsType
5
+ from _qwak_proto.qwak.builds.builds_orchestrator_service_pb2 import (
6
+ GetBuildVersioningUploadURLResponse,
7
+ )
5
8
  from qwak.clients.build_orchestrator.client import BuildOrchestratorClient
6
9
  from qwak.clients.file_versioning.client import FileVersioningManagementClient
7
10
  from qwak.exceptions import QwakException
@@ -38,7 +41,9 @@ def log_file(
38
41
  # Checking if called inside a model - then build id saved as environment variable or stays
39
42
  build_id = fetch_build_id()
40
43
 
41
- upload_url_response = BuildOrchestratorClient().get_build_versioning_upload_url(
44
+ upload_url_response: (
45
+ GetBuildVersioningUploadURLResponse
46
+ ) = BuildOrchestratorClient().get_build_versioning_upload_url(
42
47
  build_id=build_id,
43
48
  model_id=model_id,
44
49
  tag=tag,
@@ -53,7 +58,7 @@ def log_file(
53
58
  upload_data(
54
59
  upload_url_response.upload_url,
55
60
  f.read(),
56
- upload_url_response.authentication_detail,
61
+ upload_url_response.headers,
57
62
  )
58
63
 
59
64
 
@@ -12,6 +12,9 @@ from _qwak_proto.qwak.builds.build_pb2 import (
12
12
  DataTableDefinition,
13
13
  )
14
14
  from _qwak_proto.qwak.builds.build_url_pb2 import BuildVersioningTagsType
15
+ from _qwak_proto.qwak.builds.builds_orchestrator_service_pb2 import (
16
+ GetBuildVersioningUploadURLResponse,
17
+ )
15
18
  from qwak.clients.build_orchestrator.client import BuildOrchestratorClient
16
19
  from qwak.clients.data_versioning.client import DataVersioningManagementClient
17
20
  from qwak.exceptions import QwakException
@@ -63,11 +66,13 @@ def log_data(
63
66
  build_id = fetch_build_id()
64
67
 
65
68
  client = BuildOrchestratorClient()
66
- upload_url_response = client.get_build_versioning_upload_url(
67
- build_id=build_id,
68
- model_id=model_id,
69
- tag=str(data_tag),
70
- tag_type=BuildVersioningTagsType.DATA_TAG_TYPE,
69
+ upload_url_response: GetBuildVersioningUploadURLResponse = (
70
+ client.get_build_versioning_upload_url(
71
+ build_id=build_id,
72
+ model_id=model_id,
73
+ tag=str(data_tag),
74
+ tag_type=BuildVersioningTagsType.DATA_TAG_TYPE,
75
+ )
71
76
  )
72
77
 
73
78
  string_buffer = StringIO()
@@ -76,7 +81,7 @@ def log_data(
76
81
  upload_url=upload_url_response.upload_url,
77
82
  data=gzip.compress(bytes(string_buffer.getvalue(), "utf-8")),
78
83
  content_type="text/plain",
79
- authentication_details=upload_url_response.authentication_detail,
84
+ headers=upload_url_response.headers,
80
85
  )
81
86
 
82
87
  dataframe_definition = DataTableDefinition(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: qwak-core
3
- Version: 0.4.246
3
+ Version: 0.4.248
4
4
  Summary: Qwak Core contains the necessary objects and communication tools for using the Qwak Platform
5
5
  License: Apache-2.0
6
6
  Keywords: mlops,ml,deployment,serving,model
@@ -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=NI8Z0miVc9RaYzA7QH7AlrhoEjQOmUcaFlF7EcOmxO0,587
585
+ qwak/__init__.py,sha256=5N6mBzO1DFCpFv6gezURZqEuGMsOSAcu57c6E9MIo7g,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=0E9LzBcz2NOcxzAhtUZDnoX3LR5maXQBJ8d5vH8rpaY,8473
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/featureset_asterisk_handler.py,sha256=82X-h26hGDMM4dvgcXyNRsvoaGW8Ef6iJTovBLHDE3M,4707
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=on-3Twm3-THTeYXEuVHMZVd2sgVGVChtzvqzSJyO_4I,173
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
@@ -828,7 +831,7 @@ qwak/inner/di_configuration/containers.py,sha256=1Vvs_p5laNcduDWH47dZpJJa2xu3v5P
828
831
  qwak/inner/di_configuration/session.py,sha256=Pwqapcu-0dsbb5dDn7ZGewVk4bYRN9sWk6ity72IDqY,452
829
832
  qwak/inner/instance_template/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
830
833
  qwak/inner/instance_template/verify_template_id.py,sha256=-c0Fh89XAfphKCpkurYaD-YyX3M3NkkpSLH4QsNPyko,1916
831
- qwak/inner/model_loggers_utils.py,sha256=egsXQMfBTqsHZxNJq8cTGrFCS_Gxobni6xEfNTeupBE,2933
834
+ qwak/inner/model_loggers_utils.py,sha256=irVEuNYlMefINR8N5UiD9IcO8fzdcuc8jBbBzNzKC7M,2441
832
835
  qwak/inner/provider.py,sha256=3evQnyp0v0enpvGGDyaZziusO4BGi-U9j1sno8DAHo4,70
833
836
  qwak/inner/runtime_di/__init__.py,sha256=ylaHwo2Hlq3pmeziA0Ip87DMnkcuBffKKi0tTH7gYVI,281
834
837
  qwak/inner/runtime_di/containers.py,sha256=-AREM-IUAd9JhrhQablqixxpj4L9Tk1iQkK1fA5YbrA,545
@@ -958,8 +961,8 @@ qwak/model/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,
958
961
  qwak/model/utils/extract_wrapped_function.py,sha256=uIle1zL8vbmeS3PGAuaNFLIUQAsvpuzk3LlH-Teba94,320
959
962
  qwak/model/utils/feature_utils.py,sha256=jB4pfmhqN2_B4THR7YADlCWbymU3cm_8u2RzTegrv_w,2389
960
963
  qwak/model_loggers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
961
- qwak/model_loggers/artifact_logger.py,sha256=CZHTe-WO6Ov4WRYR6yVw5BuNSI0NFi-TUS117c4JQ1Y,2938
962
- qwak/model_loggers/data_logger.py,sha256=4eSfcsfnG_EvIRRX6Zj1tI-SfSOYUWCnR9naW7AzVT4,5472
964
+ qwak/model_loggers/artifact_logger.py,sha256=E5A9MaGD4bDAWlj7cuc5f9Pzet9_p5jgkGuoZiVn1B0,3090
965
+ qwak/model_loggers/data_logger.py,sha256=aTRnRwKmKUFZq9SRg4sY-b1yGDY2XB-pExlQ0WlcH0k,5629
963
966
  qwak/model_loggers/model_logger.py,sha256=WxKLEpfzDaRn3kanrI0kj4zqqKQrwT2sin1IS1WNEA8,852
964
967
  qwak/qwak_client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
965
968
  qwak/qwak_client/batch_jobs/execution.py,sha256=L0CjS6BuEsPGJbQ4_yV75FsIx-jvdUg8DirYdH6ddFQ,1757
@@ -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=vfn1f608tvTcYjo8hioiXR8_Zxg7paCkPN7abukOJdw,5969
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=CABZ2teXoSJ-X7CD3iRo5ht-w3jhW-Cvpb47APUHXEA,19089
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.246.dist-info/METADATA,sha256=HOEV8pRohcWvk7huZnH3R9NpzwIT5pLppjfhfr2bc2I,2150
1056
- qwak_core-0.4.246.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
1057
- qwak_core-0.4.246.dist-info/RECORD,,
1059
+ qwak_core-0.4.248.dist-info/METADATA,sha256=V-53JLVMprm3wnTnnPBpn2DWt5N4PpJ33JR0muYz4Sc,2150
1060
+ qwak_core-0.4.248.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
1061
+ qwak_core-0.4.248.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