tricc-oo 1.5.21__py3-none-any.whl → 1.5.23__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.
Files changed (42) hide show
  1. tests/build.py +13 -23
  2. tests/test_cql.py +37 -108
  3. tests/to_ocl.py +15 -17
  4. tricc_oo/__init__.py +0 -6
  5. tricc_oo/converters/codesystem_to_ocl.py +51 -40
  6. tricc_oo/converters/cql/cqlLexer.py +1 -0
  7. tricc_oo/converters/cql/cqlListener.py +1 -0
  8. tricc_oo/converters/cql/cqlParser.py +1 -0
  9. tricc_oo/converters/cql/cqlVisitor.py +1 -0
  10. tricc_oo/converters/cql_to_operation.py +125 -123
  11. tricc_oo/converters/datadictionnary.py +39 -53
  12. tricc_oo/converters/drawio_type_map.py +143 -61
  13. tricc_oo/converters/tricc_to_xls_form.py +14 -24
  14. tricc_oo/converters/utils.py +3 -3
  15. tricc_oo/converters/xml_to_tricc.py +286 -231
  16. tricc_oo/models/__init__.py +2 -1
  17. tricc_oo/models/base.py +300 -308
  18. tricc_oo/models/calculate.py +63 -49
  19. tricc_oo/models/lang.py +26 -27
  20. tricc_oo/models/ocl.py +146 -161
  21. tricc_oo/models/ordered_set.py +15 -19
  22. tricc_oo/models/tricc.py +144 -88
  23. tricc_oo/parsers/xml.py +15 -30
  24. tricc_oo/serializers/planuml.py +4 -6
  25. tricc_oo/serializers/xls_form.py +81 -135
  26. tricc_oo/strategies/input/base_input_strategy.py +28 -32
  27. tricc_oo/strategies/input/drawio.py +57 -69
  28. tricc_oo/strategies/output/base_output_strategy.py +108 -67
  29. tricc_oo/strategies/output/spice.py +106 -127
  30. tricc_oo/strategies/output/xls_form.py +275 -200
  31. tricc_oo/strategies/output/xlsform_cdss.py +623 -142
  32. tricc_oo/strategies/output/xlsform_cht.py +114 -120
  33. tricc_oo/strategies/output/xlsform_cht_hf.py +13 -24
  34. tricc_oo/visitors/tricc.py +1191 -1021
  35. tricc_oo/visitors/utils.py +16 -16
  36. tricc_oo/visitors/xform_pd.py +91 -89
  37. {tricc_oo-1.5.21.dist-info → tricc_oo-1.5.23.dist-info}/METADATA +3 -1
  38. tricc_oo-1.5.23.dist-info/RECORD +47 -0
  39. tricc_oo-1.5.23.dist-info/licenses/LICENSE +373 -0
  40. tricc_oo-1.5.21.dist-info/RECORD +0 -46
  41. {tricc_oo-1.5.21.dist-info → tricc_oo-1.5.23.dist-info}/WHEEL +0 -0
  42. {tricc_oo-1.5.21.dist-info → tricc_oo-1.5.23.dist-info}/top_level.txt +0 -0
@@ -1,65 +1,118 @@
1
1
  import re
2
2
  import logging
3
-
4
- from tricc_oo.converters.utils import *
5
- from tricc_oo.models import *
6
- from tricc_oo.visitors.tricc import *
3
+ import requests
4
+ import base64
5
+
6
+
7
+ from tricc_oo.converters.utils import generate_id
8
+ from tricc_oo.models.base import (
9
+ TriccBaseModel,
10
+ TriccOperator, TriccOperation, TriccStatic, TriccReference, not_clean,
11
+ and_join, or_join, clean_or_list, nand_join, TriccEdge
12
+ )
13
+ from tricc_oo.models.ordered_set import OrderedSet
14
+ from tricc_oo.models.calculate import (
15
+ TriccNodeDisplayBridge,
16
+ TriccNodeBridge,
17
+ TriccNodeWait,
18
+ TriccNodeCalculate,
19
+ TriccNodeRhombus,
20
+ TriccNodeDisplayCalculateBase,
21
+ TriccNodeExclusive,
22
+ TriccNodeProposedDiagnosis,
23
+ TriccNodeCount,
24
+ TriccNodeAdd,
25
+ TriccNodeFakeCalculateBase,
26
+ TriccRhombusMixIn,
27
+ TriccNodeInput,
28
+ TriccNodeActivityEnd,
29
+ TriccNodeActivityStart,
30
+ TriccNodeEnd,
31
+ get_node_from_id,
32
+
33
+ )
34
+ from tricc_oo.models.tricc import (
35
+ TriccNodeCalculateBase, TriccNodeActivity, TriccNodeBaseModel, TriccNodeNumber,
36
+ TriccNodeSelectMultiple,
37
+ TriccNodeSelectOption,
38
+ TriccNodeSelectYesNo,
39
+ TriccNodeInputModel,
40
+ TriccNodeSelect,
41
+ TriccNodeSelectNotAvailable,
42
+ TriccNodeMoreInfo,
43
+ TriccNodeDisplayModel,
44
+ TriccNodeMainStart,
45
+ TriccNodeAcceptDiagnostic,
46
+ )
7
47
  from tricc_oo.visitors.utils import PROCESSES
48
+ from tricc_oo.converters.cql_to_operation import transform_cql_to_operation
8
49
  from tricc_oo.converters.datadictionnary import lookup_codesystems_code
50
+ from tricc_oo.converters.tricc_to_xls_form import get_list_names, get_export_name
9
51
 
10
52
  logger = logging.getLogger("default")
11
53
  ONE_QUESTION_AT_A_TIME = False
12
54
 
13
- TRICC_TRUE_VALUE = 'true'
14
- TRICC_FALSE_VALUE = 'false'
55
+ TRICC_TRUE_VALUE = "true"
56
+ TRICC_FALSE_VALUE = "false"
57
+
15
58
 
16
- def merge_node(from_node,to_node):
59
+ def merge_node(from_node, to_node):
17
60
  if from_node.activity != to_node.activity:
18
61
  logger.critical("Cannot merge nodes from different activities")
19
- elif issubclass(from_node.__class__, TriccNodeCalculateBase) and issubclass(to_node.__class__, TriccNodeCalculateBase):
62
+ elif issubclass(from_node.__class__, TriccNodeCalculateBase) and issubclass(
63
+ to_node.__class__, TriccNodeCalculateBase
64
+ ):
20
65
  for e in to_node.activity.edges:
21
66
  if e.target == from_node.id:
22
67
  e.target = to_node.id
23
68
  else:
24
69
  logger.critical("Cannot merge not calculate nodes ")
25
-
70
+
26
71
 
27
72
  def get_max_version(dict):
28
73
  max_version = None
29
74
  for id, sim_node in dict.items():
30
- if max_version is None or max_version.version < sim_node.version :
75
+ if max_version is None or max_version.version < sim_node.version:
31
76
  max_version = sim_node
32
77
  return max_version
33
78
 
79
+
34
80
  def get_versions(name, iterable):
35
81
  return [n for n in iterable if version_filter(name)(n)]
36
82
 
83
+
37
84
  def version_filter(name):
38
- return lambda item: hasattr(item, 'name') and ( (isinstance(item, TriccNodeEnd) and name == item.get_reference()) or item.name == name ) and not isinstance(item, TriccNodeSelectOption)
85
+ return (
86
+ lambda item: hasattr(item, "name")
87
+ and ((isinstance(item, TriccNodeEnd) and name == item.get_reference()) or item.name == name)
88
+ and not isinstance(item, TriccNodeSelectOption)
89
+ )
90
+
39
91
 
40
- def get_last_version(name, processed_nodes, _list=None):
92
+ def get_last_version(name, processed_nodes, _list=None):
41
93
  max_version = None
42
94
  if isinstance(_list, dict):
43
95
  _list = _list[name].values() if name in _list else []
44
96
  if _list is None:
45
97
  if isinstance(processed_nodes, OrderedSet):
46
98
  return processed_nodes.find_last(version_filter(name))
47
- else:
99
+ else:
48
100
  _list = get_versions(name, processed_nodes)
49
101
  if _list:
50
- for sim_node in _list:
102
+ for sim_node in _list:
51
103
  # get the max version while not taking a node that have a next node before next calc
52
- if ((max_version is None
53
- or max_version.activity.path_len < sim_node.activity.path_len
54
- or max_version.path_len < sim_node.path_len
104
+ if (
105
+ max_version is None
106
+ or max_version.activity.path_len < sim_node.activity.path_len
107
+ or max_version.path_len < sim_node.path_len
55
108
  or (max_version.path_len == sim_node.path_len and hash(max_version.id) < hash(sim_node.id))
56
- ) ):
109
+ ):
57
110
  max_version = sim_node
58
111
  if not max_version:
59
- already_processed = list(filter(lambda p_node: hasattr(p_node, 'name') and p_node.name == name , _list))
112
+ already_processed = list(filter(lambda p_node: hasattr(p_node, "name") and p_node.name == name, _list))
60
113
  if already_processed:
61
- max_version = sorted(filtered, key=lambda x: x.path_len, reverse=False)[0]
62
-
114
+ max_version = sorted(already_processed, key=lambda x: x.path_len, reverse=False)[0]
115
+
63
116
  return max_version
64
117
 
65
118
 
@@ -67,324 +120,321 @@ def get_last_version(name, processed_nodes, _list=None):
67
120
  # node is the node to calculate
68
121
  # processed_nodes are the list of processed nodes
69
122
  def get_node_expressions(node, processed_nodes, process=None):
70
- get_overall_exp = issubclass(node.__class__, TriccNodeCalculateBase) and not issubclass(node.__class__, (TriccNodeDisplayBridge,TriccNodeBridge))
123
+ get_overall_exp = issubclass(node.__class__, TriccNodeCalculateBase) and not issubclass(
124
+ node.__class__, (TriccNodeDisplayBridge, TriccNodeBridge)
125
+ )
71
126
  expression = None
72
127
  # in case of recursive call processed_nodes will be None
73
128
  if processed_nodes is None or is_ready_to_process(node, processed_nodes=processed_nodes):
74
- expression = get_node_expression(node, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, process=process)
75
-
129
+ expression = get_node_expression(
130
+ node, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, process=process
131
+ )
132
+
76
133
  # if get_overall_exp:
77
- # if expression and (not isinstance(expression, str) or expression != '') and expression is not TriccStatic(True) :
134
+ # if expression and (not isinstance(expression, str) or expression != '')
135
+ # and expression is not TriccStatic(True) :
78
136
  # num_expression = TriccOperation(
79
137
  # TriccOperator.CAST_NUMBER,
80
138
  # [expression]
81
139
  # )
82
140
  # elif expression is TriccStatic(True) or (not expression and get_overall_exp):
83
- # expression = TriccStatic(True)
141
+ # expression = TriccStatic(True)
84
142
  # else:
85
143
  # expression = None
86
144
  if (
87
- issubclass(node.__class__, TriccNodeCalculateBase)
88
- and not isinstance(expression, (TriccStatic, TriccReference, TriccOperation))
89
- and str(expression) != ''
145
+ issubclass(node.__class__, TriccNodeCalculateBase)
146
+ and not isinstance(expression, (TriccStatic, TriccReference, TriccOperation))
147
+ and str(expression) != ""
90
148
  and not isinstance(node, (TriccNodeWait, TriccNodeActivityEnd, TriccNodeActivityStart, TriccNodeEnd))
91
149
  ):
92
150
  logger.warning("Calculate {0} returning no calculations".format(node.get_name()))
93
151
  expression = TriccStatic(True)
94
152
  return expression
95
153
 
154
+
96
155
  def set_last_version_false(node, processed_nodes):
97
- if isinstance(node, (TriccNodeDiagnosis, TriccNodeSelectOption)):
156
+ if isinstance(node, (TriccNodeSelectOption)):
98
157
  return
99
158
  node_name = node.name if not isinstance(node, TriccNodeEnd) else node.get_reference()
100
- #last_version = get_last_version(node_name, processed_nodes) if issubclass(node.__class__, (TriccNodeDisplayModel, TriccNodeDisplayCalculateBase, TriccNodeEnd)) and not isinstance(node, TriccNodeSelectOption) else None
101
159
  last_version = processed_nodes.find_prev(node, version_filter(node_name))
102
- if last_version and getattr(node, 'process', '') != 'pause':
103
- # 0-100 for manually specified instance. 100-200 for auto instance
160
+ if last_version and getattr(node, "process", "") != "pause":
161
+ # 0-100 for manually specified instance. 100-200 for auto instance
104
162
  node.version = get_next_version(node.name, processed_nodes, last_version.version, 0)
105
163
  last_version.last = False
106
164
  node.path_len = max(node.path_len, last_version.path_len + 1)
107
165
  return last_version
108
-
166
+
167
+
109
168
  def get_version_inheritance(node, last_version, processed_nodes):
110
- # FIXME this is for XLS form where only calculate are evaluated for a activity that is not triggered
111
- if not issubclass(node.__class__, (TriccNodeInputModel)):
112
- node.last = True
113
- if (
114
- issubclass(node.__class__, (TriccNodeDisplayCalculateBase, TriccNodeEnd)) and node.name is not None
115
- ):
116
- #logger.debug("set last to false for node {} and add its link it to next one".format(last_used_calc.get_name()))
117
- if node.prev_nodes:
118
- set_prev_next_node(last_version, node)
119
- else:
120
- expression = node.expression or node.expression_reference or getattr(node, 'relevance', None)
121
- expression = merge_expression(expression, last_version)
122
- if node.expression:
123
- node.expression = expression
124
- elif node.expression_reference:
125
- node.expression_reference = expression
126
- elif node.relevance:
127
- node.relevance = expression
128
- else:
129
- node.last = False
130
- calc = TriccNodeCalculate(
131
- id=generate_id(f"save{node.id}"),
132
- name=node.name,
133
- path_len=node.path_len+1,
134
- #version=get_next_version(node.name, processed_nodes, node.version+2),
135
- expression= merge_expression(node, last_version),
136
- label= f"merge{node.id}",
137
- last=True,
138
- activity=node.activity,
139
- group=node.group
140
- )
141
- node.activity.nodes[calc.id]=calc
142
- node.activity.calculates.append(calc)
143
- #set_last_version_false(calc, processed_nodes)
144
- processed_nodes.add(calc)
145
- if issubclass(node.__class__, TriccNodeInputModel):
146
- node.expression = TriccOperation(
147
- TriccOperator.COALESCE,
148
- [
149
- '$this',
150
- last_version
151
- ]
152
- )
153
-
169
+ # FIXME this is for XLS form where only calculate are evaluated
170
+ # for a activity that is not triggered
171
+ if not issubclass(node.__class__, (TriccNodeInputModel)):
172
+ node.last = True
173
+ if issubclass(node.__class__, (TriccNodeDisplayCalculateBase, TriccNodeEnd)) and node.name is not None:
174
+ # logger.debug("set last to false for node {}
175
+ # and add its link it to next one".format(last_used_calc.get_name()))
176
+ if node.prev_nodes:
177
+ set_prev_next_node(last_version, node)
178
+ else:
179
+ expression = node.expression or node.expression_reference or getattr(node, "relevance", None)
180
+ expression = merge_expression(expression, last_version)
181
+ if node.expression:
182
+ node.expression = expression
183
+ elif node.expression_reference:
184
+ node.expression_reference = expression
185
+ elif node.relevance:
186
+ node.relevance = expression
187
+ else:
188
+ node.last = False
189
+ calc = TriccNodeCalculate(
190
+ id=generate_id(f"save{node.id}"),
191
+ name=node.name,
192
+ path_len=node.path_len + 1,
193
+ # version=get_next_version(node.name, processed_nodes, node.version+2),
194
+ expression=merge_expression(node, last_version),
195
+ label=f"merge{node.id}",
196
+ last=True,
197
+ activity=node.activity,
198
+ group=node.group,
199
+ )
200
+ node.activity.nodes[calc.id] = calc
201
+ node.activity.calculates.append(calc)
202
+ # set_last_version_false(calc, processed_nodes)
203
+ processed_nodes.add(calc)
204
+ if issubclass(node.__class__, TriccNodeInputModel):
205
+ node.expression = TriccOperation(TriccOperator.COALESCE, ["$this", last_version])
206
+
207
+
154
208
  def merge_expression(expression, last_version):
155
209
  datatype = expression.get_datatype()
156
- if datatype == 'boolean':
157
- expression = or_join(
158
- [TriccOperation(TriccOperator.ISTRUE, [last_version]), expression]
159
- )
160
-
161
- elif datatype == 'number':
162
- expression = TriccOperation(
163
- TriccOperator.PLUS,
164
- [last_version, expression]
165
- )
210
+ if datatype == "boolean":
211
+ expression = or_join([TriccOperation(TriccOperator.ISTRUE, [last_version]), expression])
212
+
213
+ elif datatype == "number":
214
+ expression = TriccOperation(TriccOperator.PLUS, [last_version, expression])
166
215
  else:
167
- expression = TriccOperation(
168
- TriccOperator.COALESCE,
169
- [last_version, expression]
170
- )
216
+ expression = TriccOperation(TriccOperator.COALESCE, [last_version, expression])
171
217
  return expression
172
218
 
173
- def process_calculate(node,processed_nodes, stashed_nodes, calculates, used_calculates,
174
- warn = False, process=None, **kwargs ):
175
- # used_calculates dict[name, Dict[id, node]]
176
- # processed_nodes Dict[id, node]
177
- # calculates dict[name, Dict[id, node]]
178
-
179
-
219
+
220
+ def process_calculate(
221
+ node, processed_nodes, stashed_nodes, calculates, used_calculates, warn=False, process=None, **kwargs
222
+ ):
223
+ # used_calculates dict[name, Dict[id, node]]
224
+ # processed_nodes Dict[id, node]
225
+ # calculates dict[name, Dict[id, node]]
226
+
180
227
  if node not in processed_nodes:
181
228
  # generate condition
