tricc-oo 1.6.11__py3-none-any.whl → 1.6.12__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.
@@ -64,36 +64,7 @@ def start_group(
64
64
  groups[name] = 0
65
65
  relevance = relevance and cur_group.relevance is not None and cur_group.relevance != ""
66
66
  past_instances = len(getattr(cur_group.base_instance, "instances", []))
67
- group_calc_required = relevance is not None and (len(str(relevance)) > 100 or past_instances > 1)
68
67
  calc = None
69
- if group_calc_required and getattr(cur_group.relevance, 'operator', None) != TriccOperator.ISTRUE:
70
-
71
- calc = TriccNodeCalculate(
72
- id=generate_id(get_export_group_name(name)),
73
- group=cur_group.group,
74
- activity=cur_group.activity,
75
- name=get_export_group_name(name),
76
- expression=cur_group.relevance.copy()
77
- )
78
-
79
- if calc not in cur_group.activity.calculates:
80
- process_reference(
81
- calc,
82
- processed_nodes,
83
- calculates=kwargs.get('calculates', None),
84
- used_calculates=kwargs.get('used_calculates', None),
85
- replace_reference=True,
86
- warn=False,
87
- codesystems=kwargs.get('codesystems', None)
88
- )
89
- cur_group.activity.calculates.append(calc)
90
- cur_group.activity.nodes[calc.id] = calc
91
- processed_nodes.add(calc)
92
-
93
- cur_group.relevance = TriccOperation(
94
- TriccOperator.ISTRUE,
95
- [calc]
96
- )
97
68
 
98
69
  relevance_expression = cur_group.relevance
99
70
  relevance_expression = get_applicability_expression(cur_group, processed_nodes, process, relevance_expression)
@@ -124,23 +95,7 @@ def start_group(
124
95
  values.append(get_xfrom_trad(strategy, cur_group, column, SURVEY_MAP))
125
96
  df_survey.loc[len(df_survey)] = values
126
97
 
127
- # calc
128
- if calc and len(df_calculate[df_calculate["name"] == get_export_group_name(name)]) == 0:
129
- calc_values = []
130
- for column in SURVEY_MAP:
131
- if column == "type":
132
- calc_values.append("calculate")
133
- elif column == "name":
134
- value = get_export_name(calc)
135
- calc_values.append(value)
136
- elif column == "calculation":
137
- calc_values.append(f"number({strategy.get_tricc_operation_expression(calc.expression)})")
138
- elif column == "relevance":
139
- calc_values.append("")
140
- else:
141
- calc_values.append(get_xfrom_trad(strategy, cur_group, column, SURVEY_MAP))
142
-
143
- df_calculate.loc[len(df_calculate)] = calc_values
98
+ # Group calculates are now created during process_calculate phase
144
99
 
145
100
 
146
101
  # def add_background_color(input_string, color):
@@ -821,34 +821,22 @@ class XLSFormCHTStrategy(XLSFormCDSSStrategy):
821
821
  return jar_path
822
822
 
823
823
  def _ensure_odk_validate_jar(self):
824
- """Ensure ODK Validate JAR is available by extracting from medic zip."""
824
+ """Ensure ODK Validate JAR is available by downloading from GitHub releases."""
825
825
  jar_path = os.path.join(os.path.dirname(__file__), "ODK_Validate.jar")
826
826
 
827
827
  # Check if JAR already exists
828
828
  if os.path.exists(jar_path):
829
829
  return jar_path
830
830
 
831
- # Extract JAR from medic zip
832
- medic_zip_path = os.path.join(os.path.dirname(__file__), "xls2xform-medic")
833
- if not os.path.exists(medic_zip_path):
834
- logger.error("xls2xform-medic zip not found, cannot extract ODK Validate JAR")
835
- return None
836
-
831
+ # Download JAR from GitHub releases
832
+ jar_url = "https://github.com/getodk/validate/releases/download/v1.19.2/validate.jar"
837
833
  try:
838
- with zipfile.ZipFile(medic_zip_path, 'r') as zip_ref:
839
- # Extract the JAR from the zip
840
- jar_in_zip = "site-packages/pyxform/validators/odk_validate/bin/ODK_Validate.jar"
841
- zip_ref.extract(jar_in_zip, os.path.dirname(__file__))
842
-
843
- # Move to final location
844
- extracted_jar = os.path.join(os.path.dirname(__file__), jar_in_zip)
845
- shutil.move(extracted_jar, jar_path)
846
-
847
- logger.info(f"Extracted ODK Validate JAR to {jar_path}")
834
+ import urllib.request
835
+ urllib.request.urlretrieve(jar_url, jar_path)
836
+ logger.info(f"Downloaded ODK Validate JAR to {jar_path}")
848
837
  return jar_path
849
-
850
838
  except Exception as e:
851
- logger.error(f"Failed to extract ODK Validate JAR: {str(e)}")
839
+ logger.error(f"Failed to download ODK Validate JAR: {str(e)}")
852
840
  return None
853
841
 
854
842
  def tricc_operation_zscore(self, ref_expressions):
@@ -57,6 +57,16 @@ logger = logging.getLogger("default")
57
57
  ONE_QUESTION_AT_A_TIME = False
58
58
 
59
59
 
60
+ def get_main_activity(activity, processed_nodes):
61
+ """Traverse up the activity hierarchy to find the main activity (root activity)."""
62
+ activities = list(set(
63
+ n.activity for n in activity.relevance.get_references()
64
+ if hasattr(n, 'activity') and n.activity != activity and n.activity.root in processed_nodes
65
+ ))
66
+ if activities:
67
+ return activities[0]
68
+
69
+
60
70
  def merge_node(from_node, to_node):
61
71
  if from_node.activity != to_node.activity:
62
72
  logger.critical("Cannot merge nodes from different activities")
@@ -123,7 +133,7 @@ def get_last_version(name, processed_nodes, _list=None):
123
133
  def get_node_expressions(node, processed_nodes, process=None):
124
134
  get_overall_exp = issubclass(
125
135
  node.__class__,
126
- (TriccNodeDisplayCalculateBase, TriccNodeProposedDiagnosis, TriccNodeDiagnosis)
136
+ (TriccNodeDisplayCalculateBase, TriccNodeProposedDiagnosis, TriccNodeDiagnosis, TriccNodeActivity)
127
137
  ) and not isinstance(node, (TriccNodeDisplayBridge))
128
138
  expression = None
129
139
  # in case of recursive call processed_nodes will be None
@@ -245,7 +255,29 @@ def load_calculate(
245
255
  if hasattr(node, "relevance") and (node.relevance is None or isinstance(node.relevance, TriccOperation)):
246
256
  node.relevance = get_node_expressions(node, processed_nodes=processed_nodes, process=process)
247
257
  # manage not Available
248
- if isinstance(node, TriccNodeSelectNotAvailable):
258
+ if isinstance(node, TriccNodeActivity) and isinstance(node.root, TriccNodeActivityStart):
259
+ past_instances = len(getattr(node.base_instance, "instances", []))
260
+ group_calc_required = False # (len(str(node.relevance)) > 50 or past_instances > 1 or len(node.calculates)>0)
261
+ calc = None
262
+
263
+ if group_calc_required and getattr(node.relevance, 'operator', None) != TriccOperator.ISTRUE:
264
+ main_activity = get_main_activity(node, processed_nodes)
265
+ if main_activity:
266
+ calc = TriccNodeCalculate(
267
+ id=generate_id(f"gc.{node.id}"),
268
+ group=main_activity.group,
269
+ activity=main_activity,
270
+ name=f"gc.{node.name}",
271
+ expression_reference=node.relevance.copy()
272
+ )
273
+ main_activity.calculates.append(calc)
274
+ main_activity.nodes[calc.id] = calc
275
+ processed_nodes.add(calc)
276
+ node.relevance = TriccOperation(
277
+ TriccOperator.ISTRUE,
278
+ [calc]
279
+ )
280
+ elif isinstance(node, TriccNodeSelectNotAvailable):
249
281
  # update the checkbox
250
282
  if node.parent:
251
283
  if len(node.prev_nodes) == 1:
@@ -1735,14 +1767,14 @@ def replace_next_node(prev_node, next_node, old_node):
1735
1767
 
1736
1768
 
1737
1769
  # Priority constants
1738
- SAME_GROUP_PRIORITY = 7000
1739
- PARENT_GROUP_PRIORITY = 6000
1740
- ACTIVE_ACTIVITY_PRIORITY = 5000
1741
- NON_START_ACTIVITY_PRIORITY = 4000
1742
- ACTIVE_ACTIVITY_LOWER_PRIORITY = 3000
1743
- FLOW_CALCULATE_NODE_PRIORITY = 6500
1770
+ SAME_GROUP_PRIORITY = 4000
1771
+ PARENT_GROUP_PRIORITY = 3000
1772
+ ACTIVE_ACTIVITY_PRIORITY = 1400
1773
+ NON_START_ACTIVITY_PRIORITY = 1300
1774
+ ACTIVE_ACTIVITY_LOWER_PRIORITY = 1200
1775
+ FLOW_CALCULATE_NODE_PRIORITY = 2000
1744
1776
  RHOMBUS_PRIORITY = 1000
1745
- DEFAULT_PRIORITY = 2000
1777
+ DEFAULT_PRIORITY = 1100
1746
1778
 
1747
1779
 
1748
1780
  def reorder_node_list(node_list, group, processed_nodes):
@@ -1780,6 +1812,8 @@ def reorder_node_list(node_list, group, processed_nodes):
1780
1812
  priority += RHOMBUS_PRIORITY
1781
1813
  else:
1782
1814
  priority += DEFAULT_PRIORITY
1815
+
1816
+ priority = max(priority, max((get_priority(prev_node) for prev_node in node.prev_nodes), default=0))
1783
1817
 
1784
1818
  return priority
1785
1819
 
@@ -1829,6 +1863,7 @@ def get_node_expression(in_node, processed_nodes, get_overall_exp=False, is_prev
1829
1863
  expression = None
1830
1864
  negate_expression = None
1831
1865
  node = in_node
1866
+
1832
1867
  if isinstance(node, (TriccNodeActivityStart, TriccNodeMainStart)):
1833
1868
  if is_prev and get_overall_exp:
1834
1869
  expression = get_node_expression(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tricc-oo
3
- Version: 1.6.11
3
+ Version: 1.6.12
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
@@ -26,7 +26,7 @@ tricc_oo/parsers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,
26
26
  tricc_oo/parsers/xml.py,sha256=uzkb1y18MHfqVFmZqVh0sKT4cx6u0-NcAT_lV_gHBt8,4208
27
27
  tricc_oo/serializers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
28
  tricc_oo/serializers/planuml.py,sha256=t57587-6L3aDncpHh58lS77Zft8yxDE9DPtXx2BeUSU,132
29
- tricc_oo/serializers/xls_form.py,sha256=rIlTIccdIDQQv0dECcB8c9hDg5sMJShmUYsNTlSoZXg,22575
29
+ tricc_oo/serializers/xls_form.py,sha256=-nT5pQG6mKIT_iJWUUjtfn8GzeGzQCR61zlTvxRmoLE,20723
30
30
  tricc_oo/strategies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
31
  tricc_oo/strategies/input/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
32
  tricc_oo/strategies/input/base_input_strategy.py,sha256=BEODXS74na1QRRcJVQ4cxiD8F7uRqaLyhE3QzKpGVvk,3891
@@ -39,14 +39,14 @@ tricc_oo/strategies/output/openmrs_form.py,sha256=ne6TwAyhafR-WDs27QTKKFl85VD5si
39
39
  tricc_oo/strategies/output/spice.py,sha256=QMeoismVC3PdbvwTK0PtUjWX9jl9780fbQIXn76fMXw,10761
40
40
  tricc_oo/strategies/output/xls_form.py,sha256=_pNTND7n-55EjRphJ1hSVtRYa-UkXlmwpam2OKQ8o_w,30860
41
41
  tricc_oo/strategies/output/xlsform_cdss.py,sha256=X00Lt5MzV8TX14dR4dFI1MqllI5S1e13bKbeysWM9uA,17435
42
- tricc_oo/strategies/output/xlsform_cht.py,sha256=RXacGiVAib5bF_0ea564YhuJ1ASs20MuMuIeZXiP5-M,29019
42
+ tricc_oo/strategies/output/xlsform_cht.py,sha256=gztZBUJj4LdIX1jRvrG3hnLa7qpp0IZP_GpBi7bEzvc,28511
43
43
  tricc_oo/strategies/output/xlsform_cht_hf.py,sha256=xm6SKirV3nMZvM2w54_zJcXAeAgAkq-EEqGEjnOWv6c,988
44
44
  tricc_oo/visitors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
- tricc_oo/visitors/tricc.py,sha256=9jAVSxFfklJcLzwLvZAV1_sRuD8616HSgOSl8wdqPTE,110227
45
+ tricc_oo/visitors/tricc.py,sha256=PpEjW4qXbtjfvvLz4iFw4Nj0Khzida1WSBh8_ZjF9sA,112142
46
46
  tricc_oo/visitors/utils.py,sha256=j83aAq5s5atXi3OC0jc_uJd54a8XrHHmizeeEbWZQJg,421
47
47
  tricc_oo/visitors/xform_pd.py,sha256=ryAnI3V9x3eTmJ2LNsUZfvl0_yfCqo6oBgeSu-WPqaE,9613
48
- tricc_oo-1.6.11.dist-info/licenses/LICENSE,sha256=Pz2eACSxkhsGfW9_iN60pgy-enjnbGTj8df8O3ebnQQ,16726
49
- tricc_oo-1.6.11.dist-info/METADATA,sha256=VG-L_K4eTy4Fta8iaXuymORn6v9PCLSHH2E3qD9yk24,8600
50
- tricc_oo-1.6.11.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
51
- tricc_oo-1.6.11.dist-info/top_level.txt,sha256=NvbfMNAiy9m4b1unBsqpeOQWh4IgA1Xa33BtKA4abxk,15
52
- tricc_oo-1.6.11.dist-info/RECORD,,
48
+ tricc_oo-1.6.12.dist-info/licenses/LICENSE,sha256=Pz2eACSxkhsGfW9_iN60pgy-enjnbGTj8df8O3ebnQQ,16726
49
+ tricc_oo-1.6.12.dist-info/METADATA,sha256=Ifx_BtNteuGhT5iysOEJdF-0NXpFWuOGuiA_KRAt6YE,8600
50
+ tricc_oo-1.6.12.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
51
+ tricc_oo-1.6.12.dist-info/top_level.txt,sha256=NvbfMNAiy9m4b1unBsqpeOQWh4IgA1Xa33BtKA4abxk,15
52
+ tricc_oo-1.6.12.dist-info/RECORD,,