sapiopycommons 2025.2.6a421__py3-none-any.whl → 2025.2.7a424__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 (27) hide show
  1. sapiopycommons/callbacks/callback_util.py +363 -1217
  2. sapiopycommons/chem/Molecules.py +2 -0
  3. sapiopycommons/datatype/data_fields.py +1 -1
  4. sapiopycommons/eln/experiment_handler.py +1 -2
  5. sapiopycommons/eln/experiment_report_util.py +7 -7
  6. sapiopycommons/files/file_bridge.py +0 -76
  7. sapiopycommons/files/file_bridge_handler.py +110 -325
  8. sapiopycommons/files/file_data_handler.py +2 -2
  9. sapiopycommons/files/file_validator.py +5 -6
  10. sapiopycommons/flowcyto/flow_cyto.py +1 -1
  11. sapiopycommons/general/accession_service.py +1 -1
  12. sapiopycommons/general/aliases.py +27 -40
  13. sapiopycommons/general/audit_log.py +2 -2
  14. sapiopycommons/general/custom_report_util.py +1 -24
  15. sapiopycommons/general/exceptions.py +2 -41
  16. sapiopycommons/multimodal/multimodal.py +0 -1
  17. sapiopycommons/processtracking/custom_workflow_handler.py +3 -3
  18. sapiopycommons/recordmodel/record_handler.py +3 -5
  19. sapiopycommons/webhook/webhook_handlers.py +55 -445
  20. {sapiopycommons-2025.2.6a421.dist-info → sapiopycommons-2025.2.7a424.dist-info}/METADATA +1 -1
  21. {sapiopycommons-2025.2.6a421.dist-info → sapiopycommons-2025.2.7a424.dist-info}/RECORD +23 -27
  22. sapiopycommons/customreport/auto_pagers.py +0 -270
  23. sapiopycommons/elain/__init__.py +0 -0
  24. sapiopycommons/elain/tool_of_tools.py +0 -510
  25. sapiopycommons/general/directive_util.py +0 -86
  26. {sapiopycommons-2025.2.6a421.dist-info → sapiopycommons-2025.2.7a424.dist-info}/WHEEL +0 -0
  27. {sapiopycommons-2025.2.6a421.dist-info → sapiopycommons-2025.2.7a424.dist-info}/licenses/LICENSE +0 -0
@@ -1,53 +1,49 @@
1
1
  sapiopycommons/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  sapiopycommons/callbacks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- sapiopycommons/callbacks/callback_util.py,sha256=68lPK8GtE6zd8C0fQaMLxT57PtU-6HnO37Zk-u56Mrs,129933
3
+ sapiopycommons/callbacks/callback_util.py,sha256=2pGr14f_FVCqeF6dsbYP1e4cOsaUTQyQ7XVwZuUkM_k,67952
4
4
  sapiopycommons/callbacks/field_builder.py,sha256=p2XacN99MuKk3ite8GAqstUMpixqugul2CsC4gB83-o,38620
5
5
  sapiopycommons/chem/IndigoMolecules.py,sha256=slM2y39zZFHc468c366EqR8T-GYJ24UnM9HWAqWFEwQ,3900
6
- sapiopycommons/chem/Molecules.py,sha256=5PzRyE1s-Z3nfwh3Y4dCNdQOIJGhog08wyZvgTkKwyU,12384
6
+ sapiopycommons/chem/Molecules.py,sha256=9B4sbwbvYs50XHRn0TZiu-D1Oa3pKrI9qE5vNW8zv-U,12464
7
7
  sapiopycommons/chem/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  sapiopycommons/customreport/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- sapiopycommons/customreport/auto_pagers.py,sha256=9G0yo288ODzpJ5jzdMi8GknB1iWwbK_5_LGuoDUBoA8,13967
10
9
  sapiopycommons/customreport/column_builder.py,sha256=0RO53e9rKPZ07C--KcepN6_tpRw_FxF3O9vdG0ilKG8,3014
11
10
  sapiopycommons/customreport/custom_report_builder.py,sha256=BlTxZ4t1sfZA2Ciur1EfYvkZxHxJ7ADwYNAe2zwiN0c,7176