182
- if (
183
- is_ready_to_process(node, processed_nodes,True)
184
- and process_reference(
185
- node,
186
- processed_nodes=processed_nodes,
187
- calculates=calculates,
188
- used_calculates=used_calculates,
189
- replace_reference=False,
190
- warn = warn,
191
- codesystems= kwargs.get('codesystems', None)
192
- )
229
+ if is_ready_to_process(node, processed_nodes, True) and process_reference(
230
+ node,
231
+ processed_nodes=processed_nodes,
232
+ calculates=calculates,
233
+ used_calculates=used_calculates,
234
+ replace_reference=False,
235
+ warn=warn,
236
+ codesystems=kwargs.get("codesystems", None),
193
237
  ):
194
- if kwargs.get('warn', True):
195
- logger.debug('Processing relevance for node {0}'.format(node.get_name()))
238
+ if kwargs.get("warn", True):
239
+ logger.debug("Processing relevance for node {0}".format(node.get_name()))
196
240
  # tricc diagnostic have the same name as proposed diag but will be serialised with different names
197
241
 
198
- last_version = set_last_version_false(node, processed_nodes)
242
+ last_version = set_last_version_false(node, processed_nodes)
199
243
  if last_version:
200
244
  last_version = get_version_inheritance(node, last_version, processed_nodes)
201
245
 
202
- generate_calculates(node,calculates, used_calculates,processed_nodes=processed_nodes, process=process)
203
-
204
-
246
+ generate_calculates(node, calculates, used_calculates, processed_nodes=processed_nodes, process=process)
205
247
 
206
- # if has prev, create condition
207
- if hasattr(node, 'relevance') and (node.relevance is None or isinstance(node.relevance, TriccOperation)):
248
+ # if has prev, create condition
249
+ if hasattr(node, "relevance") and (node.relevance is None or isinstance(node.relevance, TriccOperation)):
208
250
  node.relevance = get_node_expressions(node, processed_nodes=processed_nodes, process=process)
209
251
  # manage not Available
210
252
  if isinstance(node, TriccNodeSelectNotAvailable):
211
253
  # update the checkbox
212
- if node.parent:
254
+ if node.parent:
213
255
  if len(node.prev_nodes) == 1:
214
256
  prev = list(node.prev_nodes)[0]
215
257
  if isinstance(prev, TriccNodeMoreInfo) and prev.parent.name == node.name:
216
258
  prev.parent = node
217
-
218
-
259
+
219
260
  # managing more info on NotAvaialbee
220
261
  parent_empty = TriccOperation(TriccOperator.ISNULL, [node.parent])
221
- node.relevance = and_join([node.parent.relevance, parent_empty])
262
+ node.relevance = and_join([node.parent.relevance, parent_empty])
222
263
  node.required = parent_empty
223
264
  node.constraint = parent_empty
224
265
  node.constraint_message = "Cannot be selected with a value entered above"
225
266
  # update the check box parent : create loop error
226
267
  node.parent.required = None # "${{{0}}}=''".format(node.name)
227
268
  else:
228
- logger.warning("not available node {} does't have a single parent".format(node.get_name()))
269
+ logger.warning("not available node {} does't have a single parent".format(node.get_name()))
229
270
  elif isinstance(node.relevance, TriccOperation):
230
271
  relevance_reference = list(node.relevance.get_references())
231
272
  for r in relevance_reference:
232
- if issubclass(r.__class__, (TriccNodeDisplayCalculateBase )):
273
+ if issubclass(r.__class__, (TriccNodeDisplayCalculateBase)):
233
274
  add_used_calculate(node, r, calculates, used_calculates, processed_nodes)
234
-
235
- if last_version and hasattr(node, 'relevance'):
275
+
276
+ if last_version and hasattr(node, "relevance"):
236
277
  if isinstance(node, TriccNodeInputModel):
237
- version_relevance = TriccOperation(
238
- TriccOperator.ISNULL,
239
- [last_version]
240
- )
278
+ version_relevance = TriccOperation(TriccOperator.ISNULL, [last_version])
241
279
  elif last_version.relevance:
242
- version_relevance = not_clean(
243
- last_version.relevance
244
- )
280
+ version_relevance = not_clean(last_version.relevance)
245
281
  elif last_version.activity.relevance:
246
282
  version_relevance = not_clean(
247
- last_version.activity.relevance,
283
+ last_version.activity.relevance,
248
284
  )
249
285
  else:
250
286
  version_relevance = None
251
-
287
+
252
288
  if version_relevance:
253
- if getattr(node, 'relevance', None):
254
- node.relevance = and_join(
255
- [
256
- version_relevance,
257
- node.relevance
258
- ])
259
-
260
- elif hasattr(node, 'relevance'):
289
+ if getattr(node, "relevance", None):
290
+ node.relevance = and_join([version_relevance, node.relevance])
291
+
292
+ elif hasattr(node, "relevance"):
261
293
  node.relevance = version_relevance
262
294
 
263
- #if hasattr(node, 'next_nodes'):
264
- #node.next_nodes=reorder_node_list(node.next_nodes, node.group)
295
+ # if hasattr(node, 'next_nodes'):
296
+ # node.next_nodes=reorder_node_list(node.next_nodes, node.group)
265
297
  process_reference(
266
- node,
267
- processed_nodes=processed_nodes,
298
+ node,
299
+ processed_nodes=processed_nodes,
268
300
  calculates=calculates,
269
- used_calculates=used_calculates,
270
- replace_reference=True,
271
- warn = warn,
272
- codesystems= kwargs.get('codesystems', None)
301
+ used_calculates=used_calculates,
302
+ replace_reference=True,
303
+ warn=warn,
304
+ codesystems=kwargs.get("codesystems", None),
273
305
  )
274
306
  if isinstance(node, (TriccNodeMainStart, TriccNodeActivityStart)):
275
307
  process_reference(
276
308
  node.activity,
277
- processed_nodes=processed_nodes,
309
+ processed_nodes=processed_nodes,
278
310
  calculates=calculates,
279
- used_calculates=used_calculates,
280
- replace_reference=True,
281
- warn = warn,
282
- codesystems= kwargs.get('codesystems', None)
311
+ used_calculates=used_calculates,
312
+ replace_reference=True,
313
+ warn=warn,
314
+ codesystems=kwargs.get("codesystems", None),
283
315
  )
284
316
 
285
317
  return True
286
318
  # not ready to process or already processed
287
319
 
288
320
  return False
289
-
290
321
 
291
322
 
292
- def get_max_named_version(calculates,name):
323
+ def get_max_named_version(calculates, name):
293
324
  max = 0
294
- if name in calculates:
295
- for node in calculates[name].values():
325
+ if name in calculates:
326
+ for node in calculates[name].values():
296
327
  if node.version > max:
297
328
  max = node.version
298
329
  return max
299
330
 
331
+
300
332
  def get_count_node(node):
301
333
  count_id = generate_id(f"count{node.id}")
302
- count_name = "cnt_"+count_id
334
+ count_name = "cnt_" + count_id
303
335
  return TriccNodeCount(
304
- id = count_id,
305
- group = node.group,
306
- activity = node.activity,
307
- label = "count: "+node.get_name(),
308
- name = count_name,
309
- path_len=node.path_len
336
+ id=count_id,
337
+ group=node.group,
338
+ activity=node.activity,
339
+ label="count: " + node.get_name(),
340
+ name=count_name,
341
+ path_len=node.path_len,
310
342
  )
311
-
312
- ### Function that inject a wait after path that will wait for the nodes
313
- def get_activity_wait(prev_nodes, nodes_to_wait, next_nodes, replaced_node = None, edge_only = False, activity = None):
314
343
 
315
- if issubclass(nodes_to_wait.__class__,TriccBaseModel):
344
+
345
+ # Function that inject a wait after path that will wait for the nodes
346
+
347
+
348
+ def get_activity_wait(prev_nodes, nodes_to_wait, next_nodes, replaced_node=None, edge_only=False, activity=None):
349
+
350
+ if issubclass(nodes_to_wait.__class__, TriccBaseModel):
316
351
  nodes_to_wait = [nodes_to_wait]
317
- if issubclass(prev_nodes.__class__,TriccBaseModel):
352
+ if issubclass(prev_nodes.__class__, TriccBaseModel):
318
353
  prev_nodes = set([prev_nodes])
319
354
  elif isinstance(prev_nodes, list):
320
355
  prev_nodes = set(prev_nodes)
321
-
356
+
322
357
  iterator = iter(prev_nodes)
323
358
  prev_node = next(iterator)
324
359
  path = prev_node if len(prev_nodes) == 1 else get_bridge_path(prev_nodes, activity)
325
-
360
+
326
361
  activity = activity or prev_node.activity
327
362
  calc_node = TriccNodeWait(
328
- id = generate_id(f"ar{''.join([x.id for x in nodes_to_wait])}{activity.id}"),
329
- reference = nodes_to_wait,
330
- activity = activity,
331
- group = activity,
332
- path = path
333
- )
363
+ id=generate_id(f"ar{''.join([x.id for x in nodes_to_wait])}{activity.id}"),
364
+ reference=nodes_to_wait,
365
+ activity=activity,
366
+ group=activity,
367
+ path=path,
368
+ )
334
369
 
335
- #start the wait and the next_nodes from the prev_nodes
336
- #add the wait as dependency of the next_nodes
370
+ # start the wait and the next_nodes from the prev_nodes
371
+ # add the wait as dependency of the next_nodes
337
372
 
338
- # add edge between rhombus and node
373
+ # add edge between rhombus and node
339
374
 
340
- set_prev_next_node(path,calc_node, edge_only=edge_only, activity=activity )
375
+ set_prev_next_node(path, calc_node, edge_only=edge_only, activity=activity)
341
376
  for next_node in next_nodes:
342
- #if prev != replaced_node and next_node != replaced_node :
343
- # set_prev_next_node(prev,next_node,replaced_node)
344
- #if first:
345
- #first = False
346
- set_prev_next_node(calc_node,next_node, edge_only=edge_only,activity=activity)
347
-
348
-
377
+ # if prev != replaced_node and next_node != replaced_node :
378
+ # set_prev_next_node(prev,next_node,replaced_node)
379
+ # if first:
380
+ # first = False
381
+ set_prev_next_node(calc_node, next_node, edge_only=edge_only, activity=activity)
382
+
349
383
  return calc_node
350
-
351
- def get_bridge_path(prev_nodes, node=None,edge_only=False):
384
+
385
+
386
+ def get_bridge_path(prev_nodes, node=None, edge_only=False):
352
387
  iterator = iter(prev_nodes)
353
- p_p_node = next(iterator)
388
+ p_p_node = next(iterator)
354
389
  if node is None:
355
390
  node = p_p_node
356
- calc_id = generate_id(f"br{''.join([x.id for x in prev_nodes])}{node.id}")
357
- calc_name = "path_"+calc_id
391
+ calc_id = generate_id(f"br{''.join([x.id for x in prev_nodes])}{node.id}")
392
+ calc_name = "path_" + calc_id
358
393
  data = {
359
- 'id': calc_id,
360
- 'group': node.group,
361
- 'activity': node.activity,
362
- 'label': "path: " + ( node.get_name()),
363
- 'name': calc_name,
364
- 'path_len': node.path_len + 1 * (node == p_p_node)
394
+ "id": calc_id,
395
+ "group": node.group,
396
+ "activity": node.activity,
397
+ "label": "path: " + (node.get_name()),
398
+ "name": calc_name,
399
+ "path_len": node.path_len + 1 * (node == p_p_node),
365
400
  }
366
-
367
- if len(prev_nodes)>1 and sum([0 if issubclass(n.__class__, (TriccNodeDisplayCalculateBase, TriccNodeRhombus)) else 1 for n in prev_nodes])>0 :
368
- calc= TriccNodeDisplayBridge( **data)
401
+
402
+ if (
403
+ len(prev_nodes) > 1
404
+ and sum(
405
+ [0 if issubclass(n.__class__, (TriccNodeDisplayCalculateBase, TriccNodeRhombus)) else 1 for n in prev_nodes]
406
+ )
407
+ > 0
408
+ ):
409
+ calc = TriccNodeDisplayBridge(**data)
369
410
  else:
370
- calc = TriccNodeBridge( **data)
411
+ calc = TriccNodeBridge(**data)
371
412
  return calc
372
-
413
+
414
+
373
415
  def inject_bridge_path(node, nodes):
374
416
 
375
- prev_nodes = [nodes[n.source] for n in list(filter(lambda x: (x.target == node.id or x.target == node) and x.source in list(nodes.keys()), node.activity.edges))]
417
+ prev_nodes = [
418
+ nodes[n.source]
419
+ for n in list(
420
+ filter(
421
+ lambda x: (x.target == node.id or x.target == node) and x.source in list(nodes.keys()),
422
+ node.activity.edges,
423
+ )
424
+ )
425
+ ]
376
426
  if prev_nodes:
377
- calc = get_bridge_path(prev_nodes, node,edge_only=True)
427
+ calc = get_bridge_path(prev_nodes, node, edge_only=True)
378
428
 
379
429
  for e in node.activity.edges:
380
430
  if e.target == node.id:
381
431
  # if e.source in node.activity.nodes and len(node.activity.nodes[e.source].next_nodes):
382
432
  # set_prev_next_node(node.activity[e.source], node, edge_only=True, replaced_node=node)
383
433
  # else:
384
- e.target = calc.id
385
-
434
+ e.target = calc.id
435
+
386
436
  # add edge between bridge and node
387
- set_prev_next_node(calc,node,edge_only=True, activity=node.activity)
437
+ set_prev_next_node(calc, node, edge_only=True, activity=node.activity)
388
438
  node.path_len += 1
389
439
  return calc
390
440
 
@@ -394,45 +444,50 @@ def inject_node_before(before, node, activity):
394
444
  before.activity = activity
395
445
  activity.nodes[before.id] = before
396
446
  nodes = activity.nodes
397
- prev_nodes = node.prev_nodes.union(set(nodes[n.source] for n in list(filter(lambda x: (x.target == node.id or x.target == node) and x.source in nodes, node.activity.edges))))
447
+ prev_nodes = node.prev_nodes.union(
448
+ set(
449
+ nodes[n.source]
450
+ for n in list(
451
+ filter(lambda x: (x.target == node.id or x.target == node) and x.source in nodes, node.activity.edges)
452
+ )
453
+ )
454
+ )
398
455
  edge_processed = False
399
456
  before.path_len = node.path_len
400
457
  for e in node.activity.edges:
401
458
  if e.target == node.id:
402
459
  e.target = before.id
403
- for p in prev_nodes:
404
- prev_processed = len(node.next_nodes) > 0
460
+ for p in prev_nodes:
405
461
  if node in p.next_nodes:
406
462
  p.next_nodes.remove(node)
407
463
  p.next_nodes.append(before)
408
464
 
409
465
  # add edge between bridge and node
410
- set_prev_next_node(before,node,edge_only=not edge_processed, activity=node.activity)
466
+ set_prev_next_node(before, node, edge_only=not edge_processed, activity=node.activity)
411
467
  node.path_len += 1
412
468
 
413
-
414
-
415
- def generate_calculates(node,calculates, used_calculates,processed_nodes, process):
469
+
470
+ def generate_calculates(node, calculates, used_calculates, processed_nodes, process):
416
471
  list_calc = []
417
472
  count_node = None
418
- ## add select calcualte
473
+ # add select calcualte
419
474
  if issubclass(node.__class__, TriccNodeCalculateBase):
420
475
  if isinstance(node, TriccNodeRhombus):
421
476
  if (
422
477
  (node.expression_reference is None or isinstance(node.expression_reference, TriccOperation))
423
478
  and isinstance(node.reference, list)
424
- and len(node.reference)==1
479
+ and len(node.reference) == 1
425
480
  and issubclass(node.reference[0].__class__, TriccNodeSelect)
426
481
  ):
427
482
 
428
483
  count_node = get_count_node(node)
429
484
  list_calc.append(count_node)
430
- set_prev_next_node(node.reference[0],count_node)
431
- node.path_len+=1
432
-
485
+ set_prev_next_node(node.reference[0], count_node)
486
+ node.path_len += 1
487
+
433
488
  if isinstance(node.expression_reference, TriccOperation):
434
489
  node.expression_reference.replace_node(node.reference, count_node)
435
- node.reference[0] = count_node
490
+ node.reference[0] = count_node
436
491
  # elif isinstance(node.reference, TriccOperation):
437
492
  # references = node.reference.get_references()
438
493
  # if len(references) == 1 and issubclass(node.reference[0].__class__, TriccNodeSelect):
