sapiopycommons 2025.10.1a772__py3-none-any.whl → 2025.10.2a773__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 (44) hide show
  1. sapiopycommons/ai/converter_service_base.py +163 -0
  2. sapiopycommons/ai/protoapi/fielddefinitions/fields_pb2.py +43 -0
  3. sapiopycommons/ai/protoapi/fielddefinitions/fields_pb2.pyi +31 -0
  4. sapiopycommons/ai/protoapi/fielddefinitions/fields_pb2_grpc.py +24 -0
  5. sapiopycommons/ai/protoapi/fielddefinitions/velox_field_def_pb2.py +123 -0
  6. sapiopycommons/ai/protoapi/fielddefinitions/velox_field_def_pb2.pyi +598 -0
  7. sapiopycommons/ai/protoapi/fielddefinitions/velox_field_def_pb2_grpc.py +24 -0
  8. sapiopycommons/ai/protoapi/plan/converter/converter_pb2.py +51 -0
  9. sapiopycommons/ai/protoapi/plan/converter/converter_pb2.pyi +63 -0
  10. sapiopycommons/ai/protoapi/plan/converter/converter_pb2_grpc.py +149 -0
  11. sapiopycommons/ai/protoapi/plan/item/item_container_pb2.py +55 -0
  12. sapiopycommons/ai/protoapi/plan/item/item_container_pb2.pyi +90 -0
  13. sapiopycommons/ai/protoapi/plan/item/item_container_pb2_grpc.py +24 -0
  14. sapiopycommons/ai/protoapi/plan/script/script_pb2.py +59 -0
  15. sapiopycommons/ai/protoapi/plan/script/script_pb2.pyi +102 -0
  16. sapiopycommons/ai/protoapi/plan/script/script_pb2_grpc.py +153 -0
  17. sapiopycommons/ai/protoapi/plan/step_output_pb2.py +45 -0
  18. sapiopycommons/ai/protoapi/plan/step_output_pb2.pyi +42 -0
  19. sapiopycommons/ai/protoapi/plan/step_output_pb2_grpc.py +24 -0
  20. sapiopycommons/ai/protoapi/plan/step_pb2.py +43 -0
  21. sapiopycommons/ai/protoapi/plan/step_pb2.pyi +43 -0
  22. sapiopycommons/ai/protoapi/plan/step_pb2_grpc.py +24 -0
  23. sapiopycommons/ai/protoapi/plan/tool/entry_pb2.py +41 -0
  24. sapiopycommons/ai/protoapi/plan/tool/entry_pb2.pyi +35 -0
  25. sapiopycommons/ai/protoapi/plan/tool/entry_pb2_grpc.py +24 -0
  26. sapiopycommons/ai/protoapi/plan/tool/tool_pb2.py +77 -0
  27. sapiopycommons/ai/protoapi/plan/tool/tool_pb2.pyi +253 -0
  28. sapiopycommons/ai/protoapi/plan/tool/tool_pb2_grpc.py +154 -0
  29. sapiopycommons/ai/protoapi/session/sapio_conn_info_pb2.py +39 -0
  30. sapiopycommons/ai/protoapi/session/sapio_conn_info_pb2.pyi +32 -0
  31. sapiopycommons/ai/protoapi/session/sapio_conn_info_pb2_grpc.py +24 -0
  32. sapiopycommons/ai/protobuf_utils.py +504 -0
  33. sapiopycommons/ai/request_validation.py +451 -0
  34. sapiopycommons/ai/server.py +152 -0
  35. sapiopycommons/ai/test_client.py +367 -0
  36. sapiopycommons/ai/tool_service_base.py +1114 -0
  37. sapiopycommons/files/file_util.py +128 -1
  38. sapiopycommons/files/temp_files.py +82 -0
  39. sapiopycommons/webhook/webservice_handlers.py +1 -1
  40. {sapiopycommons-2025.10.1a772.dist-info → sapiopycommons-2025.10.2a773.dist-info}/METADATA +1 -1
  41. {sapiopycommons-2025.10.1a772.dist-info → sapiopycommons-2025.10.2a773.dist-info}/RECORD +43 -7
  42. sapiopycommons/ai/tool_of_tools.py +0 -917
  43. {sapiopycommons-2025.10.1a772.dist-info → sapiopycommons-2025.10.2a773.dist-info}/WHEEL +0 -0
  44. {sapiopycommons-2025.10.1a772.dist-info → sapiopycommons-2025.10.2a773.dist-info}/licenses/LICENSE +0 -0
@@ -1,4 +1,7 @@
1
+ import gzip
1
2
  import io
