sapiopycommons 2024.11.19a369__tar.gz → 2024.11.22a371__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.
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/PKG-INFO +1 -1
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/pyproject.toml +1 -1
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/callbacks/field_builder.py +78 -70
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/general/custom_report_util.py +55 -35
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/recordmodel/record_handler.py +4 -4
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/sftpconnect/sftp_builder.py +1 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/webhook/webhook_handlers.py +8 -6
- sapiopycommons-2024.11.22a371/src/sapiopycommons/webhook/webservice_handlers.py +386 -0
- sapiopycommons-2024.11.19a369/src/sapiopycommons/webhook/webservice_handlers.py +0 -67
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/.gitignore +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/LICENSE +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/README.md +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/__init__.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/callbacks/__init__.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/callbacks/callback_util.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/chem/IndigoMolecules.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/chem/Molecules.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/chem/__init__.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/customreport/__init__.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/customreport/column_builder.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/customreport/custom_report_builder.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/customreport/term_builder.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/datatype/__init__.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/datatype/attachment_util.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/datatype/data_fields.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/datatype/pseudo_data_types.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/eln/__init__.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/eln/experiment_handler.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/eln/experiment_report_util.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/eln/plate_designer.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/files/__init__.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/files/complex_data_loader.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/files/file_bridge.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/files/file_bridge_handler.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/files/file_data_handler.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/files/file_util.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/files/file_validator.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/files/file_writer.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/flowcyto/flow_cyto.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/flowcyto/flowcyto_data.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/general/__init__.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/general/accession_service.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/general/aliases.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/general/audit_log.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/general/exceptions.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/general/popup_util.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/general/sapio_links.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/general/storage_util.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/general/time_util.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/multimodal/multimodal.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/multimodal/multimodal_data.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/processtracking/__init__.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/processtracking/custom_workflow_handler.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/processtracking/endpoints.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/recordmodel/__init__.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/rules/__init__.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/rules/eln_rule_handler.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/rules/on_save_rule_handler.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/sftpconnect/__init__.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/webhook/__init__.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/src/sapiopycommons/webhook/webhook_context.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/tests/AF-A0A009IHW8-F1-model_v4.cif +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/tests/_do_not_add_init_py_here +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/tests/accession_test.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/tests/bio_reg_test.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/tests/chem_test.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/tests/chem_test_curation_queue.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/tests/curation_queue_test.sdf +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/tests/data_type_models.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/tests/flowcyto/101_DEN084Y5_15_E01_008_clean.fcs +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/tests/flowcyto/101_DEN084Y5_15_E03_009_clean.fcs +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/tests/flowcyto/101_DEN084Y5_15_E05_010_clean.fcs +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/tests/flowcyto/8_color_ICS.wsp +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/tests/flowcyto/COVID19_W_001_O.fcs +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/tests/flowcyto_test.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/tests/kappa.chains.fasta +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/tests/mafft_test.py +0 -0
- {sapiopycommons-2024.11.19a369 → sapiopycommons-2024.11.22a371}/tests/test.gb +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: sapiopycommons
|
|
3
|
-
Version: 2024.11.
|
|
3
|
+
Version: 2024.11.22a371
|
|
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>
|
|
@@ -6,6 +6,7 @@ from sapiopylib.rest.pojo.datatype.FieldDefinition import VeloxStringFieldDefini
|
|
|
6
6
|
VeloxLongFieldDefinition, VeloxPickListFieldDefinition, VeloxSelectionFieldDefinition, VeloxShortFieldDefinition, \
|
|
7
7
|
SapioDoubleFormat, ListMode
|
|
8
8
|
|
|
9
|
+
from sapiopycommons.general.aliases import FieldIdentifier, DataTypeIdentifier, AliasUtil
|
|
9
10
|
from sapiopycommons.general.exceptions import SapioException
|
|
10
11
|
|
|
11
12
|
|
|
@@ -55,16 +56,17 @@ class FieldBuilder:
|
|
|
55
56
|
"""
|
|
56
57
|
data_type: str
|
|
57
58
|
|
|
58
|
-
def __init__(self, data_type:
|
|
59
|
+
def __init__(self, data_type: DataTypeIdentifier = "Default"):
|
|
59
60
|
"""
|
|
60
61
|
:param data_type: The data type name that fields created from this builder will use as their data type.
|
|
61
62
|
"""
|
|
62
|
-
self.data_type = data_type
|
|
63
|
+
self.data_type = AliasUtil.to_data_type_name(data_type)
|
|
63
64
|
|
|
64
|
-
def accession_field(self, field_name:
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
display_name: str | None = None)
|
|
65
|
+
def accession_field(self, field_name: FieldIdentifier, sequence_key: str, prefix: str | None = None,
|
|
66
|
+
suffix: str | None = None, number_of_digits: int = 8, starting_value: int = 1,
|
|
67
|
+
link_out: dict[str, str] | None = None, abstract_info: AnyFieldInfo | None = None, *,
|
|
68
|
+
data_type_name: DataTypeIdentifier | None = None, display_name: str | None = None) \
|
|
69
|
+
-> VeloxAccessionFieldDefinition:
|
|
68
70
|
"""
|
|
69
71
|
Create an accession field definition. Accession fields are text fields which generate a unique value
|
|
70
72
|
that has not been used before, incrementing from the most recently generated value. This can be used when a
|
|
@@ -98,10 +100,10 @@ class FieldBuilder:
|
|
|
98
100
|
field name doubles as the display name.
|
|
99
101
|
:return: An accession field definition with settings from the input criteria.
|
|
100
102
|
"""
|
|
103
|
+
data_type_name: str = AliasUtil.to_data_type_name(data_type_name) if data_type_name else self.data_type
|
|
104
|
+
field_name: str = AliasUtil.to_data_field_name(field_name)
|
|
101
105
|
if abstract_info is None:
|
|
102
106
|
abstract_info = AnyFieldInfo()
|
|
103
|
-
if not data_type_name:
|
|
104
|
-
data_type_name = self.data_type
|
|
105
107
|
if not display_name:
|
|
106
108
|
display_name = field_name
|
|
107
109
|
# Accession fields lock editable to false.
|
|
@@ -110,10 +112,11 @@ class FieldBuilder:
|
|
|
110
112
|
# The unique parameter has no effect, so just always set it to false.
|
|
111
113
|
return VeloxAccessionFieldDefinition(data_type_name, field_name, display_name, sequence_key, prefix, suffix,
|
|
112
114
|
number_of_digits, False, starting_value, link_out, link_out_url,
|
|
113
|
-
|
|
115
|
+
**abstract_info.__dict__)
|
|
114
116
|
|
|
115
|
-
def boolean_field(self, field_name:
|
|
116
|
-
|
|
117
|
+
def boolean_field(self, field_name: FieldIdentifier, default_value: bool | None = False,
|
|
118
|
+
abstract_info: AnyFieldInfo | None = None, *, data_type_name: DataTypeIdentifier | None = None,
|
|
119
|
+
display_name: str | None = None) -> VeloxBooleanFieldDefinition:
|
|
117
120
|
"""
|
|
118
121
|
Create a boolean field definition. Boolean fields are fields which may have a value of true or false.
|
|
119
122
|
They appear as a checkbox in the UI. Boolean fields may also have a value of null if the field is not required.
|
|
@@ -128,20 +131,21 @@ class FieldBuilder:
|
|
|
128
131
|
field name doubles as the display name.
|
|
129
132
|
:return: A boolean field definition with settings from the input criteria.
|
|
130
133
|
"""
|
|
134
|
+
data_type_name: str = AliasUtil.to_data_type_name(data_type_name) if data_type_name else self.data_type
|
|
135
|
+
field_name: str = AliasUtil.to_data_field_name(field_name)
|
|
131
136
|
if abstract_info is None:
|
|
132
137
|
abstract_info = AnyFieldInfo()
|
|
133
138
|
# Boolean fields assume that they are required if no abstract info is provided.
|
|
134
139
|
abstract_info.required = True
|
|
135
|
-
if not data_type_name:
|
|
136
|
-
data_type_name = self.data_type
|
|
137
140
|
if not display_name:
|
|
138
141
|
display_name = field_name
|
|
139
142
|
return VeloxBooleanFieldDefinition(data_type_name, field_name, display_name, default_value,
|
|
140
|
-
|
|
143
|
+
**abstract_info.__dict__)
|
|
141
144
|
|
|
142
|
-
def date_field(self, field_name:
|
|
145
|
+
def date_field(self, field_name: FieldIdentifier, default_value: int | None = None, date_time_format: str = "MMM dd, yyyy",
|
|
143
146
|
static_date: bool = False, abstract_info: AnyFieldInfo | None = None, *,
|
|
144
|
-
data_type_name:
|
|
147
|
+
data_type_name: DataTypeIdentifier | None = None, display_name: str | None = None) \
|
|
148
|
+
-> VeloxDateFieldDefinition:
|
|
145
149
|
"""
|
|
146
150
|
Create a date field definition. Date fields store date and time information as an integer
|
|
147
151
|
representing the number of milliseconds since the unix epoch. This timestamp is then displayed to users in a
|
|
@@ -162,18 +166,18 @@ class FieldBuilder:
|
|
|
162
166
|
field name doubles as the display name.
|
|
163
167
|
:return: A date field definition with settings from the input criteria.
|
|
164
168
|
"""
|
|
169
|
+
data_type_name: str = AliasUtil.to_data_type_name(data_type_name) if data_type_name else self.data_type
|
|
170
|
+
field_name: str = AliasUtil.to_data_field_name(field_name)
|
|
165
171
|
if abstract_info is None:
|
|
166
172
|
abstract_info = AnyFieldInfo()
|
|
167
|
-
if not data_type_name:
|
|
168
|
-
data_type_name = self.data_type
|
|
169
173
|
if not display_name:
|
|
170
174
|
display_name = field_name
|
|
171
175
|
return VeloxDateFieldDefinition(data_type_name, field_name, display_name, date_time_format, default_value,
|
|
172
|
-
static_date,
|
|
176
|
+
static_date, **abstract_info.__dict__)
|
|
173
177
|
|
|
174
|
-
def date_range_field(self, field_name:
|
|
178
|
+
def date_range_field(self, field_name: FieldIdentifier, default_value: str | DateRange | None = None,
|
|
175
179
|
date_time_format: str = "MMM dd, yyyy", static_date: bool = False,
|
|
176
|
-
abstract_info: AnyFieldInfo | None = None, *, data_type_name:
|
|
180
|
+
abstract_info: AnyFieldInfo | None = None, *, data_type_name: DataTypeIdentifier | None = None,
|
|
177
181
|
display_name: str | None = None) -> VeloxDateRangeFieldDefinition:
|
|
178
182
|
"""
|
|
179
183
|
Create a date range field definition. Date range fields store two unix epoch timestamps as a string of the
|
|
@@ -198,20 +202,20 @@ class FieldBuilder:
|
|
|
198
202
|
field name doubles as the display name.
|
|
199
203
|
:return: A date range field definition with settings from the input criteria.
|
|
200
204
|
"""
|
|
205
|
+
data_type_name: str = AliasUtil.to_data_type_name(data_type_name) if data_type_name else self.data_type
|
|
206
|
+
field_name: str = AliasUtil.to_data_field_name(field_name)
|
|
201
207
|
if abstract_info is None:
|
|
202
208
|
abstract_info = AnyFieldInfo()
|
|
203
|
-
if not data_type_name:
|
|
204
|
-
data_type_name = self.data_type
|
|
205
209
|
if not display_name:
|
|
206
210
|
display_name = field_name
|
|
207
211
|
if isinstance(default_value, DateRange):
|
|
208
212
|
default_value = str(default_value)
|
|
209
213
|
return VeloxDateRangeFieldDefinition(data_type_name, field_name, display_name, date_time_format, static_date,
|
|
210
|
-
default_value,
|
|
214
|
+
default_value, **abstract_info.__dict__)
|
|
211
215
|
|
|
212
|
-
def double_field(self, field_name:
|
|
216
|
+
def double_field(self, field_name: FieldIdentifier, default_value: float | None = None, min_value: float = -10.**120,
|
|
213
217
|
max_value: float = 10.**120, precision: int = 1, double_format: SapioDoubleFormat | None = None,
|
|
214
|
-
abstract_info: AnyFieldInfo | None = None, *, data_type_name:
|
|
218
|
+
abstract_info: AnyFieldInfo | None = None, *, data_type_name: DataTypeIdentifier | None = None,
|
|
215
219
|
display_name: str | None = None) -> VeloxDoubleFieldDefinition:
|
|
216
220
|
"""
|
|
217
221
|
Create a double field definition. Double fields represent decimal numerical values. They can also
|
|
@@ -232,17 +236,17 @@ class FieldBuilder:
|
|
|
232
236
|
field name doubles as the display name.
|
|
233
237
|
:return: A double field definition with settings from the input criteria.
|
|
234
238
|
"""
|
|
239
|
+
data_type_name: str = AliasUtil.to_data_type_name(data_type_name) if data_type_name else self.data_type
|
|
240
|
+
field_name: str = AliasUtil.to_data_field_name(field_name)
|
|
235
241
|
if abstract_info is None:
|
|
236
242
|
abstract_info = AnyFieldInfo()
|
|
237
|
-
if not data_type_name:
|
|
238
|
-
data_type_name = self.data_type
|
|
239
243
|
if not display_name:
|
|
240
244
|
display_name = field_name
|
|
241
245
|
return VeloxDoubleFieldDefinition(data_type_name, field_name, display_name, min_value, max_value, default_value,
|
|
242
|
-
precision, double_format,
|
|
246
|
+
precision, double_format, **abstract_info.__dict__)
|
|
243
247
|
|
|
244
|
-
def enum_field(self, field_name:
|
|
245
|
-
abstract_info: AnyFieldInfo | None = None, *, data_type_name:
|
|
248
|
+
def enum_field(self, field_name: FieldIdentifier, options: list[str], default_value: int | None = None,
|
|
249
|
+
abstract_info: AnyFieldInfo | None = None, *, data_type_name: DataTypeIdentifier | None = None,
|
|
246
250
|
display_name: str | None = None) -> VeloxEnumFieldDefinition:
|
|
247
251
|
"""
|
|
248
252
|
Create an enum field definition. Enum fields allow for the display of a list of options as a field
|
|
@@ -268,18 +272,19 @@ class FieldBuilder:
|
|
|
268
272
|
field name doubles as the display name.
|
|
269
273
|
:return: An enum field definition with settings from the input criteria.
|
|
270
274
|
"""
|
|
275
|
+
data_type_name: str = AliasUtil.to_data_type_name(data_type_name) if data_type_name else self.data_type
|
|
276
|
+
field_name: str = AliasUtil.to_data_field_name(field_name)
|
|
271
277
|
if abstract_info is None:
|
|
272
278
|
abstract_info = AnyFieldInfo()
|
|
273
|
-
if not data_type_name:
|
|
274
|
-
data_type_name = self.data_type
|
|
275
279
|
if not display_name:
|
|
276
280
|
display_name = field_name
|
|
277
281
|
return VeloxEnumFieldDefinition(data_type_name, field_name, display_name, default_value, options,
|
|
278
|
-
|
|
282
|
+
**abstract_info.__dict__)
|
|
279
283
|
|
|
280
|
-
def int_field(self, field_name:
|
|
284
|
+
def int_field(self, field_name: FieldIdentifier, default_value: int | None = None, min_value: int = -2**31,
|
|
281
285
|
max_value: int = 2**31 - 1, unique_value: bool = False, abstract_info: AnyFieldInfo | None = None, *,
|
|
282
|
-
data_type_name:
|
|
286
|
+
data_type_name: DataTypeIdentifier | None = None, display_name: str | None = None) \
|
|
287
|
+
-> VeloxIntegerFieldDefinition:
|
|
283
288
|
"""
|
|
284
289
|
Create an integer field definition. Integer fields are 32-bit whole numbers.
|
|
285
290
|
|
|
@@ -296,18 +301,19 @@ class FieldBuilder:
|
|
|
296
301
|
field name doubles as the display name.
|
|
297
302
|
:return: An integer field definition with settings from the input criteria.
|
|
298
303
|
"""
|
|
304
|
+
data_type_name: str = AliasUtil.to_data_type_name(data_type_name) if data_type_name else self.data_type
|
|
305
|
+
field_name: str = AliasUtil.to_data_field_name(field_name)
|
|
299
306
|
if abstract_info is None:
|
|
300
307
|
abstract_info = AnyFieldInfo()
|
|
301
|
-
if not data_type_name:
|
|
302
|
-
data_type_name = self.data_type
|
|
303
308
|
if not display_name:
|
|
304
309
|
display_name = field_name
|
|
305
310
|
return VeloxIntegerFieldDefinition(data_type_name, field_name, display_name, min_value, max_value,
|
|
306
|
-
default_value, unique_value,
|
|
311
|
+
default_value, unique_value, **abstract_info.__dict__)
|
|
307
312
|
|
|
308
|
-
def long_field(self, field_name:
|
|
313
|
+
def long_field(self, field_name: FieldIdentifier, default_value: int | None = None, min_value: int = -2**63,
|
|
309
314
|
max_value: int = 2**63 - 1, unique_value: bool = False, abstract_info: AnyFieldInfo | None = None, *,
|
|
310
|
-
data_type_name:
|
|
315
|
+
data_type_name: DataTypeIdentifier | None = None, display_name: str | None = None) \
|
|
316
|
+
-> VeloxLongFieldDefinition:
|
|
311
317
|
"""
|
|
312
318
|
Create a long field definition. Long fields are 64-bit whole numbers.
|
|
313
319
|
|
|
@@ -324,18 +330,19 @@ class FieldBuilder:
|
|
|
324
330
|
field name doubles as the display name.
|
|
325
331
|
:return: A long field definition with settings from the input criteria.
|
|
326
332
|
"""
|
|
333
|
+
data_type_name: str = AliasUtil.to_data_type_name(data_type_name) if data_type_name else self.data_type
|
|
334
|
+
field_name: str = AliasUtil.to_data_field_name(field_name)
|
|
327
335
|
if abstract_info is None:
|
|
328
336
|
abstract_info = AnyFieldInfo()
|
|
329
|
-
if not data_type_name:
|
|
330
|
-
data_type_name = self.data_type
|
|
331
337
|
if not display_name:
|
|
332
338
|
display_name = field_name
|
|
333
339
|
return VeloxLongFieldDefinition(data_type_name, field_name, display_name, min_value, max_value, default_value,
|
|
334
|
-
unique_value,
|
|
340
|
+
unique_value, **abstract_info.__dict__)
|
|
335
341
|
|
|
336
|
-
def pick_list_field(self, field_name:
|
|
342
|
+
def pick_list_field(self, field_name: FieldIdentifier, pick_list_name: str, default_value: str | None = None,
|
|
337
343
|
direct_edit: bool = False, abstract_info: AnyFieldInfo | None = None, *,
|
|
338
|
-
data_type_name:
|
|
344
|
+
data_type_name: DataTypeIdentifier | None = None, display_name: str | None = None) \
|
|
345
|
+
-> VeloxPickListFieldDefinition:
|
|
339
346
|
"""
|
|
340
347
|
Create a pick list field definition. Pick list fields are string fields that display a drop-down list of options
|
|
341
348
|
when being edited by a user. The list of options is backed by a pick list defined in the list manager sections
|
|
@@ -355,22 +362,22 @@ class FieldBuilder:
|
|
|
355
362
|
field name doubles as the display name.
|
|
356
363
|
:return: A pick list field definition with settings from the input criteria.
|
|
357
364
|
"""
|
|
365
|
+
data_type_name: str = AliasUtil.to_data_type_name(data_type_name) if data_type_name else self.data_type
|
|
366
|
+
field_name: str = AliasUtil.to_data_field_name(field_name)
|
|
358
367
|
if abstract_info is None:
|
|
359
368
|
abstract_info = AnyFieldInfo()
|
|
360
|
-
if not data_type_name:
|
|
361
|
-
data_type_name = self.data_type
|
|
362
369
|
if not display_name:
|
|
363
370
|
display_name = field_name
|
|
364
371
|
return VeloxPickListFieldDefinition(data_type_name, field_name, display_name, pick_list_name, default_value,
|
|
365
|
-
direct_edit,
|
|
372
|
+
direct_edit, **abstract_info.__dict__)
|
|
366
373
|
|
|
367
|
-
def selection_list_field(self, field_name:
|
|
368
|
-
multi_select: bool = False, unique_value: bool = False,
|
|
374
|
+
def selection_list_field(self, field_name: FieldIdentifier, default_value: str | None = None,
|
|
375
|
+
direct_edit: bool = False, multi_select: bool = False, unique_value: bool = False,
|
|
369
376
|
abstract_info: AnyFieldInfo | None = None, *, pick_list_name: str | None = None,
|
|
370
377
|
custom_report_name: str | None = None, plugin_name: str | None = None,
|
|
371
378
|
static_values: list[str] | None = None, user_list: bool = False,
|
|
372
379
|
user_group_list: bool = False, non_api_user_list: bool = False,
|
|
373
|
-
data_type_name:
|
|
380
|
+
data_type_name: DataTypeIdentifier | None = None, display_name: str | None = None) \
|
|
374
381
|
-> VeloxSelectionFieldDefinition:
|
|
375
382
|
"""
|
|
376
383
|
Create a selection list field definition. Selection list fields are string fields that display a drop-down list
|
|
@@ -401,10 +408,10 @@ class FieldBuilder:
|
|
|
401
408
|
field name doubles as the display name.
|
|
402
409
|
:return: A selection list field definition with settings from the input criteria.
|
|
403
410
|
"""
|
|
411
|
+
data_type_name: str = AliasUtil.to_data_type_name(data_type_name) if data_type_name else self.data_type
|
|
412
|
+
field_name: str = AliasUtil.to_data_field_name(field_name)
|
|
404
413
|
if abstract_info is None:
|
|
405
414
|
abstract_info = AnyFieldInfo()
|
|
406
|
-
if not data_type_name:
|
|
407
|
-
data_type_name = self.data_type
|
|
408
415
|
if not display_name:
|
|
409
416
|
display_name = field_name
|
|
410
417
|
|
|
@@ -443,11 +450,12 @@ class FieldBuilder:
|
|
|
443
450
|
list_mode, unique_value, multi_select,
|
|
444
451
|
default_value, pick_list_name, custom_report_name,
|
|
445
452
|
plugin_name, direct_edit, static_values,
|
|
446
|
-
|
|
453
|
+
**abstract_info.__dict__)
|
|
447
454
|
|
|
448
|
-
def short_field(self, field_name:
|
|
455
|
+
def short_field(self, field_name: FieldIdentifier, default_value: int | None = None, min_value: int = -2**15,
|
|
449
456
|
max_value: int = 2**15 - 1, unique_value: bool = False, abstract_info: AnyFieldInfo | None = None,
|
|
450
|
-
*, data_type_name:
|
|
457
|
+
*, data_type_name: DataTypeIdentifier | None = None, display_name: str | None = None) \
|
|
458
|
+
-> VeloxShortFieldDefinition:
|
|
451
459
|
"""
|
|
452
460
|
Create a short field definition. Short fields are 16-bit whole numbers.
|
|
453
461
|
|
|
@@ -464,21 +472,21 @@ class FieldBuilder:
|
|
|
464
472
|
field name doubles as the display name.
|
|
465
473
|
:return: A short field definition with settings from the input criteria.
|
|
466
474
|
"""
|
|
475
|
+
data_type_name: str = AliasUtil.to_data_type_name(data_type_name) if data_type_name else self.data_type
|
|
476
|
+
field_name: str = AliasUtil.to_data_field_name(field_name)
|
|
467
477
|
if abstract_info is None:
|
|
468
478
|
abstract_info = AnyFieldInfo()
|
|
469
|
-
if not data_type_name:
|
|
470
|
-
data_type_name = self.data_type
|
|
471
479
|
if not display_name:
|
|
472
480
|
display_name = field_name
|
|
473
481
|
return VeloxShortFieldDefinition(data_type_name, field_name, display_name, min_value, max_value, default_value,
|
|
474
|
-
unique_value,
|
|
475
|
-
|
|
476
|
-
def string_field(self, field_name: str,
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
+
unique_value, **abstract_info.__dict__)
|
|
483
|
+
|
|
484
|
+
def string_field(self, field_name: FieldIdentifier, default_value: str | None = None, max_length: int = 100,
|
|
485
|
+
unique_value: bool = False, html_editor: bool = False,
|
|
486
|
+
string_format: SapioStringFormat | None = None, num_lines: int = 1, auto_size: bool = False,
|
|
487
|
+
link_out: dict[str, str] | None = None, field_validator: FieldValidator | None = None,
|
|
488
|
+
abstract_info: AnyFieldInfo | None = None, *, data_type_name: DataTypeIdentifier | None = None,
|
|
489
|
+
display_name: str | None = None) -> VeloxStringFieldDefinition:
|
|
482
490
|
"""
|
|
483
491
|
Create a string field definition. String fields represent text, and are highly customizable, allowing the
|
|
484
492
|
field to be plain text or rich HTML, take up one line of space or multiple on a form, format as emails or
|
|
@@ -516,16 +524,16 @@ class FieldBuilder:
|
|
|
516
524
|
field name doubles as the display name.
|
|
517
525
|
:return: A string field definition with settings from the input criteria.
|
|
518
526
|
"""
|
|
527
|
+
data_type_name: str = AliasUtil.to_data_type_name(data_type_name) if data_type_name else self.data_type
|
|
528
|
+
field_name: str = AliasUtil.to_data_field_name(field_name)
|
|
519
529
|
if abstract_info is None:
|
|
520
530
|
abstract_info = AnyFieldInfo()
|
|
521
|
-
if not data_type_name:
|
|
522
|
-
data_type_name = self.data_type
|
|
523
531
|
if not display_name:
|
|
524
532
|
display_name = field_name
|
|
525
533
|
link_out, link_out_url = self._convert_link_out(link_out)
|
|
526
534
|
return VeloxStringFieldDefinition(data_type_name, field_name, display_name, default_value, max_length,
|
|
527
535
|
unique_value, html_editor, string_format, num_lines, auto_size, link_out,
|
|
528
|
-
link_out_url, field_validator,
|
|
536
|
+
link_out_url, field_validator, **abstract_info.__dict__)
|
|
529
537
|
|
|
530
538
|
@staticmethod
|
|
531
539
|
def _convert_link_out(link_out: dict[str, str] | None) -> tuple[bool, str | None]:
|
|
@@ -29,8 +29,10 @@ class CustomReportUtil:
|
|
|
29
29
|
filter on. Only those headers that both the filters and the custom report share will take effect. That is,
|
|
30
30
|
any filters that have a header name that isn't in the custom report will be ignored.
|
|
31
31
|
:param page_limit: The maximum number of pages to query. If None, exhausts all possible pages.
|
|
32
|
-
:param page_size: The size of each page of results in the search. If None, the page size is set by the server
|
|
33
|
-
|
|
32
|
+
:param page_size: The size of each page of results in the search. If None, the page size is set by the server,
|
|
33
|
+
which may be unlimited.
|
|
34
|
+
:param page_number: The page number to start the search from, If None, starts on the first page. Note that the
|
|
35
|
+
number of the first page is 0.
|
|
34
36
|
:return: The results of the report listed row by row, mapping each cell to the header it is under. The header
|
|
35
37
|
values in the dicts are the data field names of the columns.
|
|
36
38
|
If two columns in the search have the same data field name but differing data type names, then the
|
|
@@ -38,11 +40,11 @@ class CustomReportUtil:
|
|
|
38
40
|
had a Sample column with a data field name of Identifier and a Request column with the same data field name,
|
|
39
41
|
then the dictionary keys for these columns would be Sample.Identifier and Request.Identifier respectively.
|
|
40
42
|
"""
|
|
41
|
-
results: tuple = CustomReportUtil.
|
|
42
|
-
|
|
43
|
+
results: tuple = CustomReportUtil._exhaust_system_report(context, report_name, page_limit,
|
|
44
|
+
page_size, page_number)
|
|
43
45
|
columns: list[ReportColumn] = results[0]
|
|
44
46
|
rows: list[list[FieldValue]] = results[1]
|
|
45
|
-
return CustomReportUtil.
|
|
47
|
+
return CustomReportUtil._process_results(rows, columns, filters)
|
|
46
48
|
|
|
47
49
|
@staticmethod
|
|
48
50
|
def run_custom_report(context: UserIdentifier,
|
|
@@ -71,7 +73,8 @@ class CustomReportUtil:
|
|
|
71
73
|
:param page_size: The size of each page of results in the search. If None, uses the value from the given report
|
|
72
74
|
criteria. If not None, overwrites the value from the given report criteria.
|
|
73
75
|
:param page_number: The page number to start the search from, If None, uses the value from the given report
|
|
74
|
-
criteria. If not None, overwrites the value from the given report criteria.
|
|
76
|
+
criteria. If not None, overwrites the value from the given report criteria. Note that the number of the
|
|
77
|
+
first page is 0.
|
|
75
78
|
:return: The results of the report listed row by row, mapping each cell to the header it is under. The header
|
|
76
79
|
values in the dicts are the data field names of the columns.
|
|
77
80
|
If two columns in the search have the same data field name but differing data type names, then the
|
|
@@ -79,11 +82,11 @@ class CustomReportUtil:
|
|
|
79
82
|
had a Sample column with a data field name of Identifier and a Request column with the same data field name,
|
|
80
83
|
then the dictionary keys for these columns would be Sample.Identifier and Request.Identifier respectively.
|
|
81
84
|
"""
|
|
82
|
-
results: tuple = CustomReportUtil.
|
|
83
|
-
|
|
85
|
+
results: tuple = CustomReportUtil._exhaust_custom_report(context, report_criteria, page_limit,
|
|
86
|
+
page_size, page_number)
|
|
84
87
|
columns: list[ReportColumn] = results[0]
|
|
85
88
|
rows: list[list[FieldValue]] = results[1]
|
|
86
|
-
return CustomReportUtil.
|
|
89
|
+
return CustomReportUtil._process_results(rows, columns, filters)
|
|
87
90
|
|
|
88
91
|
@staticmethod
|
|
89
92
|
def run_quick_report(context: UserIdentifier,
|
|
@@ -107,16 +110,18 @@ class CustomReportUtil:
|
|
|
107
110
|
filter on. Only those headers that both the filters and the custom report share will take effect. That is,
|
|
108
111
|
any filters that have a header name that isn't in the custom report will be ignored.
|
|
109
112
|
:param page_limit: The maximum number of pages to query. If None, exhausts all possible pages.
|
|
110
|
-
:param page_size: The size of each page of results in the search. If None, the page size is set by the server
|
|
111
|
-
|
|
113
|
+
:param page_size: The size of each page of results in the search. If None, the page size is set by the server,
|
|
114
|
+
which may be unlimited.
|
|
115
|
+
:param page_number: The page number to start the search from, If None, starts on the first page. Note that the
|
|
116
|
+
number of the first page is 0.
|
|
112
117
|
:return: The results of the report listed row by row, mapping each cell to the header it is under. The header
|
|
113
118
|
values in the dicts are the data field names of the columns.
|
|
114
119
|
"""
|
|
115
|
-
results: tuple = CustomReportUtil.
|
|
116
|
-
|
|
120
|
+
results: tuple = CustomReportUtil._exhaust_quick_report(context, report_term, page_limit,
|
|
121
|
+
page_size, page_number)
|
|
117
122
|
columns: list[ReportColumn] = results[0]
|
|
118
123
|
rows: list[list[FieldValue]] = results[1]
|
|
119
|
-
return CustomReportUtil.
|
|
124
|
+
return CustomReportUtil._process_results(rows, columns, filters)
|
|
120
125
|
|
|
121
126
|
@staticmethod
|
|
122
127
|
def get_system_report_criteria(context: UserIdentifier, report_name: str) -> CustomReport:
|
|
@@ -136,14 +141,14 @@ class CustomReportUtil:
|
|
|
136
141
|
"""
|
|
137
142
|
user: SapioUser = AliasUtil.to_sapio_user(context)
|
|
138
143
|
report_man = DataMgmtServer.get_custom_report_manager(user)
|
|
139
|
-
return report_man.run_system_report_by_name(report_name, 1,
|
|
144
|
+
return report_man.run_system_report_by_name(report_name, 1, 0)
|
|
140
145
|
|
|
141
146
|
@staticmethod
|
|
142
|
-
def
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
+
def _exhaust_system_report(context: UserIdentifier,
|
|
148
|
+
report_name: str,
|
|
149
|
+
page_limit: int | None,
|
|
150
|
+
page_size: int | None,
|
|
151
|
+
page_number: int | None) \
|
|
147
152
|
-> tuple[list[ReportColumn], list[list[FieldValue]]]:
|
|
148
153
|
"""
|
|
149
154
|
Given a system report, iterate over every page of the report and collect the results
|
|
@@ -152,6 +157,11 @@ class CustomReportUtil:
|
|
|
152
157
|
user: SapioUser = AliasUtil.to_sapio_user(context)
|
|
153
158
|
report_man = DataMgmtServer.get_custom_report_manager(user)
|
|
154
159
|
|
|
160
|
+
# If a page size was provided but no page number was provided, then set the page number to 0,
|
|
161
|
+
# as both parameters are necessary in order to get paged results.
|
|
162
|
+
if page_size is not None and page_number is None:
|
|
163
|
+
page_number = 0
|
|
164
|
+
|
|
155
165
|
result = None
|
|
156
166
|
has_next_page: bool = True
|
|
157
167
|
rows: list[list[FieldValue]] = []
|
|
@@ -159,18 +169,18 @@ class CustomReportUtil:
|
|
|
159
169
|
while has_next_page and (not page_limit or cur_page <= page_limit):
|
|
160
170
|
result = report_man.run_system_report_by_name(report_name, page_size, page_number)
|
|
161
171
|
page_size = result.page_size
|
|
162
|
-
page_number = result.page_number
|
|
172
|
+
page_number = result.page_number + 1
|
|
163
173
|
has_next_page = result.has_next_page
|
|
164
174
|
rows.extend(result.result_table)
|
|
165
175
|
cur_page += 1
|
|
166
176
|
return result.column_list, rows
|
|
167
177
|
|
|
168
178
|
@staticmethod
|
|
169
|
-
def
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
179
|
+
def _exhaust_custom_report(context: UserIdentifier,
|
|
180
|
+
report: CustomReportCriteria,
|
|
181
|
+
page_limit: int | None,
|
|
182
|
+
page_size: int | None,
|
|
183
|
+
page_number: int | None) \
|
|
174
184
|
-> tuple[list[ReportColumn], list[list[FieldValue]]]:
|
|
175
185
|
"""
|
|
176
186
|
Given a custom report, iterate over every page of the report and collect the results
|
|
@@ -179,6 +189,11 @@ class CustomReportUtil:
|
|
|
179
189
|
user: SapioUser = AliasUtil.to_sapio_user(context)
|
|
180
190
|
report_man = DataMgmtServer.get_custom_report_manager(user)
|
|
181
191
|
|
|
192
|
+
# If a page size was provided but no page number was provided, then set the page number to 0,
|
|
193
|
+
# as both parameters are necessary in order to get paged results.
|
|
194
|
+
if page_size is not None and page_number is None:
|
|
195
|
+
page_number = 0
|
|
196
|
+
|
|
182
197
|
result = None
|
|
183
198
|
if page_size is not None:
|
|
184
199
|
report.page_size = page_size
|
|
@@ -190,18 +205,18 @@ class CustomReportUtil:
|
|
|
190
205
|
while has_next_page and (not page_limit or cur_page <= page_limit):
|
|
191
206
|
result = report_man.run_custom_report(report)
|
|
192
207
|
report.page_size = result.page_size
|
|
193
|
-
report.page_number = result.page_number
|
|
208
|
+
report.page_number = result.page_number + 1
|
|
194
209
|
has_next_page = result.has_next_page
|
|
195
210
|
rows.extend(result.result_table)
|
|
196
211
|
cur_page += 1
|
|
197
212
|
return result.column_list, rows
|
|
198
213
|
|
|
199
214
|
@staticmethod
|
|
200
|
-
def
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
215
|
+
def _exhaust_quick_report(context: UserIdentifier,
|
|
216
|
+
report_term: RawReportTerm,
|
|
217
|
+
page_limit: int | None,
|
|
218
|
+
page_size: int | None,
|
|
219
|
+
page_number: int | None) \
|
|
205
220
|
-> tuple[list[ReportColumn], list[list[FieldValue]]]:
|
|
206
221
|
"""
|
|
207
222
|
Given a quick report, iterate over every page of the report and collect the results
|
|
@@ -210,6 +225,11 @@ class CustomReportUtil:
|
|
|
210
225
|
user: SapioUser = AliasUtil.to_sapio_user(context)
|
|
211
226
|
report_man = DataMgmtServer.get_custom_report_manager(user)
|
|
212
227
|
|
|
228
|
+
# If a page size was provided but no page number was provided, then set the page number to 0,
|
|
229
|
+
# as both parameters are necessary in order to get paged results.
|
|
230
|
+
if page_size is not None and page_number is None:
|
|
231
|
+
page_number = 0
|
|
232
|
+
|
|
213
233
|
result = None
|
|
214
234
|
has_next_page: bool = True
|
|
215
235
|
rows: list[list[FieldValue]] = []
|
|
@@ -217,15 +237,15 @@ class CustomReportUtil:
|
|
|
217
237
|
while has_next_page and (not page_limit or cur_page <= page_limit):
|
|
218
238
|
result = report_man.run_quick_report(report_term, page_size, page_number)
|
|
219
239
|
page_size = result.page_size
|
|
220
|
-
page_number = result.page_number
|
|
240
|
+
page_number = result.page_number + 1
|
|
221
241
|
has_next_page = result.has_next_page
|
|
222
242
|
rows.extend(result.result_table)
|
|
223
243
|
cur_page += 1
|
|
224
244
|
return result.column_list, rows
|
|
225
245
|
|
|
226
246
|
@staticmethod
|
|
227
|
-
def
|
|
228
|
-
|
|
247
|
+
def _process_results(rows: list[list[FieldValue]], columns: list[ReportColumn],
|
|
248
|
+
filters: dict[FieldIdentifierKey, Iterable[FieldValue]] | None) -> list[dict[str, FieldValue]]:
|
|
229
249
|
"""
|
|
230
250
|
Given the results of a report as a list of row values and the report's columns, combine these lists to
|
|
231
251
|
result in a singular list of dictionaries for each row in the results.
|
|
@@ -297,7 +297,7 @@ class RecordHandler:
|
|
|
297
297
|
not None, in which case it overwrites the given report's value.
|
|
298
298
|
:param page_number: The page number to start the search from, If None, starts on the first page.
|
|
299
299
|
If the input report is a custom report criteria, uses the value from the criteria, unless this value is
|
|
300
|
-
not None, in which case it overwrites the given report's value.
|
|
300
|
+
not None, in which case it overwrites the given report's value. Note that the number of the first page is 0.
|
|
301
301
|
:return: The record models for the queried records that matched the given report.
|
|
302
302
|
"""
|
|
303
303
|
if isinstance(report_name, str):
|
|
@@ -966,7 +966,7 @@ class RecordHandler:
|
|
|
966
966
|
current = current.get_forward_side_link(node.data_field_name)
|
|
967
967
|
elif direction == RelationshipNodeType.REVERSE_SIDE_LINK:
|
|
968
968
|
field_name: str = node.data_field_name
|
|
969
|
-
reverse_links: list[PyRecordModel] = current.get_reverse_side_link(
|
|
969
|
+
reverse_links: list[PyRecordModel] = current.get_reverse_side_link(data_type, field_name)
|
|
970
970
|
if not reverse_links:
|
|
971
971
|
current = None
|
|
972
972
|
elif len(reverse_links) > 1:
|
|
@@ -1016,7 +1016,7 @@ class RecordHandler:
|
|
|
1016
1016
|
elif direction == RelationshipNodeType.FORWARD_SIDE_LINK:
|
|
1017
1017
|
next_search.add(search.get_forward_side_link(node.data_field_name))
|
|
1018
1018
|
elif direction == RelationshipNodeType.REVERSE_SIDE_LINK:
|
|
1019
|
-
next_search.update(search.get_reverse_side_link(node.data_field_name
|
|
1019
|
+
next_search.update(search.get_reverse_side_link(data_type, node.data_field_name))
|
|
1020
1020
|
else:
|
|
1021
1021
|
raise SapioException("Unsupported path direction.")
|
|
1022
1022
|
current_search = next_search
|
|
@@ -1064,7 +1064,7 @@ class RecordHandler:
|
|
|
1064
1064
|
elif direction == RelationshipNodeType.FORWARD_SIDE_LINK:
|
|
1065
1065
|
current = [current[0].get_forward_side_link(node.data_field_name)]
|
|
1066
1066
|
elif direction == RelationshipNodeType.REVERSE_SIDE_LINK:
|
|
1067
|
-
current = current[0].get_reverse_side_link(node.data_field_name
|
|
1067
|
+
current = current[0].get_reverse_side_link(data_type, node.data_field_name)
|
|
1068
1068
|
else:
|
|
1069
1069
|
raise SapioException("Unsupported path direction.")
|
|
1070
1070
|
ret_dict.update({model: self.inst_man.wrap(current[0], wrapper_type) if current else None})
|