sapiopycommons 2025.2.20a441__tar.gz → 2025.2.20a443__tar.gz

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 (83) hide show
  1. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/PKG-INFO +1 -1
  2. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/pyproject.toml +1 -1
  3. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/ai/tool_of_tools.py +32 -16
  4. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/.gitignore +0 -0
  5. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/LICENSE +0 -0
  6. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/README.md +0 -0
  7. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/__init__.py +0 -0
  8. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/ai/__init__.py +0 -0
  9. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/callbacks/__init__.py +0 -0
  10. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/callbacks/callback_util.py +0 -0
  11. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/callbacks/field_builder.py +0 -0
  12. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/chem/IndigoMolecules.py +0 -0
  13. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/chem/Molecules.py +0 -0
  14. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/chem/__init__.py +0 -0
  15. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/customreport/__init__.py +0 -0
  16. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/customreport/auto_pagers.py +0 -0
  17. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/customreport/column_builder.py +0 -0
  18. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/customreport/custom_report_builder.py +0 -0
  19. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/customreport/term_builder.py +0 -0
  20. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/datatype/__init__.py +0 -0
  21. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/datatype/attachment_util.py +0 -0
  22. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/datatype/data_fields.py +0 -0
  23. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/datatype/pseudo_data_types.py +0 -0
  24. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/eln/__init__.py +0 -0
  25. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/eln/experiment_handler.py +0 -0
  26. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/eln/experiment_report_util.py +0 -0
  27. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/eln/plate_designer.py +0 -0
  28. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/files/__init__.py +0 -0
  29. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/files/complex_data_loader.py +0 -0
  30. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/files/file_bridge.py +0 -0
  31. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/files/file_bridge_handler.py +0 -0
  32. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/files/file_data_handler.py +0 -0
  33. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/files/file_util.py +0 -0
  34. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/files/file_validator.py +0 -0
  35. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/files/file_writer.py +0 -0
  36. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/flowcyto/flow_cyto.py +0 -0
  37. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/flowcyto/flowcyto_data.py +0 -0
  38. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/general/__init__.py +0 -0
  39. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/general/accession_service.py +0 -0
  40. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/general/aliases.py +0 -0
  41. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/general/audit_log.py +0 -0
  42. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/general/custom_report_util.py +0 -0
  43. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/general/directive_util.py +0 -0
  44. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/general/exceptions.py +0 -0
  45. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/general/popup_util.py +0 -0
  46. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/general/sapio_links.py +0 -0
  47. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/general/storage_util.py +0 -0
  48. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/general/time_util.py +0 -0
  49. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/multimodal/multimodal.py +0 -0
  50. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/multimodal/multimodal_data.py +0 -0
  51. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/processtracking/__init__.py +0 -0
  52. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/processtracking/custom_workflow_handler.py +0 -0
  53. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/processtracking/endpoints.py +0 -0
  54. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/recordmodel/__init__.py +0 -0
  55. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/recordmodel/record_handler.py +0 -0
  56. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/rules/__init__.py +0 -0
  57. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/rules/eln_rule_handler.py +0 -0
  58. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/rules/on_save_rule_handler.py +0 -0
  59. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/samples/aliquot.py +0 -0
  60. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/sftpconnect/__init__.py +0 -0
  61. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/sftpconnect/sftp_builder.py +0 -0
  62. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/webhook/__init__.py +0 -0
  63. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/webhook/webhook_context.py +0 -0
  64. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/webhook/webhook_handlers.py +0 -0
  65. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/src/sapiopycommons/webhook/webservice_handlers.py +0 -0
  66. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/tests/AF-A0A009IHW8-F1-model_v4.cif +0 -0
  67. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/tests/_do_not_add_init_py_here +0 -0
  68. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/tests/accession_test.py +0 -0
  69. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/tests/aliquot_test.py +0 -0
  70. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/tests/bio_reg_test.py +0 -0
  71. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/tests/chem_test.py +0 -0
  72. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/tests/chem_test_curation_queue.py +0 -0
  73. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/tests/curation_queue_test.sdf +0 -0
  74. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/tests/data_type_models.py +0 -0
  75. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/tests/flowcyto/101_DEN084Y5_15_E01_008_clean.fcs +0 -0
  76. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/tests/flowcyto/101_DEN084Y5_15_E03_009_clean.fcs +0 -0
  77. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/tests/flowcyto/101_DEN084Y5_15_E05_010_clean.fcs +0 -0
  78. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/tests/flowcyto/8_color_ICS.wsp +0 -0
  79. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/tests/flowcyto/COVID19_W_001_O.fcs +0 -0
  80. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/tests/flowcyto_test.py +0 -0
  81. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/tests/kappa.chains.fasta +0 -0
  82. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/tests/mafft_test.py +0 -0
  83. {sapiopycommons-2025.2.20a441 → sapiopycommons-2025.2.20a443}/tests/test.gb +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: sapiopycommons