12
11
  sapiopycommons/customreport/term_builder.py,sha256=PNp71NF1vFxidk5v6uQNi9oQR9KJIk8WfhyntvvZN-U,18573
13
12
  sapiopycommons/datatype/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
13
  sapiopycommons/datatype/attachment_util.py,sha256=_l2swuP8noIGAl4bwzBUEhr6YlN_OVZl3-gi1XqFHYA,3364
15
- sapiopycommons/datatype/data_fields.py,sha256=C6HpqtEuF0KsxhlBUprfyv1XguaXql3EYWVbh8y-IFU,4064
14
+ sapiopycommons/datatype/data_fields.py,sha256=g8Ib6LH8ikNu9AzeVJs8Z2qS8A-cplACeFU7vYguNEY,4063
16
15
  sapiopycommons/datatype/pseudo_data_types.py,sha256=6TG7aJxgmUZ8FQkWBcgmbK5oy7AFFNtKOPpi1w1OOYA,27657
17
- sapiopycommons/elain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
- sapiopycommons/elain/tool_of_tools.py,sha256=laacUopEoExV5ayt7-UA1UeXczqDDJlt6AlRAug6dzQ,25237
19
16
  sapiopycommons/eln/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
- sapiopycommons/eln/experiment_handler.py,sha256=8hmR7sawDo9K6iBwB44QSoxlH1M91inor7dfuXQ4LKs,69323
21
- sapiopycommons/eln/experiment_report_util.py,sha256=EA2Iq8gW17bSEI6lPoHYQQ-fDvG4O28RWOoTPXpOlUw,36640
17
+ sapiopycommons/eln/experiment_handler.py,sha256=ZSx0uZy-2OtH_ArHy2OVwoNI3BYQLXSHGBmjviZl1Fw,69283
18
+ sapiopycommons/eln/experiment_report_util.py,sha256=bs9zSUgRo40q2VYtjDCVPsT-D1umdNfl5s4oZrY4uuc,36597
22
19
  sapiopycommons/eln/plate_designer.py,sha256=FYJfhhNq8hdfuXgDYOYHy6g0m2zNwQXZWF_MTPzElDg,7184
23
20
  sapiopycommons/files/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
21
  sapiopycommons/files/complex_data_loader.py,sha256=T39veNhvYl6j_uZjIIJ8Mk5Aa7otR5RB-g8XlAdkksA,1421
25
- sapiopycommons/files/file_bridge.py,sha256=vKbqxPexi15epr_-_qLrEfYoxNxB031mXN92iVtOMqE,9511
26
- sapiopycommons/files/file_bridge_handler.py,sha256=SEYDIQhSCmjI6qyLdDJE8JVKSd0WYvF7JvAq_Ahp9Do,25503
27
- sapiopycommons/files/file_data_handler.py,sha256=f96MlkMuQhUCi4oLnzJK5AiuElCp5jLI8_sJkZVwpws,36779
22
+ sapiopycommons/files/file_bridge.py,sha256=WwCVegk0OGA8eqho8chsOsLlqg1nXctO75zfh-rHF-g,5950
23
+ sapiopycommons/files/file_bridge_handler.py,sha256=bt2IfIsxJ4lcJYo_NHvCQ17ZV6C4fSAEa8Zcgixh7B4,14263
24
+ sapiopycommons/files/file_data_handler.py,sha256=SCsjODMJIPEBSsahzXUeOM7CfSCmYwPPoGAM6aOfelo,36743
28
25
  sapiopycommons/files/file_util.py,sha256=wbL3rxcFc-t2mXaPWWkoFWYGopvTcQts9Wf-L5GkhT8,29498
29
- sapiopycommons/files/file_validator.py,sha256=ryg22-93csmRO_Pv0ZpWphNkB74xWZnHyJ23K56qLj0,28761
26
+ sapiopycommons/files/file_validator.py,sha256=4OvY98ueJWPJdpndwnKv2nqVvLP9S2W7Il_dM0Y0ojo,28709
30
27
  sapiopycommons/files/file_writer.py,sha256=96Xl8TTT46Krxe_J8rmmlEMtel4nzZB961f5Yqtl1-I,17616
