tricc-oo 1.6.25__py3-none-any.whl → 1.7.0.dev1__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.
@@ -56,9 +56,6 @@ from tricc_oo.converters.tricc_to_xls_form import get_list_names, get_export_nam
56
56
  logger = logging.getLogger("default")
57
57
  ONE_QUESTION_AT_A_TIME = False
58
58
 
59
- # Track the last group that was reordered to avoid unnecessary reordering
60
- _last_reordered_group = None
61
-
62
59
 
63
60
  def merge_node(from_node, to_node):
64
61
  if from_node.activity != to_node.activity:
@@ -124,10 +121,7 @@ def get_last_version(name, processed_nodes, _list=None):
124
121
  # node is the node to calculate
125
122
  # processed_nodes are the list of processed nodes
126
123
  def get_node_expressions(node, processed_nodes, process=None):
127
- get_overall_exp = issubclass(
128
- node.__class__,
129
- (TriccNodeDisplayCalculateBase, TriccNodeProposedDiagnosis, TriccNodeDiagnosis)
130
- ) and not isinstance(node, (TriccNodeDisplayBridge))
124
+ get_overall_exp = issubclass(node.__class__, (TriccNodeDisplayCalculateBase, TriccNodeProposedDiagnosis, TriccNodeDiagnosis)) and not isinstance(node, (TriccNodeDisplayBridge))
131
125
  expression = None
132
126
  # in case of recursive call processed_nodes will be None
133
127
  if processed_nodes is None or is_ready_to_process(node, processed_nodes=processed_nodes):
@@ -158,25 +152,19 @@ def set_last_version_false(node, processed_nodes):
158
152
  return last_version
159
153
 
160
154
 
161
- def get_version_inheritance(node, all_prev_versions, processed_nodes):
162
-
163
- # Updated to merge ALL previous versions, not just the last one
164
- # This ensures inheritance works even when intermediate activities weren't triggered
165
-
155
+ def get_version_inheritance(node, last_version, processed_nodes):
156
+ # FIXME this is for XLS form where only calculate are evaluated
157
+ # for a activity that is not triggered
166
158
  if not issubclass(node.__class__, (TriccNodeInputModel)):
167
159
  node.last = True
168
160
  if issubclass(node.__class__, (TriccNodeDisplayCalculateBase, TriccNodeEnd)) and node.name is not None:
169
161
  # logger.debug("set last to false for node {}
170
162
  # and add its link it to next one".format(last_used_calc.get_name()))
171
163
  if node.prev_nodes:
172
- # Set prev_next_node only with the immediate last version
173
- for pv in all_prev_versions:
174
- set_prev_next_node(pv, node)
164
+ set_prev_next_node(last_version, node)
175
165
  else:
176
166
  expression = node.expression or node.expression_reference or getattr(node, "relevance", None)
177
- # Merge with ALL previous versions, not just the last one
178
- if all_prev_versions:
179
- expression = merge_all_expressions(expression, all_prev_versions)
167
+ expression = merge_expression(expression, last_version)
180
168
  if node.expression:
181
169
  node.expression = expression
182
170
  elif node.expression_reference:
@@ -185,25 +173,21 @@ def get_version_inheritance(node, all_prev_versions, processed_nodes):
185
173
  node.relevance = expression
186
174
  else:
187
175
  node.last = False
188
-
189
- # Create a calculate node that coalesces all previous saved values with the current node value
190
- calc_id = generate_id(f"save_{node.save}")
191
-
192
- # Build reference list with current node and all previous versions
193
- reference_list = [node] + (all_prev_versions if all_prev_versions else [])
194
176
 
