tricc-oo 1.5.13__py3-none-any.whl → 1.6.8__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.
- tests/build.py +20 -28
- tests/test_build.py +260 -0
- tests/test_cql.py +48 -109
- tests/to_ocl.py +15 -17
- tricc_oo/__init__.py +0 -6
- tricc_oo/converters/codesystem_to_ocl.py +51 -40
- tricc_oo/converters/cql/cqlLexer.py +1 -0
- tricc_oo/converters/cql/cqlListener.py +1 -0
- tricc_oo/converters/cql/cqlParser.py +1 -0
- tricc_oo/converters/cql/cqlVisitor.py +1 -0
- tricc_oo/converters/cql_to_operation.py +129 -123
- tricc_oo/converters/datadictionnary.py +45 -54
- tricc_oo/converters/drawio_type_map.py +146 -65
- tricc_oo/converters/tricc_to_xls_form.py +58 -28
- tricc_oo/converters/utils.py +4 -4
- tricc_oo/converters/xml_to_tricc.py +296 -235
- tricc_oo/models/__init__.py +2 -1
- tricc_oo/models/base.py +333 -305
- tricc_oo/models/calculate.py +66 -51
- tricc_oo/models/lang.py +26 -27
- tricc_oo/models/ocl.py +146 -161
- tricc_oo/models/ordered_set.py +15 -19
- tricc_oo/models/tricc.py +149 -89
- tricc_oo/parsers/xml.py +15 -30
- tricc_oo/serializers/planuml.py +4 -6
- tricc_oo/serializers/xls_form.py +110 -153
- tricc_oo/strategies/input/base_input_strategy.py +28 -32
- tricc_oo/strategies/input/drawio.py +59 -71
- tricc_oo/strategies/output/base_output_strategy.py +151 -65
- tricc_oo/strategies/output/dhis2_form.py +908 -0
- tricc_oo/strategies/output/fhir_form.py +377 -0
- tricc_oo/strategies/output/html_form.py +224 -0
- tricc_oo/strategies/output/openmrs_form.py +694 -0
- tricc_oo/strategies/output/spice.py +106 -127
- tricc_oo/strategies/output/xls_form.py +322 -244
- tricc_oo/strategies/output/xlsform_cdss.py +627 -142
- tricc_oo/strategies/output/xlsform_cht.py +252 -125
- tricc_oo/strategies/output/xlsform_cht_hf.py +13 -24
- tricc_oo/visitors/tricc.py +1424 -1033
- tricc_oo/visitors/utils.py +16 -16
- tricc_oo/visitors/xform_pd.py +91 -89
- {tricc_oo-1.5.13.dist-info → tricc_oo-1.6.8.dist-info}/METADATA +128 -84
- tricc_oo-1.6.8.dist-info/RECORD +52 -0
- tricc_oo-1.6.8.dist-info/licenses/LICENSE +373 -0
- {tricc_oo-1.5.13.dist-info → tricc_oo-1.6.8.dist-info}/top_level.txt +0 -0
- tricc_oo-1.5.13.dist-info/RECORD +0 -46
- {tricc_oo-1.5.13.dist-info → tricc_oo-1.6.8.dist-info}/WHEEL +0 -0
tricc_oo/models/calculate.py
CHANGED
|
@@ -1,84 +1,95 @@
|
|
|
1
|
-
|
|
1
|
+
from typing import List, Optional, Union
|
|
2
2
|
import logging
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
from typing import Dict, ForwardRef, List, Optional, Union
|
|
3
|
+
from tricc_oo.models.base import (
|
|
4
|
+
TriccBaseModel, TriccOperation, TriccStatic, TriccReference, Expression, TriccNodeType
|
|
5
|
+
)
|
|
7
6
|
|
|
8
|
-
from
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
from .tricc import *
|
|
12
|
-
from tricc_oo.converters.utils import generate_id, get_rand_name
|
|
7
|
+
from tricc_oo.models.tricc import (
|
|
8
|
+
TriccNodeCalculateBase, TriccNodeBaseModel,
|
|
9
|
+
)
|
|
13
10
|
|
|
11
|
+
from tricc_oo.converters.utils import get_rand_name
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
16
14
|
|
|
15
|
+
ACTIVITY_END_NODE_FORMAT = "aend_{}"
|
|
17
16
|
|
|
18
17
|
|
|
19
18
|
class TriccNodeDisplayCalculateBase(TriccNodeCalculateBase):
|
|
20
19
|
save: Optional[str] = None # contribute to another calculate
|
|
21
20
|
hint: Optional[str] = None # for diagnostic display
|
|
22
21
|
help: Optional[str] = None # for diagnostic display
|
|
23
|
-
|
|
22
|
+
trigger: Optional[Union[Expression, TriccOperation, TriccReference]] = None
|
|
23
|
+
applicability: Optional[Union[Expression, TriccOperation, TriccReference]] = None
|
|
24
|
+
|
|
24
25
|
# no need to copy save
|
|
25
26
|
def to_fake(self):
|
|
26
27
|
data = vars(self)
|
|
27
|
-
del data[
|
|
28
|
-
del data[
|
|
29
|
-
del data[
|
|
28
|
+
del data["hint"]
|
|
29
|
+
del data["help"]
|
|
30
|
+
del data["save"]
|
|
30
31
|
fake = TriccNodeFakeCalculateBase(**data)
|
|
31
|
-
replace_node(
|
|
32
|
+
self.replace_node(fake)
|
|
32
33
|
return fake
|
|
34
|
+
|
|
33
35
|
def __str__(self):
|
|
34
36
|
return self.get_name()
|
|
35
37
|
|
|
36
38
|
def __repr__(self):
|
|
37
39
|
return self.get_name()
|
|
38
|
-
|
|
40
|
+
|
|
41
|
+
|
|
39
42
|
class TriccNodeCalculate(TriccNodeDisplayCalculateBase):
|
|
40
43
|
tricc_type: TriccNodeType = TriccNodeType.calculate
|
|
44
|
+
remote_reference: Optional[Union[Expression, TriccOperation, TriccReference]] = None
|
|
41
45
|
|
|
42
46
|
|
|
43
47
|
class TriccNodeAdd(TriccNodeDisplayCalculateBase):
|
|
44
48
|
tricc_type: TriccNodeType = TriccNodeType.add
|
|
45
|
-
datatype: str =
|
|
49
|
+
datatype: str = "number"
|
|
46
50
|
|
|
47
51
|
|
|
48
52
|
class TriccNodeCount(TriccNodeDisplayCalculateBase):
|
|
49
53
|
tricc_type: TriccNodeType = TriccNodeType.count
|
|
50
|
-
datatype: str =
|
|
54
|
+
datatype: str = "number"
|
|
51
55
|
|
|
52
56
|
|
|
53
57
|
class TriccNodeProposedDiagnosis(TriccNodeDisplayCalculateBase):
|
|
54
58
|
tricc_type: TriccNodeType = TriccNodeType.proposed_diagnosis
|
|
55
59
|
severity: str = None
|
|
56
|
-
|
|
57
|
-
|
|
60
|
+
remote_reference: Optional[Union[Expression, TriccOperation, TriccReference]] = None
|
|
61
|
+
|
|
62
|
+
|
|
58
63
|
class TriccNodeFakeCalculateBase(TriccNodeCalculateBase):
|
|
59
64
|
...
|
|
60
65
|
|
|
66
|
+
|
|
61
67
|
class TriccNodeInput(TriccNodeFakeCalculateBase):
|
|
62
68
|
tricc_type: TriccNodeType = TriccNodeType.input
|
|
63
|
-
|
|
69
|
+
|
|
70
|
+
|
|
64
71
|
class TriccNodeDisplayBridge(TriccNodeDisplayCalculateBase):
|
|
65
72
|
tricc_type: TriccNodeType = TriccNodeType.bridge
|
|
66
|
-
|
|
73
|
+
|
|
67
74
|
|
|
68
75
|
class TriccNodeBridge(TriccNodeFakeCalculateBase):
|
|
69
76
|
tricc_type: TriccNodeType = TriccNodeType.bridge
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class TriccRhombusMixIn:
|
|
80
|
+
|
|
73
81
|
def make_mixin_instance(self, instance, instance_nb, activity, **kwargs):
|
|
74
82
|
# shallow copy
|
|
75
83
|
reference = []
|
|
76
84
|
expression_reference = None
|
|
77
85
|
instance.path = None
|
|
78
|
-
if isinstance(
|
|
86
|
+
if isinstance(
|
|
87
|
+
self.expression_reference,
|
|
88
|
+
(str, TriccOperation, TriccReference, TriccStatic),
|
|
89
|
+
):
|
|
79
90
|
expression_reference = self.expression_reference.copy()
|
|
80
91
|
reference = list(expression_reference.get_references())
|
|
81
|
-
if isinstance(self.reference, (str, TriccOperation)):
|
|
92
|
+
if isinstance(self.reference, (str, TriccOperation, TriccReference, TriccStatic)):
|
|
82
93
|
expression_reference = self.reference.copy()
|
|
83
94
|
reference = list(expression_reference.get_references())
|
|
84
95
|
elif isinstance(self.reference, list):
|
|
@@ -107,42 +118,46 @@ class TriccRhombusMixIn():
|
|
|
107
118
|
return instance
|
|
108
119
|
|
|
109
120
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
class TriccNodeRhombus(TriccNodeCalculateBase,TriccRhombusMixIn):
|
|
121
|
+
class TriccNodeRhombus(TriccNodeCalculateBase, TriccRhombusMixIn):
|
|
113
122
|
tricc_type: TriccNodeType = TriccNodeType.rhombus
|
|
114
123
|
path: Optional[TriccNodeBaseModel] = None
|
|
115
|
-
reference: Union[
|
|
116
|
-
|
|
124
|
+
reference: Union[
|
|
125
|
+
List[TriccNodeBaseModel],
|
|
126
|
+
Expression,
|
|
127
|
+
TriccOperation,
|
|
128
|
+
TriccReference,
|
|
129
|
+
List[TriccReference],
|
|
130
|
+
]
|
|
131
|
+
remote_reference: Optional[Union[Expression, TriccOperation, TriccReference]] = None
|
|
132
|
+
|
|
117
133
|
def make_instance(self, instance_nb, activity, **kwargs):
|
|
118
134
|
instance = super(TriccNodeRhombus, self).make_instance(instance_nb, activity, **kwargs)
|
|
119
135
|
instance = self.make_mixin_instance(instance, instance_nb, activity, **kwargs)
|
|
120
136
|
return instance
|
|
121
137
|
|
|
122
|
-
|
|
123
138
|
def __init__(self, **data):
|
|
124
|
-
data[
|
|
139
|
+
data["name"] = get_rand_name(data.get("id", None))
|
|
125
140
|
super().__init__(**data)
|
|
126
141
|
|
|
127
142
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
143
|
class TriccNodeDiagnosis(TriccNodeDisplayCalculateBase):
|
|
132
144
|
tricc_type: TriccNodeType = TriccNodeType.diagnosis
|
|
133
145
|
severity: str = None
|
|
146
|
+
|
|
134
147
|
def __init__(self, **data):
|
|
135
|
-
data[
|
|
148
|
+
data["reference"] = f'"final.{data["name"]}" is true'
|
|
136
149
|
super().__init__(**data)
|
|
137
150
|
|
|
138
151
|
# rename rhombus
|
|
139
152
|
self.name = get_rand_name(f"d{data.get('id', None)}")
|
|
140
153
|
|
|
154
|
+
|
|
141
155
|
class TriccNodeExclusive(TriccNodeFakeCalculateBase):
|
|
142
156
|
tricc_type: TriccNodeType = TriccNodeType.exclusive
|
|
143
157
|
|
|
158
|
+
|
|
144
159
|
def get_node_from_id(activity, node, edge_only):
|
|
145
|
-
node_id = getattr(node,
|
|
160
|
+
node_id = getattr(node, "id", node)
|
|
146
161
|
if not isinstance(node_id, str):
|
|
147
162
|
logger.critical("can set prev_next only with string or node")
|
|
148
163
|
exit(1)
|
|
@@ -151,15 +166,16 @@ def get_node_from_id(activity, node, edge_only):
|
|
|
151
166
|
elif node_id in activity.nodes:
|
|
152
167
|
node = activity.nodes[node_id]
|
|
153
168
|
elif not edge_only:
|
|
154
|
-
logger.critical(f"cannot find {node_id} in {
|
|
169
|
+
logger.critical(f"cannot find {node_id} in {activity.get_name()}")
|
|
155
170
|
exit(1)
|
|
156
171
|
return node_id, node
|
|
157
172
|
|
|
173
|
+
|
|
158
174
|
class TriccNodeWait(TriccNodeFakeCalculateBase, TriccRhombusMixIn):
|
|
159
175
|
tricc_type: TriccNodeType = TriccNodeType.wait
|
|
160
176
|
path: Optional[TriccNodeBaseModel] = None
|
|
161
177
|
reference: Union[List[TriccNodeBaseModel], Expression, TriccOperation]
|
|
162
|
-
|
|
178
|
+
|
|
163
179
|
def make_instance(self, instance_nb, activity, **kwargs):
|
|
164
180
|
instance = super(TriccNodeWait, self).make_instance(instance_nb, activity, **kwargs)
|
|
165
181
|
instance = self.make_mixin_instance(instance, instance_nb, activity, **kwargs)
|
|
@@ -182,21 +198,21 @@ class TriccNodeEnd(TriccNodeDisplayCalculateBase):
|
|
|
182
198
|
tricc_type: TriccNodeType = TriccNodeType.end
|
|
183
199
|
process: str = None
|
|
184
200
|
priority: int = 1000
|
|
201
|
+
|
|
185
202
|
def __init__(self, **data):
|
|
186
|
-
if data.get(
|
|
187
|
-
data[
|
|
203
|
+
if data.get("name", None) is None:
|
|
204
|
+
data["name"] = "tricc_end_" + data.get("process", "")
|
|
188
205
|
super().__init__(**data)
|
|
189
206
|
# FOR END
|
|
190
|
-
|
|
191
|
-
|
|
192
207
|
|
|
193
208
|
def set_name(self):
|
|
194
209
|
if self.name is None:
|
|
195
210
|
self.name = self.get_reference()
|
|
196
|
-
#self.name = END_NODE_FORMAT.format(self.activity.id)
|
|
211
|
+
# self.name = END_NODE_FORMAT.format(self.activity.id)
|
|
197
212
|
|
|
198
213
|
def get_reference(self):
|
|
199
|
-
return
|
|
214
|
+
return "tricc_end_" + (self.process or "")
|
|
215
|
+
|
|
200
216
|
|
|
201
217
|
class TriccNodeActivityStart(TriccNodeFakeCalculateBase):
|
|
202
218
|
tricc_type: TriccNodeType = TriccNodeType.activity_start
|
|
@@ -208,11 +224,10 @@ def get_node_from_list(in_nodes, node_id):
|
|
|
208
224
|
if len(nodes) > 0:
|
|
209
225
|
return nodes[0]
|
|
210
226
|
|
|
227
|
+
|
|
211
228
|
# qualculate that saves quantity, or we may merge integer/decimals
|
|
212
229
|
class TriccNodeQuantity(TriccNodeDisplayCalculateBase):
|
|
213
230
|
tricc_type: TriccNodeType = TriccNodeType.quantity
|
|
214
231
|
|
|
215
232
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
TriccNodeCalculate.update_forward_refs()
|
|
233
|
+
TriccNodeCalculate.update_forward_refs()
|
tricc_oo/models/lang.py
CHANGED
|
@@ -5,21 +5,21 @@ class SingletonLangClass(object):
|
|
|
5
5
|
languages = None
|
|
6
6
|
entries = []
|
|
7
7
|
po_file = None
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
def __init__(self):
|
|
10
10
|
self.po_file = POFile()
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
def __new__(self):
|
|
13
|
-
if not hasattr(self,
|
|
13
|
+
if not hasattr(self, "instance"):
|
|
14
14
|
self.instance = super(SingletonLangClass, self).__new__(self)
|
|
15
15
|
return self.instance
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
def add_trad(self, code, lang):
|
|
18
18
|
if self.languages is None:
|
|
19
19
|
self.languages = {}
|
|
20
20
|
self.languages[code] = lang
|
|
21
|
-
|
|
22
|
-
def get_trads(self, message,
|
|
21
|
+
|
|
22
|
+
def get_trads(self, message, force_dict=False, trad=None):
|
|
23
23
|
if isinstance(message, dict):
|
|
24
24
|
if force_dict:
|
|
25
25
|
return message
|
|
@@ -27,46 +27,45 @@ class SingletonLangClass(object):
|
|
|
27
27
|
return message[trad]
|
|
28
28
|
return list(message.values())[0]
|
|
29
29
|
message = message.strip()
|
|
30
|
-
if message ==
|
|
30
|
+
if message == "" and (self.languages is None or trad is not None):
|
|
31
31
|
if force_dict:
|
|
32
|
-
return {
|
|
33
|
-
else
|
|
34
|
-
return
|
|
35
|
-
|
|
32
|
+
return {"default": ""}
|
|
33
|
+
else:
|
|
34
|
+
return ""
|
|
35
|
+
|
|
36
36
|
if message not in self.entries:
|
|
37
|
-
self.po_file.insert(0,POEntry(msgid
|
|
37
|
+
self.po_file.insert(0, POEntry(msgid=message))
|
|
38
38
|
self.entries.append(message)
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
if self.languages is None or len(self.languages) == 0:
|
|
41
41
|
if force_dict:
|
|
42
|
-
return {
|
|
43
|
-
else
|
|
42
|
+
return {"default": message}
|
|
43
|
+
else:
|
|
44
44
|
return message
|
|
45
45
|
elif trad is not None:
|
|
46
|
-
return self.languages[trad].gettext(message) if len(message)>0 else
|
|
46
|
+
return self.languages[trad].gettext(message) if len(message) > 0 else ""
|
|
47
47
|
else:
|
|
48
48
|
trads = {}
|
|
49
49
|
for code, lang in self.languages.items():
|
|
50
|
-
trads[code]= lang.gettext(message) if len(message)>0 else
|
|
50
|
+
trads[code] = lang.gettext(message) if len(message) > 0 else ""
|
|
51
51
|
return trads
|
|
52
52
|
|
|
53
53
|
def get_trads_map(self, col):
|
|
54
54
|
if self.languages is None:
|
|
55
|
-
return {col:col}
|
|
55
|
+
return {col: col}
|
|
56
56
|
else:
|
|
57
57
|
map = {}
|
|
58
58
|
for code, lang in self.languages.items():
|
|
59
|
-
map[col+
|
|
60
|
-
|
|
61
|
-
return map
|
|
59
|
+
map[col + "::" + code] = col + "[" + code + "]"
|
|
62
60
|
|
|
63
|
-
|
|
61
|
+
return map
|
|
62
|
+
|
|
63
|
+
def join_trads(trads_1, trads_2, separator=" "):
|
|
64
64
|
dict_3 = {**trads_1, **trads_1}
|
|
65
65
|
for key, value in dict_3.items():
|
|
66
66
|
if key in trads_1 and key in trads_2:
|
|
67
|
-
|
|
68
|
-
return dict_3
|
|
69
|
-
|
|
67
|
+
dict_3[key] = value + separator + trads_1[key]
|
|
68
|
+
return dict_3
|
|
69
|
+
|
|
70
70
|
def to_po_file(self, path):
|
|
71
|
-
self.po_file.save(fpath
|
|
72
|
-
|
|
71
|
+
self.po_file.save(fpath=path)
|