31
- sapiopycommons/flowcyto/flow_cyto.py,sha256=vs9WhXXKz3urpjL8QKSk56B-NSmQR3O3x_WFBKoeO10,3227
28
+ sapiopycommons/flowcyto/flow_cyto.py,sha256=YlkKJR_zEHYRuNW0bnTqlTyZeXs0lOaeSCfG2fnfD7E,3227
32
29
  sapiopycommons/flowcyto/flowcyto_data.py,sha256=mYKFuLbtpJ-EsQxLGtu4tNHVlygTxKixgJxJqD68F58,2596
33
30
  sapiopycommons/general/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
- sapiopycommons/general/accession_service.py,sha256=QeNGd78Zr08ezWpThTuAkxO4bXusEcp5x9jJRZRwliA,13483
35
- sapiopycommons/general/aliases.py,sha256=jh68NG8VSrgfQNDiPlMv_o5qHEFFBed55-cXHxHdCyw,13806
36
- sapiopycommons/general/audit_log.py,sha256=KQq0PsvukUoE3l6TQb3-vpu5-MbSINpWlnQ9e7jojPg,8743
37
- sapiopycommons/general/custom_report_util.py,sha256=NwwmejSQLwSbrndEk1gPyFNYk9GZoS7Wrp9ab9moFgw,18014
38
- sapiopycommons/general/directive_util.py,sha256=7SeQrd2Ye5JHlXZtJZaVGgtaSLdq_Vm9EObuxf44Pz8,3905
39
- sapiopycommons/general/exceptions.py,sha256=aPlzK1cvxeMU5UsokYlLrIBGltUfJZ7LH8zvLh9DxpI,3233
31
+ sapiopycommons/general/accession_service.py,sha256=HYgyOsH_UaoRnoury-c2yTW8SeG4OtjLemdpCzoV4R8,13484
32
+ sapiopycommons/general/aliases.py,sha256=tdDBNWSGx6s39eHJ3n2kscc4xxW3ZYaUfDftct6FmJE,12910
33
+ sapiopycommons/general/audit_log.py,sha256=pvXPfLr4Rw2X52wAXJGsX5fsPllswnCqaFZQ181j_GU,8727
34
+ sapiopycommons/general/custom_report_util.py,sha256=6ZIg_Jl02TYUygfc5xqBoI1srPsSxLyxaJ9jwTolGcM,16671
35
+ sapiopycommons/general/exceptions.py,sha256=GY7fe0qOgoy4kQVn_Pn3tdzHsJZyNIpa6VCChg6tzuM,1813
40
36
  sapiopycommons/general/popup_util.py,sha256=L-4qpTemSZdlD6_6oEsDYIzLOCiZgDK6wC6DqUwzOYA,31925
41
37
  sapiopycommons/general/sapio_links.py,sha256=o9Z-8y2rz6AI0Cy6tq58ElPge9RBnisGc9NyccbaJxs,2610
42
38
  sapiopycommons/general/storage_util.py,sha256=ovmK_jN7v09BoX07XxwShpBUC5WYQOM7dbKV_VeLXJU,8892
43
39
  sapiopycommons/general/time_util.py,sha256=jU1urPoZRv6evNucR0-288EyT4PrsDpCr-H1-7BKq9A,12363
44
- sapiopycommons/multimodal/multimodal.py,sha256=PFaGJPbKvW__tnxb8KkgkJZOKjQdgxF_kGfD5chet1s,6779
40
+ sapiopycommons/multimodal/multimodal.py,sha256=A1QsC8QTPmgZyPr7KtMbPRedn2Ie4WIErodUvQ9otgU,6724
45
41
  sapiopycommons/multimodal/multimodal_data.py,sha256=0BeVPr9HaC0hNTF1v1phTIKGruvNnwerHsD994qJKBg,15099
46
42
  sapiopycommons/processtracking/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
