sapiopycommons 2025.7.22a645__py3-none-any.whl → 2025.7.23a659__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 sapiopycommons might be problematic. Click here for more details.

@@ -435,24 +435,23 @@ class ProtobufUtils:
435
435
  )
436
436
 
437
437
  @staticmethod
438
- def field_pbo_to_value(field: Any, value: FieldValuePbo) -> FieldValue:
438
+ def field_pbo_to_value(value: FieldValuePbo) -> FieldValue:
439
439
  """
440
- Convert a StepRecordFieldValue to its corresponding Python value based on the field type.
440
+ Convert a StepRecordFieldValue to its corresponding Python value.
441
441
 
442
- :param field: The VeloxFieldDefPbo or FieldTypePbo object for the given value.
443
442
  :param value: The StepRecordFieldValue object.
444
443
  :return: The corresponding Python value.
445
444
  """
446
- field_type = field.data_field_type if hasattr(field, "data_field_type") else field
447
- match field_type:
448
- case FieldTypePbo.BOOLEAN:
449
- return value.bool_value
450
- case FieldTypePbo.DOUBLE:
451
- return value.double_value
452
- case FieldTypePbo.ENUM | FieldTypePbo.INTEGER | FieldTypePbo.LONG | FieldTypePbo.SHORT:
453
- return value.int_value
454
- case _:
455
- return value.string_value
445
+ if value.HasField("string_value"):
446
+ return value.string_value
447
+ elif value.HasField("int_value"):
448
+ return value.int_value
449
+ elif value.HasField("double_value"):
450
+ return value.double_value
451
+ elif value.HasField("bool_value"):
452
+ return value.bool_value
453
+ else:
454
+ return None
456
455
 
457
456
  @staticmethod
458
457
  def field_def_pbo_to_default_value(field_def: VeloxFieldDefPbo) -> FieldValue:
@@ -10,9 +10,11 @@ from sapiopycommons.ai.api.plan.tool.proto.entry_pb2 import DataTypePbo, StepBin
10
10
  StepCsvHeaderRowPbo, StepCsvContainerPbo, StepJsonContainerPbo, StepImageContainerPbo, StepTextContainerPbo, \
11
11
  StepItemContainerPbo, StepInputBatchPbo
12
12
  from sapiopycommons.ai.api.plan.tool.proto.tool_pb2 import ProcessStepResponsePbo, ProcessStepRequestPbo, \
13
- ToolDetailsRequestPbo, ToolDetailsResponsePbo
13
+ ToolDetailsRequestPbo, ToolDetailsResponsePbo, ProcessStepResponseStatusPbo
14
14
  from sapiopycommons.ai.api.plan.tool.proto.tool_pb2_grpc import ToolServiceStub
15
15
  from sapiopycommons.ai.api.session.proto.sapio_conn_info_pb2 import SapioConnectionInfoPbo, SapioUserSecretTypePbo
16
+ from sapiopycommons.ai.protobuf_utils import ProtobufUtils
17
+ from sapiopycommons.general.aliases import FieldValue
16
18
 
17
19
 
18
20
  # FR-47422: Created class.