@@ -445,68 +500,67 @@ def generate_calculates(node,calculates, used_calculates,processed_nodes, proces
445
500
  processed_nodes.add(count_node)
446
501
  add_calculate(calculates, count_node)
447
502
  add_used_calculate(
448
- node,
449
- count_node,
450
- calculates=calculates,
503
+ node,
504
+ count_node,
505
+ calculates=calculates,
451
506
  used_calculates=used_calculates,
452
- processed_nodes=processed_nodes
507
+ processed_nodes=processed_nodes,
453
508
  )
454
-
455
-
509
+
456
510
  # if a prev node is a calculate then it must be added in used_calc
457
511
  for prev in node.prev_nodes:
458
512
  add_used_calculate(
459
- node,
460
- prev,
461
- calculates=calculates,
462
- used_calculates=used_calculates,
463
- processed_nodes=processed_nodes
513
+ node, prev, calculates=calculates, used_calculates=used_calculates, processed_nodes=processed_nodes
464
514
  )
465
- #if the node have a save
466
- if hasattr(node, 'save') and node.save is not None and node.save != '':
515
+ # if the node have a save
516
+ if hasattr(node, "save") and node.save is not None and node.save != "":
467
517
  # get fragments type.name.icdcode
468
- calculate_name=node.save
518
+ calculate_name = node.save
469
519
  if node.name != calculate_name:
470
520
  calc_id = generate_id(f"autosave{node.id}")
471
521
  if issubclass(node.__class__, TriccNodeSelect) or isinstance(node, TriccNodeSelectNotAvailable):
472
- expression = get_count_terms_details( node, processed_nodes, True, False, process)
522
+ expression = get_count_terms_details(node, processed_nodes, True, False, process)
473
523
  else:
474
- expression = get_node_expression(node,processed_nodes,True,True)
524
+ expression = get_node_expression(node, processed_nodes, True, True)
475
525
  calc_node = TriccNodeCalculate(
476
526
  name=calculate_name,
477
- id = calc_id,
478
- group = node.group,
479
- #version=get_next_version(calculate_name, processed_nodes, node.version+2),
480
- activity = node.activity,
481
- label = "save: " +node.get_name(),
482
- path_len=node.path_len+ 1,
527
+ id=calc_id,
528
+ group=node.group,
529
+ # version=get_next_version(calculate_name, processed_nodes, node.version+2),
530
+ activity=node.activity,
531
+ label="save: " + node.get_name(),
532
+ path_len=node.path_len + 1,
483
533
  last=True,
484
- expression=expression
534
+ expression=expression,
485
535
  )
486
536
  node.activity.calculates.append(calc_node)
487
537
  last_version = set_last_version_false(calc_node, processed_nodes)
488
538
  if last_version:
489
539
  calc_node.expression = merge_expression(calc_node.expression, last_version)
490
540
  processed_nodes.add(calc_node)
491
- logger.debug("generate_save_calculate:{}:{} as {}".format(calc_node.tricc_type, node.name if hasattr(node,'name') else node.id, calculate_name))
492
-
541
+ logger.debug(
542
+ "generate_save_calculate:{}:{} as {}".format(
543
+ calc_node.tricc_type, node.name if hasattr(node, "name") else node.id, calculate_name
544
+ )
545
+ )
546
+
493
547
  list_calc.append(calc_node)
494
- #add_save_calculate(calc_node, calculates, used_calculates,processed_nodes)
548
+ # add_save_calculate(calc_node, calculates, used_calculates,processed_nodes)
495
549
  for calc in list_calc:
496
550
  node.activity.nodes[calc.id] = calc
497
551
  add_calculate(calculates, calc)
498
552
  return list_calc
499
553
 
500
554
 
501
-
502
555
  def add_calculate(calculates, calc_node):
503
556
  if issubclass(calc_node.__class__, TriccNodeDisplayCalculateBase):
504
557
  if calc_node.name not in calculates:
505
- calculates[calc_node.name]= {}
558
+ calculates[calc_node.name] = {}
506
559
  calculates[calc_node.name][calc_node.id] = calc_node
507
560
 
561
+
508
562
  def get_option_code_from_label(node, option_label):
509
- if hasattr(node, 'options'):
563
+ if hasattr(node, "options"):
510
564
  for i in node.options:
511
565
  if node.options[i].label.strip() == option_label.strip():
512
566
  return node.options[i].name
@@ -515,43 +569,95 @@ def get_option_code_from_label(node, option_label):
515
569
  logger.critical(f"node {node.get_name()} has no options")
516
570
 
517
571
 
518
- def process_reference(node, processed_nodes, calculates, used_calculates=None, replace_reference=False,warn=False, codesystems=None):
519
- if getattr(node, 'expression_reference', None):
572
+ # CQL is deined as a cql library and this code will
573
+ # parse the definition and will extract the logic under the define statement
574
+
575
+
576
+ def extract_with_regex(data):
577
+ text = data
578
+ # Pattern to match define statement and capture the name and body
579
+ pattern = r'define\s+"([^"]+)":\s*(.*)'
580
+ match = re.search(pattern, text, re.DOTALL)
581
+
582
+ if match:
583
+ definition_name = match.group(1)
584
+ definition_body = match.group(2).strip()
585
+ return {"name": definition_name, "body": definition_body, "full": match.group(0)}
586
+ return None
587
+
588
+
589
+ def process_reference(
590
+ node, processed_nodes, calculates, used_calculates=None, replace_reference=False, warn=False, codesystems=None
591
+ ):
592
+ # process a remote reference coded as a cql
593
+ if getattr(node, "remote_reference", None):
594
+ remote_reference_url = node.remote_reference
595
+ print(f"Fetching remote reference from {remote_reference_url}")
596
+ response = requests.get(remote_reference_url)
597
+ response_json = response.json()
598
+ cql_content = response_json["content"][0]["data"]
599
+ decode_cql_content = base64.b64decode(cql_content).decode("utf-8")
600
+ definition = extract_with_regex(decode_cql_content)
601
+
602
+ if definition:
603
+ cql_expression = definition["body"]
604
+
605
+ # We use `transform_cql_to_operation` to parse the raw CQL string.
606
+ operation = transform_cql_to_operation(cql_expression, context=f"remote reference for {node.get_name()}")
607
+
608
+ if not operation:
609
+ logger.error(f"Failed to parse remote CQL expression for node {node.get_name()}: {cql_expression}")
610
+ return False
611
+
612
+ # The parsed operation is assigned to `expression_reference`.
613
+ # The original code incorrectly assigned the raw string to `node.reference`
614
+ # and had an unreachable `if isinstance(cql_expression, list):` block.
615
+ node.expression_reference = operation
616
+ node.remote_reference = None
617
+
618
+ # By setting `expression_reference` and clearing `remote_reference`,
619
+ # we can now re-process this node. A recursive call to `process_reference`
620
+ # will now enter the `elif getattr(node, 'expression_reference', None):`
621
+ # block, which will correctly handle the newly parsed expression.
622
+ return process_reference(
623
+ node, processed_nodes, calculates, used_calculates, replace_reference, warn, codesystems
624
+ )
625
+
626
+ elif getattr(node, "expression_reference", None):
520
627
  modified_expression = process_operation_reference(
521
- node.expression_reference,
522
- node,
628
+ node.expression_reference,
629
+ node,
523
630
  processed_nodes=processed_nodes,
524
- calculates=calculates,
525
- used_calculates=used_calculates,
631
+ calculates=calculates,
632
+ used_calculates=used_calculates,
526
633
  replace_reference=replace_reference,
527
- warn=warn,
528
- codesystems=codesystems
634
+ warn=warn,
635
+ codesystems=codesystems,
529
636
  )
530
637
  if modified_expression is False:
531
638
  return False
532
639
  elif modified_expression and replace_reference:
533
640
  node.reference = list(modified_expression.get_references())
534
641
  node.expression_reference = modified_expression
535
- elif getattr(node, 'reference', None):
642
+
643
+ elif getattr(node, "reference", None):
536
644
  reference = node.reference
537
645
  if isinstance(reference, list):
538
646
  if isinstance(node, TriccNodeWait):
539
- reference = [TriccOperation(TriccOperator.ISTRUE,[n]) for n in reference]
540
- if len(node.reference) == 1 :
647
+ reference = [TriccOperation(TriccOperator.ISTRUE, [n]) for n in reference]
648
+ if len(node.reference) == 1:
541
649
  operation = reference[0]
542
650
  else:
543
- operation = and_join(
544
- reference
545
- )
651
+ operation = and_join(reference)
546
652
  modified_expression = process_operation_reference(
547
- operation,
653
+ operation,
548
654
  node,
549
655
  processed_nodes=processed_nodes,
550
- calculates=calculates,
551
- used_calculates=used_calculates,
656
+ calculates=calculates,
657
+ used_calculates=used_calculates,
552
658
  replace_reference=replace_reference,
553
- warn=warn,
554
- codesystems=codesystems
659
+ warn=warn,
660
+ codesystems=codesystems,
555
661
  )
556
662
  if modified_expression is False:
557
663
  return False
@@ -561,14 +667,14 @@ def process_reference(node, processed_nodes, calculates, used_calculates=None,
561
667
  node.expression_reference = modified_expression
562
668
  elif isinstance(node.reference, (TriccOperation, TriccReference)):
563
669
  modified_expression = process_operation_reference(
564
- node.reference,
565
- node,
670
+ node.reference,
671
+ node,
566
672
  processed_nodes=processed_nodes,
567
- calculates=calculates,
568
- used_calculates=used_calculates,
673
+ calculates=calculates,
674
+ used_calculates=used_calculates,
569
675
  replace_reference=replace_reference,
570
- warn=warn,
571
- codesystems=codesystems
676
+ warn=warn,
677
+ codesystems=codesystems,
572
678
  )
573
679
  if modified_expression is False:
574
680
  return False
@@ -576,95 +682,95 @@ def process_reference(node, processed_nodes, calculates, used_calculates=None,
576
682
  node.reference = list(modified_expression.get_references())
577
683
  node.expression_reference = modified_expression
578
684
 
579
- if isinstance(getattr(node, 'relevance', None), (TriccOperation, TriccReference)):
685
+ if isinstance(getattr(node, "relevance", None), (TriccOperation, TriccReference)):
580
686
  modified_expression = process_operation_reference(
581
- node.relevance,
582
- node,
687
+ node.relevance,
688
+ node,
583
689
  processed_nodes=processed_nodes,
584
- calculates=calculates,
585
- used_calculates=used_calculates,
690
+ calculates=calculates,
691
+ used_calculates=used_calculates,
586
692
  replace_reference=replace_reference,
587
- warn=warn,
588
- codesystems=codesystems
693
+ warn=warn,
694
+ codesystems=codesystems,
589
695
  )
590
696
  if modified_expression is False:
591
697
  return False
592
698
  elif modified_expression and replace_reference:
593
699
  node.relevance = modified_expression
594
-
595
- if isinstance(getattr(node, 'trigger', None), (TriccOperation, TriccReference)):
700
+
701
+ if isinstance(getattr(node, "trigger", None), (TriccOperation, TriccReference)):
596
702
  modified_expression = process_operation_reference(
597
- node.trigger,
598
- node,
703
+ node.trigger,
704
+ node,
599
705
  processed_nodes=processed_nodes,
600
- calculates=calculates,
601
- used_calculates=used_calculates,
706
+ calculates=calculates,
707
+ used_calculates=used_calculates,
602
708
  replace_reference=replace_reference,
603
- warn=warn,
604
- codesystems=codesystems
709
+ warn=warn,
710
+ codesystems=codesystems,
605
711
  )
606
712
  if modified_expression is False:
607
713
  return False
608
714
  elif modified_expression and replace_reference:
609
715
  node.trigger = modified_expression
610
- if isinstance(getattr(node, 'constraint', None), (TriccOperation, TriccReference)):
716
+ if isinstance(getattr(node, "constraint", None), (TriccOperation, TriccReference)):
611
717
  modified_expression = process_operation_reference(
612
- node.constraint,
613
- node,
718
+ node.constraint,
719
+ node,
614
720
  processed_nodes=processed_nodes,
615
- calculates=calculates,
616
- used_calculates=used_calculates,
721
+ calculates=calculates,
722
+ used_calculates=used_calculates,
617
723
  replace_reference=replace_reference,
618
- warn=warn,
619
- codesystems=codesystems
724
+ warn=warn,
725
+ codesystems=codesystems,
620
726
  )
621
727
  if modified_expression is False:
622
728
  return False
623
729
  elif modified_expression and replace_reference:
624
730
  node.constraint = modified_expression
625
-
626
- if isinstance(getattr(node, 'default', None), (TriccOperation, TriccReference)):
731
+
732
+ if isinstance(getattr(node, "default", None), (TriccOperation, TriccReference)):
627
733
  modified_expression = process_operation_reference(
628
- node.default,
629
- node,
734
+ node.default,
735
+ node,
630
736
  processed_nodes=processed_nodes,
631
- calculates=calculates,
632
- used_calculates=used_calculates,
737
+ calculates=calculates,
738
+ used_calculates=used_calculates,
633
739
  replace_reference=replace_reference,
634
- warn=warn,
635
- codesystems=codesystems
636
- )
740
+ warn=warn,
741
+ codesystems=codesystems,
742
+ )
637
743
  if modified_expression is False:
638
744
  return False
639
745
  elif modified_expression and replace_reference:
640
746
  node.relevance = modified_expression
641
-
642
- if isinstance(getattr(node, 'expression', None), (TriccOperation, TriccReference)):
747
+
748
+ if isinstance(getattr(node, "expression", None), (TriccOperation, TriccReference)):
643
749
  modified_expression = process_operation_reference(
644
- node.expression,
645
- node,
750
+ node.expression,
751
+ node,
646
752
  processed_nodes=processed_nodes,
647
- calculates=calculates,
648
- used_calculates=used_calculates,
753
+ calculates=calculates,
754
+ used_calculates=used_calculates,
649
755
  replace_reference=replace_reference,
650
- warn=warn,
651
- codesystems=codesystems
756
+ warn=warn,
757
+ codesystems=codesystems,
652
758
  )
653
759
  if modified_expression is False:
654
760
  return False
655
761
  elif modified_expression and replace_reference:
656
762
  node.expression = modified_expression
657
-
658
- if isinstance(getattr(node, 'applicability', None), (TriccOperation, TriccReference)):
763
+
764
+ if isinstance(getattr(node, "applicability", None), (TriccOperation, TriccReference)):
659
765
  modified_expression = process_operation_reference(
660
- node.applicability,
661
- node,
766
+ node.applicability,
767
+ node,
662
768
  processed_nodes=processed_nodes,
663
- calculates=calculates,
664
- used_calculates=used_calculates,
769
+ calculates=calculates,
770
+ used_calculates=used_calculates,
665
771
  replace_reference=replace_reference,
666
- warn=warn,
667
- codesystems=codesystems
772
+ warn=warn,
773
+ codesystems=codesystems,
668
774
  )
669
775
  if modified_expression is False:
670
776
  return False
@@ -672,7 +778,17 @@ def process_reference(node, processed_nodes, calculates, used_calculates=None,
672
778
  node.applicability = modified_expression
673
779
  return True
674
780
 
675
- def process_operation_reference(operation, node, processed_nodes, calculates, used_calculates=None, replace_reference=False,warn=False, codesystems=None):
781
+
782
+ def process_operation_reference(
783
+ operation,
784
+ node,
785
+ processed_nodes,
786
+ calculates,
787
+ used_calculates=None,
788
+ replace_reference=False,
789
+ warn=False,
790
+ codesystems=None,
791
+ ):
676
792
  modified_operation = None
677
793
  node_reference = []
678
794
  reference = []
@@ -680,13 +796,13 @@ def process_operation_reference(operation, node, processed_nodes, calculates, us
680
796
  ref_list = [r.value for r in operation.get_references() if isinstance(r, TriccReference)]
681
797
  real_ref_list = [r for r in operation.get_references() if issubclass(r.__class__, TriccNodeBaseModel)]
682
798
  for ref in ref_list:
683
- if ref.endswith(']'):
684
- terms = ref[:-1].split('[')
799
+ if ref.endswith("]"):
800
+ terms = ref[:-1].split("[")
685
801
  option_label = terms[1]
686
802
  ref = terms[0]
687
803
  else:
688
804
  option_label = None
689
- node_in_act = [n for n in node.activity.nodes.values() if n.name == ref and n != node]
805
+ node_in_act = [n for n in node.activity.nodes.values() if n.name == ref and n != node]
690
806
  if node_in_act:
691
807
  if any(n not in processed_nodes for n in node_in_act):
692
808
  return False
@@ -694,16 +810,16 @@ def process_operation_reference(operation, node, processed_nodes, calculates, us
694
810
  last_found = node_in_act[0]
695
811
  else:
696
812
  last_found = get_last_version(name=ref, processed_nodes=processed_nodes)
697
- if last_found is None:
813
+ if last_found is None:
698
814
  if codesystems:
699
- concept = lookup_codesystems_code(codesystems, ref)
815
+ concept = lookup_codesystems_code(codesystems, ref)
700
816
  if not concept:
701
817
  logger.critical(f"reference {ref} not found in the project for{str(node)} ")
702
818
  exit(1)
703
819
  else:
704
820
  if warn:
705
821
  logger.debug(f"reference {ref}::{concept.display} not yet processed {node.get_name()}")
706
-
822
+
707
823
  elif warn:
708
824
  logger.debug(f"reference {ref} not found for a calculate {node.get_name()}")
709
825
  return False
@@ -711,7 +827,9 @@ def process_operation_reference(operation, node, processed_nodes, calculates, us
711
827
  node_reference.append(last_found)
712
828
  reference.append(TriccReference(ref))
713
829
  if replace_reference:
714
- if not issubclass(last_found.__class__, (TriccNodeDisplayModel, TriccNodeDisplayCalculateBase, TriccNodeInput)):
830
+ if not issubclass(
831
+ last_found.__class__, (TriccNodeDisplayModel, TriccNodeDisplayCalculateBase, TriccNodeInput)
832
+ ):
715
833
  last_found = get_node_expression(last_found, processed_nodes, is_prev=True)
716
834
  if isinstance(operation, (TriccOperation)):
717
835
  if modified_operation is None:
@@ -723,118 +841,141 @@ def process_operation_reference(operation, node, processed_nodes, calculates, us
723
841
  # Resolve human-readable label
724
842
  option_code = get_option_code_from_label(last_found, option_label)
725
843
  if option_code:
726
- modified_operation = replace_code_reference(operation, old=f"{ref}[{option_label}]", new=option_code )
844
+ modified_operation = replace_code_reference(
845
+ operation, old=f"{ref}[{option_label}]", new=option_code
846
+ )
727
847
  else:
728
848
  if warn:
729
849
  logger.warning(f"Could not resolve label '{option_label}' for reference {ref}")
730
850
  return False
731
- if hasattr(last_found, 'path_len'):
732
- path_len = last_found.path_len
851
+ if hasattr(last_found, "path_len"):
852
+ path_len = last_found.path_len
733
853
  elif isinstance(last_found, TriccOperation):
734
- path_len = max(getattr(n, 'path_len', 0) for n in last_found.get_references())
854
+ path_len = max(getattr(n, "path_len", 0) for n in last_found.get_references())
735
855
  else:
736
856
  path_len = 0
737
857
  node.path_len = max(node.path_len, path_len)
738
858
  for ref in real_ref_list:
739
859
  if is_prev_processed(ref, node, processed_nodes=processed_nodes, local=False) is False:
740
860
  return False
741
-
861
+
742
862
  if used_calculates is not None:
743
863
  for ref_nodes in node_reference:
744
864
  if issubclass(ref_nodes.__class__, TriccNodeCalculateBase):
745
865
  add_used_calculate(node, ref_nodes, calculates, used_calculates, processed_nodes=processed_nodes)
746
866
  return modified_operation
747
867
 
868
+
748
869
  def replace_code_reference(expression, old, new):
749
870
  if isinstance(expression, str):
750
- return expression_reference.replace(old, f"'{new}'")
871
+ return expression.replace(old, f"'{new}'")
751
872
  if isinstance(expression, TriccOperation):
752
873
  expression.replace_node(TriccReference(old), TriccStatic(new))
753
874
  return expression
754
- #add_used_calculate(node, calc_node, calculates, used_calculates, processed_nodes)
875
+
876
+
877
+ # add_used_calculate(node, calc_node, calculates, used_calculates, processed_nodes)
878
+
755
879
 
756
880
  def add_used_calculate(node, prev_node, calculates, used_calculates, processed_nodes):
757
881
  if issubclass(prev_node.__class__, TriccNodeDisplayCalculateBase):
758
882
  if prev_node in processed_nodes:
759
883
  # if not a verison, index will equal -1
760
- if prev_node.name not in calculates :
884
+ if prev_node.name not in calculates:
761
885
  logger.debug("node {} refered before being processed".format(node.get_name()))
762
886
  return False
763
- max_version = prev_node#get_max_version(calculates[node_clean_name])
887
+ max_version = prev_node # get_max_version(calculates[node_clean_name])
764
888
  if prev_node.name not in used_calculates:
765
889
  used_calculates[prev_node.name] = {}
766
- #save the max version only once
890
+ # save the max version only once
767
891
  if max_version.id not in used_calculates[prev_node.name]:
768
892
  used_calculates[prev_node.name][max_version.id] = max_version
769
893
  else:
770
- logger.debug("process_calculate_version_requirement: failed for {0} , prev Node {1} ".format(node.get_name(), prev_node.get_name()))
771
-
772
-
773
- def get_select_not_available_options(node,group,label):
774
- return {0:TriccNodeSelectOption(
775
- id = generate_id(f"notavaialble{node.id}"),
776
- name="1",
777
- label=label,
778
- select = node,
779
- group = group,
780
- list_name = node.list_name
781
- )}
782
-
894
+ logger.debug(
895
+ "process_calculate_version_requirement: failed for {0} , prev Node {1} ".format(
896
+ node.get_name(), prev_node.get_name()
897
+ )
898
+ )
899
+
900
+
901
+ def get_select_not_available_options(node, group, label):
902
+ return {
903
+ 0: TriccNodeSelectOption(
904
+ id=generate_id(f"notavaialble{node.id}"),
905
+ name="1",
906
+ label=label,
907
+ select=node,
908
+ group=group,
909
+ list_name=node.list_name,
910
+ )
911
+ }
912
+
913
+
783
914
  def get_select_yes_no_options(node, group):
784
915
  yes = TriccNodeSelectOption(
785
- id = generate_id(f'yes{node.id}'),
786
- name=f"{TRICC_TRUE_VALUE}",
787
- label="Yes",
788
- select = node,
789
- group = group,
790
- list_name = node.list_name
791
- )
916
+ id=generate_id(f"yes{node.id}"),
917
+ name=f"{TRICC_TRUE_VALUE}",
918
+ label="Yes",
919
+ select=node,
920
+ group=group,
921
+ list_name=node.list_name,
922
+ )
792
923
  no = TriccNodeSelectOption(
793
- id = generate_id(f'no{node.id}'),
794
- name=f"{TRICC_FALSE_VALUE}",
795
- label="No",
796
- select = node,
797
- group = group,
798
- list_name = node.list_name
799
- )
800
- return {0:yes, 1:no }
924
+ id=generate_id(f"no{node.id}"),
925
+ name=f"{TRICC_FALSE_VALUE}",
926
+ label="No",
927
+ select=node,
928
+ group=group,
929
+ list_name=node.list_name,
930
+ )
931
+ return {0: yes, 1: no}
932
+
801
933
 
802
- # walkthough all node in an iterative way, the same node might be parsed 2 times
934
+ # walkthough all node in an iterative way, the same node might be parsed 2 times
803
935
  # therefore to avoid double processing the nodes variable saves the node already processed
804
936
  # there 2 strategies : process it the first time or the last time (wait that all the previuous node are processed)
805
937
 
806
- def walktrhough_tricc_node_processed_stached(node, callback, processed_nodes, stashed_nodes, path_len, recursive=False, warn = False,
807
- node_path = [], process=None, **kwargs):
938
+
939
+ def walktrhough_tricc_node_processed_stached(
940
+ node,
941
+ callback,
942
+ processed_nodes,
943
+ stashed_nodes,
944
+ path_len,
945
+ recursive=False,
946
+ warn=False,
947
+ node_path=[],
948
+ process=None,
949
+ **kwargs,
950
+ ):
808
951
  ended_activity = False
809
952
  # logger.debug("walkthrough::{}::{}".format(callback.__name__, node.get_name()))
810
-
811
- path_len = max(node.activity.path_len, *[0,*[getattr(n,'path_len',0) + 1 for n in node.activity.prev_nodes]]) + 1
812
- if hasattr(node, 'prev_nodes'):
813
- path_len = max(path_len, *[0,*[getattr(n,'path_len',0)+ 1 for n in node.prev_nodes]])
814
- if hasattr(node, 'get_references'):
953
+
954
+ path_len = max(node.activity.path_len, *[0, *[getattr(n, "path_len", 0) + 1 for n in node.activity.prev_nodes]]) + 1
955
+ if hasattr(node, "prev_nodes"):
956
+ path_len = max(path_len, *[0, *[getattr(n, "path_len", 0) + 1 for n in node.prev_nodes]])
957
+ if hasattr(node, "get_references"):
815
958
  references = node.get_references()
816
959
  if references:
817
- path_len = max(path_len, *[0,*[getattr(n,'path_len',0) + 1 for n in references]])
960
+ path_len = max(path_len, *[0, *[getattr(n, "path_len", 0) + 1 for n in references]])
818
961
  node.path_len = max(node.path_len, path_len)
819
962
  prev_process = process[0] if process else None
820
- if isinstance(node, TriccNodeActivity) and getattr(node.root, 'process', None):
963
+ if isinstance(node, TriccNodeActivity) and getattr(node.root, "process", None):
821
964
  if process is None:
822
965
  process = [node.root.process]
823
966
  else:
824
967
  process[0] = node.root.process
825
- if (
826
- callback(
827
- node,
828
- processed_nodes=processed_nodes,
829
- stashed_nodes=stashed_nodes,
830
- warn = warn,
831
- node_path=node_path,
832
- process=process,
833
- **kwargs
834
- )
968
+ if callback(
969
+ node,
970
+ processed_nodes=processed_nodes,
971
+ stashed_nodes=stashed_nodes,
972
+ warn=warn,
973
+ node_path=node_path,
974
+ process=process,
975
+ **kwargs,
835
976
  ):
836
977
  node_path.append(node)
837
- # node processing succeed
978
+ # node processing succeed
838
979
  if not isinstance(node, TriccNodeActivity) and node not in processed_nodes:
839
980
  processed_nodes.add(node)
840
981
  if warn:
@@ -845,7 +986,11 @@ def walktrhough_tricc_node_processed_stached(node, callback, processed_nodes, st
845
986
  processed_nodes.add(node.activity)
846
987
  ended_activity = True
847
988
  if warn:
848
- logger.debug("{}::{}: processed ({})".format(callback.__name__, node.activity.get_name(), len(processed_nodes)))
989
+ logger.debug(
990
+ "{}::{}: processed ({})".format(
991
+ callback.__name__, node.activity.get_name(), len(processed_nodes)
992
+ )
993
+ )
849
994
  elif node in stashed_nodes:
850
995
  stashed_nodes.remove(node)
851
996
  # logger.debug("{}::{}: unstashed ({})".format(callback.__name__, node.get_name(), len(stashed_nodes)))
@@ -856,90 +1001,118 @@ def walktrhough_tricc_node_processed_stached(node, callback, processed_nodes, st
856
1001
  if recursive:
857
1002
  for gp in node.activity.groups.values():
858
1003
  walktrhough_tricc_node_processed_stached(
859
- gp,
1004
+ gp,
860
1005
  callback,
861
- processed_nodes=processed_nodes,
862
- stashed_nodes=stashed_nodes,
1006
+ processed_nodes=processed_nodes,
1007
+ stashed_nodes=stashed_nodes,
863
1008
  path_len=path_len,
864
1009
  recursive=recursive,
865
- warn = warn,
866
- node_path = node_path.copy(),
867
- **kwargs
1010
+ warn=warn,
1011
+ node_path=node_path.copy(),
1012
+ **kwargs,
868
1013
  )
869
1014
  for c in node.activity.calculates:
870
- if len(c.prev_nodes)== 0:
1015
+ if len(c.prev_nodes) == 0:
871
1016
  walktrhough_tricc_node_processed_stached(
872
1017
  c,
873
1018
  callback,
874
- processed_nodes=processed_nodes,
875
- stashed_nodes=stashed_nodes,
1019
+ processed_nodes=processed_nodes,
1020
+ stashed_nodes=stashed_nodes,
876
1021
  path_len=path_len,
877
1022
  recursive=recursive,
878
- warn = warn,
879
- node_path = node_path.copy(),
880
- **kwargs
881
- )
1023
+ warn=warn,
1024
+ node_path=node_path.copy(),
1025
+ **kwargs,
1026
+ )
882
1027
  else:
883
- stashed_nodes += [c for c in node.activity.calculates if len(c.prev_nodes)== 0]
1028
+ stashed_nodes += [c for c in node.activity.calculates if len(c.prev_nodes) == 0]
884
1029
  stashed_nodes += node.activity.groups.values()
885
1030
  elif issubclass(node.__class__, TriccNodeSelect):
886
1031
  for option in node.options.values():
887
- option.path_len = max(path_len, option.path_len)
888
- callback(option, processed_nodes=processed_nodes, stashed_nodes=stashed_nodes, warn = warn, node_path=node_path,**kwargs)
1032
+ option.path_len = max(path_len, option.path_len)
1033
+ callback(
1034
+ option,
1035
+ processed_nodes=processed_nodes,
1036
+ stashed_nodes=stashed_nodes,
1037
+ warn=warn,
1038
+ node_path=node_path,
1039
+ **kwargs,
1040
+ )
889
1041
  if option not in processed_nodes:
890
1042
  processed_nodes.add(option)
891
1043
  if warn:
892
1044
  logger.debug(
893
- "{}::{}: processed ({})".format(callback.__name__, option.get_name(), len(processed_nodes)))
894
- walkthrough_tricc_option(node, callback, processed_nodes, stashed_nodes, path_len + 1, recursive,
895
- warn = warn,node_path = node_path, **kwargs)
1045
+ "{}::{}: processed ({})".format(callback.__name__, option.get_name(), len(processed_nodes))
1046
+ )
1047
+ walkthrough_tricc_option(
1048
+ node,
1049
+ callback,
1050
+ processed_nodes,
1051
+ stashed_nodes,
1052
+ path_len + 1,
1053
+ recursive,
1054
+ warn=warn,
1055
+ node_path=node_path,
1056
+ **kwargs,
1057
+ )
896
1058
  if isinstance(node, TriccNodeActivity):
897
1059
  if node.root not in processed_nodes:
898
1060
  if node.root is not None:
899
- node.root.path_len = max(path_len, node.root.path_len)
1061
+ node.root.path_len = max(path_len, node.root.path_len)
900
1062
  if recursive:
901
- walktrhough_tricc_node_processed_stached(node.root, callback, processed_nodes, stashed_nodes, path_len,
902
- recursive, warn = warn,node_path = node_path.copy(),**kwargs)
903
- # for gp in node.groups:
904
- # walktrhough_tricc_node_processed_stached(gp, callback, processed_nodes, stashed_nodes, path_len,
905
- # recursive, warn = warn,**kwargs)
906
- # if node.calculates:
907
- # for c in node.calculates:
908
- # walktrhough_tricc_node_processed_stached(c, callback, processed_nodes, stashed_nodes, path_len,
909
- # recursive, warn = warn,**kwargs)
1063
+ walktrhough_tricc_node_processed_stached(
1064
+ node.root,
1065
+ callback,
1066
+ processed_nodes,
1067
+ stashed_nodes,
1068
+ path_len,
1069
+ recursive,
1070
+ warn=warn,
1071
+ node_path=node_path.copy(),
1072
+ **kwargs,
1073
+ )
910
1074
  elif node.root not in stashed_nodes:
911
- #stashed_nodes.insert(0,node.root)
912
1075
  stashed_nodes.insert_at_top(node.root)
913
- # if node.calculates:
914
- # stashed_nodes += node.calculates
915
- # for gp in node.groups:
916
- # stashed_nodes.add(gp)
917
- # # stashed_nodes.insert(0,gp)
918
1076
  return
919
1077
  elif ended_activity:
920
1078
  for next_node in node.next_nodes:
921
1079
  if next_node not in stashed_nodes:
922
- #stashed_nodes.insert(0,next_node)
1080
+ # stashed_nodes.insert(0,next_node)
923
1081
  if recursive:
924
- walktrhough_tricc_node_processed_stached(next_node, callback, processed_nodes, stashed_nodes, path_len,
925
- recursive, warn = warn,node_path = node_path.copy(),**kwargs)
1082
+ walktrhough_tricc_node_processed_stached(
1083
+ next_node,
1084
+ callback,
1085
+ processed_nodes,
1086
+ stashed_nodes,
1087
+ path_len,
1088
+ recursive,
1089
+ warn=warn,
1090
+ node_path=node_path.copy(),
1091
+ **kwargs,
1092
+ )
926
1093
  else:
927
1094
  stashed_nodes.insert_at_top(next_node)
928
-
929
-
930
- elif hasattr(node, 'next_nodes') and len(node.next_nodes) > 0 and not isinstance(node, TriccNodeActivity):
1095
+
1096
+ elif hasattr(node, "next_nodes") and len(node.next_nodes) > 0 and not isinstance(node, TriccNodeActivity):
931
1097
  if recursive:
932
- walkthrough_tricc_next_nodes(node, callback, processed_nodes, stashed_nodes, path_len + 1, recursive,
933
- warn = warn,node_path = node_path,**kwargs)
1098
+ walkthrough_tricc_next_nodes(
1099
+ node,
1100
+ callback,
1101
+ processed_nodes,
1102
+ stashed_nodes,
1103
+ path_len + 1,
1104
+ recursive,
1105
+ warn=warn,
1106
+ node_path=node_path,
1107
+ **kwargs,
1108
+ )
934
1109
  else:
935
1110
  for nn in node.next_nodes:
936
1111
  if nn not in stashed_nodes:
937
1112
  stashed_nodes.insert_at_top(nn)
938
1113
  if not recursive:
939
1114
  reorder_node_list(stashed_nodes, node.group, processed_nodes)
940
-
941
-
942
-
1115
+
943
1116
  else:
944
1117
  if prev_process and process and prev_process != process[0]:
945
1118
  process[0] = prev_process
@@ -950,8 +1123,10 @@ def walktrhough_tricc_node_processed_stached(node, callback, processed_nodes, st
950
1123
  logger.debug("{}::{}: stashed({})".format(callback.__name__, node.get_name(), len(stashed_nodes)))
951
1124
 
952
1125
 
953
- def walkthrough_tricc_next_nodes(node, callback, processed_nodes, stashed_nodes, path_len, recursive, warn = False, node_path = [], **kwargs):
954
-
1126
+ def walkthrough_tricc_next_nodes(
1127
+ node, callback, processed_nodes, stashed_nodes, path_len, recursive, warn=False, node_path=[], **kwargs
1128
+ ):
1129
+
955
1130
  if not recursive:
956
1131
  for next_node in node.next_nodes:
957
1132
  if next_node not in stashed_nodes:
@@ -961,73 +1136,100 @@ def walkthrough_tricc_next_nodes(node, callback, processed_nodes, stashed_nodes,
961
1136
  for next_node in list_next:
962
1137
  if not isinstance(node, (TriccNodeActivityEnd, TriccNodeEnd)):
963
1138
  if next_node not in processed_nodes:
964
- walktrhough_tricc_node_processed_stached(next_node, callback, processed_nodes, stashed_nodes,
965
- path_len + 1,recursive, warn = warn,node_path = node_path.copy(), **kwargs)
1139
+ walktrhough_tricc_node_processed_stached(
1140
+ next_node,
1141
+ callback,
1142
+ processed_nodes,
1143
+ stashed_nodes,
1144
+ path_len + 1,
1145
+ recursive,
1146
+ warn=warn,
1147
+ node_path=node_path.copy(),
1148
+ **kwargs,
1149
+ )
966
1150
  else:
967
1151
  logger.critical(
968
- "{}::end node of {} has a next node".format(callback.__name__, node.activity.get_name()))
1152
+ "{}::end node of {} has a next node".format(callback.__name__, node.activity.get_name())
1153
+ )
969
1154
  exit(1)
970
1155
 
971
1156
 
972
- def walkthrough_tricc_option(node, callback, processed_nodes, stashed_nodes, path_len, recursive, warn = False,node_path = [], **kwargs):
1157
+ def walkthrough_tricc_option(
1158
+ node, callback, processed_nodes, stashed_nodes, path_len, recursive, warn=False, node_path=[], **kwargs
1159
+ ):
973
1160
  if not recursive:
974
1161
  for option in node.options.values():
975
- if hasattr(option, 'next_nodes') and len(option.next_nodes) > 0:
1162
+ if hasattr(option, "next_nodes") and len(option.next_nodes) > 0:
976
1163
  for next_node in option.next_nodes:
977
1164
  if next_node not in stashed_nodes:
978
1165
  stashed_nodes.insert_at_top(next_node)
979
- #stashed_nodes.insert(0,next_node)
1166
+ # stashed_nodes.insert(0,next_node)
980
1167
  else:
981
1168
  list_option = []
982
1169
  while not all(elem in list_option for elem in list(node.options.values())):
983
1170
  for option in node.options.values():
984
1171
  if option not in list_option:
985
1172
  list_option.append(option)
986
- # then walk the options
987
- if hasattr(option, 'next_nodes') and len(option.next_nodes) > 0:
1173
+ # then walk the options
1174
+ if hasattr(option, "next_nodes") and len(option.next_nodes) > 0:
988
1175
  list_next = set(option.next_nodes)
989
1176
  for next_node in list_next:
990
1177
  if next_node not in processed_nodes:
991
- walktrhough_tricc_node_processed_stached(next_node, callback, processed_nodes,
992
- stashed_nodes, path_len + 1, recursive,
993
- warn = warn,
994
- node_path = node_path.copy(), **kwargs)
1178
+ walktrhough_tricc_node_processed_stached(
1179
+ next_node,
1180
+ callback,
1181
+ processed_nodes,
1182
+ stashed_nodes,
1183
+ path_len + 1,
1184
+ recursive,
1185
+ warn=warn,
1186
+ node_path=node_path.copy(),
1187
+ **kwargs,
1188
+ )
1189
+
995
1190
 
996
1191
  def get_next_version(name, processed_nodes, version=0, min=100):
997
- return max(version, min,*[(getattr(n,'version',None) or getattr(n,'instance',None) or 0) for n in get_versions(name, processed_nodes)])+1
1192
+ return (
1193
+ max(
1194
+ version,
1195
+ min,
1196
+ *[
1197
+ (getattr(n, "version", None) or getattr(n, "instance", None) or 0)
1198
+ for n in get_versions(name, processed_nodes)
1199
+ ],
1200
+ )
1201
+ + 1
1202
+ )
998
1203
 
999
1204
 
1000
1205
  def get_data_for_log(node):
1001
1206
  return "{}:{}|{} {}:{}".format(
1002
1207
  node.group.get_name() if node.group is not None else node.activity.get_name(),
1003
- node.group.instance if node.group is not None else node.activity.instance ,
1208
+ node.group.instance if node.group is not None else node.activity.instance,
1004
1209
  node.__class__,
1005
1210
  node.get_name(),
1006
- node.instance)
1211
+ node.instance,
1212
+ )
1213
+
1007
1214
 
1008
1215
  def stashed_node_func(node, callback, recursive=False, **kwargs):
1009
- processed_nodes = kwargs.pop('processed_nodes', OrderedSet())
1010
- stashed_nodes = kwargs.pop('stashed_nodes', OrderedSet())
1011
- process = kwargs.pop('process', ['main'])
1216
+ processed_nodes = kwargs.pop("processed_nodes", OrderedSet())
1217
+ stashed_nodes = kwargs.pop("stashed_nodes", OrderedSet())
1218
+ process = kwargs.pop("process", ["main"])
1012
1219
  path_len = 0
1013
-
1220
+
1014
1221
  walktrhough_tricc_node_processed_stached(
1015
- node,
1016
- callback,
1017
- processed_nodes,
1018
- stashed_nodes,
1019
- path_len,
1020
- recursive,
1021
- process=process,
1022
- **kwargs)
1222
+ node, callback, processed_nodes, stashed_nodes, path_len, recursive, process=process, **kwargs
1223
+ )
1023
1224
  # callback( node, **kwargs)
1024
- ## MANAGE STASHED NODES
1225
+ # MANAGE STASHED NODES
1025
1226
  prev_stashed_nodes = stashed_nodes.copy()
1026
1227
  loop_count = 0
1027
1228
  len_prev_processed_nodes = 0
1028
1229
  while len(stashed_nodes) > 0:
1029
- loop_count = check_stashed_loop(stashed_nodes, prev_stashed_nodes, processed_nodes, len_prev_processed_nodes,
1030
- loop_count)
1230
+ loop_count = check_stashed_loop(
1231
+ stashed_nodes, prev_stashed_nodes, processed_nodes, len_prev_processed_nodes, loop_count
1232
+ )
1031
1233
  prev_stashed_nodes = stashed_nodes.copy()
1032
1234
  len_prev_processed_nodes = len(processed_nodes)
1033
1235
  if len(stashed_nodes) > 0:
@@ -1035,11 +1237,13 @@ def stashed_node_func(node, callback, recursive=False, **kwargs):
1035
1237
  # remove duplicates
1036
1238
  if s_node in stashed_nodes:
1037
1239
  stashed_nodes.remove(s_node)
1038
- if kwargs.get('warn', True):
1039
- logger.debug("{}:: {}: unstashed for processing ({})".format(callback.__name__, s_node.__class__,
1040
- get_data_for_log(s_node),
1041
- len(stashed_nodes)))
1042
- warn = loop_count >= (9 * len(stashed_nodes )+1)
1240
+ if kwargs.get("warn", True):
1241
+ logger.debug(
1242
+ "{}:: {}: unstashed for processing ({})::{}".format(
1243
+ callback.__name__, s_node.__class__, get_data_for_log(s_node), len(stashed_nodes)
1244
+ )
1245
+ )
1246
+ warn = loop_count >= (9 * len(stashed_nodes) + 1)
1043
1247
  walktrhough_tricc_node_processed_stached(
1044
1248
  s_node,
1045
1249
  callback,
@@ -1049,77 +1253,87 @@ def stashed_node_func(node, callback, recursive=False, **kwargs):
1049
1253
  recursive,
1050
1254
  warn=warn,
1051
1255
  process=process,
1052
- **kwargs)
1256
+ **kwargs,
1257
+ )
1053
1258
 
1054
1259
 
1055
1260
  # check if the all the prev nodes are processed
1056
1261
  def is_ready_to_process(in_node, processed_nodes, strict=True, local=False):
1057
1262
  if isinstance(in_node, TriccNodeSelectOption):
1058
1263
  node = in_node.select
1059
- elif (
1060
- isinstance(in_node, (TriccNodeActivityStart, TriccNodeMainStart)) ):
1264
+ elif isinstance(in_node, (TriccNodeActivityStart, TriccNodeMainStart)):
1061
1265
  # check before
1062
1266
  return True
1063
1267
  else:
1064
1268
  node = in_node
1065
- if hasattr(node, 'prev_nodes'):
1269
+ if hasattr(node, "prev_nodes"):
1066
1270
  # ensure the previous node of the select are processed, not the option prev nodes
1067
1271
  for prev_node in node.prev_nodes:
1068
1272
  if is_prev_processed(prev_node, node, processed_nodes, local) is False:
1069
1273
  return False
1070
1274
  return True
1071
-
1275
+
1276
+
1072
1277
  def is_prev_processed(prev_node, node, processed_nodes, local):
1073
- if hasattr(prev_node, 'select'):
1074
- return is_prev_processed(prev_node.select, node, processed_nodes, local)
1278
+ if hasattr(prev_node, "select"):
1279
+ return is_prev_processed(prev_node.select, node, processed_nodes, local)
1075
1280
  if prev_node not in processed_nodes and (not local):
1076
1281
  if isinstance(prev_node, TriccNodeExclusive):
1077
1282
  iterator = iter(prev_node.prev_nodes)
1078
1283
  p_n_node = next(iterator)
1079
- logger.debug("is_ready_to_process:failed:via_excl: {} - {} > {} {}:{}".format(
1080
- get_data_for_log(p_n_node),
1081
- prev_node.get_name(),
1082
- node.__class__, node.get_name(), node.instance))
1284
+ logger.debug(
1285
+ "is_ready_to_process:failed:via_excl: {} - {} > {} {}:{}".format(
1286
+ get_data_for_log(p_n_node), prev_node.get_name(), node.__class__, node.get_name(), node.instance
1287
+ )
1288
+ )
1083
1289
 
1084
1290
  else:
1085
- logger.debug("is_ready_to_process:failed: {} -> {} {}:{}".format(
1086
- get_data_for_log(prev_node),
1087
- node.__class__, node.get_name(), node.instance))
1291
+ logger.debug(
1292
+ "is_ready_to_process:failed: {} -> {} {}:{}".format(
1293
+ get_data_for_log(prev_node), node.__class__, node.get_name(), node.instance
1294
+ )
1295
+ )
1088
1296
 
1089
- logger.debug("prev node node {}:{} for node {} not in processed".format(prev_node.__class__,
1090
- prev_node.get_name(),
1091
- node.get_name()))
1297
+ logger.debug(
1298
+ "prev node node {}:{} for node {} not in processed".format(
1299
+ prev_node.__class__, prev_node.get_name(), node.get_name()
1300
+ )
1301
+ )
1092
1302
  return False
1093
1303
  return True
1094
1304
 
1095
1305
 
1306
+ def print_trace(node, prev_node, processed_nodes, stashed_nodes, history=[]):
1096
1307
 
1097
- def print_trace(node, prev_node, processed_nodes, stashed_nodes, history = []):
1098
-
1099
1308
  if node != prev_node:
1100
1309
  if node in processed_nodes:
1101
- logger.warning("print trace :: node {} was the last not processed ({})".format(
1102
- get_data_for_log(prev_node), node.id, ">".join(history)))
1103
- #processed_nodes.add(prev_node)
1310
+ logger.warning(
1311
+ "print trace :: node {} was the last not processed ({}):{}".format(
1312
+ get_data_for_log(prev_node), node.id, ">".join(history)
1313
+ )
1314
+ )
1315
+ # processed_nodes.add(prev_node)
1104
1316
  return False
1105
1317
  elif node in history:
1106
- logger.critical("print trace :: CYCLE node {} found in history ({})".format(
1107
- get_data_for_log(prev_node), ">".join(history)))
1318
+ logger.critical(
1319
+ "print trace :: CYCLE node {} found in history ({})".format(
1320
+ get_data_for_log(prev_node), ">".join(history)
1321
+ )
1322
+ )
1108
1323
  exit(1)
1109
1324
  elif node in stashed_nodes:
1110
1325
  # logger.debug("print trace :: node {}::{} in stashed".format(node.__class__,node.get_name()))
1111
1326
  return False
1112
1327
  # else:
1113
- # logger.debug("print trace :: node {} not processed/stashed".format(node.get_name()))
1328
+ # logger.debug("print trace :: node {} not processed/stashed".format(node.get_name()))
1114
1329
  return True
1115
1330
 
1116
1331
 
1117
- def reverse_walkthrough(in_node, next_node, callback, processed_nodes, stashed_nodes, history = []):
1332
+ def reverse_walkthrough(in_node, next_node, callback, processed_nodes, stashed_nodes, history=[]):
1118
1333
  # transform dead-end nodes
1119
1334
  if next_node == in_node and next_node not in stashed_nodes:
1120
1335
  # workaround fir loop
1121
1336
  return False
1122
-
1123
1337
 
1124
1338
  if isinstance(in_node, TriccNodeSelectOption):
1125
1339
  node = in_node.select
@@ -1132,53 +1346,79 @@ def reverse_walkthrough(in_node, next_node, callback, processed_nodes, stashed_n
1132
1346
  if isinstance(in_node, TriccNodeActivity):
1133
1347
  prev_nodes = set(in_node.get_end_nodes())
1134
1348
  for prev in prev_nodes:
1135
- reverse_walkthrough(prev, next_node, callback, processed_nodes=processed_nodes, stashed_nodes=stashed_nodes, history=history)
1136
- if hasattr(node, 'prev_nodes'):
1349
+ reverse_walkthrough(
1350
+ prev,
1351
+ next_node,
1352
+ callback,
1353
+ processed_nodes=processed_nodes,
1354
+ stashed_nodes=stashed_nodes,
1355
+ history=history,
1356
+ )
1357
+ if hasattr(node, "prev_nodes"):
1137
1358
  if node.prev_nodes:
1138
1359
  for prev in node.prev_nodes:
1139
- reverse_walkthrough(prev, node, callback, processed_nodes=processed_nodes, stashed_nodes=stashed_nodes, history=history)
1360
+ reverse_walkthrough(
1361
+ prev,
1362
+ node,
1363
+ callback,
1364
+ processed_nodes=processed_nodes,
1365
+ stashed_nodes=stashed_nodes,
1366
+ history=history,
1367
+ )
1140
1368
  elif node in node.activity.calculates:
1141
- reverse_walkthrough(prev, node.activity.root, callback, processed_nodes=processed_nodes, stashed_nodes=stashed_nodes, history=history)
1369
+ reverse_walkthrough(
1370
+ prev,
1371
+ node.activity.root,
1372
+ callback,
1373
+ processed_nodes=processed_nodes,
1374
+ stashed_nodes=stashed_nodes,
1375
+ history=history,
1376
+ )
1142
1377
 
1143
1378
  if issubclass(node.__class__, TriccRhombusMixIn):
1144
1379
  if isinstance(node.reference, list):
1145
1380
  for ref in node.reference:
1146
- reverse_walkthrough(ref, node, callback, processed_nodes=processed_nodes, stashed_nodes=stashed_nodes, history= history)
1147
-
1148
-
1381
+ reverse_walkthrough(
1382
+ ref,
1383
+ node,
1384
+ callback,
1385
+ processed_nodes=processed_nodes,
1386
+ stashed_nodes=stashed_nodes,
1387
+ history=history,
1388
+ )
1149
1389
 
1150
1390
 
1151
1391
  def get_prev_node_by_name(processed_nodes, name, node):
1152
- # look for the node in the same activity
1153
- last_calc = get_last_version(
1154
- name,
1155
- processed_nodes
1156
- )
1392
+ # look for the node in the same activity
1393
+ last_calc = get_last_version(name, processed_nodes)
1157
1394
  if last_calc:
1158
1395
  return last_calc
1159
-
1396
+
1160
1397
  filtered = list(
1161
- filter(lambda p_node:
1162
- hasattr(p_node,'name')
1163
- and p_node.name == name
1164
- and p_node.instance == node.instance
1165
- and p_node.path_len <= node.path_len, processed_nodes
1166
- ))
1398
+ filter(
1399
+ lambda p_node: hasattr(p_node, "name")
1400
+ and p_node.name == name
1401
+ and p_node.instance == node.instance
1402
+ and p_node.path_len <= node.path_len,
1403
+ processed_nodes,
1404
+ )
1405
+ )
1167
1406
  if len(filtered) == 0:
1168
- filtered = list(filter(lambda p_node: hasattr(p_node, 'name') and p_node.name == name , processed_nodes))
1407
+ filtered = list(filter(lambda p_node: hasattr(p_node, "name") and p_node.name == name, processed_nodes))
1169
1408
  if len(filtered) > 0:
1170
1409
  return sorted(filtered, key=lambda x: x.path_len, reverse=False)[0]
1171
1410
 
1411
+
1172
1412
  MIN_LOOP_COUNT = 10
1173
1413
 
1414
+
1174
1415
  def check_stashed_loop(stashed_nodes, prev_stashed_nodes, processed_nodes, len_prev_processed_nodes, loop_count):
1175
- loop_out = {}
1176
-
1416
+
1177
1417
  if len(stashed_nodes) == len(prev_stashed_nodes):
1178
- # to avoid checking the details
1179
- if loop_count<=0:
1418
+ # to avoid checking the details
1419
+ if loop_count <= 0:
1180
1420
  if loop_count < -MIN_LOOP_COUNT:
1181
- loop_count = MIN_LOOP_COUNT+1
1421
+ loop_count = MIN_LOOP_COUNT + 1
1182
1422
  else:
1183
1423
  loop_count -= 1
1184
1424
  if loop_count > MIN_LOOP_COUNT:
@@ -1186,51 +1426,56 @@ def check_stashed_loop(stashed_nodes, prev_stashed_nodes, processed_nodes, len_p
1186
1426
  loop_count += 1
1187
1427
  if loop_count > max(MIN_LOOP_COUNT, 11 * len(prev_stashed_nodes) + 1):
1188
1428
  logger.critical("Stashed node list was unchanged: loop likely or unresolved dependence")
1189
- waited, looped = get_all_dependant(stashed_nodes, stashed_nodes, processed_nodes)
1429
+ waited, looped = get_all_dependant(stashed_nodes, stashed_nodes, processed_nodes)
1190
1430
  logger.debug(f"{len(looped)} nodes waiting stashed nodes")
1191
1431
  logger.info("unresolved reference")
1192
1432
  for es_node in [n for n in stashed_nodes if isinstance(n, TriccReference)]:
1193
- logger.info("Stashed node {}:{}|{} {}".format(
1194
- es_node.activity.get_name() if hasattr(es_node,'activity') else '' ,
1195
- es_node.activity.instance if hasattr(es_node,'activity') else '',
1196
- es_node.__class__,
1197
- es_node.get_name()))
1198
- for es_node in [node for node_list in looped.values() for node in node_list if isinstance(node, TriccReference)]:
1199
- logger.info("looped node {}:{}|{} {}".format(
1200
- es_node.activity.get_name() if hasattr(es_node,'activity') else '' ,
1201
- es_node.activity.instance if hasattr(es_node,'activity') else '',
1202
- es_node.__class__,
1203
- es_node.get_name()))
1204
- for es_node in [node for node_list in waited.values() for node in node_list if isinstance(node, TriccReference)]:
1205
- logger.info("waited node {}:{}|{} {}".format(
1206
- es_node.activity.get_name() if hasattr(es_node,'activity') else '' ,
1207
- es_node.activity.instance if hasattr(es_node,'activity') else '',
1208
- es_node.__class__,
1209
- es_node.get_name()))
1433
+ logger.info(
1434
+ "Stashed node {}:{}|{} {}".format(
1435
+ es_node.activity.get_name() if hasattr(es_node, "activity") else "",
1436
+ es_node.activity.instance if hasattr(es_node, "activity") else "",
1437
+ es_node.__class__,
1438
+ es_node.get_name(),
1439
+ )
1440
+ )
1441
+ for es_node in [
1442
+ node for node_list in looped.values() for node in node_list if isinstance(node, TriccReference)
1443
+ ]:
1444
+ logger.info(
1445
+ "looped node {}:{}|{} {}".format(
1446
+ es_node.activity.get_name() if hasattr(es_node, "activity") else "",
1447
+ es_node.activity.instance if hasattr(es_node, "activity") else "",
1448
+ es_node.__class__,
1449
+ es_node.get_name(),
1450
+ )
1451
+ )
1452
+ for es_node in [
1453
+ node for node_list in waited.values() for node in node_list if isinstance(node, TriccReference)
1454
+ ]:
1455
+ logger.info(
1456
+ "waited node {}:{}|{} {}".format(
1457
+ es_node.activity.get_name() if hasattr(es_node, "activity") else "",
1458
+ es_node.activity.instance if hasattr(es_node, "activity") else "",
1459
+ es_node.__class__,
1460
+ es_node.get_name(),
1461
+ )
1462
+ )
1210
1463
  logger.info("looped nodes")
1211
1464
  for dep_list in looped:
1212
1465
  for d in looped[dep_list]:
1213
1466
  if str(d) in looped:
1214
- logger.critical("[{}] depends on [{}]".format(
1215
- dep_list, str(d)
1216
- ))
1467
+ logger.critical("[{}] depends on [{}]".format(dep_list, str(d)))
1217
1468
  else:
1218
- logger.error("[{}] depends on [{}]".format(
1219
- dep_list, str(d)
1220
- ))
1469
+ logger.error("[{}] depends on [{}]".format(dep_list, str(d)))
1221
1470
  if dep_list in waited:
1222
1471
  for d in waited[dep_list]:
1223
- logger.warning("[{}] depends on [{}]".format(
1224
- dep_list, str(d)
1225
- ))
1472
+ logger.warning("[{}] depends on [{}]".format(dep_list, str(d)))
1226
1473
  logger.info("waited nodes")
1227
1474
  for dep_list in waited:
1228
1475
  if dep_list not in looped:
1229
1476
  for d in waited[dep_list]:
1230
- logger.warning("[{}] depends on [{}]".format(
1231
- dep_list, d.get_name()
1232
- ))
1233
-
1477
+ logger.warning("[{}] depends on [{}]".format(dep_list, d.get_name()))
1478
+
1234
1479
  if len(stashed_nodes) == len(prev_stashed_nodes):
1235
1480
  exit(1)
1236
1481
  else:
@@ -1239,6 +1484,7 @@ def check_stashed_loop(stashed_nodes, prev_stashed_nodes, processed_nodes, len_p
1239
1484
  loop_count = 0
1240
1485
  return loop_count
1241
1486
 
1487
+
1242
1488
  def add_to_tree(tree, n, d):
1243
1489
  n_str = str(n)
1244
1490
  if n_str not in tree:
@@ -1247,10 +1493,10 @@ def add_to_tree(tree, n, d):
1247
1493
  tree[n_str].append(d)
1248
1494
  return tree
1249
1495
 
1250
-
1251
- def get_all_dependant(loop, stashed_nodes, processed_nodes, depth=0, waited=None , looped=None, path = None):
1496
+
1497
+ def get_all_dependant(loop, stashed_nodes, processed_nodes, depth=0, waited=None, looped=None, path=None):
1252
1498
  if path is None:
1253
- path =[]
1499
+ path = []
1254
1500
  if looped is None:
1255
1501
  looped = {}
1256
1502
  if waited is None:
@@ -1260,50 +1506,55 @@ def get_all_dependant(loop, stashed_nodes, processed_nodes, depth=0, waited=None
1260
1506
  cur_path = path.copy()
1261
1507
  cur_path.append(n)
1262
1508
  dependant = OrderedSet()
1263
- i=0
1264
- #logger.critical(f"{i}: {n.__class__}::{n.get_name()}::{getattr(n,'instance','')}::{process_reference(n, processed_nodes, [])}")
1265
- i += 1
1266
- if hasattr(n, 'prev_nodes') and n.prev_nodes:
1267
- dependant = dependant | n.prev_nodes
1268
- if hasattr(n, 'get_references'):
1269
- dependant = dependant | (n.get_references() or OrderedSet())
1509
+ if hasattr(n, "prev_nodes") and n.prev_nodes:
1510
+ dependant = dependant | n.prev_nodes
1511
+ if hasattr(n, "get_references"):
1512
+ dependant = dependant | (n.get_references() or OrderedSet())
1270
1513
  if not isinstance(dependant, list):
1271
1514
  pass
1272
1515
  for d in dependant:
1273
1516
  if d in path:
1274
- logger.warning(f"loop {str(d)} already in path {'::'.join(map(str, path))} ")
1517
+ logger.warning(
1518
+ f"loop {str(d)} already in path {'::'.join(map(str, path))} "
1519
+ )
1275
1520
  if isinstance(d, TriccNodeSelectOption):
1276
1521
  d = d.select
1277
-
1522
+
1278
1523
  if isinstance(d, TriccReference):
1279
1524
  if not any(n.name == d.value for n in processed_nodes):
1280
1525
  if not any(n.name == d.value for n in stashed_nodes):
1281
1526
  waited = add_to_tree(waited, n, d)
1282
- else :
1527
+ else:
1283
1528
  looped = add_to_tree(looped, n, d)
1284
-
1529
+
1285
1530
  elif d not in processed_nodes:
1286
1531
  if d in stashed_nodes:
1287
1532
  looped = add_to_tree(looped, n, d)
1288
- else :
1533
+ else:
1289
1534
  waited = add_to_tree(waited, n, d)
1290
1535
  all_dependant = all_dependant.union(dependant)
1291
1536
  if depth < MAX_DRILL:
1292
- waited, looped = get_all_dependant(all_dependant, stashed_nodes, processed_nodes, depth+1, waited , looped, path=cur_path)
1293
-
1537
+ waited, looped = get_all_dependant(
1538
+ all_dependant, stashed_nodes, processed_nodes, depth + 1, waited, looped, path=cur_path
1539
+ )
1540
+
1294
1541
  return waited, looped
1295
1542
 
1296
1543
 
1297
1544
  MAX_DRILL = 3
1298
1545
 
1546
+
1299
1547
  def get_last_end_node(processed_nodes, process=None):
1300
- end_name = 'tricc_end_'
1548
+ end_name = "tricc_end_"
1301
1549
  if process:
1302
1550
  end_name += process
1303
1551
  return get_last_version(end_name, processed_nodes)
1304
1552
 
1553
+
1305
1554
  # Set the source next node to target and clean next nodes of replace node
1306
- def set_prev_next_node(source_node, target_node, replaced_node=None, edge_only = False, activity=None):
1555
+
1556
+
1557
+ def set_prev_next_node(source_node, target_node, replaced_node=None, edge_only=False, activity=None):
1307
1558
  activity = activity or source_node.activity
1308
1559
  source_id, source_node = get_node_from_id(activity, source_node, edge_only)
1309
1560
  target_id, target_node = get_node_from_id(activity, target_node, edge_only)
@@ -1311,36 +1562,39 @@ def set_prev_next_node(source_node, target_node, replaced_node=None, edge_only =
1311
1562
  if not edge_only:
1312
1563
  set_prev_node(source_node, target_node, replaced_node, edge_only)
1313
1564
  set_next_node(source_node, target_node, replaced_node, edge_only)
1314
-
1315
- if activity and not any([(e.source == source_id) and ( e.target == target_id) for e in activity.edges]):
1565
+
1566
+ if activity and not any([(e.source == source_id) and (e.target == target_id) for e in activity.edges]):
1316
1567
  label = "continue" if issubclass(source_node.__class__, TriccNodeSelect) else None
1317
- activity.edges.append(TriccEdge(id = generate_id(), source = source_id, target = target_id, value = label))
1568
+ activity.edges.append(TriccEdge(id=generate_id(), source=source_id, target=target_id, value=label))
1569
+
1318
1570
 
1319
1571
  def remove_prev_next(prev_node, next_node, activity=None):
1320
1572
  activity = activity or prev_node.activity
1321
- if hasattr(prev_node, 'next_nodes') and next_node in prev_node.next_nodes:
1573
+ if hasattr(prev_node, "next_nodes") and next_node in prev_node.next_nodes:
1322
1574
  prev_node.next_nodes.remove(next_node)
1323
- if hasattr(next_node, 'prev_nodes') and prev_node in next_node.prev_nodes:
1575
+ if hasattr(next_node, "prev_nodes") and prev_node in next_node.prev_nodes:
1324
1576
  next_node.prev_nodes.remove(prev_node)
1325
-
1577
+
1326
1578
  for e in list(activity.edges):
1327
- if (e.target == getattr(next_node, 'id', next_node) and e.source == getattr(prev_node, 'id', prev_node)):
1579
+ if e.target == getattr(next_node, "id", next_node) and e.source == getattr(prev_node, "id", prev_node):
1328
1580
  activity.edges.remove(e)
1329
-
1330
-
1331
-
1332
- def set_next_node(source_node, target_node, replaced_node=None, edge_only = False, activity=None):
1581
+
1582
+
1583
+ def set_next_node(source_node, target_node, replaced_node=None, edge_only=False, activity=None):
1333
1584
  activity = activity or source_node.activity
1334
1585
  replace_target = None
1335
- if not edge_only:
1336
- if replaced_node is not None and hasattr(source_node, 'path') and replaced_node == source_node.path:
1586
+ if not edge_only:
1587
+ if replaced_node is not None and hasattr(source_node, "path") and replaced_node == source_node.path:
1337
1588
  source_node.path = target_node
1338
- elif replaced_node is not None and hasattr(source_node, 'next_nodes') and replaced_node in source_node.next_nodes:
1589
+ elif (
1590
+ replaced_node is not None and hasattr(source_node, "next_nodes") and replaced_node in source_node.next_nodes
1591
+ ):
1339
1592
  replace_target = True
1340
1593
  source_node.next_nodes.remove(replaced_node)
1341
- if hasattr(replaced_node, 'prev_nodes') and source_node in replaced_node.prev_nodes:
1594
+ if hasattr(replaced_node, "prev_nodes") and source_node in replaced_node.prev_nodes:
1342
1595
  replaced_node.prev_nodes.remove(source_node)
1343
- #if replaced_node is not None and hasattr(target_node, 'next_nodes') and replaced_node in target_node.next_nodes:
1596
+ # if replaced_node is not None and hasattr(target_node, 'next_nodes')
1597
+ # and replaced_node in target_node.next_nodes:
1344
1598
  # target_node.next_nodes.remove(replaced_node)
1345
1599
  if target_node not in source_node.next_nodes:
1346
1600
  source_node.next_nodes.add(target_node)
@@ -1359,31 +1613,34 @@ def set_next_node(source_node, target_node, replaced_node=None, edge_only = Fals
1359
1613
  if replaced_node and replace_target:
1360
1614
  if replaced_node.id in replaced_node.activity.nodes:
1361
1615
  del replaced_node.activity.nodes[replaced_node.id]
1362
- next_edges = set([
1363
- e for e in replaced_node.activity.edges if (e.target == replaced_node.id or e.target == replaced_node)
1364
- ] + [
1365
- e for e in activity.edges if (e.target == replaced_node.id or e.target == replaced_node)
1366
- ])
1367
- if len(next_edges)==0:
1368
- for e in next_edges:
1616
+ next_edges = set(
1617
+ [
1618
+ e for e in replaced_node.activity.edges
1619
+ if (e.target == replaced_node.id or e.target == replaced_node)
1620
+ ] + [
1621
+ e for e in activity.edges
1622
+ if (e.target == replaced_node.id or e.target == replaced_node)
1623
+ ]
1624
+ )
1625
+ if len(next_edges) == 0:
1626
+ for e in next_edges:
1369
1627
  e.target = target_node.id
1370
1628
 
1371
-
1372
1629
 
1373
1630
  # Set the target_node prev node to source and clean prev nodes of replace_node
1374
- def set_prev_node(source_node, target_node, replaced_node=None, edge_only = False, activity=None):
1631
+ def set_prev_node(source_node, target_node, replaced_node=None, edge_only=False, activity=None):
1375
1632
  activity = activity or source_node.activity
1376
1633
  replace_source = False
1377
1634
  # update the prev node of the target not if not an end node
1378
1635
  # update directly the prev node of the target
1379
- if replaced_node is not None and hasattr(target_node, 'path') and replaced_node == target_node.path:
1636
+ if replaced_node is not None and hasattr(target_node, "path") and replaced_node == target_node.path:
1380
1637
  target_node.path = source_node
1381
- if replaced_node is not None and hasattr(target_node, 'prev_nodes') and replaced_node in target_node.prev_nodes:
1638
+ if replaced_node is not None and hasattr(target_node, "prev_nodes") and replaced_node in target_node.prev_nodes:
1382
1639
  replace_source = True
1383
1640
  target_node.prev_nodes.remove(replaced_node)
1384
- if hasattr(replaced_node, 'next_nodes') and source_node in replaced_node.next_nodes:
1641
+ if hasattr(replaced_node, "next_nodes") and source_node in replaced_node.next_nodes:
1385
1642
  replaced_node.next_nodes.remove(source_node)
1386
- #if replaced_node is not None and hasattr(source_node, 'prev_nodes') and replaced_node in source_node.prev_nodes:
1643
+ # if replaced_node is not None and hasattr(source_node, 'prev_nodes') and replaced_node in source_node.prev_nodes:
1387
1644
  # source_node.prev_nodes.remove(replaced_node)
1388
1645
  if source_node not in target_node.prev_nodes:
1389
1646
  target_node.prev_nodes.add(source_node)
@@ -1391,18 +1648,17 @@ def set_prev_node(source_node, target_node, replaced_node=None, edge_only = Fals
1391
1648
  activity.nodes[source_node.id] = source_node
1392
1649
  if replaced_node and replace_source:
1393
1650
  if replaced_node.id in replaced_node.activity.nodes:
1394
- del replaced_node.activity.nodes[replaced_node.id]
1395
- next_edges = set([
1396
- e for e in replaced_node.activity.edges if (e.source == replaced_node.id or e.source == replaced_node)
1397
- ] + [
1398
- e for e in activity.edges if (e.source == replaced_node.id or e.source == replaced_node)
1399
- ])
1400
- if len(next_edges)==0:
1401
- for e in next_edges:
1651
+ del replaced_node.activity.nodes[replaced_node.id]
1652
+ next_edges = set(
1653
+ [e for e in replaced_node.activity.edges if (e.source == replaced_node.id or e.source == replaced_node)]
1654
+ + [e for e in activity.edges if (e.source == replaced_node.id or e.source == replaced_node)]
1655
+ )
1656
+ if len(next_edges) == 0:
1657
+ for e in next_edges:
1402
1658
  e.target = target_node.id
1403
-
1404
1659
 
1405
- def replace_node(old, new, page = None):
1660
+
1661
+ def replace_node(old, new, page=None):
1406
1662
  if page is None:
1407
1663
  page = old.activity
1408
1664
  logger.debug("replacing node {} with node {} from page {}".format(old.get_name(), new.get_name(), page.get_name()))
@@ -1429,23 +1685,25 @@ def replace_node(old, new, page = None):
1429
1685
  if edge.target == old.id:
1430
1686
  edge.target = new.id
1431
1687
 
1432
- def replace_prev_next_node(prev_node, next_node, old_node, force = False):
1688
+
1689
+ def replace_prev_next_node(prev_node, next_node, old_node, force=False):
1433
1690
  replace_prev_node(prev_node, next_node, old_node)
1434
1691
  replace_next_node(prev_node, next_node, old_node)
1435
1692
 
1436
- def replace_prev_node(prev_node, next_node, old_node, force = False):
1437
- #create a copy pf the list
1693
+
1694
+ def replace_prev_node(prev_node, next_node, old_node, force=False):
1695
+ # create a copy pf the list
1438
1696
  list_nodes = list(next_node.prev_nodes)
1439
1697
  # replace in case old node is found
1440
1698
  for p_n_node in list_nodes:
1441
1699
  if p_n_node == old_node or force:
1442
1700
  set_prev_next_node(prev_node, next_node, old_node)
1443
-
1444
-
1445
- def replace_next_node(prev_node,next_node,old_node):
1701
+
1702
+
1703
+ def replace_next_node(prev_node, next_node, old_node):
1446
1704
  list_nodes = list(prev_node.next_nodes)
1447
1705
  for n_p_node in list_nodes:
1448
- if n_p_node == old_node :
1706
+ if n_p_node == old_node:
1449
1707
  set_prev_next_node(prev_node, next_node, old_node)
1450
1708
 
1451
1709
 
@@ -1458,6 +1716,7 @@ ACTIVE_ACTIVITY_LOWER_PRIORITY = 3000
1458
1716
  RHOMBUS_PRIORITY = 1000
1459
1717
  DEFAULT_PRIORITY = 2000
1460
1718
 
1719
+
1461
1720
  def reorder_node_list(node_list, group, processed_nodes):
1462
1721
  # Cache active activities for O(1) lookup
1463
1722
  active_activities = {n.activity for n in processed_nodes}
@@ -1493,49 +1752,51 @@ def reorder_node_list(node_list, group, processed_nodes):
1493
1752
 
1494
1753
  # Sort in place, highest priority first
1495
1754
  node_list.sort(key=get_priority, reverse=True)
1496
-
1755
+
1756
+
1497
1757
  def loop_info(loop, **kwargs):
1498
1758
  logger.critical("dependency details")
1499
1759
  for n in loop:
1500
- i=0
1760
+ i = 0
1501
1761
  logger.critical(f"{i}: {n.__class__}::{n.get_name()}")
1502
1762
  i += 1
1503
1763
 
1504
1764
 
1505
- def has_loop(node, processed_nodes, stashed_nodes, warn , node_path=[], action_on_loop=loop_info,action_on_other=None, **kwargs):
1765
+ def has_loop(
1766
+ node, processed_nodes, stashed_nodes, warn, node_path=[], action_on_loop=loop_info, action_on_other=None, **kwargs
1767
+ ):
1506
1768
  next_nodes = get_extended_next_nodes(node)
1507
- for next_node in next_nodes:
1769
+ for next_node in next_nodes:
1508
1770
  if next_node in node_path:
1509
1771
  loop_start_key = node_path.index(next_node)
1510
1772
  loop = node_path[loop_start_key:]
1511
1773
  loop.append(node)
1512
1774
  loop.append(next_node)
1513
1775
  action_on_loop(loop, **kwargs)
1514
- return False
1776
+ return False
1515
1777
  if callable(action_on_other):
1516
1778
  action_on_other(next_node, **kwargs)
1517
1779
  return True
1518
-
1519
-
1780
+
1520
1781
 
1521
1782
  def get_extended_next_nodes(node):
1522
-
1523
- nodes = node.next_nodes if hasattr(node,'next_nodes') else set()
1524
- if issubclass(node.__class__, TriccNodeSelect ):
1783
+
1784
+ nodes = node.next_nodes if hasattr(node, "next_nodes") else set()
1785
+ if issubclass(node.__class__, TriccNodeSelect):
1525
1786
  for o in node.options.values():
1526
1787
  nodes = nodes | o.next_nodes
1527
- if isinstance(node, ( TriccNodeActivity) ):
1788
+ if isinstance(node, (TriccNodeActivity)):
1528
1789
  nodes = nodes | node.root.next_nodes
1529
1790
  return nodes
1530
-
1791
+
1531
1792
 
1532
1793
  # calculate or retrieve a node expression
1533
- def get_node_expression( in_node, processed_nodes, get_overall_exp=False, is_prev=False, negate=False, process=None):
1794
+ def get_node_expression(in_node, processed_nodes, get_overall_exp=False, is_prev=False, negate=False, process=None):
1534
1795
  # in case of calculate we only use the select multiple if none is not selected
1535
1796
  expression = None
1536
1797
  negate_expression = None
1537
1798
  node = in_node
1538
- if isinstance(node, (TriccNodeActivityStart,TriccNodeMainStart)):
1799
+ if isinstance(node, (TriccNodeActivityStart, TriccNodeMainStart)):
1539
1800
  if is_prev and get_overall_exp:
1540
1801
  expression = get_node_expression(
1541
1802
  node.activity,
@@ -1543,13 +1804,13 @@ def get_node_expression( in_node, processed_nodes, get_overall_exp=False, is_pre
1543
1804
  get_overall_exp=True,
1544
1805
  is_prev=is_prev,
1545
1806
  negate=negate,
1546
- process=process
1807
+ process=process,
1547
1808
  )
1548
1809
  if isinstance(node, TriccNodeMainStart):
1549
- expression = get_applicability_expression(node.activity, processed_nodes, process, expression )
1810
+ expression = get_applicability_expression(node.activity, processed_nodes, process, expression)
1550
1811
  elif isinstance(node, (TriccNodeActivityStart)):
1551
1812
  return TriccStatic(True)
1552
-
1813
+
1553
1814
  elif isinstance(node, TriccNodeWait):
1554
1815
  if is_prev:
1555
1816
  # the wait don't do any calculation with the reference it is only use to wait until the reference are valid
@@ -1558,86 +1819,78 @@ def get_node_expression( in_node, processed_nodes, get_overall_exp=False, is_pre
1558
1819
  processed_nodes=processed_nodes,
1559
1820
  get_overall_exp=get_overall_exp,
1560
1821
  is_prev=True,
1561
- process=process
1562
- )
1822
+ process=process,
1823
+ )
1563
1824
  else:
1564
- #it is a empty calculate
1825
+ # it is a empty calculate
1565
1826
  return None
1566
1827
  elif isinstance(node, TriccNodeRhombus):
1567
- # if is_prev:
1568
- # expression = TriccOperation(
1569
- # TriccOperator.ISTRUE,
1570
- # [node]
1571
- # )
1572
- # else:
1573
- expression = get_rhombus_terms(node, processed_nodes, process=process) # if issubclass(node.__class__, TricNodeDisplayCalulate) else TRICC_CALC_EXPRESSION.format(get_export_name(node)) #
1828
+ expression = get_rhombus_terms(node, processed_nodes, process=process)
1574
1829
  negate_expression = not_clean(expression)
1575
- if node.path is None :
1830
+ if node.path is None:
1576
1831
  if len(node.prev_nodes) == 1:
1577
1832
  node.path = list(node.prev_nodes)[0]
1578
1833
  elif len(node.prev_nodes) > 1:
1579
1834
  logger.critical(f"missing path for Rhombus {node.get_name()}")
1580
1835
  exit(1)
1581
1836
  prev_exp = get_node_expression(
1582
- node.path,
1583
- processed_nodes=processed_nodes,
1584
- get_overall_exp=get_overall_exp,
1585
- is_prev=True,
1586
- process=process)
1837
+ node.path, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, is_prev=True, process=process
1838
+ )
1587
1839
  if prev_exp and expression:
1588
1840
  expression = and_join([prev_exp, expression])
1589
- negate_expression = and_join([
1590
- prev_exp,
1591
- negate_expression
1592
- ])
1841
+ negate_expression = and_join([prev_exp, negate_expression])
1593
1842
 
1594
1843
  elif prev_exp:
1595
-
1844
+
1596
1845
  logger.error(f"useless rhombus {node.get_name()}")
1597
1846
  expression = prev_exp
1598
1847
  negate_expression = prev_exp
1599
1848
  logger.critical(f"Rhombus without expression {node.get_name()}")
1600
1849
  elif is_prev and issubclass(node.__class__, TriccNodeDisplayCalculateBase):
1601
1850
  expression = TriccOperation(TriccOperator.ISTRUE, [node])
1602
- elif hasattr(node, 'expression_reference') and isinstance(node.expression_reference, TriccOperation):
1851
+ elif hasattr(node, "expression_reference") and isinstance(node.expression_reference, TriccOperation):
1603
1852
  # if issubclass(node.__class__, TriccNodeDisplayCalculateBase):
1604
1853
  # expression = TriccOperation(
1605
1854
  # TriccOperator.CAST_NUMBER,
1606
1855
  # [node.expression_reference])
1607
- # else:
1608
- expression = node.expression_reference
1856
+ # else:
1857
+ expression = node.expression_reference
1609
1858
  elif is_prev and isinstance(node, TriccNodeSelectOption):
1610
1859
  if negate:
1611
1860
  negate_expression = get_selected_option_expression(node, negate)
1612
1861
  else:
1613
1862
  expression = get_selected_option_expression(node, negate)
1614
- #TODO remove that and manage it on the "Save" part
1863
+ # TODO remove that and manage it on the "Save" part
1615
1864
  elif is_prev and isinstance(node, TriccNodeSelectNotAvailable):
1616
- expression = TriccOperation(
1617
- TriccOperator.SELECTED,
1618
- [
1619
- node,
1620
- TriccStatic(1)
1621
- ]
1622
- )
1865
+ expression = TriccOperation(TriccOperator.SELECTED, [node, TriccStatic(1)])
1623
1866
  elif issubclass(node.__class__, TriccNodeCalculateBase):
1624
1867
  if negate:
1625
- negate_expression = get_calculation_terms(node, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, negate=True, process=process)
1868
+ negate_expression = get_calculation_terms(
1869
+ node, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, negate=True, process=process
1870
+ )
1626
1871
  else:
1627
- expression = get_calculation_terms(node, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, process=process)
1628
-
1629
- elif (not is_prev or not ONE_QUESTION_AT_A_TIME) and hasattr(node, 'relevance') and isinstance(node.relevance, (TriccOperation, TriccStatic)):
1630
- expression = node.relevance
1631
- elif ONE_QUESTION_AT_A_TIME and is_prev and not get_overall_exp and hasattr(node, 'required') and node.required:
1872
+ expression = get_calculation_terms(
1873
+ node, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, process=process
1874
+ )
1875
+
1876
+ elif (
1877
+ (not is_prev or not ONE_QUESTION_AT_A_TIME)
1878
+ and hasattr(node, "relevance")
1879
+ and isinstance(node.relevance, (TriccOperation, TriccStatic))
1880
+ ):
1881
+ expression = node.relevance
1882
+ elif ONE_QUESTION_AT_A_TIME and is_prev and not get_overall_exp and hasattr(node, "required") and node.required:
1632
1883
  expression = get_required_node_expression(node)
1633
-
1884
+
1634
1885
  if expression is None:
1635
- expression = get_prev_node_expression(node, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, process=process)
1636
- # in_node not in processed_nodes is need for calculates that can but run after the end of the activity
1637
- #if isinstance(node, TriccNodeActivitiy) and not prev:
1638
- # expression = get_applicability_expression(node, processed_nodes, process, expression)
1639
- # expression = get_prev_instance_skip_expression(node, processed_nodes, process, expression)
1640
- # expression = get_process_skip_expression(node, processed_nodes, process, expression)
1886
+ expression = get_prev_node_expression(
1887
+ node, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, process=process
1888
+ )
1889
+ # in_node not in processed_nodes is need for calculates that can but run after the end of the activity
1890
+ # if isinstance(node, TriccNodeActivitiy) and not prev:
1891
+ # expression = get_applicability_expression(node, processed_nodes, process, expression)
1892
+ # expression = get_prev_instance_skip_expression(node, processed_nodes, process, expression)
1893
+ # expression = get_process_skip_expression(node, processed_nodes, process, expression)
1641
1894
  if negate:
1642
1895
  if negate_expression is not None:
1643
1896
  return negate_expression
@@ -1648,64 +1901,50 @@ def get_node_expression( in_node, processed_nodes, get_overall_exp=False, is_pre
1648
1901
  # exit(1)
1649
1902
  else:
1650
1903
  return expression
1651
-
1904
+
1905
+
1652
1906
  def get_applicability_expression(node, processed_nodes, process, expression=None):
1653
- if isinstance(node.applicability,(TriccStatic,TriccOperation, TriccReference)):
1907
+ if isinstance(node.applicability, (TriccStatic, TriccOperation, TriccReference)):
1654
1908
  if expression:
1655
1909
  expression = and_join([node.applicability, expression])
1656
1910
  else:
1657
1911
  expression = node.applicability
1658
-
1912
+
1659
1913
  return expression
1660
-
1661
1914
 
1662
1915
 
1663
-
1664
-
1665
1916
  def get_prev_instance_skip_expression(node, processed_nodes, process, expression=None):
1666
1917
  if node.base_instance is not None:
1667
- activity = node
1668
1918
  expression_inputs = []
1669
- past_instances = [
1670
- n for n in processed_nodes if getattr(n.base_instance, 'id', None) == node.base_instance.id
1671
- ]
1919
+ past_instances = [n for n in processed_nodes if getattr(n.base_instance, "id", None) == node.base_instance.id]
1672
1920
  for past_instance in past_instances:
1673
1921
  add_sub_expression(
1674
- expression_inputs,
1922
+ expression_inputs,
1675
1923
  get_node_expression(
1676
- past_instance,
1677
- processed_nodes=processed_nodes,
1678
- get_overall_exp=True,
1679
- is_prev=True,
1680
- process=process
1681
- )
1924
+ past_instance, processed_nodes=processed_nodes, get_overall_exp=True, is_prev=True, process=process
1925
+ ),
1682
1926
  )
1683
1927
  if expression and expression_inputs:
1684
1928
  add_sub_expression(expression_inputs, expression)
1685
1929
  expression = nand_join(expression, or_join(expression_inputs))
1686
1930
  elif expression_inputs:
1687
- expression = negate_term(or_join(expression_inputs))
1931
+ expression = negate_term(or_join(expression_inputs))
1688
1932
  return expression
1689
1933
 
1690
1934
 
1691
1935
  # end def
1692
1936
  def get_process_skip_expression(node, processed_nodes, process, expression=None):
1693
- list_ends = OrderedSet(
1694
- filter(
1695
- lambda x: issubclass(x.__class__, TriccNodeEnd),
1696
- processed_nodes
1697
- )
1698
- )
1937
+ list_ends = OrderedSet(filter(lambda x: issubclass(x.__class__, TriccNodeEnd), processed_nodes))
1699
1938
  if list_ends:
1700
1939
  end_expressions = []
1701
1940
  f_end_expression = get_end_expression(list_ends)
1702
1941
  if f_end_expression:
1703
1942
  end_expressions.append(f_end_expression)
1704
- b_end_expression = get_end_expression(list_ends, 'pause')
1943
+ b_end_expression = get_end_expression(list_ends, "pause")
1705
1944
  if b_end_expression:
1706
- end_expressions.append(b_end_expression)
1945
+ end_expressions.append(b_end_expression)
1707
1946
  if process[0] in PROCESSES:
1708
- for p in PROCESSES[PROCESSES.index(process[0])+1:]:
1947
+ for p in PROCESSES[PROCESSES.index(process[0]) + 1:]:
1709
1948
  p_end_expression = get_end_expression(list_ends, p)
1710
1949
  if p_end_expression:
1711
1950
  end_expressions.append(p_end_expression)
@@ -1717,16 +1956,12 @@ def get_process_skip_expression(node, processed_nodes, process, expression=None)
1717
1956
  else:
1718
1957
  expression = and_join(end_expressions)
1719
1958
  return expression
1720
-
1959
+
1960
+
1721
1961
  def get_end_expression(processed_nodes, process=None):
1722
1962
  end_node = get_last_end_node(processed_nodes, process)
1723
1963
  if end_node:
1724
- return TriccOperation(
1725
- TriccOperator.ISNOTTRUE,
1726
- [end_node]
1727
- )
1728
-
1729
-
1964
+ return TriccOperation(TriccOperator.ISNOTTRUE, [end_node])
1730
1965
 
1731
1966
 
1732
1967
  def export_proposed_diags(activity, diags=None, **kwargs):
@@ -1736,11 +1971,10 @@ def export_proposed_diags(activity, diags=None, **kwargs):
1736
1971
  if isinstance(node, TriccNodeActivity):
1737
1972
  diags = export_proposed_diags(node, diags, **kwargs)
1738
1973
  if isinstance(node, TriccNodeProposedDiagnosis):
1739
- if node.last is not False\
1740
- and not any([diag.name == node.name for diag in diags]):
1741
- diags.append(node)
1974
+ if node.last is not False and not any([diag.name == node.name for diag in diags]):
1975
+ diags.append(node)
1742
1976
  return diags
1743
-
1977
+
1744
1978
 
1745
1979
  def get_accept_diagnostic_node(code, display, severity, priority, activity):
1746
1980
  node = TriccNodeAcceptDiagnostic(
@@ -1751,11 +1985,12 @@ def get_accept_diagnostic_node(code, display, severity, priority, activity):
1751
1985
  activity=activity,
1752
1986
  group=activity,
1753
1987
  severity=severity,
1754
- priority=priority
1988
+ priority=priority,
1755
1989
  )
1756
1990
  node.options = get_select_accept_reject_options(node, node.activity)
1757
1991
  return node
1758
1992
 
1993
+
1759
1994
  def get_diagnostic_node(code, display, severity, priority, activity):
1760
1995
  node = TriccNodeCalculate(
1761
1996
  id=generate_id("final." + code),
@@ -1764,51 +1999,48 @@ def get_diagnostic_node(code, display, severity, priority, activity):
1764
1999
  activity=activity,
1765
2000
  group=activity,
1766
2001
  priority=priority,
1767
- expression_reference=or_join([
1768
- TriccOperation(TriccOperator.ISTRUE, [TriccReference("pre_final." + code)]),
1769
- TriccOperation(
1770
- TriccOperator.SELECTED,
1771
- [TriccReference('tricc.manual.diag'), TriccStatic(code)]
1772
- )
1773
- ])
2002
+ expression_reference=or_join(
2003
+ [
2004
+ TriccOperation(TriccOperator.ISTRUE, [TriccReference("pre_final." + code)]),
2005
+ TriccOperation(TriccOperator.SELECTED, [TriccReference("tricc.manual.diag"), TriccStatic(code)]),
2006
+ ]
2007
+ ),
1774
2008
  )
1775
2009
  return node
1776
2010
 
2011
+
1777
2012
  def get_select_accept_reject_options(node, group):
1778
2013
  yes = TriccNodeSelectOption(
1779
- id = generate_id(f'accept{node.id}'),
1780
- name=f"{TRICC_TRUE_VALUE}",
1781
- label="Accept",
1782
- select = node,
1783
- group = group,
1784
- list_name = node.list_name
1785
- )
2014
+ id=generate_id(f"accept{node.id}"),
2015
+ name=f"{TRICC_TRUE_VALUE}",
2016
+ label="Accept",
2017
+ select=node,
2018
+ group=group,
2019
+ list_name=node.list_name,
2020
+ )
1786
2021
  no = TriccNodeSelectOption(
1787
- id = generate_id(f'reject{node.id}'),
1788
- name=f"{TRICC_FALSE_VALUE}",
1789
- label="Reject",
1790
- select = node,
1791
- group = group,
1792
- list_name = node.list_name
1793
- )
1794
- return {0:yes, 1:no }
2022
+ id=generate_id(f"reject{node.id}"),
2023
+ name=f"{TRICC_FALSE_VALUE}",
2024
+ label="Reject",
2025
+ select=node,
2026
+ group=group,
2027
+ list_name=node.list_name,
2028
+ )
2029
+ return {0: yes, 1: no}
2030
+
1795
2031
 
1796
2032
  def create_determine_diagnosis_activity(diags):
1797
2033
  start = TriccNodeMainStart(
1798
- id=generate_id('start.determine-diagnosis'),
1799
- name="start.determine-diagnosis",
1800
- process='determine-diagnosis'
2034
+ id=generate_id("start.determine-diagnosis"), name="start.determine-diagnosis", process="determine-diagnosis"
1801
2035
  )
1802
2036
 
1803
-
1804
2037
  activity = TriccNodeActivity(
1805
- id=generate_id('activity-determine-diagnosis'),
1806
- name='determine-diagnosis',
1807
- label='Diagnosis',
2038
+ id=generate_id("activity-determine-diagnosis"),
2039
+ name="determine-diagnosis",
2040
+ label="Classifications",
1808
2041
  root=start,
1809
2042
  )
1810
2043
 
1811
-
1812
2044
  start.activity = activity
1813
2045
  start.group = activity
1814
2046
  diags_conf = []
@@ -1818,17 +2050,16 @@ def create_determine_diagnosis_activity(diags):
1818
2050
  activity=activity,
1819
2051
  group=activity,
1820
2052
  )
1821
- activity.nodes[end.id]=end
1822
-
2053
+ activity.nodes[end.id] = end
2054
+
1823
2055
  f = TriccNodeSelectMultiple(
1824
2056
  name="tricc.manual.diag",
1825
- label="Add diagnosis",
1826
- list_name='manual_diag',
2057
+ label="Add classifications",
2058
+ list_name="manual_diag",
1827
2059
  id=generate_id("tricc.manual.diag"),
1828
2060
  activity=activity,
1829
2061
  group=activity,
1830
2062
  required=TriccStatic(False),
1831
-
1832
2063
  )
1833
2064
  for proposed in diags:
1834
2065
  d = get_accept_diagnostic_node(proposed.name, proposed.label, proposed.severity, proposed.priority, activity)
@@ -1837,14 +2068,12 @@ def create_determine_diagnosis_activity(diags):
1837
2068
  r = TriccNodeRhombus(
1838
2069
  path=start,
1839
2070
  id=generate_id(f"proposed-rhombus{proposed.id}"),
1840
- expression_reference=TriccOperation(
1841
- TriccOperator.ISTRUE,
1842
- [TriccReference(proposed.name)]
1843
- ),
2071
+ expression_reference=TriccOperation(TriccOperator.ISTRUE, [TriccReference(proposed.name)]),
1844
2072
  reference=[TriccReference(proposed.name)],
1845
2073
  activity=activity,
1846
2074
  priority=proposed.priority,
1847
- group=activity)
2075
+ group=activity,
2076
+ )
1848
2077
  activity.calculates.append(r)
1849
2078
  activity.calculates.append(c)
1850
2079
  set_prev_next_node(r, d, edge_only=False)
@@ -1852,11 +2081,11 @@ def create_determine_diagnosis_activity(diags):
1852
2081
  wait2 = get_activity_wait([activity.root], diags_conf, [f], edge_only=False)
1853
2082
  activity.nodes[d.options[0].id] = d.options[0]
1854
2083
  activity.nodes[d.options[1].id] = d.options[1]
1855
- activity.nodes[d.id]=d
1856
- activity.nodes[r.id]=r
1857
- activity.nodes[c.id]=c
1858
- activity.nodes[f.id]=f
1859
- activity.nodes[wait2.id]=wait2
2084
+ activity.nodes[d.id] = d
2085
+ activity.nodes[r.id] = r
2086
+ activity.nodes[c.id] = c
2087
+ activity.nodes[f.id] = f
2088
+ activity.nodes[wait2.id] = wait2
1860
2089
  # fallback
1861
2090
 
1862
2091
  options = [
@@ -1866,220 +2095,182 @@ def create_determine_diagnosis_activity(diags):
1866
2095
  label=d.label,
1867
2096
  list_name=f.list_name,
1868
2097
  relevance=d.activity.applicability,
1869
- select=f
1870
- ) for d in diags
2098
+ select=f,
2099
+ )
2100
+ for d in diags
1871
2101
  ]
1872
- f.options=dict(zip(range(0, len(options)), options))
1873
- activity.nodes[f.id]=f
2102
+ f.options = dict(zip(range(0, len(options)), options))
2103
+ activity.nodes[f.id] = f
1874
2104
  set_prev_next_node(f, end, edge_only=False)
1875
-
2105
+
1876
2106
  return activity
1877
-
1878
- def get_prev_node_expression( node, processed_nodes, get_overall_exp=False, excluded_name=None, process=None):
2107
+
2108
+
2109
+ def get_prev_node_expression(node, processed_nodes, get_overall_exp=False, excluded_name=None, process=None):
1879
2110
  expression = None
1880
2111
  if node is None:
1881
2112
  pass
1882
2113
  # when getting the prev node, we calculate the
1883
- if hasattr(node, 'expression_inputs') and len(node.expression_inputs) > 0:
2114
+ if hasattr(node, "expression_inputs") and len(node.expression_inputs) > 0:
1884
2115
  expression_inputs = node.expression_inputs
1885
2116
  expression_inputs = clean_or_list(expression_inputs)
1886
2117
  else:
1887
- expression_inputs = []
2118
+ expression_inputs = []
1888
2119
  prev_activities = {}
1889
2120
  for prev_node in node.prev_nodes:
1890
2121
  if prev_node.activity.id not in prev_activities:
1891
- prev_activities[prev_node.activity.id]=[]
2122
+ prev_activities[prev_node.activity.id] = []
1892
2123
  prev_activities[prev_node.activity.id].append(prev_node)
1893
-
2124
+
1894
2125
  for act_id in prev_activities:
1895
2126
  act_expression_inputs = []
1896
2127
  for prev_node in prev_activities[act_id]:
1897
- if excluded_name is None or prev_node != excluded_name or (
1898
- isinstance(excluded_name, str) and hasattr(prev_node, 'name') and prev_node.name != excluded_name): # or isinstance(prev_node, TriccNodeActivityEnd):
2128
+ if (
2129
+ excluded_name is None
2130
+ or prev_node != excluded_name
2131
+ or (
2132
+ # or isinstance(prev_node, TriccNodeActivityEnd):
2133
+ isinstance(excluded_name, str)
2134
+ and hasattr(prev_node, "name")
2135
+ and prev_node.name != excluded_name
2136
+ )
2137
+ ):
1899
2138
  # the rhombus should calculate only reference
1900
2139
  sub = get_node_expression(
1901
2140
  prev_node,
1902
2141
  processed_nodes=processed_nodes,
1903
2142
  get_overall_exp=get_overall_exp,
1904
2143
  is_prev=True,
1905
- process=process)
1906
- if isinstance(node, TriccNodeActivity) or get_overall_exp:
1907
- add_sub_expression(act_expression_inputs, sub )
2144
+ process=process,
2145
+ )
2146
+ if isinstance(node, TriccNodeActivity) or get_overall_exp:
2147
+ add_sub_expression(act_expression_inputs, sub)
1908
2148
  else:
1909
- add_sub_expression(expression_inputs, sub )
1910
-
2149
+ add_sub_expression(expression_inputs, sub)
2150
+
1911
2151
  if act_expression_inputs:
1912
2152
  act_sub = or_join(act_expression_inputs)
1913
- if act_sub == TriccStatic(True):
1914
- act_sub = get_node_expression(
2153
+ if act_sub == TriccStatic(True):
2154
+ act_sub = get_node_expression(
1915
2155
  prev_node.activity,
1916
2156
  processed_nodes=processed_nodes,
1917
2157
  get_overall_exp=True,
1918
2158
  is_prev=True,
1919
2159
  negate=False,
1920
- process=process
2160
+ process=process,
1921
2161
  )
1922
- add_sub_expression(expression_inputs, act_sub )
2162
+ add_sub_expression(expression_inputs, act_sub)
1923
2163
  # avoid void is there is not conditions to avoid looping too much itme
1924
2164
  # expression_inputs = clean_or_list(
1925
2165
  # [
1926
- # get_tricc_operation_operand(e)
1927
- # if isinstance(expression, TriccOperation)
1928
- # else e
2166
+ # get_tricc_operation_operand(e)
2167
+ # if isinstance(expression, TriccOperation)
2168
+ # else e
1929
2169
  # for e in expression_inputs])
1930
-
2170
+
1931
2171
  if expression_inputs:
1932
- expression = or_join(
1933
- expression_inputs
1934
- )
2172
+ expression = or_join(expression_inputs)
1935
2173
  # if isinstance(node, TriccNodeExclusive):
1936
2174
  # expression = TRICC_NEGATE.format(expression)
1937
- # only used for activityStart
2175
+ # only used for activityStart
1938
2176
  else:
1939
2177
  expression = TriccStatic(True)
1940
2178
  return expression
1941
2179
 
1942
- def get_activity_end_terms( node, processed_nodes, process=None):
2180
+
2181
+ def get_activity_end_terms(node, processed_nodes, process=None):
1943
2182
  end_nodes = node.get_end_nodes()
1944
2183
  expression_inputs = []
1945
2184
  for end_node in end_nodes:
1946
2185
  add_sub_expression(
1947
2186
  expression_inputs,
1948
2187
  get_node_expression(
1949
- end_node,
1950
- processed_nodes=processed_nodes,
1951
- get_overall_exp=False,
1952
- is_prev=True,
1953
- process=process))
2188
+ end_node, processed_nodes=processed_nodes, get_overall_exp=False, is_prev=True, process=process
2189
+ ),
2190
+ )
2191
+
2192
+ return or_join(expression_inputs)
1954
2193
 
1955
- return or_join(expression_inputs)
1956
2194
 
1957
- def get_count_terms( node, processed_nodes, get_overall_exp, negate=False, process=None):
2195
+ def get_count_terms(node, processed_nodes, get_overall_exp, negate=False, process=None):
1958
2196
  terms = []
1959
-
2197
+
1960
2198
  for prev_node in node.prev_nodes:
1961
- term = get_count_terms_details( prev_node, processed_nodes, get_overall_exp, negate, process)
2199
+ term = get_count_terms_details(prev_node, processed_nodes, get_overall_exp, negate, process)
1962
2200
  if term:
1963
2201
  terms.append(term)
1964
2202
  if len(terms) == 1:
1965
- return TriccOperation(
1966
- TriccOperator.CAST_NUMBER,
1967
- [terms[0]]
1968
- )
2203
+ return TriccOperation(TriccOperator.CAST_NUMBER, [terms[0]])
1969
2204
  elif len(terms) > 0:
1970
- return TriccOperation(
1971
- TriccOperator.PLUS,
1972
- [
1973
- TriccOperation(
1974
- TriccOperator.CAST_NUMBER,
1975
- [term]
1976
- ) for term in terms
1977
- ]
1978
- )
1979
-
1980
- def get_count_terms_details( prev_node, processed_nodes, get_overall_exp, negate=False, process=None):
1981
- operation_none = TriccOperation(
1982
- TriccOperator.SELECTED,
1983
- [
1984
- prev_node,
1985
- TriccStatic('opt_none')
1986
- ]
1987
- )
1988
- if isinstance(prev_node, TriccNodeSelectYesNo):
2205
+ return TriccOperation(TriccOperator.PLUS, [TriccOperation(TriccOperator.CAST_NUMBER, [term]) for term in terms])
2206
+
2207
+
2208
+ def get_count_terms_details(prev_node, processed_nodes, get_overall_exp, negate=False, process=None):
2209
+ operation_none = TriccOperation(TriccOperator.SELECTED, [prev_node, TriccStatic("opt_none")])
2210
+ if isinstance(prev_node, TriccNodeSelectYesNo):
2211
+ return TriccOperation(TriccOperator.SELECTED, [prev_node, TriccStatic(prev_node.options[0].name)])
2212
+ elif issubclass(prev_node.__class__, TriccNodeSelect):
2213
+ if negate:
2214
+ return
2215
+ # terms.append(TRICC_SELECT_MULTIPLE_CALC_NONE_EXPRESSION.format(get_export_name(prev_node)))
2216
+ else:
1989
2217
  return TriccOperation(
1990
- TriccOperator.SELECTED,
2218
+ TriccOperator.MINUS,
1991
2219
  [
1992
- prev_node,
1993
- TriccStatic(prev_node.options[0].name)
1994
- ]
2220
+ TriccOperation(TriccOperator.COUNT, [prev_node]),
2221
+ TriccOperation(TriccOperator.CAST_NUMBER, [operation_none]),
2222
+ ],
1995
2223
  )
