sapiopycommons 2025.10.10a779__py3-none-any.whl → 2025.10.13a781__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.

@@ -1,5 +1,6 @@
1
1
  import base64
2
2
  import json
3
+ import os
3
4
  from enum import Enum
4
5
  from typing import Any
5
6
 
@@ -20,6 +21,7 @@ from sapiopycommons.ai.protoapi.plan.tool.tool_pb2_grpc import ToolServiceStub
20
21
  from sapiopycommons.ai.protoapi.session.sapio_conn_info_pb2 import SapioConnectionInfoPbo, SapioUserSecretTypePbo
21
22
  from sapiopycommons.ai.protobuf_utils import ProtobufUtils
22
23
  from sapiopycommons.general.aliases import FieldValue
24
+ from sapiopycommons.general.time_util import TimeUtil
23
25
 
24
26
 
25
27
  class ContainerType(Enum):
@@ -63,39 +65,42 @@ class AgentOutput:
63
65
  self.new_records = []
64
66
  self.logs = []
65
67
 
66
- def save_outputs(self, path: str = "test_outputs", file_extensions: list[str] | None = None) -> None:
68
+ def save_outputs(self, path: str = "test_outputs", subfolder: str | None = None, file_extensions: list[str] | None = None) -> None:
67
69
  """
68
- Save all outputs to files in the specified directory. The files will be named according to the agent name
69
- and the output type.
70
+ Save all outputs to files in the specified output directory.
70
71
 
71
72
  :param path: The directory to save the output files to.
73
+ :param subfolder: An optional subfolder within the path to save the output files to. Useful for when you are
74
+ calling the same agent multiple times for separate test cases.
72
75
  :param file_extensions: A list of file extensions to use for binary output files. The length of this list
73
76
  should match the number of binary outputs.
74
77
  """
75
78
  if not self:
76
79
  return
77
- import os
78
- os.makedirs(path, exist_ok=True)
79
- if self.binary_output and (not file_extensions or len(file_extensions) != len(self.binary_output)):
80
+ output_path: str = os.path.join(path, self.agent_name)
81
+ if subfolder:
82
+ output_path = os.path.join(output_path, subfolder)
83
+ os.makedirs(output_path, exist_ok=True)
84
+ if self.binary_output and (file_extensions is None or len(file_extensions) != len(self.binary_output)):
80
85
  raise ValueError("File extensions must be provided for each binary output.")
81
86
  for i, output in enumerate(self.binary_output):
82
87
  ext: str = "." + file_extensions[i].lstrip(".")
83
88
  for j, entry in enumerate(output):
84
- with open(os.path.join(path, self.agent_name, f"binary_output_{i}_{j}{ext}"), "wb") as f:
89
+ with open(os.path.join(output_path, f"binary_output_{i}_{j}{ext}"), "wb") as f:
85
90
  f.write(entry)
86
91
  for i, output in enumerate(self.csv_output):
87
- with open(os.path.join(path, self.agent_name, f"csv_output_{i}.csv"), "w", encoding="utf-8") as f:
92
+ with open(os.path.join(output_path, f"csv_output_{i}.csv"), "w", encoding="utf-8") as f:
88
93
  headers = output[0].keys()
89
94
  f.write(",".join(headers) + "\n")
90
95
  for row in output:
91
96
  f.write(",".join(f'"{str(row[h])}"' for h in headers) + "\n")
92
97
  for i, output in enumerate(self.json_output):
93
98
  for j, entry in enumerate(output):
94
- with open(os.path.join(path, self.agent_name, f"json_output_{i}_{j}.json"), "w", encoding="utf-8") as f:
99
+ with open(os.path.join(output_path, f"json_output_{i}_{j}.json"), "w", encoding="utf-8") as f:
95
100
  json.dump(entry, f, indent=2)
96
101
  for i, output in enumerate(self.text_output):
97
102
  for j, entry in enumerate(output):
98
- with open(os.path.join(path, self.agent_name, f"text_output_{i}_{j}.txt"), "w", encoding="utf-8") as f:
103
+ with open(os.path.join(output_path, f"text_output_{i}_{j}.txt"), "w", encoding="utf-8") as f:
99
104
  f.write(entry)
100
105
 
101
106
  def __bool__(self):