@@ -23,13 +25,16 @@ class ToolOutput:
23
25
  """
24
26
  tool_name: str
25
27
 
28
+ status: str
29
+ message: str
30
+
26
31
  binary_output: list[bytes]
27
32
  csv_output: list[dict[str, Any]]
28
33
  json_output: list[Any]
29
34
  image_output: list[bytes]
30
35
  text_output: list[str]
31
36
 
32
- new_records: list[Mapping[str, FieldValuePbo]]
37
+ new_records: list[dict[str, FieldValue]]
33
38
 
34
39
  logs: list[str]
35
40
 
@@ -45,29 +50,38 @@ class ToolOutput:
45
50
 
46
51
  def __str__(self):
47
52
  ret_val: str = f"{self.tool_name} Output:\n"
53
+ ret_val += f"\tStatus: {self.status}\n"
54
+ ret_val += f"\tMessage: {self.message}\n"
48
55
  ret_val += "-" * 25 + "\n"
56
+
49
57
  ret_val += f"Binary Output: {len(self.binary_output)} item(s)\n"
50
58
  for binary in self.binary_output:
51
59
  ret_val += f"\t{len(binary)} byte(s)\n"
52
60
  ret_val += f"\t{binary[:50]}...\n"
61
+
53
62
  ret_val += f"CSV Output: {len(self.csv_output)} item(s)\n"
54
63
  if self.csv_output:
55
64
  ret_val += f"\tHeaders: {', '.join(self.csv_output[0].keys())}\n"
56
65
  for i, csv_row in enumerate(self.csv_output):
57
66
  ret_val += f"\t{i}: {', '.join(f'{v}' for k, v in csv_row.items())}\n"
67
+
58
68
  ret_val += f"JSON Output: {len(self.json_output)} item(s)\n"
59
69
  if self.json_output:
60
- ret_val += f"\t{json.dumps(self.json_output, indent=2)}\n"
70
+ ret_val += f"{json.dumps(self.json_output, indent=2)}\n"
71
+
61
72
  ret_val += f"Image Output: {len(self.image_output)} item(s)\n"
62
73
  for image in self.image_output:
63
74
  ret_val += f"\t{len(image)} bytes\n"
64
75
  ret_val += f"\t{image[:50]}...\n"
76
+
65
77
  ret_val += f"Text Output: {len(self.text_output)} item(s)\n"
66
78
  for text in self.text_output:
67
- ret_val += f"\t{text}...\n"
79
+ ret_val += f"\t{text}\n"
80
+
68
81
  ret_val += f"New Records: {len(self.new_records)} item(s)\n"
69
82
  for record in self.new_records:
70
- ret_val += f"\t{json.dumps(record, indent=2)}\n"
83
+ ret_val += f"{json.dumps(record, indent=2)}\n"
84
+
71
85
  ret_val += f"Logs: {len(self.logs)} item(s)\n"
72
86
  for log in self.logs:
73
87
  ret_val += f"\t{log}\n"
@@ -215,12 +229,13 @@ class TestClient:
215
229
  stub = ToolServiceStub(channel)
216
230
  return stub.GetToolDetails(ToolDetailsRequestPbo(sapio_conn_info=self.connection))
217
231
 
218
- def call_tool(self, tool_name: str) -> ToolOutput:
232
+ def call_tool(self, tool_name: str, is_dry_run: bool = False) -> ToolOutput:
219
233
  """
220
234
  Send the request to the tool service for a particular tool name. This will send all the inputs that have been
221
235
  added using the add_X_input functions.
222
236
 
223
237
  :param tool_name: The name of the tool to call on the server.
238
+ :param is_dry_run: If True, the tool will not be executed, but the request will be validated.
224
239
  :return: A ToolOutput object containing the results of the tool service call.