3
+ import tarfile
4
+ import time
2
5
  import warnings
3
6
  import zipfile
4
7
 
@@ -322,7 +325,7 @@ class FileUtil:
322
325
  @staticmethod
323
326
  def zip_files(files: dict[str, str | bytes]) -> bytes:
324
327
  """
325
- Create a zip file for a collection of files.
328
+ Create a .zip file for a collection of files.
326
329
 
327
330
  :param files: A dictionary of file name to file data as a string or bytes.
328
331
  :return: The bytes for a zip file containing the input files.
@@ -335,6 +338,130 @@ class FileUtil:
335
338
  # throws an I/O exception.
336
339
  return zip_buffer.getvalue()
337
340
 
341
+ # FR-47422: Add a function for unzipping files that may have been zipped by the above function.
342
+ @staticmethod
343
+ def unzip_files(zip_file: bytes) -> dict[str, bytes]:
344
+ """
345
+ Decompress a .zip file from an in-memory bytes object and extracts all files into a dictionary.
346
+
347
+ :param zip_file: The bytes of the zip file to be decompressed.
348
+ :return: A dictionary of file name to file bytes for each file in the zip.
349
+ """
350
+ extracted_files: dict[str, bytes] = {}
351
+ with io.BytesIO(zip_file) as zip_buffer:
352
+ with zipfile.ZipFile(zip_buffer, "r") as zip_file:
353
+ for file_name in zip_file.namelist():
354
+ with zip_file.open(file_name) as file:
355
+ extracted_files[file_name] = file.read()
356
+ return extracted_files
357
+
358
+ # FR-47422: Add functions for compressing and decompressing .gz, .tar, and .tar.gz files.
359
+ @staticmethod
360
+ def gzip_file(file_data: bytes | str) -> bytes:
361
+ """
362
+ Create a .gz file for a single file.
363
+
364
+ :param file_data: The file data to be compressed as bytes or a string.
365
+ :return: The bytes of the gzip-compressed file.
366
+ """
367
+ return gzip.compress(file_data.encode() if isinstance(file_data, str) else file_data)
368
+
369
+ @staticmethod
370
+ def ungzip_file(gzip_file: bytes) -> bytes:
371
+ """
372
+ Decompress a .gz file.
373
+
374
+ :param gzip_file: The bytes of the gzip-compressed file.
375
+ :return: The decompressed file data as bytes.
376
+ """
377
+ return gzip.decompress(gzip_file)
378
+
379
+ @staticmethod
380
+ def tar_files(files: dict[str, str | bytes]) -> bytes:
381
+ """
382
+ Create a .tar file for a collection of files.
383
+
384
+ :param files: A dictionary of file name to file data as a string or bytes.
385
+ :return: The bytes for a tar file containing the input files.
386
+ """
387
+ with io.BytesIO() as tar_buffer:
388
+ with tarfile.open(fileobj=tar_buffer, mode="w") as tar:
389
+ for name, data in files.items():
390
+ if isinstance(data, str):
391
+ data: bytes = data.encode('utf-8')
392
+
393
+ tarinfo = tarfile.TarInfo(name=name)
394
+ tarinfo.size = len(data)
395
+ tarinfo.mtime = int(time.time())
396
+
397
+ with io.BytesIO(data) as file:
398
+ tar.addfile(tarinfo=tarinfo, fileobj=file)
399
+
400
+ tar_buffer.seek(0)
401
+ return tar_buffer.getvalue()
402
+
403
+ @staticmethod
404
+ def untar_files(tar_file: bytes) -> dict[str, bytes]:
405
+ """
406
+ Decompress a .tar file from an in-memory bytes object and extracts all files into a dictionary.
407
+
408
+ :param tar_file: The bytes of the tar file to be decompressed.
409
+ :return: A dictionary of file name to file bytes for each file in the tar.
410
+ """
411
+ extracted_files: dict[str, bytes] = {}
412
+ with io.BytesIO(tar_file) as tar_buffer:
413
+ with tarfile.open(fileobj=tar_buffer, mode="r") as tar:
414
+ for member in tar.getmembers():
415
+ if member.isfile():
416
+ file_obj = tar.extractfile(member)
417
+ if file_obj:
418
+ with file_obj:
419
+ extracted_files[member.name] = file_obj.read()
420
+ return extracted_files
421
+
422
+ @staticmethod
423
+ def tar_gzip_files(files: dict[str, str | bytes]) -> bytes:
424
+ """
425
+ Create a .tar.gz file for a collection of files.
426
+
427
+ :param files: A dictionary of file name to file data as a string or bytes.
428
+ :return: The bytes for a tar.gz file containing the input files.
429
+ """
430
+ with io.BytesIO() as tar_buffer:
431
+ with tarfile.open(fileobj=tar_buffer, mode="w:gz") as tar:
432
+ for name, data in files.items():
433
+ if isinstance(data, str):
434
+ data: bytes = data.encode('utf-8')
435
+
436
+ tarinfo = tarfile.TarInfo(name=name)
437
+ tarinfo.size = len(data)
438
+ tarinfo.mtime = int(time.time())
439
+
440
+ with io.BytesIO(data) as file:
441
+ tar.addfile(tarinfo=tarinfo, fileobj=file)
442
+
443
+ tar_buffer.seek(0)
444
+ return tar_buffer.getvalue()
445
+
446
+ @staticmethod
447
+ def untar_gzip_files(tar_gzip_file: bytes) -> dict[str, bytes]:
448
+ """
449
+ Decompress a .tar.gz file from an in-memory bytes object and extracts all files into a dictionary.
450
+
451
+ :param tar_gzip_file: The bytes of the tar.gz file to be decompressed.
452
+ :return: A dictionary of file name to file bytes for each file in the tar.gz
453
+ """
454
+ extracted_files: dict[str, bytes] = {}
455
+ with io.BytesIO(tar_gzip_file) as tar_buffer:
456
+ with tarfile.open(fileobj=tar_buffer, mode="r:gz") as tar:
457
+ for member in tar.getmembers():
458
+ if member.isfile():
459
+ file_obj = tar.extractfile(member)
460
+ if file_obj:
461
+ with file_obj:
462
+ extracted_files[member.name] = file_obj.read()
463
+ return extracted_files
464
+
338
465
  # Deprecated functions:
339
466
 
340
467
  # FR-46097 - Add write file request shorthand functions to FileUtil.
@@ -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) -> None:
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()
@@ -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.1a772
3
+ Version: 2025.10.2a773
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,6 +1,41 @@
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/converter_service_base.py,sha256=HiUXmwqv1STgyQeF9_eTFXzjIFXp5-NJ7sEhMpV3aAU,6351
4
+ sapiopycommons/ai/protobuf_utils.py,sha256=cBjbxoFAwU02kNUxEce95WnMU2CMuDD-qFaeWgvQJMQ,24599
5
+ sapiopycommons/ai/request_validation.py,sha256=AOpLoXYRnKf0h7MRNj6ev_rfcRxXREzQgBcbpBp5loY,24014
6
+ sapiopycommons/ai/server.py,sha256=1ksOax2cab9MH7ESXQ5dwVNZcBKiWpNVhkzO4KkFTSg,6370
7
+ sapiopycommons/ai/test_client.py,sha256=Um93jXmIx0YaHf-YbV5NSamPTHveJ0kU_UaAfOApnZg,16342
8
+ sapiopycommons/ai/tool_service_base.py,sha256=_KHd9Y2C8gg3Ad-4ubP9fMf5_kMC41k5LZh8EfAW6MU,54435
9
+ sapiopycommons/ai/protoapi/fielddefinitions/fields_pb2.py,sha256=8tKXwLXcqFGdQHHSEBSi6Fd7dcaCFoOqmhjzqhenb_M,2372
10
+ sapiopycommons/ai/protoapi/fielddefinitions/fields_pb2.pyi,sha256=FwtXmNAf7iYGEFm4kbqb04v77jNHbZg18ZmEDhle_bU,1444
11
+ sapiopycommons/ai/protoapi/fielddefinitions/fields_pb2_grpc.py,sha256=uO25bcnfGqXpP4ggUur54Nr73Wj-DGWftExzLNcxdHI,931
12
+ sapiopycommons/ai/protoapi/fielddefinitions/velox_field_def_pb2.py,sha256=in9iHiLPYcnLWoLeqy4nWSI0jZGHD_bMhEFRIRtJPuo,20864
13
+ sapiopycommons/ai/protoapi/fielddefinitions/velox_field_def_pb2.pyi,sha256=U5zXrbBxsWilLTsRWJd1TqjdjLKFsr3enF9OJ8GfyWw,34028
14
+ sapiopycommons/ai/protoapi/fielddefinitions/velox_field_def_pb2_grpc.py,sha256=Vj6qDKvsHgl25iBi3UjtTuGxihekgqCuufExvnJKzQI,940
15
+ sapiopycommons/ai/protoapi/plan/step_output_pb2.py,sha256=EBNCzLUDwwCqDCh35zSfFdfq0RP8WrmTMXEzEPu_1_E,2655
16
+ sapiopycommons/ai/protoapi/plan/step_output_pb2.pyi,sha256=yuxOYnDZ9DRuu-TLzaKOW_B4LUiYxTrNc2AbssXg4kE,2022
17
+ sapiopycommons/ai/protoapi/plan/step_output_pb2_grpc.py,sha256=ebWLIfOFeVE2WuUIThMBerVweH-1phviGX195UTwYyg,924
18
+ sapiopycommons/ai/protoapi/plan/step_pb2.py,sha256=mKTm_syaX99GzhWtGIPkxMTsfcsvW0QbRqjv06eHSM0,2433
19
+ sapiopycommons/ai/protoapi/plan/step_pb2.pyi,sha256=QPIcsjcUvEGQkdZMUMiVzFFNDl8yOUe_qJtf5XEp5Ck,2062
20
+ sapiopycommons/ai/protoapi/plan/step_pb2_grpc.py,sha256=1CBna5NBBxPwQhrkN8-Fim_j3FGmOfDo5C4c8sIBV8Q,917
21
+ sapiopycommons/ai/protoapi/plan/converter/converter_pb2.py,sha256=rZYBRfR0umwDYvBdYnzxR1VZSutRqunhd3QsdtQXiCM,3593
22
+ sapiopycommons/ai/protoapi/plan/converter/converter_pb2.pyi,sha256=_35yHfKTJH3SMdA5_c6qF6OZG6UwFWXpNh6dwRFDKkk,4250
23
+ sapiopycommons/ai/protoapi/plan/converter/converter_pb2_grpc.py,sha256=6T5FCmT_vEFSywUVlAlWWfBDPaILb0Dq8yCGuO_Q-BU,6448
24
+ sapiopycommons/ai/protoapi/plan/item/item_container_pb2.py,sha256=VIXmIw8-9jtH7peJZ16BEmGDfaVjjxTKhmlfcHWT82M,3863
25
+ sapiopycommons/ai/protoapi/plan/item/item_container_pb2.pyi,sha256=bbPNQDwfFDd7_S7yU99Co1O7sRhxjle-RM0_nK8jgjc,4246
26
+ sapiopycommons/ai/protoapi/plan/item/item_container_pb2_grpc.py,sha256=1NzBWBUINC0Rk-NGYZ-97BVKvVUxcn_I44IjQO2h-nQ,932
27
+ sapiopycommons/ai/protoapi/plan/script/script_pb2.py,sha256=swyahlxM7fKm-RqtgMd1Czqd1JrbXRw3sYqFTkjbbyM,5144
28
+ sapiopycommons/ai/protoapi/plan/script/script_pb2.pyi,sha256=GqlqLf9UX_B5vCR9cm-VoYLHFJNmZjJafcPJ6EDa8Qw,6192
29
+ sapiopycommons/ai/protoapi/plan/script/script_pb2_grpc.py,sha256=ginPYpsiI6U6dB6gfWHJM8LWjSHUgcqz_gR7Dmdsyck,6864
30
+ sapiopycommons/ai/protoapi/plan/tool/entry_pb2.py,sha256=yNyyyVvz94ewjGaHw3t0pUP-KH7ACg5hLC0QzrsFPis,2130
31
+ sapiopycommons/ai/protoapi/plan/tool/entry_pb2.pyi,sha256=2vI0WSy0KGFHDewMSRyX5rUkmmmSaMBLvFO7txqA6Ug,2354
32
+ sapiopycommons/ai/protoapi/plan/tool/entry_pb2_grpc.py,sha256=i24BfJEt7LtyROxHVEyS9RLYqLZKPvyJMKRFZj6NUTg,923
33
+ sapiopycommons/ai/protoapi/plan/tool/tool_pb2.py,sha256=4SqqRZAyxTnR86irNuuOVRvo3r8MFqgVkkqpHwu3uSY,8563
34
+ sapiopycommons/ai/protoapi/plan/tool/tool_pb2.pyi,sha256=fVx33ImMoZWVDSFLZWs6uukjRzLfY7OI9mUhDUS2-8g,17518
35
+ sapiopycommons/ai/protoapi/plan/tool/tool_pb2_grpc.py,sha256=CLSGEgSpN4D6wcE-P_5lzb2Nttjr4XjumxGUrZQSip0,6915
36
+ sapiopycommons/ai/protoapi/session/sapio_conn_info_pb2.py,sha256=MhWzTyJz3xZgpdW8_LCVKuzKXT0cv6iHMRB-UNCUNzM,2094
37
+ sapiopycommons/ai/protoapi/session/sapio_conn_info_pb2.pyi,sha256=vLYA8Tkzq2AwgVadoUp5vAg4HgGlgga0kzeS3e_XkCQ,1621
38
+ sapiopycommons/ai/protoapi/session/sapio_conn_info_pb2_grpc.py,sha256=imcciy_kbmm7OV_W3jYZ53R6GQ6Yh-eUcVW0A9GkWdg,931
4
39
  sapiopycommons/callbacks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
40
  sapiopycommons/callbacks/callback_util.py,sha256=Z1LcXnRRjXyhmcSDUwh4NzcA6ICtcbFUMKcvAqQcS8E,153811
6
41
  sapiopycommons/callbacks/field_builder.py,sha256=rnIP-RJafk3mZlAx1eJ8a0eSW9Ps_L6_WadCmusnENw,38772
@@ -31,9 +66,10 @@ sapiopycommons/files/file_bridge.py,sha256=vKbqxPexi15epr_-_qLrEfYoxNxB031mXN92i
31
66
  sapiopycommons/files/file_bridge_handler.py,sha256=SEYDIQhSCmjI6qyLdDJE8JVKSd0WYvF7JvAq_Ahp9Do,25503
32
67
  sapiopycommons/files/file_data_handler.py,sha256=f96MlkMuQhUCi4oLnzJK5AiuElCp5jLI8_sJkZVwpws,36779
33
68
  sapiopycommons/files/file_text_converter.py,sha256=Gaj_divTiKXWd6flDOgrxNXpcn9fDWqxX6LUG0joePk,7516
34
- sapiopycommons/files/file_util.py,sha256=djouyGjsYgWzjz2OBRnSeMDgj6NrsJUm1a2J93J8Wco,31915
69
+ sapiopycommons/files/file_util.py,sha256=WBA3FYG8R2HtfxjWSzQhZKW6_1s6JSxTo9lk3SeNDu8,37140
35
70
  sapiopycommons/files/file_validator.py,sha256=ryg22-93csmRO_Pv0ZpWphNkB74xWZnHyJ23K56qLj0,28761
36
71
  sapiopycommons/files/file_writer.py,sha256=hACVl0duCjP28gJ1NPljkjagNCLod0ygUlPbvUmRDNM,17605
72
+ sapiopycommons/files/temp_files.py,sha256=i-xgh4puYLtREI1ZtKq8y5q1lRWQX_UrVyJd2yQO0hw,3183
37
73
  sapiopycommons/flowcyto/flow_cyto.py,sha256=B6DFquLi-gcWfJWyP4vYfwTXXJKl6O9W5-k8FzkM0Oo,2610
38
74
  sapiopycommons/flowcyto/flowcyto_data.py,sha256=mYKFuLbtpJ-EsQxLGtu4tNHVlygTxKixgJxJqD68F58,2596
39
75
  sapiopycommons/general/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -65,8 +101,8 @@ sapiopycommons/sftpconnect/sftp_builder.py,sha256=lFK3FeXk-sFLefW0hqY8WGUQDeYiGa
65
101
  sapiopycommons/webhook/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
102
  sapiopycommons/webhook/webhook_context.py,sha256=D793uLsb1691SalaPnBUk3rOSxn_hYLhdvkaIxjNXss,1909
67
103
  sapiopycommons/webhook/webhook_handlers.py,sha256=7o_wXOruhT9auNh8OfhJAh4WhhiPKij67FMBSpGPICc,39939
68
- sapiopycommons/webhook/webservice_handlers.py,sha256=tyaYGG1-v_JJrJHZ6cy5mGCxX9z1foLw7pM4MDJlFxs,14297
69
- sapiopycommons-2025.10.1a772.dist-info/METADATA,sha256=46DnmYqeaCn2LEDVsAa04CKrMG-itXhYN7jp6imhzCI,3142
70
- sapiopycommons-2025.10.1a772.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
71
- sapiopycommons-2025.10.1a772.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
72
- sapiopycommons-2025.10.1a772.dist-info/RECORD,,
104
+ sapiopycommons/webhook/webservice_handlers.py,sha256=cvW6Mk_110BzYqkbk63Kg7jWrltBCDALOlkJRu8h4VQ,14300
105
+ sapiopycommons-2025.10.2a773.dist-info/METADATA,sha256=OSVEDDTYHDZMjMAbq5ptDU5Nsu4uZ774wYZqnFIZ7Ww,3142
106
+ sapiopycommons-2025.10.2a773.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
107
+ sapiopycommons-2025.10.2a773.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
108
+ sapiopycommons-2025.10.2a773.dist-info/RECORD,,