1996
- elif issubclass(prev_node.__class__, TriccNodeSelect):
1997
- if negate:
1998
- return
1999
- #terms.append(TRICC_SELECT_MULTIPLE_CALC_NONE_EXPRESSION.format(get_export_name(prev_node)))
2000
- else:
2001
- return TriccOperation(
2002
- TriccOperator.MINUS,
2003
- [
2004
- TriccOperation(
2005
- TriccOperator.NATIVE,
2006
- [
2007
- 'count-selected',
2008
- prev_node
2009
- ]
2010
- ),TriccOperation(
2011
- TriccOperator.CAST_NUMBER,
2012
- [
2013
- operation_none
2014
- ]
2015
- )
2016
- ])
2017
- #terms.append(TRICC_SELECT_MULTIPLE_CALC_EXPRESSION.format(get_export_name(prev_node)))
2018
- elif isinstance(prev_node, (TriccNodeSelectNotAvailable)):
2224
+ # terms.append(TRICC_SELECT_MULTIPLE_CALC_EXPRESSION.format(get_export_name(prev_node)))
2225
+ elif isinstance(prev_node, (TriccNodeSelectNotAvailable)):
2226
+ return TriccOperation(TriccOperator.SELECTED, [prev_node, TriccStatic("1")])
2227
+ # terms.append(TRICC_SELECTED_EXPRESSION.format(get_export_name(prev_node), '1'))
2228
+ elif isinstance(prev_node, TriccNodeSelectOption):
2229
+ return get_selected_option_expression(prev_node, negate)
2230
+ else:
2231
+ if negate:
2019
2232
  return TriccOperation(
2020
- TriccOperator.SELECTED,
2233
+ TriccOperator.CAST_NUMBER,
2021
2234
  [
2022
- prev_node,
2023
- TriccStatic('1')
2024
- ]
2025
- )
2026
- #terms.append(TRICC_SELECTED_EXPRESSION.format(get_export_name(prev_node), '1'))
2027
- elif isinstance(prev_node, TriccNodeSelectOption):
2028
- return get_selected_option_expression(prev_node, negate)
2029
- else:
2030
- if negate:
2031
- return TriccOperation(
2032
- TriccOperator.CAST_NUMBER,
2235
+ TriccOperation(
2236
+ TriccOperator.NATIVE,
2033
2237
  [
2034
2238
  TriccOperation(
2035
- TriccOperator.NATIVE,
2239
+ TriccOperator.CAST_NUMBER,
2036
2240
  [
2037
- TriccOperation(
2038
- TriccOperator.CAST_NUMBER,
2039
- [
2040
- get_node_expression(
2041
- prev_node,
2042
- processed_nodes=processed_nodes,
2043
- get_overall_exp=True,
2044
- is_prev=True,
2045
- process=process)
2046
- ]),
2047
- TriccStatic('0')
2048
- ]
2049
- )
2050
- ]
2241
+ get_node_expression(
2242
+ prev_node,
2243
+ processed_nodes=processed_nodes,
2244
+ get_overall_exp=True,
2245
+ is_prev=True,
2246
+ process=process,
2247
+ )
2248
+ ],
2249
+ ),
2250
+ TriccStatic("0"),
2251
+ ],
2051
2252
  )