- sapiopycommons/processtracking/custom_workflow_handler.py,sha256=NY0HboLMI9WX1u7Fwad-KreEyhaHtYBTAmi-fHtZGCg,23509
43
+ sapiopycommons/processtracking/custom_workflow_handler.py,sha256=B8KxQlwlLGkxnEid2jb9igGyGqrtcsBMhcOb9MfnO9E,23465
48
44
  sapiopycommons/processtracking/endpoints.py,sha256=w5bziI2xC7450M95rCF8JpRwkoni1kEDibyAux9B12Q,10848
49
45
  sapiopycommons/recordmodel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
- sapiopycommons/recordmodel/record_handler.py,sha256=47VNr3CfL51myaySGZ8yElNJrljcbHaxEfx0V9xPGog,64945
46
+ sapiopycommons/recordmodel/record_handler.py,sha256=5kCO5zsSg0kp3uYpgw1vf0WLHw30pMNC_6Bn3G7iQkI,64796
51
47
  sapiopycommons/rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
48
  sapiopycommons/rules/eln_rule_handler.py,sha256=JYzDA_14D2nLnlqwbpIxVOrfKWzbOS27AYf4TQfGr4Q,10469
53
49
  sapiopycommons/rules/on_save_rule_handler.py,sha256=Rkqvph20RbNq6m-RF4fbvCP-YfD2CZYBM2iTr3nl0eY,10236
@@ -55,9 +51,9 @@ sapiopycommons/sftpconnect/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
55
51
  sapiopycommons/sftpconnect/sftp_builder.py,sha256=lFK3FeXk-sFLefW0hqY8WGUQDeYiGaT6yDACzT_zFgQ,3015
56
52
  sapiopycommons/webhook/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
53
  sapiopycommons/webhook/webhook_context.py,sha256=D793uLsb1691SalaPnBUk3rOSxn_hYLhdvkaIxjNXss,1909
58
- sapiopycommons/webhook/webhook_handlers.py,sha256=M5PMt-j7PpnzUQMUQDTvqwJUyJNxuFtC9wdnk5VRNpI,39703
54
+ sapiopycommons/webhook/webhook_handlers.py,sha256=MdsVK4bHffkMNmNWl0_qvu-5Lz8-qGu4Ryi7lZO1BZs,18586
59
55
  sapiopycommons/webhook/webservice_handlers.py,sha256=Y5dHx_UFWFuSqaoPL6Re-fsKYRuxvCWZ8bj6KSZ3jfM,14285
