tricc-oo 1.4.17__tar.gz → 1.4.18__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/PKG-INFO +2 -1
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/pyproject.toml +2 -1
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/converters/cql_to_operation.py +7 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/converters/datadictionnary.py +4 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/converters/xml_to_tricc.py +3 -1
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/models/base.py +11 -12
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/models/tricc.py +5 -2
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/serializers/xls_form.py +9 -116
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/strategies/input/drawio.py +1 -1
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/strategies/output/xls_form.py +10 -7
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/strategies/output/xlsform_cdss.py +0 -4
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/visitors/tricc.py +105 -80
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo.egg-info/PKG-INFO +2 -1
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo.egg-info/requires.txt +1 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/README.md +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/setup.cfg +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tests/build.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tests/test_cql.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tests/to_ocl.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/__init__.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/converters/__init__.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/converters/codesystem_to_ocl.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/converters/cql/cqlLexer.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/converters/cql/cqlListener.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/converters/cql/cqlParser.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/converters/cql/cqlVisitor.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/converters/drawio_type_map.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/converters/tricc_to_xls_form.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/converters/utils.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/models/__init__.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/models/calculate.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/models/lang.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/models/ocl.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/models/ordered_set.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/parsers/__init__.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/parsers/xml.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/serializers/__init__.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/serializers/planuml.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/strategies/__init__.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/strategies/input/__init__.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/strategies/input/base_input_strategy.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/strategies/output/base_output_strategy.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/strategies/output/spice.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/strategies/output/xlsform_cht.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/strategies/output/xlsform_cht_hf.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/visitors/__init__.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/visitors/utils.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo/visitors/xform_pd.py +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo.egg-info/SOURCES.txt +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo.egg-info/dependency_links.txt +0 -0
- {tricc_oo-1.4.17 → tricc_oo-1.4.18}/tricc_oo.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: tricc-oo
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.18
|
|
4
4
|
Summary: Python library that converts CDSS L2 in L3
|
|
5
5
|
Project-URL: Homepage, https://github.com/SwissTPH/tricc
|
|
6
6
|
Project-URL: Issues, https://github.com/SwissTPH/tricc/issues
|
|
@@ -14,6 +14,7 @@ Requires-Dist: markdownify
|
|
|
14
14
|
Requires-Dist: pydantic
|
|
15
15
|
Requires-Dist: babel
|
|
16
16
|
Requires-Dist: xlsxwriter
|
|
17
|
+
Requires-Dist: html2text
|
|
17
18
|
Requires-Dist: pandas
|
|
18
19
|
Requires-Dist: polib
|
|
19
20
|
Requires-Dist: strenum
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "tricc-oo"
|
|
7
|
-
version = "1.4.
|
|
7
|
+
version = "1.4.18"
|
|
8
8
|
description = "Python library that converts CDSS L2 in L3"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
|
|
@@ -19,6 +19,7 @@ dependencies = [
|
|
|
19
19
|
"pydantic",
|
|
20
20
|
"babel",
|
|
21
21
|
"xlsxwriter",
|
|
22
|
+
"html2text",
|
|
22
23
|
"pandas",
|
|
23
24
|
"polib",
|
|
24
25
|
"strenum",
|
|
@@ -150,6 +150,13 @@ class cqlToXlsFormVisitor(cqlVisitor):
|
|
|
150
150
|
function_name = ctx.getChild(2).getText()
|
|
151
151
|
return not_clean(self._get_membership_expression(ctx, function_name))
|
|
152
152
|
|
|
153
|
+
def visitInvocationExpressionTerm(self, ctx):
|
|
154
|
+
result = super().visitInvocationExpressionTerm(ctx)
|
|
155
|
+
if isinstance(result, list) and all(isinstance(x, TriccStatic) for x in result):
|
|
156
|
+
value = '.'.join([x.value for x in result])
|
|
157
|
+
logger.warning(f"guessed reference for '{value}'")
|
|
158
|
+
return TriccReference(value)
|
|
159
|
+
return result
|
|
153
160
|
|
|
154
161
|
def visitBetweenExpression(self, ctx):
|
|
155
162
|
ref = self.visit(ctx.expression(0))
|
|
@@ -16,6 +16,10 @@ logger = logging.getLogger("default")
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
def lookup_codesystems_code(codesystems, ref):
|
|
19
|
+
if ref.startswith('final.'):
|
|
20
|
+
concept = lookup_codesystems_code(codesystems, ref[6:])
|
|
21
|
+
if concept:
|
|
22
|
+
return concept
|
|
19
23
|
for code_system in codesystems.values():
|
|
20
24
|
for concept in code_system.concept or []:
|
|
21
25
|
if concept.code == ref:
|
|
@@ -35,6 +35,7 @@ DISPLAY_ATTRIBUTES = [
|
|
|
35
35
|
'help'
|
|
36
36
|
]
|
|
37
37
|
logger = logging.getLogger("default")
|
|
38
|
+
import html2text
|
|
38
39
|
|
|
39
40
|
|
|
40
41
|
|
|
@@ -211,6 +212,7 @@ def process_edges(diagram, media_path, activity, nodes):
|
|
|
211
212
|
):
|
|
212
213
|
if isinstance(nodes[edge.source], TriccNodeRhombus):
|
|
213
214
|
edge.source = nodes[edge.source].path.id
|
|
215
|
+
edge.source_external_id = None
|
|
214
216
|
processed = True
|
|
215
217
|
elif label.lower() in (TRICC_YES_LABEL) or label == "":
|
|
216
218
|
# do nothinbg for yes
|
|
@@ -219,7 +221,7 @@ def process_edges(diagram, media_path, activity, nodes):
|
|
|
219
221
|
calc = process_factor_edge(edge, nodes)
|
|
220
222
|
elif label.lower() in TRICC_NO_LABEL:
|
|
221
223
|
calc = process_exclusive_edge(edge, nodes)
|
|
222
|
-
elif any(reserved in label.lower() for reserved in ([str(o) for o in list(TriccOperator)] + list(OPERATION_LIST.keys()) + ['$this'])):
|
|
224
|
+
elif any(reserved in html2text.html2text(label.lower()) for reserved in ([str(o) for o in list(TriccOperator)] + list(OPERATION_LIST.keys()) + ['$this'])):
|
|
223
225
|
# manage comment
|
|
224
226
|
calc = process_condition_edge(edge, nodes)
|
|
225
227
|
else:
|
|
@@ -118,10 +118,6 @@ class TriccBaseModel(BaseModel):
|
|
|
118
118
|
|
|
119
119
|
def make_instance(self, nb_instance, **kwargs):
|
|
120
120
|
instance = self.copy()
|
|
121
|
-
# change the id to avoid collision of name
|
|
122
|
-
instance.id = generate_id(f"{self.id}{nb_instance}")
|
|
123
|
-
instance.instance = int(nb_instance)
|
|
124
|
-
instance.base_instance = self
|
|
125
121
|
attr_dict = self.to_dict()
|
|
126
122
|
for attr, value in attr_dict.items():
|
|
127
123
|
if not attr.startswith('_') and value is not None:
|
|
@@ -132,6 +128,13 @@ class TriccBaseModel(BaseModel):
|
|
|
132
128
|
setattr(instance, attr, value)
|
|
133
129
|
except Exception as e:
|
|
134
130
|
logger.warning(f"Warning: Could not copy attribute {attr}: {e}")
|
|
131
|
+
|
|
132
|
+
# change the id to avoid collision of name
|
|
133
|
+
instance.id = generate_id(f"{self.id}{nb_instance}")
|
|
134
|
+
instance.instance = int(nb_instance)
|
|
135
|
+
instance.base_instance = self
|
|
136
|
+
|
|
137
|
+
|
|
135
138
|
# assign the defualt group
|
|
136
139
|
# if activity is not None and self.group == activity.base_instance:
|
|
137
140
|
# instance.group = instance
|
|
@@ -269,7 +272,7 @@ class TriccNodeBaseModel(TriccBaseModel):
|
|
|
269
272
|
if self.name is None:
|
|
270
273
|
self.name = get_rand_name(self.id)
|
|
271
274
|
def get_references(self):
|
|
272
|
-
return OrderedSet(
|
|
275
|
+
return OrderedSet()
|
|
273
276
|
|
|
274
277
|
class TriccStatic(BaseModel):
|
|
275
278
|
value: Union[str, float, int, bool]
|
|
@@ -706,17 +709,13 @@ def nand_join(left, right):
|
|
|
706
709
|
right_issue = right is None or right == ''
|
|
707
710
|
left_neg = left == False or left == 0 or left == '0' or left == TriccStatic(False)
|
|
708
711
|
right_neg = right == False or right == 0 or right == '0' or right == TriccStatic(False)
|
|
709
|
-
if issubclass(left.__class__, TriccNodeBaseModel):
|
|
710
|
-
left = get_export_name(left)
|
|
711
|
-
if issubclass(right.__class__, TriccNodeBaseModel):
|
|
712
|
-
right = get_export_name(right)
|
|
713
712
|
if left_issue and right_issue:
|
|
714
713
|
logger.critical("and with both terms empty")
|
|
715
714
|
elif left_issue:
|
|
716
715
|
logger.debug('and with empty left term')
|
|
717
|
-
return
|
|
716
|
+
return not_clean(right)
|
|
718
717
|
elif left == '1' or left == 1 or left == TriccStatic(True):
|
|
719
|
-
return
|
|
718
|
+
return not_clean(right)
|
|
720
719
|
elif right_issue :
|
|
721
720
|
logger.debug('and with empty right term')
|
|
722
721
|
return TriccStatic(False)
|
|
@@ -725,7 +724,7 @@ def nand_join(left, right):
|
|
|
725
724
|
elif right_neg:
|
|
726
725
|
return left
|
|
727
726
|
else:
|
|
728
|
-
return and_join([left,
|
|
727
|
+
return and_join([left, not_clean(right)])
|
|
729
728
|
|
|
730
729
|
|
|
731
730
|
TriccGroup.update_forward_refs()
|
|
@@ -96,7 +96,9 @@ class TriccNodeActivity(TriccNodeBaseModel):
|
|
|
96
96
|
return self.instances[instance_nb]
|
|
97
97
|
else:
|
|
98
98
|
instance = super().make_instance(instance_nb, activity=None)
|
|
99
|
-
self.
|
|
99
|
+
base_instance = (self.base_instance or self)
|
|
100
|
+
base_instance.instances[instance_nb] = instance
|
|
101
|
+
instance.base_instance = base_instance
|
|
100
102
|
# instance.base_instance = self
|
|
101
103
|
# we duplicate all the related nodes (not the calculate, duplication is manage in calculate version code)
|
|
102
104
|
nodes = {}
|
|
@@ -124,7 +126,7 @@ class TriccNodeActivity(TriccNodeBaseModel):
|
|
|
124
126
|
if node in self.calculates and instance_node:
|
|
125
127
|
instance.calculates.append(instance_node)
|
|
126
128
|
# update parents
|
|
127
|
-
for node in list(filter(lambda p_node:
|
|
129
|
+
for node in list(filter(lambda p_node: getattr(p_node, 'parent', None) is not None, list(instance.nodes.values()))):
|
|
128
130
|
new_parent = list(filter(lambda p_node: p_node.base_instance == node.parent,list(instance.nodes.values())))
|
|
129
131
|
if new_parent:
|
|
130
132
|
node.parent = new_parent[0]
|
|
@@ -179,6 +181,7 @@ class TriccNodeActivity(TriccNodeBaseModel):
|
|
|
179
181
|
if issubclass(node_instance.__class__, TriccRhombusMixIn):
|
|
180
182
|
old_path = node_origin.path
|
|
181
183
|
if old_path is not None:
|
|
184
|
+
node_instance.path = None
|
|
182
185
|
for n in node_instance.activity.nodes.values():
|
|
183
186
|
if n.base_instance.id == old_path.id:
|
|
184
187
|
node_instance.path = n
|
|
@@ -18,6 +18,9 @@ from tricc_oo.visitors.tricc import (
|
|
|
18
18
|
add_calculate,
|
|
19
19
|
TRICC_TRUE_VALUE,
|
|
20
20
|
TRICC_FALSE_VALUE,
|
|
21
|
+
get_applicability_expression,
|
|
22
|
+
get_prev_instance_skip_expression,
|
|
23
|
+
get_process_skip_expression,
|
|
21
24
|
)
|
|
22
25
|
|
|
23
26
|
logger = logging.getLogger("default")
|
|
@@ -32,7 +35,7 @@ BOOLEAN_MAP = {
|
|
|
32
35
|
|
|
33
36
|
|
|
34
37
|
def start_group(
|
|
35
|
-
strategy, cur_group, groups, df_survey, df_calculate, relevance=False, **kwargs
|
|
38
|
+
strategy, cur_group, groups, df_survey, df_calculate, processed_nodes, process, relevance=False, **kwargs
|
|
36
39
|
):
|
|
37
40
|
name = get_export_name(cur_group)
|
|
38
41
|
|
|
@@ -46,12 +49,17 @@ def start_group(
|
|
|
46
49
|
relevance = (
|
|
47
50
|
relevance and cur_group.relevance is not None and cur_group.relevance != ""
|
|
48
51
|
)
|
|
52
|
+
|
|
49
53
|
|
|
50
54
|
group_calc_required = (
|
|
51
55
|
False and relevance and not is_activity and len(relevance) > 100
|
|
52
56
|
)
|
|
53
57
|
|
|
54
58
|
relevance_expression = cur_group.relevance
|
|
59
|
+
relevance_expression = get_applicability_expression(cur_group, processed_nodes, process, relevance_expression)
|
|
60
|
+
relevance_expression = get_prev_instance_skip_expression(cur_group, processed_nodes, process, relevance_expression)
|
|
61
|
+
relevance_expression = get_process_skip_expression(cur_group, processed_nodes, process, relevance_expression)
|
|
62
|
+
|
|
55
63
|
if not relevance:
|
|
56
64
|
relevance_expression = ""
|
|
57
65
|
elif isinstance(relevance_expression, TriccOperation):
|
|
@@ -628,118 +636,3 @@ def get_input_calc_line(node, replace_dots=True):
|
|
|
628
636
|
]
|
|
629
637
|
|
|
630
638
|
|
|
631
|
-
def get_diagnostic_start_group_line():
|
|
632
|
-
label = langs.get_trads("List of diagnostics", force_dict=True)
|
|
633
|
-
empty = langs.get_trads("", force_dict=True)
|
|
634
|
-
return [
|
|
635
|
-
"begin group",
|
|
636
|
-
"l_diag_list25",
|
|
637
|
-
*list(label.values()),
|
|
638
|
-
*list(empty.values()), # hint
|
|
639
|
-
*list(empty.values()), # help
|
|
640
|
-
"", # default
|
|
641
|
-
"field-list", #'appearance',
|
|
642
|
-
"", #'constraint',
|
|
643
|
-
*list(empty.values()), #'constraint_message'
|
|
644
|
-
"", #'relevance'
|
|
645
|
-
"", #'disabled'
|
|
646
|
-
"", #'required'
|
|
647
|
-
*list(empty.values()), #'required message'
|
|
648
|
-
"", #'read only'
|
|
649
|
-
"", #'expression'
|
|
650
|
-
"", #'repeat_count'
|
|
651
|
-
"", #'image'
|
|
652
|
-
"",
|
|
653
|
-
]
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
def get_diagnostic_add_line(diags, df_choice):
|
|
657
|
-
for diag in diags:
|
|
658
|
-
df_choice.loc[len(df_choice)] = [
|
|
659
|
-
"tricc_diag_add",
|
|
660
|
-
get_export_name(diag),
|
|
661
|
-
*list(langs.get_trads(diag.label, True).values()),
|
|
662
|
-
"", # filter
|
|
663
|
-
"", # min y
|
|
664
|
-
"", # max Y
|
|
665
|
-
"", # l
|
|
666
|
-
"", # m
|
|
667
|
-
"", # s
|
|
668
|
-
]
|
|
669
|
-
label = langs.get_trads("Add a missing diagnostic", force_dict=True)
|
|
670
|
-
empty = langs.get_trads("", force_dict=True)
|
|
671
|
-
return [
|
|
672
|
-
"select_multiple tricc_diag_add",
|
|
673
|
-
"new_diag",
|
|
674
|
-
*list(label.values()),
|
|
675
|
-
*list(empty.values()), # hint
|
|
676
|
-
*list(empty.values()), # help
|
|
677
|
-
"", # default
|
|
678
|
-
"minimal", #'appearance',
|
|
679
|
-
"", #'constraint',
|
|
680
|
-
*list(empty.values()), #'constraint_message',
|
|
681
|
-
"", #'relevance'
|
|
682
|
-
"", #'disabled'
|
|
683
|
-
"", #'required'
|
|
684
|
-
*list(empty.values()), #'required message'
|
|
685
|
-
"", #'read only'
|
|
686
|
-
"", #'expression'
|
|
687
|
-
"", #'repeat_count'
|
|
688
|
-
"", #'image'
|
|
689
|
-
"",
|
|
690
|
-
]
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
def get_diagnostic_none_line(diags):
|
|
694
|
-
relevance = ""
|
|
695
|
-
for diag in diags:
|
|
696
|
-
relevance += TRICC_CALC_EXPRESSION.format(get_export_name(diag)) + " or "
|
|
697
|
-
label = langs.get_trads(
|
|
698
|
-
"Aucun diagnostic trouvé par l'outil mais cela ne veut pas dire que le patient est en bonne santé",
|
|
699
|
-
force_dict=True,
|
|
700
|
-
)
|
|
701
|
-
empty = langs.get_trads("", force_dict=True)
|
|
702
|
-
return [
|
|
703
|
-
"note",
|
|
704
|
-
"l_diag_none25",
|
|
705
|
-
*list(label.values()),
|
|
706
|
-
*list(empty.values()),
|
|
707
|
-
*list(empty.values()),
|
|
708
|
-
"", # default
|
|
709
|
-
"", #'appearance',
|
|
710
|
-
"", #'constraint',
|
|
711
|
-
*list(empty.values()),
|
|
712
|
-
f"not({relevance[:-4]})", #'relevance'
|
|
713
|
-
"", #'disabled'
|
|
714
|
-
"", #'required'
|
|
715
|
-
*list(empty.values()),
|
|
716
|
-
"", #'read only'
|
|
717
|
-
"", #'expression'
|
|
718
|
-
"", #'repeat_count'
|
|
719
|
-
"", #'image' TRICC_NEGATE
|
|
720
|
-
"",
|
|
721
|
-
]
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
def get_diagnostic_stop_group_line():
|
|
725
|
-
label = langs.get_trads("", force_dict=True)
|
|
726
|
-
return [
|
|
727
|
-
"end group",
|
|
728
|
-
"l_diag_list25",
|
|
729
|
-
*list(label.values()),
|
|
730
|
-
*list(label.values()),
|
|
731
|
-
*list(label.values()), # help
|
|
732
|
-
"", # default
|
|
733
|
-
"", #'appearance',
|
|
734
|
-
"", #'constraint',
|
|
735
|
-
*list(label.values()),
|
|
736
|
-
"", #'relevance'
|
|
737
|
-
"", #'disabled'
|
|
738
|
-
"", #'required'
|
|
739
|
-
*list(label.values()),
|
|
740
|
-
"", #'read only'
|
|
741
|
-
"", #'expression'
|
|
742
|
-
"", #'repeat_count'
|
|
743
|
-
"", #'image'
|
|
744
|
-
"",
|
|
745
|
-
]
|
|
@@ -126,8 +126,8 @@ class DrawioStrategy(BaseInputStrategy):
|
|
|
126
126
|
|
|
127
127
|
node_edge = list(
|
|
128
128
|
filter(lambda x: (
|
|
129
|
-
(x.source_external_id and x.source_external_id == node.external_id) or
|
|
130
129
|
( x.source and x.source == node.id) or
|
|
130
|
+
(not x.source and x.source_external_id and x.source_external_id == node.external_id) or
|
|
131
131
|
x.source == node
|
|
132
132
|
), page.edges)
|
|
133
133
|
)
|
|
@@ -85,7 +85,7 @@ class XLSFormStrategy(BaseOutPutStrategy):
|
|
|
85
85
|
|
|
86
86
|
|
|
87
87
|
def clean_coalesce(self, expression):
|
|
88
|
-
if re.match(r"^coalesce\(\${[^}]+},''\)$", expression):
|
|
88
|
+
if re.match(r"^coalesce\(\${[^}]+},''\)$", str(expression)):
|
|
89
89
|
return expression[9:-4]
|
|
90
90
|
return expression
|
|
91
91
|
|
|
@@ -174,8 +174,9 @@ class XLSFormStrategy(BaseOutPutStrategy):
|
|
|
174
174
|
cur_group = activity
|
|
175
175
|
groups[activity.id] = 0
|
|
176
176
|
path_len = 0
|
|
177
|
+
process = ['main']
|
|
177
178
|
# keep the vesrions on the group id, max version
|
|
178
|
-
start_group(self, cur_group=cur_group, groups=groups, **self.get_kwargs())
|
|
179
|
+
start_group(self, cur_group=cur_group, groups=groups, processed_nodes=processed_nodes, process=process, **self.get_kwargs())
|
|
179
180
|
walktrhough_tricc_node_processed_stached(
|
|
180
181
|
activity.root,
|
|
181
182
|
self.generate_export,
|
|
@@ -183,6 +184,7 @@ class XLSFormStrategy(BaseOutPutStrategy):
|
|
|
183
184
|
stashed_nodes,
|
|
184
185
|
path_len,
|
|
185
186
|
cur_group=activity.root.group,
|
|
187
|
+
process=process,
|
|
186
188
|
recursive=False,
|
|
187
189
|
**self.get_kwargs()
|
|
188
190
|
)
|
|
@@ -218,6 +220,8 @@ class XLSFormStrategy(BaseOutPutStrategy):
|
|
|
218
220
|
self,
|
|
219
221
|
cur_group=s_node.group,
|
|
220
222
|
groups=groups,
|
|
223
|
+
processed_nodes=processed_nodes,
|
|
224
|
+
process=process,
|
|
221
225
|
relevance=True,
|
|
222
226
|
**self.get_kwargs()
|
|
223
227
|
)
|
|
@@ -314,9 +318,8 @@ class XLSFormStrategy(BaseOutPutStrategy):
|
|
|
314
318
|
save_calc = save_calc.iloc[0]
|
|
315
319
|
if save_calc["name"] != drop_calc["name"]:
|
|
316
320
|
self.df_survey.replace(
|
|
317
|
-
"
|
|
318
|
-
"
|
|
319
|
-
regex=True,
|
|
321
|
+
"${" + drop_calc["name"] + "}",
|
|
322
|
+
"${" + save_calc["name"] + "}",
|
|
320
323
|
)
|
|
321
324
|
else:
|
|
322
325
|
logger.critical(
|
|
@@ -325,7 +328,7 @@ class XLSFormStrategy(BaseOutPutStrategy):
|
|
|
325
328
|
)
|
|
326
329
|
)
|
|
327
330
|
for index, empty_calc in df_empty_calc.iterrows():
|
|
328
|
-
self.df_survey.replace("
|
|
331
|
+
self.df_survey.replace("${" + empty_calc["name"] + "}", "1", regex=True)
|
|
329
332
|
|
|
330
333
|
# TODO try to reinject calc to reduce complexity
|
|
331
334
|
for i, c in self.df_calculate[
|
|
@@ -334,7 +337,7 @@ class XLSFormStrategy(BaseOutPutStrategy):
|
|
|
334
337
|
real_calc = re.find(r"^number\((.+)\)$", c["calculation"])
|
|
335
338
|
if real_calc is not None and real_calc != "":
|
|
336
339
|
self.df_survey[~self.df_survey["name"] == c["name"]].replace(
|
|
337
|
-
real_calc, "
|
|
340
|
+
real_calc, "${" + c["name"] + "}"
|
|
338
341
|
)
|
|
339
342
|
|
|
340
343
|
df_duplicate = self.df_survey[
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from tricc_oo.models.tricc import TriccNodeActivity
|
|
3
3
|
from tricc_oo.models.calculate import TriccNodeProposedDiagnosis, TriccNodeInput
|
|
4
|
-
from tricc_oo.serializers.xls_form import (
|
|
5
|
-
get_diagnostic_none_line,
|
|
6
|
-
get_diagnostic_start_group_line,
|
|
7
|
-
get_diagnostic_stop_group_line)
|
|
8
4
|
from tricc_oo.converters.tricc_to_xls_form import get_export_name
|
|
9
5
|
from tricc_oo.strategies.output.xls_form import XLSFormStrategy
|
|
10
6
|
from tricc_oo.models.lang import SingletonLangClass
|
|
@@ -657,7 +657,7 @@ def process_operation_reference(operation, node, processed_nodes, calculates, us
|
|
|
657
657
|
if codesystems:
|
|
658
658
|
concept = lookup_codesystems_code(codesystems, ref)
|
|
659
659
|
if not concept:
|
|
660
|
-
logger.critical(f"reference {ref} not found in the project")
|
|
660
|
+
logger.critical(f"reference {ref} not found in the project for{str(node)} ")
|
|
661
661
|
exit(1)
|
|
662
662
|
else:
|
|
663
663
|
if warn:
|
|
@@ -1144,23 +1144,34 @@ def check_stashed_loop(stashed_nodes, prev_stashed_nodes, processed_nodes, len_p
|
|
|
1144
1144
|
es_node.activity.instance if hasattr(es_node,'activity') else '',
|
|
1145
1145
|
es_node.__class__,
|
|
1146
1146
|
es_node.get_name()))
|
|
1147
|
+
for es_node in [node for node_list in looped.values() for node in node_list if isinstance(node, TriccReference)]:
|
|
1148
|
+
logger.info("looped node {}:{}|{} {}".format(
|
|
1149
|
+
es_node.activity.get_name() if hasattr(es_node,'activity') else '' ,
|
|
1150
|
+
es_node.activity.instance if hasattr(es_node,'activity') else '',
|
|
1151
|
+
es_node.__class__,
|
|
1152
|
+
es_node.get_name()))
|
|
1153
|
+
for es_node in [node for node_list in waited.values() for node in node_list if isinstance(node, TriccReference)]:
|
|
1154
|
+
logger.info("waited node {}:{}|{} {}".format(
|
|
1155
|
+
es_node.activity.get_name() if hasattr(es_node,'activity') else '' ,
|
|
1156
|
+
es_node.activity.instance if hasattr(es_node,'activity') else '',
|
|
1157
|
+
es_node.__class__,
|
|
1158
|
+
es_node.get_name()))
|
|
1147
1159
|
logger.info("looped nodes")
|
|
1148
1160
|
for dep_list in looped:
|
|
1149
1161
|
for d in looped[dep_list]:
|
|
1150
|
-
if d
|
|
1151
|
-
logger.critical("[{}] depends on
|
|
1152
|
-
dep_list,
|
|
1162
|
+
if str(d) in looped:
|
|
1163
|
+
logger.critical("[{}] depends on [{}]".format(
|
|
1164
|
+
dep_list, str(d)
|
|
1165
|
+
))
|
|
1166
|
+
else:
|
|
1167
|
+
logger.error("[{}] depends on [{}]".format(
|
|
1168
|
+
dep_list, str(d)
|
|
1153
1169
|
))
|
|
1154
|
-
logger.error("[{}] depends on [{}]".format(
|
|
1155
|
-
dep_list, str(d)
|
|
1156
|
-
))
|
|
1157
1170
|
if dep_list in waited:
|
|
1158
1171
|
for d in waited[dep_list]:
|
|
1159
1172
|
logger.warning("[{}] depends on [{}]".format(
|
|
1160
1173
|
dep_list, str(d)
|
|
1161
1174
|
))
|
|
1162
|
-
|
|
1163
|
-
#reverse_walkthrough(es_node, es_node, print_trace, processed_nodes, stashed_nodes)
|
|
1164
1175
|
logger.info("waited nodes")
|
|
1165
1176
|
for dep_list in waited:
|
|
1166
1177
|
if dep_list not in looped:
|
|
@@ -1177,7 +1188,6 @@ def check_stashed_loop(stashed_nodes, prev_stashed_nodes, processed_nodes, len_p
|
|
|
1177
1188
|
loop_count = 0
|
|
1178
1189
|
return loop_count
|
|
1179
1190
|
|
|
1180
|
-
|
|
1181
1191
|
def add_to_tree(tree, n, d):
|
|
1182
1192
|
n_str = str(n)
|
|
1183
1193
|
if n_str not in tree:
|
|
@@ -1187,12 +1197,16 @@ def add_to_tree(tree, n, d):
|
|
|
1187
1197
|
return tree
|
|
1188
1198
|
|
|
1189
1199
|
|
|
1190
|
-
def get_all_dependant(loop, stashed_nodes, processed_nodes, depth=0, waited=None , looped=None):
|
|
1200
|
+
def get_all_dependant(loop, stashed_nodes, processed_nodes, depth=0, waited=None , looped=None, path = None):
|
|
1201
|
+
if path is None:
|
|
1202
|
+
path =[]
|
|
1191
1203
|
if looped is None:
|
|
1192
1204
|
looped = {}
|
|
1193
1205
|
if waited is None:
|
|
1194
1206
|
waited = {}
|
|
1195
1207
|
for n in loop:
|
|
1208
|
+
cur_path = path.copy()
|
|
1209
|
+
cur_path.append(n)
|
|
1196
1210
|
dependant = OrderedSet()
|
|
1197
1211
|
i=0
|
|
1198
1212
|
#logger.critical(f"{i}: {n.__class__}::{n.get_name()}::{getattr(n,'instance','')}::{process_reference(n, processed_nodes, [])}")
|
|
@@ -1204,28 +1218,30 @@ def get_all_dependant(loop, stashed_nodes, processed_nodes, depth=0, waited=None
|
|
|
1204
1218
|
if not isinstance(dependant, list):
|
|
1205
1219
|
pass
|
|
1206
1220
|
for d in dependant:
|
|
1221
|
+
if d in path:
|
|
1222
|
+
logger.warning(f"loop {str(d)} already in path {'::'.join(map(path, str))} ")
|
|
1207
1223
|
if isinstance(d, TriccNodeSelectOption):
|
|
1208
1224
|
d = d.select
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
else :
|
|
1215
|
-
looped = add_to_tree(looped, n, d)
|
|
1216
|
-
|
|
1217
|
-
elif d not in processed_nodes:
|
|
1218
|
-
if d in stashed_nodes:
|
|
1219
|
-
looped = add_to_tree(looped, n, d)
|
|
1225
|
+
|
|
1226
|
+
if isinstance(d, TriccReference):
|
|
1227
|
+
if not any(n.name == d.value for n in processed_nodes):
|
|
1228
|
+
if not any(n.name == d.value for n in stashed_nodes):
|
|
1229
|
+
waited = add_to_tree(waited, n, d)
|
|
1220
1230
|
else :
|
|
1221
|
-
|
|
1231
|
+
looped = add_to_tree(looped, n, d)
|
|
1232
|
+
|
|
1233
|
+
elif d not in processed_nodes:
|
|
1234
|
+
if d in stashed_nodes:
|
|
1235
|
+
looped = add_to_tree(looped, n, d)
|
|
1236
|
+
else :
|
|
1237
|
+
waited = add_to_tree(waited, n, d)
|
|
1222
1238
|
if depth < MAX_DRILL:
|
|
1223
|
-
return get_all_dependant(
|
|
1239
|
+
return get_all_dependant(looped, stashed_nodes, processed_nodes, depth+1, waited , looped, path=cur_path)
|
|
1224
1240
|
|
|
1225
1241
|
return waited, looped
|
|
1226
1242
|
|
|
1227
1243
|
|
|
1228
|
-
MAX_DRILL =
|
|
1244
|
+
MAX_DRILL = 3
|
|
1229
1245
|
|
|
1230
1246
|
def get_last_end_node(processed_nodes, process=None):
|
|
1231
1247
|
end_name = 'tricc_end_'
|
|
@@ -1548,61 +1564,10 @@ def get_node_expression( in_node, processed_nodes, is_calculate=False, is_prev=F
|
|
|
1548
1564
|
if expression is None:
|
|
1549
1565
|
expression = get_prev_node_expression(node, processed_nodes=processed_nodes, is_calculate=is_calculate, process=process)
|
|
1550
1566
|
# in_node not in processed_nodes is need for calculates that can but run after the end of the activity
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
if node.base_instance is not None and not is_prev:
|
|
1557
|
-
activity = node
|
|
1558
|
-
expression_inputs = []
|
|
1559
|
-
past_instances = [
|
|
1560
|
-
n for n in processed_nodes if getattr(n.base_instance, 'id', None) == node.base_instance.id
|
|
1561
|
-
]
|
|
1562
|
-
for past_instance in past_instances:
|
|
1563
|
-
add_sub_expression(
|
|
1564
|
-
expression_inputs,
|
|
1565
|
-
get_node_expression(
|
|
1566
|
-
past_instance,
|
|
1567
|
-
processed_nodes=processed_nodes,
|
|
1568
|
-
is_calculate=False,
|
|
1569
|
-
is_prev=True,
|
|
1570
|
-
process=process
|
|
1571
|
-
)
|
|
1572
|
-
)
|
|
1573
|
-
|
|
1574
|
-
if isinstance(node.applicability,(TriccStatic,TriccOperation, TriccReference)):
|
|
1575
|
-
if expression:
|
|
1576
|
-
expression = and_join([node.applicability, expression])
|
|
1577
|
-
else:
|
|
1578
|
-
expression = node.applicability
|
|
1579
|
-
if expression and expression_inputs:
|
|
1580
|
-
add_sub_expression(expression_inputs, expression)
|
|
1581
|
-
expression = nand_join(expression, or_join(expression_inputs))
|
|
1582
|
-
elif expression_inputs:
|
|
1583
|
-
expression = negate_term(or_join(expression_inputs))
|
|
1584
|
-
if not is_prev:
|
|
1585
|
-
end_expressions = []
|
|
1586
|
-
f_end_expression = get_end_expression(processed_nodes)
|
|
1587
|
-
if f_end_expression:
|
|
1588
|
-
end_expressions.append(f_end_expression)
|
|
1589
|
-
if process[0] in PROCESSES:
|
|
1590
|
-
for p in PROCESSES[PROCESSES.index(process[0])+1:]:
|
|
1591
|
-
p_end_expression = get_end_expression(processed_nodes, p)
|
|
1592
|
-
if p_end_expression:
|
|
1593
|
-
end_expressions.append(p_end_expression)
|
|
1594
|
-
if node.applicability:
|
|
1595
|
-
end_expressions.append(node.applicability)
|
|
1596
|
-
if end_expressions:
|
|
1597
|
-
if expression:
|
|
1598
|
-
end_expressions.append(expression)
|
|
1599
|
-
if len(end_expressions) == 1:
|
|
1600
|
-
expression = end_expressions[0]
|
|
1601
|
-
else:
|
|
1602
|
-
expression = and_join(end_expressions)
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1567
|
+
#if isinstance(node, TriccNodeActivitiy) and not prev:
|
|
1568
|
+
# expression = get_applicability_expression(node, processed_nodes, process, expression)
|
|
1569
|
+
# expression = get_prev_instance_skip_expression(node, processed_nodes, process, expression)
|
|
1570
|
+
# expression = get_process_skip_expression(node, processed_nodes, process, expression)
|
|
1606
1571
|
if negate:
|
|
1607
1572
|
if negate_expression is not None:
|
|
1608
1573
|
return negate_expression
|
|
@@ -1613,7 +1578,67 @@ def get_node_expression( in_node, processed_nodes, is_calculate=False, is_prev=F
|
|
|
1613
1578
|
# exit(1)
|
|
1614
1579
|
else:
|
|
1615
1580
|
return expression
|
|
1581
|
+
|
|
1582
|
+
def get_applicability_expression(node, processed_nodes, process, expression=None):
|
|
1583
|
+
if isinstance(node.applicability,(TriccStatic,TriccOperation, TriccReference)):
|
|
1584
|
+
if expression:
|
|
1585
|
+
expression = and_join([node.applicability, expression])
|
|
1586
|
+
else:
|
|
1587
|
+
expression = node.applicability
|
|
1588
|
+
|
|
1589
|
+
return expression
|
|
1590
|
+
|
|
1591
|
+
|
|
1592
|
+
|
|
1593
|
+
|
|
1594
|
+
|
|
1595
|
+
def get_prev_instance_skip_expression(node, processed_nodes, process, expression=None):
|
|
1596
|
+
if node.base_instance is not None:
|
|
1597
|
+
activity = node
|
|
1598
|
+
expression_inputs = []
|
|
1599
|
+
past_instances = [
|
|
1600
|
+
n for n in processed_nodes if getattr(n.base_instance, 'id', None) == node.base_instance.id
|
|
1601
|
+
]
|
|
1602
|
+
for past_instance in past_instances:
|
|
1603
|
+
add_sub_expression(
|
|
1604
|
+
expression_inputs,
|
|
1605
|
+
get_node_expression(
|
|
1606
|
+
past_instance,
|
|
1607
|
+
processed_nodes=processed_nodes,
|
|
1608
|
+
is_calculate=False,
|
|
1609
|
+
is_prev=True,
|
|
1610
|
+
process=process
|
|
1611
|
+
)
|
|
1612
|
+
)
|
|
1613
|
+
if expression and expression_inputs:
|
|
1614
|
+
add_sub_expression(expression_inputs, expression)
|
|
1615
|
+
expression = nand_join(expression, or_join(expression_inputs))
|
|
1616
|
+
elif expression_inputs:
|
|
1617
|
+
expression = negate_term(or_join(expression_inputs))
|
|
1618
|
+
return expression
|
|
1616
1619
|
|
|
1620
|
+
|
|
1621
|
+
# end def
|
|
1622
|
+
def get_process_skip_expression(node, processed_nodes, process, expression=None):
|
|
1623
|
+
|
|
1624
|
+
end_expressions = []
|
|
1625
|
+
f_end_expression = get_end_expression(processed_nodes)
|
|
1626
|
+
if f_end_expression:
|
|
1627
|
+
end_expressions.append(f_end_expression)
|
|
1628
|
+
if process[0] in PROCESSES:
|
|
1629
|
+
for p in PROCESSES[PROCESSES.index(process[0])+1:]:
|
|
1630
|
+
p_end_expression = get_end_expression(processed_nodes, p)
|
|
1631
|
+
if p_end_expression:
|
|
1632
|
+
end_expressions.append(p_end_expression)
|
|
1633
|
+
if end_expressions:
|
|
1634
|
+
if expression:
|
|
1635
|
+
end_expressions.append(expression)
|
|
1636
|
+
if len(end_expressions) == 1:
|
|
1637
|
+
expression = end_expressions[0]
|
|
1638
|
+
else:
|
|
1639
|
+
expression = and_join(end_expressions)
|
|
1640
|
+
return expression
|
|
1641
|
+
|
|
1617
1642
|
def get_end_expression(processed_nodes, process=None):
|
|
1618
1643
|
end_node = get_last_end_node(processed_nodes, process)
|
|
1619
1644
|
if end_node:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tricc-oo
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.18
|
|
4
4
|
Summary: Python library that converts CDSS L2 in L3
|
|
5
5
|
Project-URL: Homepage, https://github.com/SwissTPH/tricc
|
|
6
6
|
Project-URL: Issues, https://github.com/SwissTPH/tricc/issues
|
|
@@ -14,6 +14,7 @@ Requires-Dist: markdownify
|
|
|
14
14
|
Requires-Dist: pydantic
|
|
15
15
|
Requires-Dist: babel
|
|
16
16
|
Requires-Dist: xlsxwriter
|
|
17
|
+
Requires-Dist: html2text
|
|
17
18
|
Requires-Dist: pandas
|
|
18
19
|
Requires-Dist: polib
|
|
19
20
|
Requires-Dist: strenum
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|