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.
Files changed (47) hide show
  1. tests/build.py +20 -28
  2. tests/test_build.py +260 -0
  3. tests/test_cql.py +48 -109
  4. tests/to_ocl.py +15 -17
  5. tricc_oo/__init__.py +0 -6
  6. tricc_oo/converters/codesystem_to_ocl.py +51 -40
  7. tricc_oo/converters/cql/cqlLexer.py +1 -0
  8. tricc_oo/converters/cql/cqlListener.py +1 -0
  9. tricc_oo/converters/cql/cqlParser.py +1 -0
  10. tricc_oo/converters/cql/cqlVisitor.py +1 -0
  11. tricc_oo/converters/cql_to_operation.py +129 -123
  12. tricc_oo/converters/datadictionnary.py +45 -54
  13. tricc_oo/converters/drawio_type_map.py +146 -65
  14. tricc_oo/converters/tricc_to_xls_form.py +58 -28
  15. tricc_oo/converters/utils.py +4 -4
  16. tricc_oo/converters/xml_to_tricc.py +296 -235
  17. tricc_oo/models/__init__.py +2 -1
  18. tricc_oo/models/base.py +333 -305
  19. tricc_oo/models/calculate.py +66 -51
  20. tricc_oo/models/lang.py +26 -27
  21. tricc_oo/models/ocl.py +146 -161
  22. tricc_oo/models/ordered_set.py +15 -19
  23. tricc_oo/models/tricc.py +149 -89
  24. tricc_oo/parsers/xml.py +15 -30
  25. tricc_oo/serializers/planuml.py +4 -6
  26. tricc_oo/serializers/xls_form.py +110 -153
  27. tricc_oo/strategies/input/base_input_strategy.py +28 -32
  28. tricc_oo/strategies/input/drawio.py +59 -71
  29. tricc_oo/strategies/output/base_output_strategy.py +151 -65
  30. tricc_oo/strategies/output/dhis2_form.py +908 -0
  31. tricc_oo/strategies/output/fhir_form.py +377 -0
  32. tricc_oo/strategies/output/html_form.py +224 -0
  33. tricc_oo/strategies/output/openmrs_form.py +694 -0
  34. tricc_oo/strategies/output/spice.py +106 -127
  35. tricc_oo/strategies/output/xls_form.py +322 -244
  36. tricc_oo/strategies/output/xlsform_cdss.py +627 -142
  37. tricc_oo/strategies/output/xlsform_cht.py +252 -125
  38. tricc_oo/strategies/output/xlsform_cht_hf.py +13 -24
  39. tricc_oo/visitors/tricc.py +1424 -1033
  40. tricc_oo/visitors/utils.py +16 -16
  41. tricc_oo/visitors/xform_pd.py +91 -89
  42. {tricc_oo-1.5.13.dist-info → tricc_oo-1.6.8.dist-info}/METADATA +128 -84
  43. tricc_oo-1.6.8.dist-info/RECORD +52 -0
  44. tricc_oo-1.6.8.dist-info/licenses/LICENSE +373 -0
  45. {tricc_oo-1.5.13.dist-info → tricc_oo-1.6.8.dist-info}/top_level.txt +0 -0
  46. tricc_oo-1.5.13.dist-info/RECORD +0 -46
  47. {tricc_oo-1.5.13.dist-info → tricc_oo-1.6.8.dist-info}/WHEEL +0 -0
@@ -1,84 +1,95 @@
1
-
1
+ from typing import List, Optional, Union
2
2
  import logging
3
- import random
4
- import string
5
- from enum import Enum, auto
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 pydantic import BaseModel, constr
9
- from strenum import StrEnum
10
- from .base import *
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
- applicability: Optional[Union[Expression, TriccOperation]] = None
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['hint']
28
- del data['help']
29
- del data['save']
28
+ del data["hint"]
29
+ del data["help"]
30
+ del data["save"]
30
31
  fake = TriccNodeFakeCalculateBase(**data)
31
- replace_node(self,fake)
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 = 'number'
49
+ datatype: str = "number"
46
50
 
47
51
 
48
52
  class TriccNodeCount(TriccNodeDisplayCalculateBase):
49
53
  tricc_type: TriccNodeType = TriccNodeType.count
50
- datatype: str = 'number'
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
- class TriccRhombusMixIn():
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(self.expression_reference, (str, TriccOperation)):
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[List[TriccNodeBaseModel], Expression, TriccOperation, TriccReference, List[TriccReference]]
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['name'] = get_rand_name(data.get('id', None))
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['reference'] = f'"final.{data["name"]}" is true'
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,'id',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 {activiy.get_name()}")
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('name', None) is None:
187
- data['name'] = 'tricc_end_' + data.get('process', '')
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 'tricc_end_' + (self.process or '')
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, 'instance'):
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, force_dict = False,trad=None):
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 == '' and (self.languages is None or trad is not None):
30
+ if message == "" and (self.languages is None or trad is not None):
31
31
  if force_dict:
32
- return {'default': ''}
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 = message))
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 {'default': message}
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+'::'+code] = col+'['+code+']'
60
-
61
- return map
59
+ map[col + "::" + code] = col + "[" + code + "]"
62
60
 
63
- def join_trads(trads_1, trads_2, separator= ' '):
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
- dict_3[key] = value + separator + trads_1[key]
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 = path)
72
-
71
+ self.po_file.save(fpath=path)