2052
-
2053
- else:
2054
- return TriccOperation(
2055
- TriccOperator.CAST_NUMBER,
2056
- [
2057
- get_node_expression(
2058
- prev_node,
2059
- processed_nodes=processed_nodes,
2060
- get_overall_exp=True,
2061
- is_prev=True,
2062
- process=process)
2063
- ]
2253
+ ],
2254
+ )
2255
+
2256
+ else:
2257
+ return TriccOperation(
2258
+ TriccOperator.CAST_NUMBER,
2259
+ [
2260
+ get_node_expression(
2261
+ prev_node, processed_nodes=processed_nodes, get_overall_exp=True, is_prev=True, process=process
2064
2262
  )
2065
-
2066
-
2067
-
2068
- def get_add_terms( node, processed_nodes, get_overall_exp=False, negate=False, process=None):
2263
+ ],
2264
+ )
2265
+
2266
+
2267
+ def get_add_terms(node, processed_nodes, get_overall_exp=False, negate=False, process=None):
2069
2268
  if negate:
2070
2269
  logger.warning("negate not supported for Add node {}".format(node.get_name()))
2071
2270
  terms = []
2072
2271
  for prev_node in node.prev_nodes:
2073
2272
  if issubclass(prev_node, TriccNodeNumber) or isinstance(node, TriccNodeCount):