3
- Version: 2025.2.20a441
3
+ Version: 2025.2.20a443
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>
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sapiopycommons"
7
- version='2025.02.20a441'
7
+ version='2025.02.20a443'
8
8
  authors = [
9
9
  { name="Jonathan Steck", email="jsteck@sapiosciences.com" },
10
10
  { name="Yechen Qiao", email="yqiao@sapiosciences.com" },
@@ -2,7 +2,7 @@ import base64
2
2
  import io
3
3
  import math
4
4
  import re
5
- from typing import Final, Mapping, Any
5
+ from typing import Final, Mapping, Any, cast
6
6
 
7
7
  import requests
8
8
  from pandas import DataFrame
@@ -18,7 +18,8 @@ from sapiopylib.rest.pojo.chartdata.DashboardEnums import ChartGroupingType, Cha
18
18
  from sapiopylib.rest.pojo.chartdata.DashboardSeries import GaugeChartSeries
19
19
  from sapiopylib.rest.pojo.datatype.DataType import DataTypeDefinition
20
20
  from sapiopylib.rest.pojo.datatype.DataTypeLayout import DataTypeLayout, TableLayout
21
- from sapiopylib.rest.pojo.datatype.FieldDefinition import AbstractVeloxFieldDefinition, FieldType
21
+ from sapiopylib.rest.pojo.datatype.FieldDefinition import AbstractVeloxFieldDefinition, FieldType, \
22
+ VeloxStringFieldDefinition
22
23
  from sapiopylib.rest.pojo.eln.ElnEntryPosition import ElnEntryPosition
23
24
  from sapiopylib.rest.pojo.eln.ElnExperiment import ElnExperiment
24
25
  from sapiopylib.rest.pojo.eln.ExperimentEntry import ExperimentEntry
@@ -310,17 +311,39 @@ class AiHelper:
310
311
  # Determine which fields in the JSON can be used to create field definitions.
311
312
  fb = FieldBuilder()
312
313
  fields: list[AbstractVeloxFieldDefinition] = []
313
- fields_by_name: dict[str, AbstractVeloxFieldDefinition] = {}
314
+ fields_by_json_key: dict[str, AbstractVeloxFieldDefinition] = {}
315
+ string_field_lengths: dict[str, int] = {}
314
316
  for key, value in json_list[0].items():
315
- field_name: str = key.replace(" ", "_")
317
+ # The field name is the JSON key name, but with spaces and dashes replaced by underscores and with a leading
318
+ # underscore added if the field name starts with a number.
319
+ field_name: str = key.strip()
320
+ if " " in field_name:
321
+ field_name = field_name.replace(" ", "_")
322
+ if "-" in field_name:
323
+ field_name = field_name.replace("-", "_")
324
+ if field_name[0].isnumeric():
325
+ field_name = "_" + field_name
326
+
316
327
  if isinstance(value, str):
317
328
  field = fb.string_field(field_name, display_name=key)
318
329
  fields.append(field)
319
- fields_by_name[key] = field
330
+ fields_by_json_key[key] = field
331
+ string_field_lengths[key] = 100
320
332
  elif isinstance(value, (int, float)):
321
333
  field = fb.double_field(field_name, display_name=key, precision=3)
322
334
  fields.append(field)
323
- fields_by_name[key] = field
335
+ fields_by_json_key[key] = field
336
+
337
+ # Determine the max length of each string field.
338
+ for values in json_list:
339
+ for key in string_field_lengths:
340
+ length: int = len(values.get(key)) if values.get(key) else 0
341
+ string_field_lengths[key] = max(string_field_lengths[key], length)
342
+
343
+ # Update the max length of each string field.
344
+ for key in string_field_lengths:
345
+ field = cast(VeloxStringFieldDefinition, fields_by_json_key[key])
346
+ field.max_length = string_field_lengths[key]
324
347
 
325
348
  # Sort the JSON list if requested.
326
349
  if sort_field and sort_direction != SortDirection.NONE:
@@ -340,7 +363,7 @@ class AiHelper:
340
363
  field_maps: list[dict[str, Any]] = []
341
364
  for json_dict in json_list:
342
365
  field_map: dict[str, Any] = {}
343
- for key, field in fields_by_name.items():
366
+ for key, field in fields_by_json_key.items():
344
367
  # Watch out for NaN values or other special values in numeric columns.
345
368
  val: Any = json_dict.get(key)
346
369
  if (field.data_field_type == FieldType.DOUBLE
@@ -497,14 +520,14 @@ class AiHelper:
497
520
  with io.BytesIO(image) as bytes_io:
498
521
  self.dr_man.set_record_image(record, bytes_io)
499
522
 
500
- def create_bar_chart(self, entry_name: str, source_entry: ExperimentEntry, tab: ElnExperimentTab,
523
+ def create_bar_chart(self, entry_name: str, tab: ElnExperimentTab, source_entry: ExperimentEntry,
501
524
  x_axis: str, y_axis: str) -> ExperimentEntry:
502
525
  """
503
526
  Create a bar chart in the experiment based on the contents of the given source entry.
504
527
 
505
528
  :param entry_name: The name of the bar chart.
506
- :param source_entry: The source entry to base the bar chart on.
507
529
  :param tab: The tab to create the bar chart in.
530
+ :param source_entry: The source entry to base the bar chart on.
508
531
  :param x_axis: The field to use for the x-axis.
509
532
  :param y_axis: The field to use for the y-axis.
510
533
  :return: The newly created bar chart entry.
@@ -676,13 +699,6 @@ class ToolOfToolsHelper:
676
699
  dash_update_crit.column_span = 2
677
700
  self.eln_man.update_experiment_entry(self.exp_id, self.progress_gauge_entry.get_id(), dash_update_crit)
678
701
 
679
- # TODO: Bulk updates aren't working?
680
- # self.eln_man.update_experiment_entries(self.exp_id, {
681
- # self.progress_entry.get_id(): form_update_crit,
682
- # self.progress_gauge_entry.get_id(): dash_update_crit,
683
- # self.description_entry.get_id(): text_update_crit
684
- # })
685
-
686
702
  # Create a results entry if this tool produces result records.
687
703
  if self.results_data_type:
688
704
  results_entry = ELNStepFactory.create_table_step(self.helper.protocol, f"{self.name} Results",