60
- sapiopycommons-2025.2.6a421.dist-info/METADATA,sha256=90F0XGGSIBnyrH9EKr1tN-ej-0XNoGxKBBXOebv3898,3142
61
- sapiopycommons-2025.2.6a421.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
62
- sapiopycommons-2025.2.6a421.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
63
- sapiopycommons-2025.2.6a421.dist-info/RECORD,,
56
+ sapiopycommons-2025.2.7a424.dist-info/METADATA,sha256=NgAKSa4bMurJPQ7m1b0gqRBEjMC73Too_nJi2LOphQg,3142
57
+ sapiopycommons-2025.2.7a424.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
58
+ sapiopycommons-2025.2.7a424.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
59
+ sapiopycommons-2025.2.7a424.dist-info/RECORD,,
@@ -1,270 +0,0 @@
1
- from abc import ABC
2
- from copy import copy
3
- from queue import Queue
4
-
5
- from sapiopylib.rest.CustomReportService import CustomReportManager
6
- from sapiopylib.rest.DataMgmtService import DataMgmtServer
7
- from sapiopylib.rest.pojo.CustomReport import CustomReportCriteria, CustomReport, RawReportTerm, ReportColumn
8
- from sapiopylib.rest.pojo.datatype.FieldDefinition import FieldType
9
- from sapiopylib.rest.utils.autopaging import SapioPyAutoPager, PagerResultCriteriaType, _default_report_page_size, \
10
- _default_record_page_size
11
- from sapiopylib.rest.utils.recordmodel.RecordModelWrapper import WrappedType
12
-
13
- from sapiopycommons.general.aliases import FieldValue, UserIdentifier, AliasUtil, RecordModel
14
- from sapiopycommons.general.custom_report_util import CustomReportUtil
15
- from sapiopycommons.general.exceptions import SapioException
16
- from sapiopycommons.recordmodel.record_handler import RecordHandler
17
-
18
-
19
- # FR-47389: Create auto pagers for running custom/system/quick reports that return dictionaries or records for each row.
20
- class _DictReportPagerBase(SapioPyAutoPager[CustomReportCriteria, dict[str, FieldValue]], ABC):
21
- """
22
- A base class for automatically paging through a report and returning the results as a list of dictionaries.
23
- """
24
- _columns: list[ReportColumn]
25
- _report_man: CustomReportManager
26
-
27
- def __init__(self, user: UserIdentifier, first_page_criteria: CustomReportCriteria):
28
- self._columns = first_page_criteria.column_list
29
- super().__init__(AliasUtil.to_sapio_user(user), first_page_criteria)
30
- self._report_man = DataMgmtServer.get_custom_report_manager(self.user)
31
-
32
- def get_all_at_once(self) -> list[dict[str, FieldValue]]:
33
- """
34
- Get the results of all pages. Be cautious of client memory usage.
35
- """
36
- if self.has_iterated:
37
- raise BrokenPipeError("Cannot use this method if the iterator has already been used.")
38
- return [x for x in self]
39
-
40
- def default_first_page_criteria(self) -> PagerResultCriteriaType:
41
- raise ValueError("Cannot generate a default first page criteria for custom reports.")
42
-
43
- def get_next_page_result(self) -> tuple[CustomReportCriteria | None, Queue[dict[str, FieldValue]]]:
44
- report: CustomReport = self._report_man.run_custom_report(self.next_page_criteria)
45
- queue: Queue[dict[str, FieldValue]] = Queue()
46
- for row in _process_results(report.result_table, self._columns):
47
- queue.put(row)
48
- if report.has_next_page:
49
- next_page_criteria = copy(self.next_page_criteria)
50
- next_page_criteria.page_number += 1
51
- return next_page_criteria, queue
52
- else:
53
- return None, queue
54
-
55
-
56
- class CustomReportDictAutoPager(_DictReportPagerBase):
57
- """
58
- A class that automatically pages through a custom report and returns the results as a list of dictionaries.
59
- """
60
- def __init__(self, user: UserIdentifier, report_criteria: CustomReportCriteria,
61
- page_number: int = 0, page_size: int = _default_report_page_size):
62
- """
63
- :param user: The current webhook context or a user object to send requests from.
64
- :param report_criteria: The custom report criteria to run.
65
- :param page_number: The page number to start on. The first page is page 0.
66
- :param page_size: The number of results to return per page.
67
- """
68
- first_page_criteria: CustomReportCriteria = copy(report_criteria)
69
- first_page_criteria.page_number = page_number
70
- first_page_criteria.page_size = page_size
71
- super().__init__(user, first_page_criteria)
72
-
73
-
74
- class SystemReportDictAutoPager(_DictReportPagerBase):
75
- """
76
- A class that automatically pages through a system report and returns the results as a list of dictionaries.
77
-
78
- System reports are also known as predefined searches in the system and must be defined in the data designer for
79
- a specific data type. That is, saved searches created by users cannot be run using this function.
80
- """
81
- def __init__(self, user: UserIdentifier, report_name: str,
82
- page_number: int = 0, page_size: int = _default_report_page_size):
83
- """
84
- :param user: The current webhook context or a user object to send requests from.
85
- :param report_name: The name of the system report to run.
86
- :param page_number: The page number to start on. The first page is page 0.
87
- :param page_size: The number of results to return per page.
88
- """
89
- first_page_criteria: CustomReportCriteria = CustomReportUtil.get_system_report_criteria(user, report_name)
90
- first_page_criteria.page_number = page_number
91
- first_page_criteria.page_size = page_size
92
- super().__init__(user, first_page_criteria)
93
-
94
-
95
- class QuickReportDictAutoPager(_DictReportPagerBase):
96
- """
97
- A class that automatically pages through a quick report and returns the results as a list of dictionaries.
98
- """
99
- def __init__(self, user: UserIdentifier, report_term: RawReportTerm,
100
- page_number: int = 0, page_size: int = _default_report_page_size):
101
- """
102
- :param user: The current webhook context or a user object to send requests from.
103
- :param report_term: The raw report term to use for the quick report.
104
- :param page_number: The page number to start on. The first page is page 0.
105
- :param page_size: The number of results to return per page.
106
- """
107
- first_page_criteria: CustomReportCriteria = CustomReportUtil.get_quick_report_criteria(user, report_term)
108
- first_page_criteria.page_number = page_number
109
- first_page_criteria.page_size = page_size
110
- super().__init__(user, first_page_criteria)
111
-
112
-
113
- class _RecordReportPagerBase(SapioPyAutoPager[CustomReportCriteria, WrappedType], ABC):
114
- """
115
- A base class for automatically paging through a report and returning the results as a list of records.
116
- """
117
- _columns: list[ReportColumn]
118
- _wrapper: type[WrappedType]
119
- _data_type: str
120
- _rec_handler: RecordHandler
121
- _report_man: CustomReportManager
122
-
123
- def __init__(self, user: UserIdentifier, first_page_criteria: CustomReportCriteria, wrapper_type: type[WrappedType]):
124
- self._columns = first_page_criteria.column_list
125
- self._wrapper = wrapper_type
126
- self._data_type = wrapper_type.get_wrapper_data_type_name()
127
- self._rec_handler = RecordHandler(user)
128
- super().__init__(AliasUtil.to_sapio_user(user), first_page_criteria)
129
- self._report_man = DataMgmtServer.get_custom_report_manager(self.user)
130
-
131
- def get_all_at_once(self) -> list[RecordModel]:
132
- """
133
- Get the results of all pages. Be cautious of client memory usage.
134
- """
135
- if self.has_iterated:
136
- raise BrokenPipeError("Cannot use this method if the iterator has already been used.")
137
- return [x for x in self]
138
-
139
- def default_first_page_criteria(self) -> PagerResultCriteriaType:
140
- raise ValueError("Cannot generate a default first page criteria for custom reports.")
141
-
142
- def get_next_page_result(self) -> tuple[CustomReportCriteria | None, Queue[WrappedType]]:
143
- report: CustomReport = self._report_man.run_custom_report(self.next_page_criteria)
144
- queue: Queue[WrappedType] = Queue()
145
- id_index: int = -1
146
- for i, column in enumerate(self._columns):
147
- if column.data_type_name == self._data_type and column.data_field_name == "RecordId":
148
- id_index = i
149
- break
150
- if id_index == -1:
151
- raise SapioException(f"This report does not contain a Record ID column for the given record model type "
152
- f"{self._data_type}.")
153
- ids: list[int] = [row[id_index] for row in report.result_table]
154
- for row in self._rec_handler.query_models_by_id(self._wrapper, ids, page_size=report.page_size):
155
- queue.put(row)
156
- if report.has_next_page:
157
- next_page_criteria = copy(self.next_page_criteria)
158
- next_page_criteria.page_number += 1
159
- return next_page_criteria, queue
160
- else:
161
- return None, queue
162
-
163
-
164
- class CustomReportRecordAutoPager(_RecordReportPagerBase):
165
- """
166
- A class that automatically pages through a custom report and returns the results as a list of records.
167
- """
168
- def __init__(self, user: UserIdentifier, report_criteria: CustomReportCriteria, wrapper_type: type[WrappedType],
169
- page_number: int = 0, page_size: int = _default_record_page_size):
170
- """
171
- :param user: The current webhook context or a user object to send requests from.
172
- :param report_criteria: The custom report criteria to run.
173
- :param wrapper_type: The record model wrapper type to use for the records.
174
- :param page_number: The page number to start on. The first page is page 0.
175
- :param page_size: The number of results to return per page.
176
- """
177
- first_page_criteria: CustomReportCriteria = copy(report_criteria)
178
- _add_record_id_column(first_page_criteria, wrapper_type)
179
- first_page_criteria.page_number = page_number
180
- first_page_criteria.page_size = page_size
181
- super().__init__(user, first_page_criteria, wrapper_type)
182
-
183
-
184
- class SystemReportRecordAutoPager(_RecordReportPagerBase):
185
- """
186
- A class that automatically pages through a system report and returns the results as a list of records.
187
-
188
- System reports are also known as predefined searches in the system and must be defined in the data designer for
189
- a specific data type. That is, saved searches created by users cannot be run using this function.
190
- """
191
- def __init__(self, user: UserIdentifier, report_name: str, wrapper_type: type[WrappedType],
192
- page_number: int = 0, page_size: int = _default_record_page_size):
193
- """
194
- :param user: The current webhook context or a user object to send requests from.
195
- :param report_name: The name of the system report to run.
196
- :param wrapper_type: The record model wrapper type to use for the records.
197
- :param page_number: The page number to start on. The first page is page 0.
198
- :param page_size: The number of results to return per page.
199
- """
200
- first_page_criteria: CustomReportCriteria = CustomReportUtil.get_system_report_criteria(user, report_name)
201
- _add_record_id_column(first_page_criteria, wrapper_type)
202
- first_page_criteria.page_number = page_number
203
- first_page_criteria.page_size = page_size
204
- super().__init__(user, first_page_criteria, wrapper_type)
205
-
206
-
207
- class QuickReportRecordAutoPager(_RecordReportPagerBase):
208
- """
209
- A class that automatically pages through a quick report and returns the results as a list of records.
210
- """
211
- def __init__(self, user: UserIdentifier, report_term: RawReportTerm, wrapper_type: type[WrappedType],
212
- page_number: int = 0, page_size: int = _default_record_page_size):
213
- """
214
- :param user: The current webhook context or a user object to send requests from.
215
- :param report_term: The raw report term to use for the quick report.
216
- :param wrapper_type: The record model wrapper type to use for the records.
217
- :param page_number: The page number to start on. The first page is page 0.
218
- :param page_size: The number of results to return per page.
219
- """
220
- if report_term.data_type_name != wrapper_type.get_wrapper_data_type_name():
221
- raise SapioException("The data type name of the report term must match the data type name of the wrapper type.")
222
- first_page_criteria: CustomReportCriteria = CustomReportUtil.get_quick_report_criteria(user, report_term)
223
- first_page_criteria.page_number = page_number
224
- first_page_criteria.page_size = page_size
225
- super().__init__(user, first_page_criteria, wrapper_type)
226
-
227
-
228
- def _add_record_id_column(report: CustomReportCriteria, wrapper_type: type[WrappedType]) -> None:
229
- """
230
- Given a custom report criteria, ensure that the report contains a Record ID column for the given record model's
231
- data type. Add one if it is missing.
232
- """
233
- dt: str = wrapper_type.get_wrapper_data_type_name()
234
- # Ensure that the root data type is the one we're looking for.
235
- report.root_data_type = dt
236
- # Enforce that the given custom report has a record ID column.
237
- if not any([x.data_type_name == dt and x.data_field_name == "RecordId" for x in report.column_list]):
238
- report.column_list.append(ReportColumn(dt, "RecordId", FieldType.LONG))
239
-
240
-
241
- def _process_results(rows: list[list[FieldValue]], columns: list[ReportColumn]) -> list[dict[str, FieldValue]]:
242
- """
243
- Given the results of a report as a list of row values and the report's columns, combine these lists to
244
- result in a singular list of dictionaries for each row in the results.
245
- """
246
- # It may be the case that two columns have the same data field name but differing data type names.
247
- # If this occurs, then we need to be able to differentiate these columns in the resulting dictionary.
248
- prepend_dt: set[str] = set()
249
- encountered_names: list[str] = []
250
- for column in columns:
251
- field_name: str = column.data_field_name
252
- if field_name in encountered_names:
253
- prepend_dt.add(field_name)
254
- else:
255
- encountered_names.append(field_name)
256
-
257
- ret: list[dict[str, FieldValue]] = []
258
- for row in rows:
259
- row_data: dict[str, FieldValue] = {}
260
- filter_row: bool = False
261
- for value, column in zip(row, columns):
262
- header: str = column.data_field_name
263
- # If two columns share the same data field name, prepend the data type name of the column to the
264
- # data field name.
265
- if header in prepend_dt:
266
- header = column.data_type_name + "." + header
267
- row_data.update({header: value})
268
- if filter_row is False:
269
- ret.append(row_data)
270
- return ret
File without changes