225
240
  """
226
241
  with grpc.insecure_channel(self.grpc_server_url) as channel:
@@ -231,6 +246,8 @@ class TestClient:
231
246
  sapio_user=self.connection,
232
247
  tool_name=tool_name,
233
248
  config_field_values=self._config_fields,
249
+ dry_run=is_dry_run,
250
+ verbose_logging=True,
234
251
  input=[
235
252
  StepInputBatchPbo(is_partial=False, item_container=item)
236
253
  for item in self._request_inputs
@@ -239,6 +256,16 @@ class TestClient:
239
256
  )
240
257
 
241
258
  results = ToolOutput(tool_name)
259
+
260
+ match response.status:
261
+ case ProcessStepResponseStatusPbo.SUCCESS:
262
+ results.status = "Success"
263
+ case ProcessStepResponseStatusPbo.FAILURE:
264
+ results.status = "Failure"
265
+ case _:
266
+ results.status = "Unknown"
267
+ results.message = response.status_message
268
+
242
269
  for item in response.output:
243
270
  container = item.item_container
244
271
 
@@ -253,7 +280,8 @@ class TestClient:
253
280
  results.text_output.extend(container.text_container.items)
254
281
 
255
282
  for record in response.new_records:
256
- results.new_records.append(record.fields)
283
+ field_map: dict[str, Any] = {x: ProtobufUtils.field_pbo_to_value(y) for x, y in record.fields.items()}
284
+ results.new_records.append(field_map)
257
285
 
258
286
  results.logs.extend(response.log)
259
287
 
@@ -893,7 +893,7 @@ class ToolBase(ABC):
893
893
  if field_name not in raw_configs:
894
894
  config_fields[field_name] = ProtobufUtils.field_def_pbo_to_default_value(field_def)
895
895
  else:
896
- config_fields[field_name] = ProtobufUtils.field_pbo_to_value(field_def, raw_configs[field_name])
896
+ config_fields[field_name] = ProtobufUtils.field_pbo_to_value(raw_configs[field_name])
897
897
  return config_fields
898
898
 
899
899
  @staticmethod
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: sapiopycommons
3
- Version: 2025.7.22a645
3
+ Version: 2025.7.23a659
4
4
  Summary: Official Sapio Python API Utilities Package
5
5
  Project-URL: Homepage, https://github.com/sapiosciences
6
6
  Author-email: Jonathan Steck <jsteck@sapiosciences.com>, Yechen Qiao <yqiao@sapiosciences.com>
@@ -1,8 +1,8 @@
1
1
  sapiopycommons/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  sapiopycommons/ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- sapiopycommons/ai/protobuf_utils.py,sha256=8VYGhAdD731Ojy5PTy61PlTcvfEdydkIdX-4rOFPtxM,24911
4
- sapiopycommons/ai/test_client.py,sha256=d5P01dUNRKpEgTENZQoIHUvPE0nEut5D9upT5txQWB8,11173
5
- sapiopycommons/ai/tool_service_base.py,sha256=8SvmxWyu2nKeRjtq5qNAizL-lnfURr4Cbuw4K7hpWxs,41947
3
+ sapiopycommons/ai/protobuf_utils.py,sha256=C0e5NIr4eodfAkUm9QciKe7AT4hBlnJFDdChBJOMxVo,24669
4
+ sapiopycommons/ai/test_client.py,sha256=BEA6RQRBmHPdshmP7bI0fhoEsGPGlUB0ae095YPggGg,12141
5
+ sapiopycommons/ai/tool_service_base.py,sha256=nAMy3Ch4juCTm3FQI6TAo3oDepOaR89j9bUJ8lNO3lM,41936
6
6
  sapiopycommons/ai/api/fielddefinitions/proto/fields_pb2.py,sha256=YcZjb_YM-XeLErM8hEC_S7vGMVGvcXAMGs2b-u5zvOE,2377
7
7
  sapiopycommons/ai/api/fielddefinitions/proto/fields_pb2.pyi,sha256=FwtXmNAf7iYGEFm4kbqb04v77jNHbZg18ZmEDhle_bU,1444
8
8
  sapiopycommons/ai/api/fielddefinitions/proto/fields_pb2_grpc.py,sha256=wPImJPdCUZNVEVoUWzsba9kGIXjEKPdUkawP5SnVyiU,932
@@ -90,7 +90,7 @@ sapiopycommons/webhook/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
90
90
  sapiopycommons/webhook/webhook_context.py,sha256=D793uLsb1691SalaPnBUk3rOSxn_hYLhdvkaIxjNXss,1909
91
91
  sapiopycommons/webhook/webhook_handlers.py,sha256=7o_wXOruhT9auNh8OfhJAh4WhhiPKij67FMBSpGPICc,39939
92
92
  sapiopycommons/webhook/webservice_handlers.py,sha256=cvW6Mk_110BzYqkbk63Kg7jWrltBCDALOlkJRu8h4VQ,14300
93
- sapiopycommons-2025.7.22a645.dist-info/METADATA,sha256=3xkEPFb_VlBP8y6_6kkFX3J2HNMmwibStcVQUQs-uCk,3143
94
- sapiopycommons-2025.7.22a645.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
95
- sapiopycommons-2025.7.22a645.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
96
- sapiopycommons-2025.7.22a645.dist-info/RECORD,,
93
+ sapiopycommons-2025.7.23a659.dist-info/METADATA,sha256=T5mZ0vKZqHkUwtjKVc9Mlxj5eGLfrpPgcU-cwKUMUok,3143
94
+ sapiopycommons-2025.7.23a659.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
95
+ sapiopycommons-2025.7.23a659.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
96
+ sapiopycommons-2025.7.23a659.dist-info/RECORD,,