sapiopycommons 2025.10.13a781__py3-none-any.whl → 2025.10.15a782__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.

@@ -908,7 +908,7 @@ class AgentBase(ABC):
908
908
  if len(matching_creds) > 1:
909
909
  raise ValueError(f"Multiple credentials found for category '{category}' and host '{host}'.")
910
910
 
911
- return ExternalCredentials(matching_creds[0])
911
+ return ExternalCredentials.from_pbo(matching_creds[0])
912
912
 
913
913
  def call_subprocess(self,
914
914
  args: str | bytes | PathLike[str] | PathLike[bytes] | Sequence[str | bytes | PathLike[str] | PathLike[bytes]],
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from sapiopycommons.ai.protoapi.externalcredentials.external_credentials_pb2 import ExternalCredentialsPbo
2
4
 
3
5
 
@@ -5,26 +7,97 @@ class ExternalCredentials:
5
7
  """
6
8
  A class representing external credentials.
7
9
  """
8
- id: str
9
- display_name: str
10
- description: str
11
- category: str
12
- url: str
13
- username: str
14
- password: str
15
- token: str
16
- custom_fields: dict[str, str]
17
-
18
- def __init__(self, pbo: ExternalCredentialsPbo):
19
- self.id = pbo.id
20
- self.display_name = pbo.display_name
21
- self.description = pbo.description
22
- self.category = pbo.category
23
- self.url = pbo.url
24
- self.username = pbo.username
25
- self.password = pbo.password
26
- self.token = pbo.token
27
- self.custom_fields = dict(pbo.custom_field)
10
+ _identifier: str
11
+ _display_name: str
12
+ _description: str
13
+ _category: str
14
+ _url: str
15
+ _username: str
16
+ _password: str
17
+ _token: str
18
+ _custom_fields: dict[str, str]
19
+
20
+ def __init__(self, url: str, category: str, identifier: str = "", display_name: str = "", description: str = "",
21
+ username: str = "", password: str = "", token: str = "", custom_fields: dict[str, str] | None = None):
22
+ """
23
+ :param url: The URL that the credentials are for.
24
+ :param category: The category of the credentials. This can be used to search for the credentials using the
25
+ AgentBase.get_credentials function.
26
+ :param identifier: The unique identifier for the credentials.
27
+ :param display_name: The display name for the credentials.
28
+ :param description: A description of the credentials.
29
+ :param username: The username for the credentials.
30
+ :param password: The password for the credentials.
31
+ :param token: The token for the credentials.
32
+ :param custom_fields: A dictionary of custom fields associated with the credentials.
33
+ """
34
+ self._identifier = identifier
35
+ self._display_name = display_name
36
+ self._description = description
37
+ self._category = category
38
+ self._url = url
39
+ self._username = username
40
+ self._password = password
41
+ self._token = token
42
+ self._custom_fields = custom_fields or {}
43
+
44
+ @staticmethod
45
+ def from_pbo(pbo: ExternalCredentialsPbo) -> ExternalCredentials:
46
+ """
47
+ Create an ExternalCredentials instance from a protobuf object.
48
+
49
+ :param pbo: An ExternalCredentialsPbo object.
50
+ :return: An ExternalCredentials instance.
51
+ """
52
+ creds = ExternalCredentials(pbo.url, pbo.category)
53
+ creds._identifier = pbo.id
54
+ creds._display_name = pbo.display_name
55
+ creds._description = pbo.description
56
+ creds._username = pbo.username
57
+ creds._password = pbo.password
58
+ creds._token = pbo.token
59
+ creds._custom_fields = dict(pbo.custom_field)
60
+ return creds
61
+
62
+ @property
63
+ def identifier(self) -> str:
64
+ """The unique identifier for the credentials."""
65
+ return self._identifier
66
+
67
+ @property
68
+ def display_name(self) -> str:
69
+ """The display name for the credentials."""
70
+ return self._display_name
71
+
72
+ @property
73
+ def description(self) -> str:
74
+ """A description of the credentials."""
75
+ return self._description
76
+
77
+ @property
78
+ def category(self) -> str:
79
+ """The category of the credentials."""
80
+ return self._category
81
+
82
+ @property
83
+ def url(self) -> str:
84
+ """The URL that the credentials are for."""
85
+ return self._url
86
+
87
+ @property
88
+ def username(self) -> str:
89
+ """The username for the credentials."""
90
+ return self._username
91
+
92
+ @property
93
+ def password(self) -> str:
94
+ """The password for the credentials."""
95
+ return self._password
96
+
97
+ @property
98
+ def token(self) -> str:
99
+ """The token for the credentials."""
100
+ return self._token
28
101
 
29
102
  def get_custom_field(self, key: str, default: str = None) -> str | None:
30
103
  """
@@ -34,4 +107,22 @@ class ExternalCredentials:
34
107
  :param default: The value to return if the key does not exist.
35
108
  :return: The value of the custom field, or None if the key does not exist.
36
109
  """
37
- return self.custom_fields.get(key, default)
110
+ return self._custom_fields.get(key, default)
111
+
112
+ def to_pbo(self) -> ExternalCredentialsPbo:
113
+ """
114
+ Convert the ExternalCredentials instance to a protobuf object.
115
+
116
+ :return: An ExternalCredentialsPbo object.
117
+ """
118
+ return ExternalCredentialsPbo(
119
+ id=self._identifier,
120
+ display_name=self._display_name,
121
+ description=self._description,
122
+ category=self._category,
123
+ url=self._url,
124
+ username=self._username,
125
+ password=self._password,
126
+ token=self._token,
127
+ custom_field=self._custom_fields
128
+ )
@@ -7,6 +7,8 @@ from typing import Any
7
7
  import grpc
8
8
  from sapiopylib.rest.User import SapioUser
9
9
 
10
+ from sapiopycommons.ai.external_credentials import ExternalCredentials
11
+ from sapiopycommons.ai.protoapi.externalcredentials.external_credentials_pb2 import ExternalCredentialsPbo
10
12
  from sapiopycommons.ai.protoapi.fielddefinitions.fields_pb2 import FieldValuePbo
11
13
  from sapiopycommons.ai.protoapi.plan.converter.converter_pb2 import ConverterDetailsRequestPbo, \
12
14
  ConverterDetailsResponsePbo, ConvertResponsePbo, ConvertRequestPbo
@@ -65,7 +67,8 @@ class AgentOutput:
65
67
  self.new_records = []
66
68
  self.logs = []
67
69
 
68
- def save_outputs(self, path: str = "test_outputs", subfolder: str | None = None, file_extensions: list[str] | None = None) -> None:
70
+ def save_outputs(self, path: str = "test_outputs", subfolder: str | None = None,
71
+ file_extensions: list[str] | None = None) -> None:
69
72
  """
70
73
  Save all outputs to files in the specified output directory.
71
74
 
@@ -168,6 +171,7 @@ class TestClient:
168
171
  connection: SapioConnectionInfoPbo
169
172
  _request_inputs: list[StepItemContainerPbo]
170
173
  _config_fields: dict[str, FieldValuePbo]
174
+ _credentials: list[ExternalCredentialsPbo]
171
175
 
172
176
  def __init__(self, grpc_server_url: str, message_mb_size: int = 1024, user: SapioUser | None = None,
173
177
  options: list[tuple[str, Any]] | None = None):
@@ -188,6 +192,7 @@ class TestClient:
188
192
  self._create_connection(user)
189
193
  self._request_inputs = []
190
194
  self._config_fields = {}
195
+ self._credentials = []
191
196
 
192
197
  def _create_connection(self, user: SapioUser | None = None):
193
198
  """
@@ -272,10 +277,28 @@ class TestClient:
272
277
  """
273
278
  self._config_fields.clear()
274
279
 
280
+ def add_credentials(self, credentials: list[ExternalCredentials]) -> None:
281
+ """
282
+ Add external credentials to the connection info for the next request.
283
+
284
+ :param credentials: A list of ExternalCredentialsPbo objects to add to the connection info.
285
+ """
286
+ for cred in credentials:
287
+ self._credentials.append(cred.to_pbo())
288
+
289
+ def clear_credentials(self) -> None:
290
+ """
291
+ Clear all external credentials that have been added to the next request.
292
+ This is useful if you want to start a new request without the previous credentials.
293
+ """
294
+ self._credentials.clear()
295
+
275
296
  def clear_request(self) -> None:
276
297
  """
277
298
  Clear all inputs and configuration fields that have been added to the next request.
278
299
  This is useful if you want to start a new request without the previous inputs and configurations.
300
+
301
+ Credentials are not cleared, as they may be reused across multiple requests.
279
302
  """
280
303
  self.clear_inputs()
281
304
  self.clear_configs()
@@ -331,6 +354,7 @@ class TestClient:
331
354
  config_field_values=self._config_fields,
332
355
  dry_run=is_dry_run,
333
356
  verbose_logging=is_verbose,
357
+ external_credential=self._credentials,
334
358
  input=[
335
359
  StepInputBatchPbo(is_partial=False, item_container=item)
336
360
  for item in self._request_inputs
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: sapiopycommons
3
- Version: 2025.10.13a781
3
+ Version: 2025.10.15a782
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,12 +1,12 @@
1
1
  sapiopycommons/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  sapiopycommons/ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- sapiopycommons/ai/agent_service_base.py,sha256=UF5mSCXMxX0qUtEUWRtQ6_690aOo6pCRB89dyj8Amug,56292
3
+ sapiopycommons/ai/agent_service_base.py,sha256=LVZg_4Kw5WTcIB7ru5hEqJoMWQr2eTDYjMrX8pzpn9I,56301
4
4
  sapiopycommons/ai/converter_service_base.py,sha256=HiUXmwqv1STgyQeF9_eTFXzjIFXp5-NJ7sEhMpV3aAU,6351
5
- sapiopycommons/ai/external_credentials.py,sha256=40AI7VtHf6PzvwJLR_mZemUCrfAUvC--tGH-npaDIgo,1163
5
+ sapiopycommons/ai/external_credentials.py,sha256=ki_xIH4J843b_sSwEa8YHr8vW9erVv-jowZJXSgPQs8,4347
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=aiS58O_A3KSgRCzDT61iKyVXy9F4UY7xUyGQu5E7bTw,19432
9
+ sapiopycommons/ai/test_client.py,sha256=IRZ-8prhg7XMDmN9aC1MQr5mSkMgfT37aLsOy-VB-MU,20495
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.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,,
109
+ sapiopycommons-2025.10.15a782.dist-info/METADATA,sha256=DIeUTx52EZpA1ZIecBFRA4_LsTMKBwOZLzB6i2iBgxs,3143
110
+ sapiopycommons-2025.10.15a782.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
111
+ sapiopycommons-2025.10.15a782.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
112
+ sapiopycommons-2025.10.15a782.dist-info/RECORD,,