qwak-sdk 0.5.24__py3-none-any.whl → 0.5.26__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-sdk might be problematic. Click here for more details.

qwak_sdk/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  # fmt: off
2
2
  __author__ = '''Qwak.ai'''
3
- __version__ = '0.5.24'
3
+ __version__ = '0.5.26'
4
4
 
5
5
  from qwak.inner import wire_dependencies
6
6
 
@@ -2,6 +2,7 @@ from typing import List, Optional, Tuple
2
2
 
3
3
  from _qwak_proto.qwak.feature_store.features.feature_set_pb2 import Feature
4
4
  from _qwak_proto.qwak.features_operator.v3.features_operator_pb2 import (
5
+ Outputs,
5
6
  SparkColumnDescription,
6
7
  ValidationSuccessResponse,
7
8
  )
@@ -129,6 +130,7 @@ def _handle_data_source_validation(
129
130
 
130
131
  response = getattr(result, result.WhichOneof("type"))
131
132
  if isinstance(response, ValidationSuccessResponse):
133
+ print_validation_outputs(response)
132
134
  print("✅ Validation completed successfully, got data source columns:")
133
135
 
134
136
  table = [
@@ -219,6 +221,7 @@ def _handle_batch_v1_feature_set_validation(
219
221
 
220
222
  response = getattr(result, result.WhichOneof("type"))
221
223
  if isinstance(response, ValidationSuccessResponse):
224
+ print_validation_outputs(response)
222
225
  print("✅ Validation completed successfully, got data source columns:")
223
226
  table = [
224
227
  (x.column_name, x.spark_type) for x in response.spark_column_description
@@ -288,3 +291,22 @@ def _batch_v1_feature_set_validation(
288
291
  else:
289
292
  print(f"Skipping validation for '{feature_set.name}' feature set")
290
293
  return spark_columns_features
294
+
295
+
296
+ def print_validation_outputs(response: ValidationSuccessResponse) -> bool:
297
+ did_print = False
298
+ outputs = response.outputs
299
+
300
+ if isinstance(outputs, Outputs) and (outputs.stdout or outputs.stderr):
301
+ message = "Validation outputs: "
302
+
303
+ if outputs.stdout:
304
+ message += f"stdout: {outputs.stdout}\n "
305
+
306
+ if outputs.stderr:
307
+ message += f"stderr: {outputs.stderr}"
308
+
309
+ print(message)
310
+ did_print = True
311
+
312
+ return did_print
@@ -2,6 +2,7 @@ from dataclasses import dataclass, field
2
2
  from os.path import expandvars
3
3
  from typing import Dict, List, Optional, Tuple, Union
4
4
 
5
+ from _qwak_proto.qwak.builds.build_pb2 import BaseDockerImageType
5
6
  from _qwak_proto.qwak.builds.builds_pb2 import (
6
7
  BuildConfiguration,
7
8
  BuildEnvironment,
@@ -16,10 +17,9 @@ from _qwak_proto.qwak.builds.builds_pb2 import (
16
17
  Step,
17
18
  VirtualEnvironmentBuild,
18
19
  )
20
+ from _qwak_proto.qwak.instance_template.instance_template_pb2 import InstanceType
19
21
  from qwak.clients.build_orchestrator import BuildOrchestratorClient
20
22
  from qwak.clients.instance_template.client import InstanceTemplateManagementClient
21
- from _qwak_proto.qwak.builds.build_pb2 import BaseDockerImageType
22
- from _qwak_proto.qwak.instance_template.instance_template_pb2 import InstanceType
23
23
  from qwak.inner.tool.run_config import (
24
24
  QwakConfigBase,
25
25
  YamlConfigMixin,
@@ -32,6 +32,7 @@ from qwak.inner.tool.run_config import (
32
32
 
33
33
  from qwak_sdk.commands.models.build._logic.util.protobuf_factory import protobuf_factory
34
34
  from qwak_sdk.common.run_config import ConfigCliMap
35
+ from qwak_sdk.common.run_config.utils import purchase_option_validation
35
36
 
36
37
  CONFIG_MAPPING: List[ConfigCliMap] = [
37
38
  # ConfigV1
@@ -97,6 +98,7 @@ CONFIG_MAPPING: List[ConfigCliMap] = [
97
98
  ConfigCliMap("verbose", "verbose", validate_int),
98
99
  ConfigCliMap("deploy", "deploy", validate_bool),
99
100
  ConfigCliMap("deployment_instance", "deployment_instance", validate_string),
101
+ ConfigCliMap("purchase_option", "purchase_option", purchase_option_validation),
100
102
  ]
101
103
 
102
104
 
@@ -217,6 +219,7 @@ class ConfigV1(YamlConfigMixin, QwakConfigBase):
217
219
  step: Step = field(default_factory=Step)
218
220
  deploy: bool = field(default=False)
219
221
  deployment_instance: Optional[str] = field(default=None)
222
+ purchase_option: Optional[str] = field(default=None)
220
223
  verbose: int = field(default=0)
221
224
 
222
225
  def __post_init__(self):
@@ -235,19 +238,33 @@ class ConfigV1(YamlConfigMixin, QwakConfigBase):
235
238
  self.build_env.docker.env_vars = list(self.build_env.docker.env_vars)
236
239
  self.build_env.docker.params = list(self.build_env.docker.params)
237
240
 
238
- def fetch_base_docker_image_name(self, build_orchestrator: BuildOrchestratorClient, instance_template: InstanceTemplateManagementClient):
241
+ def fetch_base_docker_image_name(
242
+ self,
243
+ build_orchestrator: BuildOrchestratorClient,
244
+ instance_template: InstanceTemplateManagementClient,
245
+ ):
239
246
  if not self.build_env.docker.base_image:
240
- is_gpu_used = self.build_env.remote.resources.gpu_type \
241
- and self.build_env.remote.resources.gpu_amount \
242
- and self.build_env.remote.resources.gpu_amount > 0
247
+ is_gpu_used = (
248
+ self.build_env.remote.resources.gpu_type
249
+ and self.build_env.remote.resources.gpu_amount
250
+ and self.build_env.remote.resources.gpu_amount > 0
251
+ )
243
252
 
244
253
  if self.build_env.remote.resources.instance and not is_gpu_used:
245
- instance_spec = instance_template.get_instance_template(self.build_env.remote.resources.instance)
246
- is_gpu_used = instance_spec.instance_type == InstanceType.INSTANCE_TYPE_GPU
254
+ instance_spec = instance_template.get_instance_template(
255
+ self.build_env.remote.resources.instance
256
+ )
257
+ is_gpu_used = (
258
+ instance_spec.instance_type == InstanceType.INSTANCE_TYPE_GPU
259
+ )
247
260
 
248
261
  if is_gpu_used or self.build_properties.gpu_compatible:
249
- result = build_orchestrator.fetch_base_docker_image_name(BaseDockerImageType.GPU)
262
+ result = build_orchestrator.fetch_base_docker_image_name(
263
+ BaseDockerImageType.GPU
264
+ )
250
265
  self.build_env.docker.base_image = result.base_docker_image_name
251
266
  else:
252
- result = build_orchestrator.fetch_base_docker_image_name(BaseDockerImageType.CPU)
267
+ result = build_orchestrator.fetch_base_docker_image_name(
268
+ BaseDockerImageType.CPU
269
+ )
253
270
  self.build_env.docker.base_image = result.base_docker_image_name
@@ -201,6 +201,13 @@ from qwak_sdk.inner.tools.config_handler import config_handler
201
201
  help="The instance size to deploy on - 'small', 'medium', 'large', etc...",
202
202
  default=None,
203
203
  )
204
+ @click.option(
205
+ "--purchase-option",
206
+ required=False,
207
+ type=str,
208
+ help="The type of the instance to build on - 'ondemand' or 'spot'",
209
+ default=None,
210
+ )
204
211
  @click.argument("uri", required=False)
205
212
  def models_build(**kwargs):
206
213
  return build(**kwargs)
@@ -12,7 +12,7 @@ from qwak_sdk.commands.workspaces.config.workspace_config import WorkspaceConfig
12
12
 
13
13
  def _update_workspace(config: WorkspaceConfig):
14
14
  """
15
- Updating a new workspace
15
+ Updating a workspace
16
16
 
17
17
  Args:
18
18
  config: The workspace configuration
@@ -198,6 +198,40 @@ def validate_variation(value: Any) -> bool:
198
198
  return True
199
199
 
200
200
 
201
+ def purchase_option_validation(purchase_option: str, is_required: bool):
202
+ """Validate purchase option strings
203
+
204
+ Args:
205
+ purchase_option: the purchase option to validate.
206
+ is_required: True if value is required.
207
+
208
+ Returns:
209
+ bool: True if value is valid.
210
+
211
+ Examples:
212
+ >>> purchase_option_validation("spot", False)
213
+ True
214
+ >>> purchase_option_validation("ondemand", False)
215
+ True
216
+ >>> purchase_option_validation(None, False)
217
+ True
218
+ >>> purchase_option_validation("Ondemand", False)
219
+ False
220
+ """
221
+ if not purchase_option and not is_required:
222
+ return True
223
+ if purchase_option and (
224
+ not validate_string(purchase_option, False)
225
+ or purchase_option
226
+ not in [
227
+ "ondemand",
228
+ "spot",
229
+ ]
230
+ ):
231
+ return False
232
+ return True
233
+
234
+
201
235
  def validate_variations(value: Any, is_required: bool) -> bool:
202
236
  """Validate if value is a variation.
203
237
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: qwak-sdk
3
- Version: 0.5.24
3
+ Version: 0.5.26
4
4
  Summary: Qwak SDK and CLI for qwak models
5
5
  License: Apache-2.0
6
6
  Keywords: mlops,ml,deployment,serving,model
@@ -27,7 +27,7 @@ Requires-Dist: pandas (<1.4) ; (python_full_version >= "3.7.1" and python_versio
27
27
  Requires-Dist: pandas (>=1.4.3,<2.0.0) ; (python_version >= "3.8" and python_version < "3.10") and (extra == "batch" or extra == "feedback")
28
28
  Requires-Dist: pyarrow (>=6.0.0,<11.0.0) ; extra == "batch"
29
29
  Requires-Dist: python-json-logger (>=2.0.2)
30
- Requires-Dist: qwak-core (==0.0.212)
30
+ Requires-Dist: qwak-core (==0.0.217)
31
31
  Requires-Dist: qwak-inference (==0.1.8)
32
32
  Requires-Dist: tabulate (>=0.8.0)
33
33
  Requires-Dist: yaspin (>=2.0.0)
@@ -1,4 +1,4 @@
1
- qwak_sdk/__init__.py,sha256=piQZEtKNuGjuodFyerNkMl0e7vC_UHb5Eha_YOpRlrw,135
1
+ qwak_sdk/__init__.py,sha256=_sJYnhQp9CgmuCiUM6pYmC2oumKITETcHT0VqbeM-E8,135
2
2
  qwak_sdk/cli.py,sha256=FIK1dUNxR57ypb-CeD7fKSJnPJ02lrjR9G4aj2qMLPU,2458
3
3
  qwak_sdk/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  qwak_sdk/commands/_logic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -87,7 +87,7 @@ qwak_sdk/commands/feature_store/list/ui.py,sha256=NuXnQ3cdXSDCFAcC2jmgx4sAdjNuyI
87
87
  qwak_sdk/commands/feature_store/pause/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
88
88
  qwak_sdk/commands/feature_store/pause/ui.py,sha256=C89yl4ly-RpyZub30q5xV5g1UDnI_GmHSndvXAkXkw4,695
89
89
  qwak_sdk/commands/feature_store/register/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
90
- qwak_sdk/commands/feature_store/register/_logic.py,sha256=saR4ldU-pp-GEH3rVhgmALBvK3ywhtFZ6YWYZOIRh_o,10893
90
+ qwak_sdk/commands/feature_store/register/_logic.py,sha256=TYXaa1H4kn1bf5vgGJYtIlBx_arJQoZXLm2wlDmMF88,11472
91
91
  qwak_sdk/commands/feature_store/register/ui.py,sha256=WDtQ1V0WoPDir14mZ_N8_RDFZfe68QrtqLDlf64eNwY,2822
92
92
  qwak_sdk/commands/feature_store/resume/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
93
93
  qwak_sdk/commands/feature_store/resume/ui.py,sha256=nI87xvA30qNQVJnT67lYJgwKGBtvZAurC6XX9ttpCZA,700
@@ -108,7 +108,7 @@ qwak_sdk/commands/models/build/_logic/client_logs/notifier_impl.py,sha256=TLAvkm
108
108
  qwak_sdk/commands/models/build/_logic/client_logs/spinner.py,sha256=iph1eVC7QtSzNobNP2j_x0DC2k7bbka9eT8rcBpZGeQ,359
109
109
  qwak_sdk/commands/models/build/_logic/client_logs/time_source.py,sha256=UFio1BSAffLLWZh617nIj7YjwH2IUI9HkWheqrn9UxE,975
110
110
  qwak_sdk/commands/models/build/_logic/client_logs/utils.py,sha256=0VcMlmWHtOR1fR4JUDQTDqeQmi3tH3cG8pBZf5Hfusc,311
111
- qwak_sdk/commands/models/build/_logic/config/config_v1.py,sha256=cSbH33dV3TedtBIouFFHOMCkmKmsQr4PigzuhbxbjT8,10523
111
+ qwak_sdk/commands/models/build/_logic/config/config_v1.py,sha256=BJPzm5CaIg_xKioncUxxFkpvcno0KOHj2jAwZ7_krWs,10929
112
112
  qwak_sdk/commands/models/build/_logic/constant/host_resource.py,sha256=b3Bibo2v7bfDLYsMJsQJrkWQxOVMCboxuuvwBN-C8OI,131
113
113
  qwak_sdk/commands/models/build/_logic/constant/step_description.py,sha256=hrzWSNAjI_I_9iX3FTOIA_qjWDvWrhNjO3bueg1iaEY,881
114
114
  qwak_sdk/commands/models/build/_logic/constant/temp_dir.py,sha256=_tms51gfEZFGuQE4GmXOApi9OW7GeXPV_NBRVx2azkQ,73
@@ -145,7 +145,7 @@ qwak_sdk/commands/models/build/_logic/util/__init__.py,sha256=47DEQpj8HBSa-_TImW
145
145
  qwak_sdk/commands/models/build/_logic/util/protobuf_factory.py,sha256=ar_oY38w_x0sxgVF7EBs5h7gchNsDntvtKK5sSYxb24,1686
146
146
  qwak_sdk/commands/models/build/_logic/util/step_decorator.py,sha256=fSEn7_oVWcp-9R_h5JmFlqQMJjV5-ZUQgVzg3pDdoqs,1181
147
147
  qwak_sdk/commands/models/build/_logic/util/text.py,sha256=tH-v19Mt8l90sMVxku5XRtrderT0qdRqJ-jLijqannA,188
148
- qwak_sdk/commands/models/build/ui.py,sha256=z5lElqAy39Al1ozkKFJ4qYkjW6uJg1eGHOuQ8mYw9sg,6818
148
+ qwak_sdk/commands/models/build/ui.py,sha256=9R0QCAzpvmffDmFPKZ8uNGmflRaziN7QzAD3IG1Hvuc,6984
149
149
  qwak_sdk/commands/models/builds/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
150
150
  qwak_sdk/commands/models/builds/builds_commands_group.py,sha256=0nSfTY8TracXG61rFboQWUTXJisHO6dgtJKeijy6ru8,491
151
151
  qwak_sdk/commands/models/builds/cancel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -325,13 +325,13 @@ qwak_sdk/commands/workspaces/stop/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeR
325
325
  qwak_sdk/commands/workspaces/stop/_logic.py,sha256=3_dqIr_ae-GQvauykoIXlgBKl8roNesMrP9L8PJy3v4,1257
326
326
  qwak_sdk/commands/workspaces/stop/ui.py,sha256=XhuBoU7x1MrEDQcfQuxiuLEb2yQvbrDzlbcDBJ72nvk,599
327
327
  qwak_sdk/commands/workspaces/update/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
328
- qwak_sdk/commands/workspaces/update/_logic.py,sha256=tSxMOAGhTU0D9C-lbd49Ah7rEtf9eoEMeUXU9--gWMQ,2650
328
+ qwak_sdk/commands/workspaces/update/_logic.py,sha256=Xx-Fzqc95FeSEsE0e3hWjfeWriDBCPmaKPKLlJIfEAM,2646
329
329
  qwak_sdk/commands/workspaces/update/ui.py,sha256=pqS4SosS145ciZoIkFhW951Y_Ec86PKIldCiv3iEU8w,1515
330
330
  qwak_sdk/commands/workspaces/workspaces_commands_group.py,sha256=yuW-UC73J_vp-i4fILX90TAUrxaFocAmltBrRIg67lY,795
331
331
  qwak_sdk/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
332
332
  qwak_sdk/common/run_config/__init__.py,sha256=E73GRxqdEbTYsdd5EE7Wu4YXxTjxF4YkrBY_7-hZ4dU,437
333
333
  qwak_sdk/common/run_config/base.py,sha256=lbCl2DXBM90IXyLCFR2dUY35afwJlp9D4KgM8HP5_MQ,3166
334
- qwak_sdk/common/run_config/utils.py,sha256=g7HoOapU5Rog3lxZGmc5ZkiETmgmKN4YW0AJ7tdaiWQ,6087
334
+ qwak_sdk/common/run_config/utils.py,sha256=2WvNxPiNhdqXBK5FzDMWl4ersdD7rX7KSecc4LMRLZc,6960
335
335
  qwak_sdk/exceptions/__init__.py,sha256=wWO9G6LyuA2zP_vbH3DbeHKUNSoZw9xvWqQL-Bt9MhI,381
336
336
  qwak_sdk/exceptions/qwak_command_exception.py,sha256=R2gZ12PA-_32UcxbC19k6a0JJ1QVywjAfh8gMS3p2fE,48
337
337
  qwak_sdk/exceptions/qwak_deploy_new_build_failed.py,sha256=KhGraVwBYK8xE2ObPW-LMWjmBVPaaG4BTZETxxDyU_Y,133
@@ -355,7 +355,7 @@ qwak_sdk/tools/colors.py,sha256=7pui_GGjC4uZKYFsIyXaJjYsjLxJVHb4OrfTgr93hqo,287
355
355
  qwak_sdk/tools/files.py,sha256=AyKJTOy7NhvP3SrqwIw_lxYNCOy1CvLgMmSJpWZ0OKM,2257
356
356
  qwak_sdk/tools/log_handling.py,sha256=CC9XC3z3eHr_fehQgDsXZr4VP29VaMRwC05xvC5Wue4,5616
357
357
  qwak_sdk/tools/utils.py,sha256=SHmU4r_m2ABZyFYMC03P17GvltPbYbmB39hvalIZEtI,1168
358
- qwak_sdk-0.5.24.dist-info/entry_points.txt,sha256=vSl0ELYDyj640oMM57u0AjBP87wtLYxCcGOendhEx80,47
359
- qwak_sdk-0.5.24.dist-info/WHEEL,sha256=vVCvjcmxuUltf8cYhJ0sJMRDLr1XsPuxEId8YDzbyCY,88
360
- qwak_sdk-0.5.24.dist-info/METADATA,sha256=xgkhDuuwxYPcpkoQmBJ9NG4oCyqPlposFOM1vCudhKc,1852
361
- qwak_sdk-0.5.24.dist-info/RECORD,,
358
+ qwak_sdk-0.5.26.dist-info/entry_points.txt,sha256=vSl0ELYDyj640oMM57u0AjBP87wtLYxCcGOendhEx80,47
359
+ qwak_sdk-0.5.26.dist-info/WHEEL,sha256=vVCvjcmxuUltf8cYhJ0sJMRDLr1XsPuxEId8YDzbyCY,88
360
+ qwak_sdk-0.5.26.dist-info/METADATA,sha256=5i_ZdGveFUyeilkY7TbGbH-_zOmZijcYb2pKJxOBcPk,1852
361
+ qwak_sdk-0.5.26.dist-info/RECORD,,