177
+ # Create a calculate node that coalesces the previous saved value with the current node value
178
+ calc_id = generate_id(f"save_{node.save}")
195
179
  calc = TriccNodeCalculate(
196
180
  id=calc_id,
197
181
  name=node.save,
198
182
  path_len=node.path_len + 1,
199
183
  expression_reference=TriccOperation(
200
184
  TriccOperator.COALESCE,
201
- reference_list,
185
+ [TriccReference(node.save), last_version],
202
186
  ),
203
- reference=reference_list,
187
+ reference=[TriccReference(n.name)],
204
188
  activity=node.activity,
205
189
  group=node.group,
206
- label=f"Save calculation for {node.label}",
190
+ label=f"Save calculation for {n.label}",
207
191
  last=True,
208
192
  )
209
193
  node.activity.nodes[calc.id] = calc
@@ -211,9 +195,7 @@ def get_version_inheritance(node, all_prev_versions, processed_nodes):
211
195
  # set_last_version_false(calc, processed_nodes)
212
196
  processed_nodes.add(calc)
213
197
  if issubclass(node.__class__, TriccNodeInputModel):
214
- # Coalesce with all previous versions
215
- coalesce_operands = ["$this"] + (all_prev_versions if all_prev_versions else [])
216
- node.expression = TriccOperation(TriccOperator.COALESCE, coalesce_operands)
198
+ node.expression = TriccOperation(TriccOperator.COALESCE, ["$this", last_version])
217
199
 
218
200
 
219
201
  def merge_expression(expression, last_version):
@@ -228,30 +210,6 @@ def merge_expression(expression, last_version):
228
210
  return expression
229
211
 
230
212
 
231
- def merge_all_expressions(expression, all_versions):
232
- """
233
- Merge an expression with ALL previous versions, not just the last one.
234
- This ensures inheritance works even when intermediate versions weren't evaluated
235
- due to activity relevance conditions.
236
- """
237
- if not all_versions:
238
- return expression
239
-
240
- datatype = expression.get_datatype() if expression else "unknown"
241
-
242
- if datatype == "boolean":
243
- expression = or_join([expression, *all_versions])
244
-
245
- else:
246
- # COALESCE through all previous versions, then the current expression
247
- coalesce_operands = list(all_versions)
248
- if expression:
249
- coalesce_operands.append(expression)
250
- expression = TriccOperation(TriccOperator.COALESCE, coalesce_operands)
251
-
252
- return expression
253
-
254
-
255
213
  def load_calculate(
256
214
  node, processed_nodes, stashed_nodes, calculates, used_calculates, warn=False, process=None, **kwargs
257
215
  ):