@@ -314,9 +319,11 @@ class TestClient:
314
319
  :param is_dry_run: If True, the agent will not be executed, but the request will be validated.
315
320
  :return: An AgentOutput object containing the results of the agent service call.
316
321
  """
322
+ print(f"Calling agent \"{agent_name}\"...")
317
323
  with grpc.insecure_channel(self.grpc_server_url, options=self.options) as channel:
318
324
  stub = ToolServiceStub(channel)
319
325
 
326
+ start = TimeUtil.now_in_millis()
320
327
  response: ProcessStepResponsePbo = stub.ProcessData(
321
328
  ProcessStepRequestPbo(
322
329
  sapio_user=self.connection,
@@ -330,6 +337,8 @@ class TestClient:
330
337
  ]
331
338
  )
332
339
  )
340
+ end = TimeUtil.now_in_millis()
341
+ print(f"Agent call completed in {(end - start) / 1000.:.3f} seconds")
333
342
 
334
343
  results = AgentOutput(agent_name)
335
344
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: sapiopycommons
3
- Version: 2025.10.10a779
3
+ Version: 2025.10.13a781
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>
@@ -6,7 +6,7 @@ sapiopycommons/ai/external_credentials.py,sha256=40AI7VtHf6PzvwJLR_mZemUCrfAUvC-
6
6
  sapiopycommons/ai/protobuf_utils.py,sha256=cBjbxoFAwU02kNUxEce95WnMU2CMuDD-qFaeWgvQJMQ,24599
7
7
  sapiopycommons/ai/request_validation.py,sha256=TD2EUi_G5cy1OOVK1AmY2SQc3PEoAKGWs2pT8Qnp2Oo,25092
8
8
  sapiopycommons/ai/server.py,sha256=gutSskn_Fenq1uz0DDMvjx4QVFiKt2WVEP3-01a69eU,6384
9
- sapiopycommons/ai/test_client.py,sha256=jHIKaBy2jta2UCcci6z0dvX_BZZuiV_0z2HPr9dEI_s,18897
9
+ sapiopycommons/ai/test_client.py,sha256=aiS58O_A3KSgRCzDT61iKyVXy9F4UY7xUyGQu5E7bTw,19432
10
10
  sapiopycommons/ai/protoapi/externalcredentials/external_credentials_pb2.py,sha256=mEonoj6Iq-AyvO4m3YsPYu85aZfD1E0a0cL8B9yPfEo,2481
11
11
  sapiopycommons/ai/protoapi/externalcredentials/external_credentials_pb2.pyi,sha256=sfExq8fFwIwFxCpV50ytdxW5ePNBjJBr_80_trq_JQw,1658
12
12
  sapiopycommons/ai/protoapi/externalcredentials/external_credentials_pb2_grpc.py,sha256=TNS1CB_QGBSa1YU9sYR_hF-pmBwv2GpxjaNQoM_r9iU,948
@@ -106,7 +106,7 @@ sapiopycommons/webhook/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
106
106
  sapiopycommons/webhook/webhook_context.py,sha256=D793uLsb1691SalaPnBUk3rOSxn_hYLhdvkaIxjNXss,1909
107
107
  sapiopycommons/webhook/webhook_handlers.py,sha256=7o_wXOruhT9auNh8OfhJAh4WhhiPKij67FMBSpGPICc,39939
108
108
  sapiopycommons/webhook/webservice_handlers.py,sha256=cvW6Mk_110BzYqkbk63Kg7jWrltBCDALOlkJRu8h4VQ,14300
109
- sapiopycommons-2025.10.10a779.dist-info/METADATA,sha256=5rW00M6gy8crugEHSZZCOCNdoe-Bi8gbVBwfOqoNk0U,3143
110
- sapiopycommons-2025.10.10a779.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
111
- sapiopycommons-2025.10.10a779.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
112
- sapiopycommons-2025.10.10a779.dist-info/RECORD,,
109
+ sapiopycommons-2025.10.13a781.dist-info/METADATA,sha256=Ex7Fc6UXveEGSs8qgYNAUSzjwKhsBOZU3jyOzIWKlyY,3143
110
+ sapiopycommons-2025.10.13a781.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
111
+ sapiopycommons-2025.10.13a781.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
112
+ sapiopycommons-2025.10.13a781.dist-info/RECORD,,