2074
- terms.append(
2075
- TriccOperation(
2076
- TriccOperator.COALESCE,
2077
- [
2078
- prev_node,
2079
- TriccStatic(0)
2080
- ]
2081
- )
2082
- )
2273
+ terms.append(TriccOperation(TriccOperator.COALESCE, [prev_node, TriccStatic(0)]))
2083
2274
  else:
2084
2275
  terms.append(
2085
2276
  TriccOperation(
@@ -2089,33 +2280,28 @@ def get_add_terms( node, processed_nodes, get_overall_exp=False, negate=False, p
2089
2280
  prev_node,
2090
2281
  processed_nodes=processed_nodes,
2091
2282
  get_overall_exp=True,
2092
- is_prev=True,
2093
- process=process)
2094
- ]
2283
+ is_prev=True,
2284
+ process=process,
2285
+ )
2286
+ ],
2095
2287
  )
2096
2288
  )
2097
2289
  if len(terms) > 0:
2098
2290
  operation = terms[0]
2099
2291
  if len(terms) > 1:
2100
2292
  for term in terms[1:]:
2101
- operation = TriccOperation(
2102
- TriccOperator.ADD,
2103
- [
2104
- operation,
2105
- term
2106
- ]
2107
- )
2293
+ operation = TriccOperation(TriccOperator.ADD, [operation, term])
2108
2294
  return operation