@@ -275,14 +233,8 @@ def load_calculate(
275
233
  # tricc diagnostic have the same name as proposed diag but will be serialised with different names
276
234
 
277
235
  last_version = set_last_version_false(node, processed_nodes)
278
- # Get all previous versions from processed_nodes, not just the last one
279
- node_name = node.name if not isinstance(node, TriccNodeEnd) else node.get_reference()
280
- all_prev_versions = get_versions(node_name, processed_nodes)
281
- # Exclude the current node itself
282
- all_prev_versions = [v for v in all_prev_versions if v != node]
283
-
284
236
  if last_version:
285
- get_version_inheritance(node, all_prev_versions, processed_nodes)
237
+ last_version = get_version_inheritance(node, last_version, processed_nodes)
286
238
 
287
239
  generate_calculates(node, calculates, used_calculates, processed_nodes=processed_nodes, process=process)
288
240
 
@@ -450,11 +402,6 @@ def get_bridge_path(prev_nodes, node=None, edge_only=False):
450
402
  calc = TriccNodeDisplayBridge(**data)
451
403
  else:
452
404
  calc = TriccNodeBridge(**data)
453
- if node:
454
- priority = getattr(node, 'priority', None)
455
- if priority:
456
- calc.priority = priority
457
-
458
405
  return calc
459
406
 
460
407
 
@@ -855,7 +802,7 @@ def process_operation_reference(
855
802
  operation,
856
803
  node,
857
804
  processed_nodes,
858
- calculates=None,
805
+ calculates,
859
806
  used_calculates=None,
860
807
  replace_reference=False,
861
808
  warn=False,
@@ -1018,7 +965,6 @@ def walktrhough_tricc_node_processed_stached(
1018
965
  warn=False,
1019
966
  node_path=[],
1020
967
  process=None,
1021
- loop_count=0,
1022
968
  **kwargs,
1023
969
  ):
1024
970
  ended_activity = False
@@ -1184,10 +1130,7 @@ def walktrhough_tricc_node_processed_stached(
1184
1130
  if nn not in stashed_nodes:
1185
1131
  stashed_nodes.insert_at_top(nn)
1186
1132
  if not recursive:
1187
- global _last_reordered_group
1188
- if _last_reordered_group != node.group:
1189
- reorder_node_list(stashed_nodes, node.group, processed_nodes)
1190
- _last_reordered_group = node.group
1133
+ reorder_node_list(stashed_nodes, node.group, processed_nodes)
1191
1134
 
1192
1135
  else:
1193
1136
  if prev_process and process and prev_process != process[0]:
@@ -1334,7 +1277,7 @@ def stashed_node_func(node, callback, recursive=False, **kwargs):
1334
1277
 
1335
1278
 
1336
1279
  # check if the all the prev nodes are processed
1337
- def is_ready_to_process(in_node, processed_nodes, strict=True, local=False, loop_count=0):
1280
+ def is_ready_to_process(in_node, processed_nodes, strict=True, local=False):
1338
1281
  if isinstance(in_node, TriccNodeSelectOption):
1339
1282
  node = in_node.select
1340
1283
  elif isinstance(in_node, (TriccNodeActivityStart, TriccNodeMainStart)):
@@ -1345,38 +1288,36 @@ def is_ready_to_process(in_node, processed_nodes, strict=True, local=False, loop
1345
1288
  if hasattr(node, "prev_nodes"):
1346
1289
  # ensure the previous node of the select are processed, not the option prev nodes
1347
1290
  for prev_node in node.prev_nodes:
1348
- if is_prev_processed(prev_node, node, processed_nodes, local, loop_count) is False:
1291
+ if is_prev_processed(prev_node, node, processed_nodes, local) is False:
1349
1292
  return False
1350
1293
  return True
1351
1294
 
1352
1295
 
1353
- def is_prev_processed(prev_node, node, processed_nodes, local, loop_count=0):
1296
+ def is_prev_processed(prev_node, node, processed_nodes, local):
1354
1297
  if hasattr(prev_node, "select"):
1355
- return is_prev_processed(prev_node.select, node, processed_nodes, local, loop_count)
1298
+ return is_prev_processed(prev_node.select, node, processed_nodes, local)
1356
1299
  if prev_node not in processed_nodes and (not local):
1357
- # Only log detailed failures when we suspect dependency loops (loop_count > 5)
1358
- if loop_count > 5:
1359
- if isinstance(prev_node, TriccNodeExclusive):
1360
- iterator = iter(prev_node.prev_nodes)
1361
- p_n_node = next(iterator)
1362
- logger.debug(
1363
- "is_ready_to_process:failed:via_excl: {} - {} > {} {}:{}".format(
1364
- get_data_for_log(p_n_node), prev_node.get_name(), node.__class__, node.get_name(), node.instance
1365
- )
1366
- )
1367
-
1368
- else:
1369
- logger.debug(
1370
- "is_ready_to_process:failed: {} -> {} {}:{}".format(
1371
- get_data_for_log(prev_node), node.__class__, node.get_name(), node.instance
1372
- )
1300
+ if isinstance(prev_node, TriccNodeExclusive):
1301
+ iterator = iter(prev_node.prev_nodes)
1302
+ p_n_node = next(iterator)
1303
+ logger.debug(
1304
+ "is_ready_to_process:failed:via_excl: {} - {} > {} {}:{}".format(
1305
+ get_data_for_log(p_n_node), prev_node.get_name(), node.__class__, node.get_name(), node.instance
1373
1306
  )
1307
+ )
1374
1308
 
1309
+ else:
1375
1310
  logger.debug(
1376
- "prev node node {}:{} for node {} not in processed".format(
1377
- prev_node.__class__, prev_node.get_name(), node.get_name()
1311
+ "is_ready_to_process:failed: {} -> {} {}:{}".format(
1312
+ get_data_for_log(prev_node), node.__class__, node.get_name(), node.instance
1378
1313
  )
1379
1314
  )
1315
+
1316
+ logger.debug(
1317
+ "prev node node {}:{} for node {} not in processed".format(
1318
+ prev_node.__class__, prev_node.get_name(), node.get_name()
1319
+ )
1320
+ )
1380
1321
  return False
1381
1322
  return True
1382
1323
 
@@ -1791,36 +1732,28 @@ def replace_next_node(prev_node, next_node, old_node):
1791
1732
 
1792
1733
 
1793
1734
  # Priority constants
1794
- SAME_GROUP_PRIORITY = 70
1795
- PARENT_GROUP_PRIORITY = 60
1796
- ACTIVE_ACTIVITY_PRIORITY = 50
1797
- NON_START_ACTIVITY_PRIORITY = 40
1798
- ACTIVE_ACTIVITY_LOWER_PRIORITY = 30
1799
- FLOW_CALCULATE_NODE_PRIORITY_TOP_UP = 3
1800
- RHOMBUS_PRIORITY_TO_UP = 3
1801
-
1802
-
1735
+ SAME_GROUP_PRIORITY = 7000
1736
+ PARENT_GROUP_PRIORITY = 6000
1737
+ ACTIVE_ACTIVITY_PRIORITY = 5000
1738
+ NON_START_ACTIVITY_PRIORITY = 4000
1739
+ ACTIVE_ACTIVITY_LOWER_PRIORITY = 3000
1740
+ RHOMBUS_PRIORITY = 1000
1741
+ DEFAULT_PRIORITY = 2000
1742
+
1743
+
1803
1744
  def reorder_node_list(node_list, group, processed_nodes):
1804
1745
  # Cache active activities for O(1) lookup
1805
1746
  active_activities = {n.activity for n in processed_nodes}
1806
- MAP_PRIORITIES = {}
1807
- def get_priority(node):
1808
- if node.id in MAP_PRIORITIES:
1809
- return MAP_PRIORITIES[node.id]
1810
- if isinstance(node, (TriccNodeActivityStart, TriccNodeMainStart)):
1811
- return get_priority(node.activity)
1812
- if isinstance(node, (TriccNodeSelectOption)):
1813
- return get_priority(node.select)
1814
1747
 
1748
+ def get_priority(node):
1815
1749
  # Cache attributes to avoid repeated getattr calls
1816
- explicit_priority = getattr(node, "priority", None)
1817
- priority = int(explicit_priority or 0)
1750
+ priority = int(getattr(node, "priority", 0) or 0)
1818
1751
  node_group = getattr(node, "group", None)
1819
1752
  activity = getattr(node, "activity", None)
1820
1753
 
1821
1754
  # Check for same group
1822
1755
  if group is not None and node_group and node_group.id == group.id:
1823
- priority += SAME_GROUP_PRIORITY
1756
+ priority += SAME_GROUP_PRIORITY
1824
1757
  # Check for parent group
1825
1758
  elif hasattr(group, "group") and group.group and node_group and node_group.id == group.group.id:
1826
1759
  priority += PARENT_GROUP_PRIORITY
@@ -1834,21 +1767,11 @@ def reorder_node_list(node_list, group, processed_nodes):
1834
1767
  elif activity and activity in active_activities:
1835
1768
  priority += ACTIVE_ACTIVITY_LOWER_PRIORITY
1836
1769
  # Check for rhombus nodes
1837
-
1838
-
1839
- if (
1840
- issubclass(node.__class__, TriccNodeDisplayCalculateBase) or
1841
- isinstance(node, TriccNodeEnd)
1842
- ) and not isinstance(node, TriccNodeActivityEnd) and hasattr(node, 'prev_nodes') and len(node.prev_nodes) > 0:
1843
- priority += FLOW_CALCULATE_NODE_PRIORITY_TOP_UP
1844
1770
  elif issubclass(node.__class__, TriccRhombusMixIn):
1845
- priority += RHOMBUS_PRIORITY_TO_UP
1771
+ priority += RHOMBUS_PRIORITY
1772
+ else:
1773
+ priority += DEFAULT_PRIORITY
1846
1774
 
1847
- if node.prev_nodes and not explicit_priority and not isinstance(node, TriccNodeMainStart):
1848
- priority = max(priority, *[get_priority(p) for p in node.prev_nodes])
1849
-
1850
- MAP_PRIORITIES[node.id] = priority
1851
-
1852
1775
  return priority
1853
1776
 
1854
1777
  # Sort in place, highest priority first
@@ -2044,7 +1967,7 @@ def get_prev_instance_skip_expression(node, processed_nodes, process, expression
2044
1967
 
2045
1968
  # end def
2046
1969
  def get_process_skip_expression(node, processed_nodes, process, expression=None):
2047
- list_ends = [x for x in processed_nodes if isinstance(x, TriccNodeEnd)]
1970
+ list_ends = OrderedSet(filter(lambda x: issubclass(x.__class__, TriccNodeEnd), processed_nodes))
2048
1971
  if list_ends:
2049
1972
  end_expressions = []
2050
1973
  f_end_expression = get_end_expression(list_ends)
@@ -2053,11 +1976,8 @@ def get_process_skip_expression(node, processed_nodes, process, expression=None)
2053
1976
  b_end_expression = get_end_expression(list_ends, "pause")
2054
1977
  if b_end_expression:
2055
1978
  end_expressions.append(b_end_expression)
2056
- process_index = None
2057
- if process and process[0] in PROCESSES:
2058
- process_index = PROCESSES.index(process[0])
2059
- if process_index is not None:
2060
- for p in PROCESSES[process_index + 1:]:
1979
+ if process[0] in PROCESSES:
1980
+ for p in PROCESSES[PROCESSES.index(process[0]) + 1:]:
2061
1981
  p_end_expression = get_end_expression(list_ends, p)
2062
1982
  if p_end_expression:
2063
1983
  end_expressions.append(p_end_expression)
@@ -2104,7 +2024,7 @@ def get_accept_diagnostic_node(code, display, severity, priority, activity):
2104
2024
  return node
2105
2025
 
2106
2026
 
2107
- def get_diagnostic_node(code, display, severity, priority, activity, option):
2027
+ def get_diagnostic_node(code, display, severity, priority, activity):
2108
2028
  node = TriccNodeCalculate(
2109
2029
  id=generate_id("final." + code),
2110
2030
  name="final." + code,
@@ -2115,7 +2035,7 @@ def get_diagnostic_node(code, display, severity, priority, activity, option):
2115
2035
  expression_reference=or_join(
2116
2036
  [
2117
2037
  TriccOperation(TriccOperator.ISTRUE, [TriccReference("pre_final." + code)]),
2118
- TriccOperation(TriccOperator.SELECTED, [TriccReference("tricc.manual.diag"), TriccStatic(option)]),
2038
+ TriccOperation(TriccOperator.SELECTED, [TriccReference("tricc.manual.diag"), TriccStatic(code)]),
2119
2039
  ]
2120
2040
  ),
2121
2041
  )
@@ -2174,19 +2094,9 @@ def create_determine_diagnosis_activity(diags):
2174
2094
  group=activity,
2175
2095
  required=TriccStatic(False),
2176
2096
  )
2177
- options = []
2178
2097
  for proposed in diags:
2179
- option = TriccNodeSelectOption(
2180
- id=generate_id(proposed.name),
2181
- name=proposed.name,
2182
- label=proposed.label,
2183
- list_name=f.list_name,
2184
- relevance=proposed.activity.applicability,
2185
- select=f,
2186
- )
2187
- options.append(option)
2188
2098
  d = get_accept_diagnostic_node(proposed.name, proposed.label, proposed.severity, proposed.priority, activity)
2189
- c = get_diagnostic_node(proposed.name, proposed.label, proposed.severity, proposed.priority, activity, option)
2099
+ c = get_diagnostic_node(proposed.name, proposed.label, proposed.severity, proposed.priority, activity)
2190
2100
  diags_conf.append(d)
2191
2101
  r = TriccNodeRhombus(
2192
2102
  path=start,
@@ -2211,6 +2121,17 @@ def create_determine_diagnosis_activity(diags):
2211
2121
  activity.nodes[wait2.id] = wait2
2212
2122
  # fallback
2213
2123
 
2124
+ options = [
2125
+ TriccNodeSelectOption(
2126
+ id=generate_id(d.name),
2127
+ name=d.name,
2128
+ label=d.label,
2129
+ list_name=f.list_name,
2130
+ relevance=d.activity.applicability,
2131
+ select=f,
2132
+ )
2133
+ for d in diags
2134
+ ]
2214
2135
  f.options = dict(zip(range(0, len(options)), options))
2215
2136
  activity.nodes[f.id] = f
2216
2137
  set_prev_next_node(f, end, edge_only=False)
@@ -2236,9 +2157,7 @@ def get_prev_node_expression(node, processed_nodes, get_overall_exp=False, exclu
2236
2157
 
2237
2158
  for act_id in prev_activities:
2238
2159
  act_expression_inputs = []
2239
- none_sequence_defined_prev_node = False
2240
2160
  for prev_node in prev_activities[act_id]:
2241
- none_sequence_defined_prev_node = none_sequence_defined_prev_node or not prev_node.is_sequence_defined
2242
2161
  if (
2243
2162
  excluded_name is None
2244
2163
  or prev_node != excluded_name
@@ -2265,7 +2184,8 @@ def get_prev_node_expression(node, processed_nodes, get_overall_exp=False, exclu
2265
2184
  if act_expression_inputs:
2266
2185
  act_sub = or_join(act_expression_inputs)
2267
2186
  # if there is condition fallback on the calling activity condition
2268
- act_relevance = get_node_expression(
2187
+ if act_sub == TriccStatic(True):
2188
+ act_sub = get_node_expression(
2269
2189
  prev_node.activity,
2270
2190
  processed_nodes=processed_nodes,
2271
2191
  get_overall_exp=get_overall_exp,
@@ -2273,25 +2193,6 @@ def get_prev_node_expression(node, processed_nodes, get_overall_exp=False, exclu
2273
2193
  negate=False,
2274
2194
  process=process,
2275
2195
  )
2276
- if act_sub == TriccStatic(True):
2277
- act_sub = act_relevance
2278
- elif act_relevance != TriccStatic(True) and none_sequence_defined_prev_node:
2279
- # For nodes with is_sequence_defined = False, AND the activity relevance with the prev expression
2280
- # activity_relevance = get_node_expression(
2281
- # prev_node.activity,
2282
- # processed_nodes=processed_nodes,
2283
- # get_overall_exp=get_overall_exp,
2284
- # is_prev=True,
2285
- # negate=False,
2286
- # process=process,
2287
- # )
2288
- act_sub = and_join([
2289
- TriccOperation(
2290
- TriccOperator.ISTRUE,
2291
- [prev_node.activity.root]
2292
- ),
2293
- act_sub
2294
- ])
2295
2196
  add_sub_expression(expression_inputs, act_sub)
2296
2197
  # avoid void is there is not conditions to avoid looping too much itme
2297
2198
  # expression_inputs = clean_or_list(
@@ -2338,27 +2239,10 @@ def get_count_terms(node, processed_nodes, get_overall_exp, negate=False, proces
2338
2239
  return TriccOperation(TriccOperator.PLUS, [TriccOperation(TriccOperator.CAST_NUMBER, [term]) for term in terms])
2339
2240
 
2340
2241
 
2341
- def get_none_option(node):
2342
- if hasattr(node, "options"):
2343
- for opt in node.options.values():
2344
- if opt.name == "opt_none":
2345
- return opt
2346
- return None
2347
-
2348
-
2349
2242
  def get_count_terms_details(prev_node, processed_nodes, get_overall_exp, negate=False, process=None):
2350
- opt_none = get_none_option(prev_node)
2351
- if opt_none:
2352
- if isinstance(opt_none, str):
2353
- operation_none = TriccOperation(TriccOperator.SELECTED, [prev_node, TriccStatic(opt_none)])
2354
- elif issubclass(opt_none.__class__, TriccBaseModel):
2355
- operation_none = TriccOperation(TriccOperator.SELECTED, [prev_node, opt_none])
2356
- else:
2357
- logger.critical(f"unexpected none option value {opt_none}")
2358
- else:
2359
- operation_none = TriccOperation(TriccOperator.SELECTED, [prev_node, TriccStatic("opt_none")])
2243
+ operation_none = TriccOperation(TriccOperator.SELECTED, [prev_node, TriccStatic("opt_none")])
2360
2244
  if isinstance(prev_node, TriccNodeSelectYesNo):
2361
- return TriccOperation(TriccOperator.SELECTED, [prev_node, TriccStatic(prev_node.options[0])])
2245
+ return TriccOperation(TriccOperator.SELECTED, [prev_node, TriccStatic(prev_node.options[0].name)])
2362
2246
  elif issubclass(prev_node.__class__, TriccNodeSelect):
2363
2247
  if negate:
2364
2248
  return
@@ -2408,11 +2292,7 @@ def get_count_terms_details(prev_node, processed_nodes, get_overall_exp, negate=
2408
2292
  TriccOperator.CAST_NUMBER,
2409
2293
  [
2410
2294
  get_node_expression(
2411
- prev_node,
2412
- processed_nodes=processed_nodes,
2413
- get_overall_exp=get_overall_exp,
2414
- is_prev=True,
2415
- process=process
2295
+ prev_node, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, is_prev=True, process=process
2416
2296
  )
2417
2297
  ],
2418
2298
  )
@@ -2603,6 +2483,15 @@ def get_calculation_terms(node, processed_nodes, get_overall_exp=False, negate=F
2603
2483
 
2604
2484
  if isinstance(node.expression_reference, (TriccOperation, TriccStatic)):
2605
2485
  expression = node.expression_reference
2486
+ elif node.reference is not None and node.expression_reference is not None:
2487
+ expression = get_prev_node_expression(
2488
+ node, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, process=process
2489
+ )
2490
+ ref_expression = node.expression_reference.format(*[get_export_name(ref) for ref in node.reference])
2491
+ if expression is not None and expression != "":
2492
+ expression = and_join([expression, ref_expression])
2493
+ else:
2494
+ expression = ref_expression
2606
2495
  elif expression is None:
2607
2496
  expression = get_prev_node_expression(
2608
2497
  node, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, process=process
@@ -2665,13 +2554,16 @@ def get_selected_option_expression_single(option_node, negate):
2665
2554
 
2666
2555
  def get_selected_option_expression_multiple(option_node, negate):
2667
2556
 
2668
- selected = TriccOperation(TriccOperator.SELECTED, [option_node.select, TriccStatic(option_node)])
2557
+ selected = TriccOperation(TriccOperator.SELECTED, [option_node.select, option_node])
2669
2558
 
2670
2559
  if negate:
2671
- return and_join([
2560
+ return TriccOperation(
2561
+ operator=TriccOperator.AND,
2562
+ resource=[
2672
2563
  TriccOperation(operator=TriccOperator.NOT, resource=[selected]),
2673
2564
  TriccOperation(operator=TriccOperator.ISNOTNULL, resource=[option_node.select]),
2674
- ])
2565
+ ],
2566
+ )
2675
2567
 
2676
2568
  else:
2677
2569
  return selected
@@ -2692,12 +2584,6 @@ def generate_calculate(node, processed_nodes, **kwargs):
2692
2584
  if node not in processed_nodes:
2693
2585
  if kwargs.get("warn", True):
2694
2586
  logger.debug("generation of calculate for node {}".format(node.get_name()))
2695
-
2696
- # Set is_sequence_defined for calculate nodes based on dependencies
2697
- if issubclass(node.__class__, TriccNodeCalculateBase):
2698
- # Calculate node is sequence defined if ALL prev_nodes have is_sequence_defined = True
2699
- node.is_sequence_defined = all(prev_node.is_sequence_defined for prev_node in node.prev_nodes)
2700
-
2701
2587
  if (
2702
2588
  hasattr(node, "expression")
2703
2589
  and (node.expression is None)
@@ -2738,26 +2624,24 @@ def generate_base(node, processed_nodes, **kwargs):
2738
2624
  # we don't overright if define in the diagram
2739
2625
  if node.constraint is None:
2740
2626
  if isinstance(node, TriccNodeSelectMultiple):
2741
- none_opt = get_none_option(node)
2742
- if none_opt:
2743
- node.constraint = or_join(
2744
- [
2745
- TriccOperation(
2746
- TriccOperator.EQUAL,
2747
- ["$this", TriccStatic(none_opt)],
2748
- ),
2749
- TriccOperation(
2750
- TriccOperator.NOT,
2751
- [
2752
- TriccOperation(
2753
- TriccOperator.SELECTED,
2754
- ["$this", TriccStatic(none_opt)],
2755
- )
2756
- ],
2757
- ),
2758
- ]
2759
- ) # '.=\'opt_none\' or not(selected(.,\'opt_none\'))'
2760
- node.constraint_message = "**None** cannot be selected together with choice."
2627
+ node.constraint = or_join(
2628
+ [
2629
+ TriccOperation(
2630
+ TriccOperator.EQUAL,
2631
+ ["$this", TriccStatic("opt_none")],
2632
+ ),
2633
+ TriccOperation(
2634
+ TriccOperator.NOT,
2635
+ [
2636
+ TriccOperation(
2637
+ TriccOperator.SELECTED,
2638
+ ["$this", TriccStatic("opt_none")],
2639
+ )
2640
+ ],
2641
+ ),
2642
+ ]
2643
+ ) # '.=\'opt_none\' or not(selected(.,\'opt_none\'))'
2644
+ node.constraint_message = "**None** cannot be selected together with choice."
2761
2645
  elif node.tricc_type in (
2762
2646
  TriccNodeType.integer,
2763
2647
  TriccNodeType.decimal,
@@ -2782,7 +2666,7 @@ def generate_base(node, processed_nodes, **kwargs):
2782
2666
  )
2783
2667
  constraints_max = "The maximum value is {0}.".format(node.max)
2784
2668
  if len(constraints) > 1:
2785
- node.constraint = and_join(constraints)
2669
+ node.constraint = TriccOperation(TriccOperator.AND, constraints)
2786
2670
  node.constraint_message = (constraints_min + " " + constraints_max).strip()
2787
2671
  elif len(constraints) == 1:
2788
2672
  node.constraint = constraints[0]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tricc-oo
3
- Version: 1.6.25
3
+ Version: 1.7.0.dev1
4
4
  Summary: Python library that converts CDSS L2 in L3
5
5
  Project-URL: Homepage, https://github.com/SwissTPH/tricc
6
6
  Project-URL: Issues, https://github.com/SwissTPH/tricc/issues