sapiopycommons 2025.10.17a787__py3-none-any.whl → 2025.10.20a789__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.

Files changed (50) hide show
  1. sapiopycommons/ai/agent_service_base.py +1226 -0
  2. sapiopycommons/ai/converter_service_base.py +163 -0
  3. sapiopycommons/ai/external_credentials.py +128 -0
  4. sapiopycommons/ai/protoapi/externalcredentials/external_credentials_pb2.py +41 -0
  5. sapiopycommons/ai/protoapi/externalcredentials/external_credentials_pb2.pyi +35 -0
  6. sapiopycommons/ai/protoapi/externalcredentials/external_credentials_pb2_grpc.py +24 -0
  7. sapiopycommons/ai/protoapi/fielddefinitions/fields_pb2.py +43 -0
  8. sapiopycommons/ai/protoapi/fielddefinitions/fields_pb2.pyi +31 -0
  9. sapiopycommons/ai/protoapi/fielddefinitions/fields_pb2_grpc.py +24 -0
  10. sapiopycommons/ai/protoapi/fielddefinitions/velox_field_def_pb2.py +123 -0
  11. sapiopycommons/ai/protoapi/fielddefinitions/velox_field_def_pb2.pyi +598 -0
  12. sapiopycommons/ai/protoapi/fielddefinitions/velox_field_def_pb2_grpc.py +24 -0
  13. sapiopycommons/ai/protoapi/plan/converter/converter_pb2.py +51 -0
  14. sapiopycommons/ai/protoapi/plan/converter/converter_pb2.pyi +63 -0
  15. sapiopycommons/ai/protoapi/plan/converter/converter_pb2_grpc.py +149 -0
  16. sapiopycommons/ai/protoapi/plan/item/item_container_pb2.py +55 -0
  17. sapiopycommons/ai/protoapi/plan/item/item_container_pb2.pyi +90 -0
  18. sapiopycommons/ai/protoapi/plan/item/item_container_pb2_grpc.py +24 -0
  19. sapiopycommons/ai/protoapi/plan/script/script_pb2.py +61 -0
  20. sapiopycommons/ai/protoapi/plan/script/script_pb2.pyi +108 -0
  21. sapiopycommons/ai/protoapi/plan/script/script_pb2_grpc.py +153 -0
  22. sapiopycommons/ai/protoapi/plan/step_output_pb2.py +45 -0
  23. sapiopycommons/ai/protoapi/plan/step_output_pb2.pyi +42 -0
  24. sapiopycommons/ai/protoapi/plan/step_output_pb2_grpc.py +24 -0
  25. sapiopycommons/ai/protoapi/plan/step_pb2.py +43 -0
  26. sapiopycommons/ai/protoapi/plan/step_pb2.pyi +43 -0
  27. sapiopycommons/ai/protoapi/plan/step_pb2_grpc.py +24 -0
  28. sapiopycommons/ai/protoapi/plan/tool/entry_pb2.py +41 -0
  29. sapiopycommons/ai/protoapi/plan/tool/entry_pb2.pyi +35 -0
  30. sapiopycommons/ai/protoapi/plan/tool/entry_pb2_grpc.py +24 -0
  31. sapiopycommons/ai/protoapi/plan/tool/tool_pb2.py +79 -0
  32. sapiopycommons/ai/protoapi/plan/tool/tool_pb2.pyi +261 -0
  33. sapiopycommons/ai/protoapi/plan/tool/tool_pb2_grpc.py +154 -0
  34. sapiopycommons/ai/protoapi/session/sapio_conn_info_pb2.py +39 -0
  35. sapiopycommons/ai/protoapi/session/sapio_conn_info_pb2.pyi +32 -0
  36. sapiopycommons/ai/protoapi/session/sapio_conn_info_pb2_grpc.py +24 -0
  37. sapiopycommons/ai/protobuf_utils.py +504 -0
  38. sapiopycommons/ai/request_validation.py +478 -0
  39. sapiopycommons/ai/server.py +152 -0
  40. sapiopycommons/ai/test_client.py +446 -0
  41. sapiopycommons/callbacks/callback_util.py +4 -18
  42. sapiopycommons/files/file_util.py +128 -1
  43. sapiopycommons/files/temp_files.py +82 -0
  44. sapiopycommons/general/aliases.py +0 -3
  45. sapiopycommons/webhook/webservice_handlers.py +1 -1
  46. {sapiopycommons-2025.10.17a787.dist-info → sapiopycommons-2025.10.20a789.dist-info}/METADATA +1 -1
  47. {sapiopycommons-2025.10.17a787.dist-info → sapiopycommons-2025.10.20a789.dist-info}/RECORD +49 -9
  48. sapiopycommons/ai/tool_of_tools.py +0 -917
  49. {sapiopycommons-2025.10.17a787.dist-info → sapiopycommons-2025.10.20a789.dist-info}/WHEEL +0 -0
  50. {sapiopycommons-2025.10.17a787.dist-info → sapiopycommons-2025.10.20a789.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,82 @@
1
+ import os
2
+ import shutil
3
+ import tempfile
4
+ from typing import Callable, Any
5
+
6
+
7
+ # FR-47422: Created class.
8
+ class TempFileHandler:
9
+ """
10
+ A utility class to manage temporary files and directories.
11
+ """
12
+ directories: list[str]
13
+ files: list[str]
14
+
15
+ def __init__(self):
16
+ self.directories = []
17
+ self.files = []
18
+
19
+ def create_temp_directory(self) -> str:
20
+ """
21
+ Create a temporary directory.
22
+
23
+ :return: The path to a newly created temporary directory.
24
+ """
25
+ directory: str = tempfile.mkdtemp()
26
+ self.directories.append(directory)
27
+ return directory
28
+
29
+ def create_temp_file(self, data: str | bytes, suffix: str = "") -> str:
30
+ """
31
+ Create a temporary file with the specified data and optional suffix.
32
+
33
+ :param data: The data to write to the temporary file.
34
+ :param suffix: An optional suffix for the temporary file.
35
+ :return: The path to a newly created temporary file containing the provided data.
36
+ """
37
+ mode: str = 'w' if isinstance(data, str) else 'wb'
38
+ with tempfile.NamedTemporaryFile(mode=mode, suffix=suffix, delete=False) as tmp_file:
39
+ tmp_file.write(data)
40
+ file_path: str = tmp_file.name
41
+ self.files.append(file_path)
42
+ return file_path
43
+
44
+ def create_temp_file_from_func(self, func: Callable, params: dict[str, Any], suffix: str = "",
45
+ is_binary: bool = True) -> str:
46
+ """
47
+ Create a temporary file and populate it using the provided function. The function should accept parameters as
48
+ specified in the `params` dictionary.
49
+
50
+ :param func: The function to call with the temporary file path that will populate the file.
51
+ :param params: Keyword arguments to pass to the function. If "<NEW_FILE>" is used as a value, it will be
52
+ replaced with the temporary file object. If "<NEW_FILE_PATH>" is used as a value, it will be replaced with
53
+ the temporary file path.
54
+ :param suffix: An optional suffix for the temporary file.
55
+ :param is_binary: Whether to open the temporary file in binary mode.
56
+ :return: The path to the newly created temporary file.
57
+ """
58
+ mode: str = 'wb' if is_binary else 'w'
59
+ with tempfile.NamedTemporaryFile(mode, suffix=suffix, delete=False) as tmp_file:
60
+ for key, value in params.items():
61
+ if value == "<NEW_FILE>":
62
+ params[key] = tmp_file
63
+ elif value == "<NEW_FILE_PATH>":
64
+ params[key] = tmp_file.name
65
+ func(**params)
66
+ file_path: str = tmp_file.name
67
+ self.files.append(file_path)
68
+ return file_path
69
+
70
+ def cleanup(self) -> None:
71
+ """
72
+ Delete all temporary files and directories created by this handler.
73
+ """
74
+ for directory in self.directories:
75
+ if os.path.exists(directory):
76
+ shutil.rmtree(directory)
77
+ self.directories.clear()
78
+
79
+ for file_path in self.files:
80
+ if os.path.exists(file_path):
81
+ os.remove(file_path)
82
+ self.files.clear()
@@ -224,11 +224,8 @@ class AliasUtil:
224
224
  fields: FieldMap = {f: record.fields.get(f) for f in record.fields}
225
225
  # PR-47457: Only include the record ID if the caller requests it, since including the record ID can break
226
226
  # callbacks in certain circumstances if the record ID is negative.
227
- # PR-47894: Also remove the RecordId key if it exists and the caller doesn't want it included.
228
227
  if include_record_id:
229
228
  fields["RecordId"] = AliasUtil.to_record_id(record)
230
- elif "RecordId" in fields:
231
- del fields["RecordId"]
232
229
  return fields
233
230
 
234
231
  @staticmethod
@@ -140,7 +140,7 @@ class AbstractWebserviceHandler(AbstractWebhookHandler):
140
140
  # Get the login credentials from the headers.
141
141
  auth: str = headers.get("Authorization")
142
142
  if auth and auth.startswith("Basic "):
143
- credentials: list[str] = b64decode(auth.split("Basic ")[1]).decode().split(":")
143
+ credentials: list[str] = b64decode(auth.split("Basic ")[1]).decode().split(":", 1)
144
144
  user = self.basic_auth(url, credentials[0], credentials[1])
145
145
  elif auth and auth.startswith("Bearer "):
146
146
  user = self.bearer_token_auth(url, auth.split("Bearer ")[1])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: sapiopycommons
3
- Version: 2025.10.17a787
3
+ Version: 2025.10.20a789
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,47 @@
1
1
  sapiopycommons/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  sapiopycommons/ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- sapiopycommons/ai/tool_of_tools.py,sha256=zYmQ4rNX-qYQnc-vNDnYZjtv9JgmQAmVVuHfVOdBF3w,46984
3
+ sapiopycommons/ai/agent_service_base.py,sha256=eTJunFQoxLc0risWiQIkQK946XpHzSFO38NzzRvOn9Q,60325
4
+ sapiopycommons/ai/converter_service_base.py,sha256=HiUXmwqv1STgyQeF9_eTFXzjIFXp5-NJ7sEhMpV3aAU,6351
5
+ sapiopycommons/ai/external_credentials.py,sha256=ki_xIH4J843b_sSwEa8YHr8vW9erVv-jowZJXSgPQs8,4347
6
+ sapiopycommons/ai/protobuf_utils.py,sha256=cBjbxoFAwU02kNUxEce95WnMU2CMuDD-qFaeWgvQJMQ,24599
7
+ sapiopycommons/ai/request_validation.py,sha256=dsCZXWDSHLm7pGywArB_GRymXxo1l-eGMn6veUwSg20,25641
8
+ sapiopycommons/ai/server.py,sha256=gutSskn_Fenq1uz0DDMvjx4QVFiKt2WVEP3-01a69eU,6384
9
+ sapiopycommons/ai/test_client.py,sha256=IRZ-8prhg7XMDmN9aC1MQr5mSkMgfT37aLsOy-VB-MU,20495
10
+ sapiopycommons/ai/protoapi/externalcredentials/external_credentials_pb2.py,sha256=mEonoj6Iq-AyvO4m3YsPYu85aZfD1E0a0cL8B9yPfEo,2481
11
+ sapiopycommons/ai/protoapi/externalcredentials/external_credentials_pb2.pyi,sha256=sfExq8fFwIwFxCpV50ytdxW5ePNBjJBr_80_trq_JQw,1658
12
+ sapiopycommons/ai/protoapi/externalcredentials/external_credentials_pb2_grpc.py,sha256=TNS1CB_QGBSa1YU9sYR_hF-pmBwv2GpxjaNQoM_r9iU,948
13
+ sapiopycommons/ai/protoapi/fielddefinitions/fields_pb2.py,sha256=8tKXwLXcqFGdQHHSEBSi6Fd7dcaCFoOqmhjzqhenb_M,2372
14
+ sapiopycommons/ai/protoapi/fielddefinitions/fields_pb2.pyi,sha256=FwtXmNAf7iYGEFm4kbqb04v77jNHbZg18ZmEDhle_bU,1444
15
+ sapiopycommons/ai/protoapi/fielddefinitions/fields_pb2_grpc.py,sha256=uO25bcnfGqXpP4ggUur54Nr73Wj-DGWftExzLNcxdHI,931
16
+ sapiopycommons/ai/protoapi/fielddefinitions/velox_field_def_pb2.py,sha256=in9iHiLPYcnLWoLeqy4nWSI0jZGHD_bMhEFRIRtJPuo,20864
17
+ sapiopycommons/ai/protoapi/fielddefinitions/velox_field_def_pb2.pyi,sha256=U5zXrbBxsWilLTsRWJd1TqjdjLKFsr3enF9OJ8GfyWw,34028
18
+ sapiopycommons/ai/protoapi/fielddefinitions/velox_field_def_pb2_grpc.py,sha256=Vj6qDKvsHgl25iBi3UjtTuGxihekgqCuufExvnJKzQI,940
19
+ sapiopycommons/ai/protoapi/plan/step_output_pb2.py,sha256=EBNCzLUDwwCqDCh35zSfFdfq0RP8WrmTMXEzEPu_1_E,2655
20
+ sapiopycommons/ai/protoapi/plan/step_output_pb2.pyi,sha256=yuxOYnDZ9DRuu-TLzaKOW_B4LUiYxTrNc2AbssXg4kE,2022
21
+ sapiopycommons/ai/protoapi/plan/step_output_pb2_grpc.py,sha256=ebWLIfOFeVE2WuUIThMBerVweH-1phviGX195UTwYyg,924
22
+ sapiopycommons/ai/protoapi/plan/step_pb2.py,sha256=mKTm_syaX99GzhWtGIPkxMTsfcsvW0QbRqjv06eHSM0,2433
23
+ sapiopycommons/ai/protoapi/plan/step_pb2.pyi,sha256=QPIcsjcUvEGQkdZMUMiVzFFNDl8yOUe_qJtf5XEp5Ck,2062
24
+ sapiopycommons/ai/protoapi/plan/step_pb2_grpc.py,sha256=1CBna5NBBxPwQhrkN8-Fim_j3FGmOfDo5C4c8sIBV8Q,917
25
+ sapiopycommons/ai/protoapi/plan/converter/converter_pb2.py,sha256=rZYBRfR0umwDYvBdYnzxR1VZSutRqunhd3QsdtQXiCM,3593
26
+ sapiopycommons/ai/protoapi/plan/converter/converter_pb2.pyi,sha256=_35yHfKTJH3SMdA5_c6qF6OZG6UwFWXpNh6dwRFDKkk,4250
27
+ sapiopycommons/ai/protoapi/plan/converter/converter_pb2_grpc.py,sha256=6T5FCmT_vEFSywUVlAlWWfBDPaILb0Dq8yCGuO_Q-BU,6448
28
+ sapiopycommons/ai/protoapi/plan/item/item_container_pb2.py,sha256=VIXmIw8-9jtH7peJZ16BEmGDfaVjjxTKhmlfcHWT82M,3863
29
+ sapiopycommons/ai/protoapi/plan/item/item_container_pb2.pyi,sha256=bbPNQDwfFDd7_S7yU99Co1O7sRhxjle-RM0_nK8jgjc,4246
30
+ sapiopycommons/ai/protoapi/plan/item/item_container_pb2_grpc.py,sha256=1NzBWBUINC0Rk-NGYZ-97BVKvVUxcn_I44IjQO2h-nQ,932
31
+ sapiopycommons/ai/protoapi/plan/script/script_pb2.py,sha256=4TN7NlJEENAVqwfymoEDj5hhHYxHLdrHdpRUVgzVG8A,5621
32
+ sapiopycommons/ai/protoapi/plan/script/script_pb2.pyi,sha256=l250ak1sOfm7Ue-PyBQC-7j7-p4DeBxltnOzwDsQIYc,6870
33
+ sapiopycommons/ai/protoapi/plan/script/script_pb2_grpc.py,sha256=ginPYpsiI6U6dB6gfWHJM8LWjSHUgcqz_gR7Dmdsyck,6864
34
+ sapiopycommons/ai/protoapi/plan/tool/entry_pb2.py,sha256=yNyyyVvz94ewjGaHw3t0pUP-KH7ACg5hLC0QzrsFPis,2130
35
+ sapiopycommons/ai/protoapi/plan/tool/entry_pb2.pyi,sha256=2vI0WSy0KGFHDewMSRyX5rUkmmmSaMBLvFO7txqA6Ug,2354
36
+ sapiopycommons/ai/protoapi/plan/tool/entry_pb2_grpc.py,sha256=i24BfJEt7LtyROxHVEyS9RLYqLZKPvyJMKRFZj6NUTg,923
37
+ sapiopycommons/ai/protoapi/plan/tool/tool_pb2.py,sha256=aLD5j60lWUxhHW8b1AoUOClLOjFPjEMmM1KrY337-gI,9095
38
+ sapiopycommons/ai/protoapi/plan/tool/tool_pb2.pyi,sha256=HGNou2THKPk8o9G_ZPvbGXDb6cBnv8L1R_l10i9ceHI,18441
39
+ sapiopycommons/ai/protoapi/plan/tool/tool_pb2_grpc.py,sha256=CLSGEgSpN4D6wcE-P_5lzb2Nttjr4XjumxGUrZQSip0,6915
40
+ sapiopycommons/ai/protoapi/session/sapio_conn_info_pb2.py,sha256=MhWzTyJz3xZgpdW8_LCVKuzKXT0cv6iHMRB-UNCUNzM,2094
41
+ sapiopycommons/ai/protoapi/session/sapio_conn_info_pb2.pyi,sha256=vLYA8Tkzq2AwgVadoUp5vAg4HgGlgga0kzeS3e_XkCQ,1621
42
+ sapiopycommons/ai/protoapi/session/sapio_conn_info_pb2_grpc.py,sha256=imcciy_kbmm7OV_W3jYZ53R6GQ6Yh-eUcVW0A9GkWdg,931
4
43
  sapiopycommons/callbacks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- sapiopycommons/callbacks/callback_util.py,sha256=aLkH5p5PMI74MN7tdrJ3Xy6LDDggHpCf4Lhr9XuOreA,154535
44
+ sapiopycommons/callbacks/callback_util.py,sha256=Z1LcXnRRjXyhmcSDUwh4NzcA6ICtcbFUMKcvAqQcS8E,153811
6
45
  sapiopycommons/callbacks/field_builder.py,sha256=rnIP-RJafk3mZlAx1eJ8a0eSW9Ps_L6_WadCmusnENw,38772
7
46
  sapiopycommons/chem/IndigoMolecules.py,sha256=7ucCaRMLu1zfH2uPIvXwRTSdpNcS03O1P9p_O-5B4xQ,5110
8
47
  sapiopycommons/chem/Molecules.py,sha256=mVqPn32MPMjF0iZas-5MFkS-upIdoW5OB72KKZmJRJA,12523
@@ -31,14 +70,15 @@ sapiopycommons/files/file_bridge.py,sha256=vKbqxPexi15epr_-_qLrEfYoxNxB031mXN92i
31
70
  sapiopycommons/files/file_bridge_handler.py,sha256=SEYDIQhSCmjI6qyLdDJE8JVKSd0WYvF7JvAq_Ahp9Do,25503
32
71
  sapiopycommons/files/file_data_handler.py,sha256=f96MlkMuQhUCi4oLnzJK5AiuElCp5jLI8_sJkZVwpws,36779
33
72
  sapiopycommons/files/file_text_converter.py,sha256=Gaj_divTiKXWd6flDOgrxNXpcn9fDWqxX6LUG0joePk,7516
34
- sapiopycommons/files/file_util.py,sha256=djouyGjsYgWzjz2OBRnSeMDgj6NrsJUm1a2J93J8Wco,31915
73
+ sapiopycommons/files/file_util.py,sha256=WBA3FYG8R2HtfxjWSzQhZKW6_1s6JSxTo9lk3SeNDu8,37140
35
74
  sapiopycommons/files/file_validator.py,sha256=ryg22-93csmRO_Pv0ZpWphNkB74xWZnHyJ23K56qLj0,28761
36
75
  sapiopycommons/files/file_writer.py,sha256=hACVl0duCjP28gJ1NPljkjagNCLod0ygUlPbvUmRDNM,17605
76
+ sapiopycommons/files/temp_files.py,sha256=s2sGvn9uh2dTI8AVAQJWOf6RAZ0xZs7DSccCi4AGmlw,3175
37
77
  sapiopycommons/flowcyto/flow_cyto.py,sha256=B6DFquLi-gcWfJWyP4vYfwTXXJKl6O9W5-k8FzkM0Oo,2610
38
78
  sapiopycommons/flowcyto/flowcyto_data.py,sha256=mYKFuLbtpJ-EsQxLGtu4tNHVlygTxKixgJxJqD68F58,2596
39
79
  sapiopycommons/general/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
80
  sapiopycommons/general/accession_service.py,sha256=ZvtvZg7d_siMJUedjrF14mcqo5ZqVA5IJxDa5enlB-8,12792
41
- sapiopycommons/general/aliases.py,sha256=pHfpH5veukVdjlR62_INCy2ItZG1omQv4dCoo8NeGlM,14869
81
+ sapiopycommons/general/aliases.py,sha256=VwnWf_P803pcteoAIs0DkLScVChCS5XNgryTp8FzaNc,14696
42
82
  sapiopycommons/general/audit_log.py,sha256=sQAMcJx0cNkgZm7nTZSaGPxWvHG0_x6dBtU0jESavb4,9131
43
83
  sapiopycommons/general/custom_report_util.py,sha256=9elLEUSgfM0gli8nRPz1uYkhaXN4Vnx3piSiNHv5IBs,19156
44
84
  sapiopycommons/general/data_structure_util.py,sha256=fbQR_Fh4Scg67IpFPbQW9wVLw1oxlYxqp4LjBRTpjgU,4702
@@ -65,8 +105,8 @@ sapiopycommons/sftpconnect/sftp_builder.py,sha256=lFK3FeXk-sFLefW0hqY8WGUQDeYiGa
65
105
  sapiopycommons/webhook/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
106
  sapiopycommons/webhook/webhook_context.py,sha256=D793uLsb1691SalaPnBUk3rOSxn_hYLhdvkaIxjNXss,1909
67
107
  sapiopycommons/webhook/webhook_handlers.py,sha256=7o_wXOruhT9auNh8OfhJAh4WhhiPKij67FMBSpGPICc,39939
68
- sapiopycommons/webhook/webservice_handlers.py,sha256=tyaYGG1-v_JJrJHZ6cy5mGCxX9z1foLw7pM4MDJlFxs,14297
69
- sapiopycommons-2025.10.17a787.dist-info/METADATA,sha256=3mZft6DRxhP-QWhIDnysHuAHlxoYaghDr4kWHRpUG9g,3143
70
- sapiopycommons-2025.10.17a787.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
71
- sapiopycommons-2025.10.17a787.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
72
- sapiopycommons-2025.10.17a787.dist-info/RECORD,,
108
+ sapiopycommons/webhook/webservice_handlers.py,sha256=cvW6Mk_110BzYqkbk63Kg7jWrltBCDALOlkJRu8h4VQ,14300
109
+ sapiopycommons-2025.10.20a789.dist-info/METADATA,sha256=LW1ECHFl-cG6BPslNdeFfIGKFHCxPgtivYUg9mqsnSQ,3143
110
+ sapiopycommons-2025.10.20a789.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
111
+ sapiopycommons-2025.10.20a789.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
112
+ sapiopycommons-2025.10.20a789.dist-info/RECORD,,