2109
-
2110
- def get_rhombus_terms( node, processed_nodes, get_overall_exp=False, negate=False, process=None):
2295
+
2296
+
2297
+ def get_rhombus_terms(node, processed_nodes, get_overall_exp=False, negate=False, process=None):
2111
2298
  expression = None
2112
2299
  left_term = None
2113
- operator = None
2114
2300
  if node.reference is not None:
2115
2301
  if isinstance(node.reference, set):
2116
2302
  node.reference = list(node.reference)
2117
2303
  # calcualte the expression only for select muzltiple and fake calculate
2118
- if issubclass(node.reference.__class__, (list,OrderedSet)):
2304
+ if issubclass(node.reference.__class__, (list, OrderedSet)):
2119
2305
  if node.expression_reference is None and len(node.reference) == 1:
2120
2306
  ref = node.reference[0]
2121
2307
  if issubclass(ref.__class__, TriccNodeBaseModel):
@@ -2123,81 +2309,79 @@ def get_rhombus_terms( node, processed_nodes, get_overall_exp=False, negate=Fals
2123
2309
  expression = get_activity_end_terms(ref, processed_nodes, process=process)
2124
2310
  elif issubclass(ref.__class__, TriccNodeFakeCalculateBase):
2125
2311
  expression = get_node_expression(
2126
- ref,
2127
- processed_nodes=processed_nodes,
2128
- get_overall_exp=True,
2129
- is_prev=True,
2130
- process=process
2312
+ ref, processed_nodes=processed_nodes, get_overall_exp=True, is_prev=True, process=process
2131
2313
  )
2132
2314
  else:
2133
2315
  expression = ref
2134
2316
  elif issubclass(ref.__class__, TriccReference):
2135
2317
  expression = ref
2136
2318
  else:
2137
- logger.critical('reference {0} was not found in the previous nodes of node {1}'.format(node.reference,
2138
- node.get_name()))
2319
+ logger.critical(
2320
+ "reference {0} was not found in the previous nodes of node {1}".format(
2321
+ node.reference, node.get_name()
2322
+ )
2323
+ )
2139
2324
  exit(1)
2140
- elif node.expression_reference is not None and node.expression_reference != '':
2325
+ elif node.expression_reference is not None and node.expression_reference != "":
2141
2326
  if isinstance(node.expression_reference, (TriccOperation, TriccReference, TriccStatic)):
2142
2327
  return node.expression_reference
2143
2328
  elif isinstance(node.expression_reference, str):
2144
2329
  expression = node.expression_reference.format(*get_list_names(node.reference))
2145
2330
  else:
2146
- logger.critical('expression_reference {0} unsuported type {1}'.format(node.expression_reference, node.expression_reference.__class__.__name__))
2331
+ logger.critical(
2332
+ "expression_reference {0} unsuported type {1}".format(
2333
+ node.expression_reference, node.expression_reference.__class__.__name__
2334
+ )
2335
+ )
2147
2336
  exit(1)
2148
2337
 
2149
2338
  else:
2150
2339
  logger.warning("missing expression for node {}".format(node.get_name()))
2151
2340
  else:
2152
- logger.critical('reference {0} is not a list {1}'.format(node.reference, node.get_name()))
2341
+ logger.critical("reference {0} is not a list {1}".format(node.reference, node.get_name()))
2153
2342
  exit(1)
2154
2343
  else:
2155
- logger.critical('reference empty for Rhombis {}'.format( node.get_name()))
2344
+ logger.critical("reference empty for Rhombis {}".format(node.get_name()))
2156
2345
  exit(1)
2157
2346
 
2158
2347
  if expression is not None:
2159
2348
  if isinstance(expression, (TriccOperation, TriccStatic)):
2160
2349
  return expression
2161
- elif issubclass(expression.__class__ , TriccNodeCalculateBase):
2350
+ elif issubclass(expression.__class__, TriccNodeCalculateBase):
2162
2351
  return TriccOperation(
2163
2352
  TriccOperator.CAST_NUMBER,
2164
2353
  [
2165
2354
  get_node_expression(
2166
- expression,
2167
- processed_nodes=processed_nodes,
2168
- get_overall_exp=True,
2169
- is_prev=True,
2170
- process=process
2355
+ expression, processed_nodes=processed_nodes, get_overall_exp=True, is_prev=True, process=process
2171
2356
  )
2172
- ])
2173
- elif issubclass(expression.__class__ , (TriccOperation) ):
2174
- return expression
2175
- elif issubclass(expression.__class__ , (TriccNodeDisplayModel, TriccReference)):
2176
- return TriccOperation(
2177
- TriccOperator.ISTRUE,
2178
- [
2179
- expression
2180
- ]
2357
+ ],
2181
2358
  )
2359
+ elif issubclass(expression.__class__, (TriccOperation)):
2360
+ return expression
2361
+ elif issubclass(expression.__class__, (TriccNodeDisplayModel, TriccReference)):
2362
+ return TriccOperation(TriccOperator.ISTRUE, [expression])
2182
2363
  else:
2183
2364
  if left_term is not None and re.search(" (+)|(-)|(or)|(and) ", expression):
2184
2365
  expression = "({0}){1}".format(expression, left_term)
2185
2366
  else:
2186
2367
  expression = "{0}{1}".format(expression, left_term)
2187
2368
  else:
2188
- logger.critical("Rhombus reference was not found for node {}, reference {}".format(
2189
- node.get_name(),
2190
- node.reference
2191
- ))
2369
+ logger.critical(
2370
+ "Rhombus reference was not found for node {}, reference {}".format(node.get_name(), node.reference)
2371
+ )
2192
2372
  exit(1)
2193
2373
 
2194
2374
  return expression
2375
+
2376
+
2195
2377
  # function that generate the calculation terms return by calculate node
2196
2378
  # @param node calculate node to assess
2197
2379
  # @param processed_nodes list of node already processed, importnat because only processed node could be use
2198
2380
  # @param get_overall_exp used when this funciton is called in the evaluation of another calculate
2199
2381
  # @param negate use to retriece the negation of a calculation
2200
- def get_calculation_terms( node, processed_nodes, get_overall_exp=False, negate=False, process=None):
2382
+
2383
+
2384
+ def get_calculation_terms(node, processed_nodes, get_overall_exp=False, negate=False, process=None):
2201
2385
  # returns something directly only if the negate is managed
2202
2386
  expression = None
2203
2387
  if isinstance(node, TriccNodeAdd):
@@ -2206,22 +2390,25 @@ def get_calculation_terms( node, processed_nodes, get_overall_exp=False, negate=
2206
2390
  return get_count_terms(node, False, negate, process=process)
2207
2391
  elif isinstance(node, TriccNodeRhombus):
2208
2392
  return get_rhombus_terms(
2209
- node,
2210
- processed_nodes=processed_nodes,
2211
- get_overall_exp=False,
2212
- negate=negate,
2213
- process=process
2393
+ node, processed_nodes=processed_nodes, get_overall_exp=False, negate=negate, process=process
2214
2394
  )
2215
- elif isinstance(node, ( TriccNodeWait)):
2395
+ elif isinstance(node, (TriccNodeWait)):
2216
2396
  # just use to force order of question
2217
2397
  expression = None
2218
- # in case of calulate expression evaluation, we need to get the relevance of the activity
2398
+ # in case of calulate expression evaluation, we need to get the relevance of the activity
2219
2399
  # because calculate are not the the activity group
2220
2400
  elif isinstance(node, (TriccNodeActivityStart)) and get_overall_exp:
2221
- expression = get_prev_node_expression(node.activity, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, negate=negate, process=process)
2401
+ expression = get_prev_node_expression(
2402
+ node.activity,
2403
+ processed_nodes=processed_nodes,
2404
+ get_overall_exp=get_overall_exp,
2405
+ negate=negate,
2406
+ process=process,
2407
+ )
2222
2408
  elif isinstance(node, (TriccNodeActivityStart, TriccNodeActivityEnd)):
2223
2409
  # the group have the relevance for the activity, not needed to replicate it
2224
- expression = None #return get_prev_node_expression(node.activity, processed_nodes, get_overall_exp=False, excluded_name=None)
2410
+ # return get_prev_node_expression(node.activity, processed_nodes, get_overall_exp=False, excluded_name=None)
2411
+ expression = None
2225
2412
  elif isinstance(node, TriccNodeExclusive):
2226
2413
  if len(node.prev_nodes) == 1:
2227
2414
  iterator = iter(node.prev_nodes)
@@ -2236,8 +2423,8 @@ def get_calculation_terms( node, processed_nodes, get_overall_exp=False, negate=
2236
2423
  get_overall_exp=True,
2237
2424
  is_prev=True,
2238
2425
  negate=True,
2239
- process=process
2240
- )
2426
+ process=process,
2427
+ )
2241
2428
  elif isinstance(node_to_negate, TriccNodeActivity):
2242
2429
  return get_node_expression(
2243
2430
  node_to_negate,
@@ -2245,36 +2432,45 @@ def get_calculation_terms( node, processed_nodes, get_overall_exp=False, negate=
2245
2432
  get_overall_exp=True,
2246
2433
  is_prev=True,
2247
2434
  negate=True,
2248
- process=process
2435
+ process=process,
2249
2436
  )
2250
2437
  else:
2251
- logger.critical(f"exclusive node {node.get_name()}\
2438
+ logger.critical(
2439
+ f"exclusive node {node.get_name()}\
2252
2440
  does not depend of a calculate but on\
2253
- {node_to_negate.__class__}::{node_to_negate.get_name()}")
2441
+ {node_to_negate.__class__}::{node_to_negate.get_name()}"
2442
+ )
2254
2443
 
2255
2444
  else:
2256
2445
  logger.critical("exclusive node {} has no ou too much parent".format(node.get_name()))
2257
-
2446
+
2258
2447
  if isinstance(node.expression_reference, (TriccOperation, TriccStatic)):
2259
2448
  expression = node.expression_reference
2260
- elif node.reference is not None and node.expression_reference is not None :
2261
- expression = get_prev_node_expression(node, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, process=process)
2449
+ elif node.reference is not None and node.expression_reference is not None:
2450
+ expression = get_prev_node_expression(
2451
+ node, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, process=process
2452
+ )
2262
2453
  ref_expression = node.expression_reference.format(*[get_export_name(ref) for ref in node.reference])
2263
- if expression is not None and expression != '':
2264
- expression = and_join([expression,ref_expression])
2454
+ if expression is not None and expression != "":
2455
+ expression = and_join([expression, ref_expression])
2265
2456
  else:
2266
2457
  expression = ref_expression
2267
2458
  elif expression is None:
2268
- expression = get_prev_node_expression(node, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, process=process)
2269
-
2459
+ expression = get_prev_node_expression(
2460
+ node, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, process=process
2461
+ )
2462
+
2270
2463
  # manage the generic negation
2271
2464
  if negate:
2272
-
2465
+
2273
2466
  return negate_term(expression)
2274
2467
  else:
2275
2468
  return expression
2276
-
2469
+
2470
+
2277
2471
  # Function that add element to array is not None or ''
2472
+
2473
+
2278
2474
  def add_sub_expression(array, sub):
2279
2475
  if isinstance(sub, (TriccOperation, TriccStatic)):
2280
2476
  not_sub = negate_term(sub)
@@ -2288,62 +2484,36 @@ def add_sub_expression(array, sub):
2288
2484
  pass
2289
2485
  # elif sub is None:
2290
2486
  # array.append(TriccStatic(True))
2291
-
2292
-
2293
2487
 
2294
2488
  # function that negate terms
2489
+
2490
+
2295
2491
  # @param expression to negate
2296
- def negate_term(expression):
2297
-
2298
- return not_clean(expression)
2299
2492
 
2300
2493
 
2494
+ def negate_term(expression):
2495
+
2496
+ return not_clean(expression)
2301
2497
 
2302
2498
 
2303
2499
  # if the node is "required" then we can take the fact that it has value for the next elements
2304
2500
  def get_required_node_expression(node):
2305
- return TriccOperation(
2306
- operator=TriccOperator.EXISTS,
2307
- reference=[
2308
- node
2309
- ]
2310
- )
2501
+ return TriccOperation(operator=TriccOperator.EXISTS, reference=[node])
2311
2502
 
2312
2503
 
2313
2504
  # Get a selected option
2314
2505
  def get_selected_option_expression(option_node, negate):
2315
-
2316
- selected = TriccOperation(
2317
- TriccOperator.SELECTED,
2318
- [
2319
- option_node.select,
2320
- TriccStatic(option_node.name)
2321
- ]
2322
- )
2323
-
2506
+
2507
+ selected = TriccOperation(TriccOperator.SELECTED, [option_node.select, TriccStatic(option_node.name)])
2508
+
2324
2509
  if negate:
2325
2510
  return TriccOperation(
2326
2511
  operator=TriccOperator.AND,
2327
2512
  resource=[
2328
- TriccOperation(
2329
- operator=TriccOperator.NOT,
2330
- resource=[
2331
- selected
2332
- ]
2333
- ),TriccOperation(
2334
- operator=TriccOperator.NATIVE,
2335
- resource=[
2336
- 'count-selected',
2337
- option_node.select
2338
- ]
2339
- )
2340
- ])
2341
-
2513
+ TriccOperation(operator=TriccOperator.NOT, resource=[selected]),
2514
+ TriccOperation(operator=TriccOperator.NATIVE, resource=["count-selected", option_node.select]),
2515
+ ],
2516
+ )
2517
+
2342
2518
  else:
2343
2519
  return selected
2344
-
2345
-
2346
-
2347
-
2348
-
2349
-