tricc-oo 1.6.9__py3-none-any.whl → 1.6.10__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.
@@ -36,7 +36,7 @@ def get_export_name(node, replace_dots=True):
36
36
  elif isinstance(node, bool):
37
37
  return BOOLEAN_MAP[str(TRICC_TRUE_VALUE)] if node else BOOLEAN_MAP[str(TRICC_FALSE_VALUE)]
38
38
  elif isinstance(node, TriccReference):
39
- logger.warning(f"Reference {node.value} use in export, bad serialiuation probable")
39
+ logger.warning(f"Reference {node.value} use in export, bad serialization probable")
40
40
  return str(node.value)
41
41
  elif isinstance(node, (str, TriccStatic, TriccNodeSelectOption)):
42
42
  if isinstance(node, TriccNodeSelectOption):
@@ -64,19 +64,30 @@ 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)
67
+ group_calc_required = False and relevance is not None and (len(str(relevance)) > 100 or past_instances > 1)
68
68
  calc = None
69
69
  if group_calc_required and getattr(cur_group.relevance, 'operator', None) != TriccOperator.ISTRUE:
70
70
 
71
71
  calc = TriccNodeCalculate(
72
72
  id=generate_id(get_export_group_name(name)),
73
- group=cur_group,
73
+ group=cur_group.group,
74
74
  activity=cur_group.activity,
75
75
  name=get_export_group_name(name),
76
- expression=cur_group.relevance
76
+ expression=cur_group.relevance.copy()
77
77
  )
78
- if calc not in cur_group.calculates:
79
- cur_group.calculates.append(calc)
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
80
91
  processed_nodes.add(calc)
81
92
 
82
93
  cur_group.relevance = TriccOperation(
@@ -123,7 +134,7 @@ def start_group(
123
134
  value = get_export_name(calc)
124
135
  calc_values.append(value)
125
136
  elif column == "calculation":
126
- calc_values.append(f"number({strategy.get_tricc_operation_expression(calc.expression)}")
137
+ calc_values.append(f"number({strategy.get_tricc_operation_expression(calc.expression)})")
127
138
  elif column == "relevance":
128
139
  calc_values.append("")
129
140
  else:
@@ -216,7 +216,7 @@ class DHIS2Strategy(BaseOutPutStrategy):
216
216
  if hasattr(node, 'expression') and node.expression:
217
217
  relevance = node.expression
218
218
  if relevance:
219
- relevance_str = self.convert_expression_to_string(not_clean(relevance))
219
+ relevance_str = self.convert_expression_to_string(relevance)
220
220
  if relevance_str and relevance_str != 'false':
221
221
  # Create program rule action for hiding/showing based on relevance
222
222
  rule_id = self.generate_id(f"rule_{node.get_name()}_relevance")
@@ -232,7 +232,7 @@ class DHIS2Strategy(BaseOutPutStrategy):
232
232
  "programRule": {"id": rule_id},
233
233
  }
234
234
  self.program_rule_actions.append(program_rule_action)
235
- elif not issubclass(node.__class__, TriccNodeCalculateBase) and not isinstance(node, (TriccNodeNote, TriccNodeMoreInfo)):
235
+ elif issubclass(node.__class__, TriccNodeDisplayModel) and not issubclass(node.__class__, TriccNodeCalculateBase) and not isinstance(node, (TriccNodeNote, TriccNodeMoreInfo, TriccNodeSelectOption)):
236
236
  # For regular nodes that get DataElements, use HIDEFIELD action
237
237
  # Exclude TriccNodeNote and TriccNodeMoreInfo as they don't get DataElements
238
238
  program_rule_action = {
@@ -309,8 +309,8 @@ class DHIS2Strategy(BaseOutPutStrategy):
309
309
  "id": de_id,
310
310
  "name": self.get_export_name(node),
311
311
  "shortName": node.name[:50],
312
- "displayFormName": self.get_display(node),
313
- "formName": self.get_display(node),
312
+ "displayFormName": "More infromation" if isinstance(node, TriccNodeMoreInfo) else self.get_display(node),
313
+ "formName": "More infromation" if isinstance(node, TriccNodeMoreInfo) else self.get_display(node),
314
314
  "valueType": value_type,
315
315
  "domainType": "TRACKER",
316
316
  "aggregationType": "NONE"
@@ -554,7 +554,27 @@ class DHIS2Strategy(BaseOutPutStrategy):
554
554
  self.handle_note_as_section_description(node, processed_nodes, **kwargs)
555
555
  elif isinstance(node, TriccNodeMoreInfo):
556
556
  logger.info(f"Found TriccNodeMoreInfo: {node.get_name()}")
557
- self.handle_note_as_section_description(node, processed_nodes, **kwargs)
557
+ # Create boolean checkbox data element for moreinfo
558
+ data_element = self.generate_data_element(node)
559
+ if data_element:
560
+ # Add to program stage
561
+ if self.program_metadata["programStages"]:
562
+ psde_id = self.generate_id(f"psde_{node.name}")
563
+ psde = {
564
+ "id": psde_id,
565
+ "dataElement": {"id": data_element["id"]},
566
+ "compulsory": False
567
+ }
568
+ self.program_metadata["programStages"][-1]["programStageDataElements"].append(psde)
569
+
570
+ # Add data element to current section
571
+ if self.current_section and self.current_section in self.sections:
572
+ self.sections[self.current_section]["dataElements"].append({"id": data_element["id"]})
573
+
574
+ # Handle the note section with checkbox conditioning
575
+ checkbox_reference = TriccReference(node.name)
576
+ checkbox_condition = TriccOperation(TriccOperator.ISTRUE, [checkbox_reference])
577
+ self.handle_note_as_section_description(node, processed_nodes, additional_condition=checkbox_condition, **kwargs)
558
578
  # Skip creating data elements for calculate nodes - they should only be program rule variables
559
579
  elif not issubclass(node.__class__, TriccNodeCalculateBase):
560
580
  data_element = self.generate_data_element(node)
@@ -575,8 +595,14 @@ class DHIS2Strategy(BaseOutPutStrategy):
575
595
 
576
596
  return True
577
597
 
578
- def handle_note_as_section_description(self, node, processed_nodes, **kwargs):
579
- """Transform TriccNodeNote into section description and create hide logic with section duplication"""
598
+ def handle_note_as_section_description(self, node, processed_nodes, additional_condition=None, **kwargs):
599
+ """Transform TriccNodeNote into section description and create hide logic with section duplication
600
+
601
+ Args:
602
+ node: The node to process (TriccNodeNote or TriccNodeMoreInfo)
603
+ processed_nodes: Set of already processed nodes
604
+ additional_condition: Optional additional condition to combine with existing relevance
605
+ """
580
606
  logger.info(f"Processing note {node.get_name()} for section description")
581
607
  if not self.current_section or self.current_section not in self.sections:
582
608
  logger.warning(f"No current section found for note {node.get_name()}")
@@ -594,13 +620,6 @@ class DHIS2Strategy(BaseOutPutStrategy):
594
620
  "dataElements": original_section.get("dataElements", []).copy(), # Copy data elements
595
621
  "activity_ref": original_section.get("activity_ref")
596
622
  }
597
- self.sections[duplicated_section_id] = duplicated_section
598
-
599
- # Add duplicated section to program stage
600
- if self.program_metadata["programStages"]:
601
- self.program_metadata["programStages"][-1]["programStageSections"].append({"id": duplicated_section_id})
602
-
603
- logger.info(f"Duplicated section {self.current_section} as {duplicated_section_id}")
604
623
 
605
624
  # 2. Create a new section for the note/moreinfo with name and ID from the node
606
625
  note_section_id = self.generate_id(self.get_export_name(node))
@@ -635,6 +654,14 @@ class DHIS2Strategy(BaseOutPutStrategy):
635
654
  logger.info(f"Created note section {note_section_id} with name '{note_section_name}'")
636
655
 
637
656
  # 3. Inject the duplicated section as the new current section
657
+ self.sections[duplicated_section_id] = duplicated_section
658
+
659
+ # Add duplicated section to program stage
660
+ if self.program_metadata["programStages"]:
661
+ self.program_metadata["programStages"][-1]["programStageSections"].append({"id": duplicated_section_id})
662
+
663
+ logger.info(f"Duplicated section {self.current_section} as {duplicated_section_id}")
664
+
638
665
  self.current_section = duplicated_section_id
639
666
  logger.info(f"Set current section to duplicated section {duplicated_section_id}")
640
667
 
@@ -657,6 +684,17 @@ class DHIS2Strategy(BaseOutPutStrategy):
657
684
  else:
658
685
  combined_relevance = node.relevance
659
686
 
687
+ # Combine with additional condition if provided
688
+ if additional_condition:
689
+ if combined_relevance:
690
+ # Combine using AND operation
691
+ combined_relevance = TriccOperation(
692
+ TriccOperator.AND,
693
+ [combined_relevance, additional_condition]
694
+ )
695
+ else:
696
+ combined_relevance = additional_condition
697
+
660
698
  # Create hide logic if there's relevance - applied to the note section
661
699
  if combined_relevance:
662
700
  relevance_str = self.convert_expression_to_string(not_clean(combined_relevance))
@@ -676,9 +714,12 @@ class DHIS2Strategy(BaseOutPutStrategy):
676
714
  # Create program rule referencing the action
677
715
  condition = self.simplify_expression(f"({relevance_str})==false") # Negate for hide when true
678
716
  condition = self.simplify_expression(condition)
717
+ rule_name = f"Hide note section `{note_section_name}` based on relevance"
718
+ if additional_condition:
719
+ rule_name = f"Hide moreinfo section `{note_section_name}` when checkbox false"
679
720
  self.program_rules.append({
680
721
  "id": rule_id,
681
- "name": f"Hide note section `{note_section_name}` based on relevance",
722
+ "name": rule_name,
682
723
  "description": f"Hide note section `{self.get_display(node)[:128]}` based on combined relevance",
683
724
  "condition": condition,
684
725
  "programRuleActions": [{"id": action_id}]
@@ -865,7 +906,7 @@ class DHIS2Strategy(BaseOutPutStrategy):
865
906
  return self.get_tricc_operation_expression(r)
866
907
  elif isinstance(r, TriccReference):
867
908
  # Use variable name from concept_map
868
- node_id = self.concept_map.get(r.value.name, self.get_export_name(r.value))
909
+ node_id = self.concept_map.get(r.value, self.get_export_name(r.value))
869
910
  return f"#{{{node_id}}}"
870
911
  elif isinstance(r, TriccStatic):
871
912
  if isinstance(r.value, bool):
@@ -3,8 +3,12 @@ import logging
3
3
  import os
4
4
  import shutil
5
5
  import subprocess
6
+ import tempfile
7
+ import zipfile
6
8
  import pandas as pd
7
9
 
10
+ from pyxform.xls2xform import convert
11
+
8
12
  from tricc_oo.models.lang import SingletonLangClass
9
13
  from tricc_oo.models.calculate import TriccNodeEnd
10
14
  from tricc_oo.models.tricc import TriccNodeDisplayModel
@@ -740,10 +744,12 @@ class XLSFormCHTStrategy(XLSFormCDSSStrategy):
740
744
  generated_files = self.export(self.project.start_pages, version=version)
741
745
 
742
746
  logger.info("validate the output")
743
- self.validate(generated_files)
747
+ if not self.validate(generated_files):
748
+ logger.error("CHT validation failed - aborting build")
749
+ exit(1)
744
750
 
745
751
  def validate(self, generated_files=None):
746
- """Validate the generated XLS form(s) using xls2xform-medic."""
752
+ """Validate the generated XLS form(s) using pyxform conversion and ODK Validate JAR."""
747
753
  if generated_files is None:
748
754
  # Fallback for single file validation
749
755
  if self.project.start_pages["main"].root.form_id is not None:
@@ -753,10 +759,10 @@ class XLSFormCHTStrategy(XLSFormCDSSStrategy):
753
759
  logger.error("Form ID not found for validation")
754
760
  return False
755
761
 
756
- # Ensure xls2xform-medic is available
757
- medic_tool = self._ensure_xls2xform_medic()
758
- if not medic_tool:
759
- logger.error("xls2xform-medic tool not available, skipping CHT validation")
762
+ # Ensure ODK Validate JAR is available
763
+ jar_path = self._ensure_odk_validate_jar()
764
+ if not jar_path:
765
+ logger.error("ODK Validate JAR not available, skipping CHT validation")
760
766
  return False
761
767
 
762
768
  all_valid = True
@@ -767,49 +773,82 @@ class XLSFormCHTStrategy(XLSFormCDSSStrategy):
767
773
  continue
768
774
 
769
775
  try:
770
- # Run xls2xform-medic validation
771
- result = subprocess.run(
772
- [medic_tool, xls_file],
773
- capture_output=True,
774
- text=True,
775
- cwd=self.output_path
776
+ # Convert XLS to XForm using pyxform (without validation)
777
+ xform_path = xls_file.replace('.xlsx', '.xml')
778
+ convert_result = convert(
779
+ xlsform=xls_file,
780
+ validate=False, # Don't validate during conversion
781
+ pretty_print=True
776
782
  )
783
+ xform_content = convert_result.xform
784
+
785
+ # Write XForm to temporary file for validation
786
+ with tempfile.NamedTemporaryFile(mode='w', suffix='.xml', delete=False) as temp_file:
787
+ temp_file.write(xform_content)
788
+ temp_xform_path = temp_file.name
789
+
790
+ try:
791
+ # Run ODK Validate JAR on the XForm
792
+ result = subprocess.run(
793
+ ["java", "-Djava.awt.headless=true", "-jar", jar_path, temp_xform_path],
794
+ capture_output=True,
795
+ text=True,
796
+ cwd=self.output_path
797
+ )
777
798
 
778
- if result.returncode == 0:
779
- logger.info(f"CHT XLSForm validation successful: {os.path.basename(xls_file)}")
780
- else:
781
- logger.error(f"CHT XLSForm validation failed for {os.path.basename(xls_file)}: {result.stderr}")
782
- all_valid = False
799
+ if result.returncode == 0 or "Cycle detected" in result.stderr:
800
+ logger.info(f"CHT XLSForm validation successful: {os.path.basename(xls_file)}")
801
+ else:
802
+ logger.error(f"CHT XLSForm validation failed for {os.path.basename(xls_file)}: {result.stderr}")
803
+ all_valid = False
804
+
805
+ finally:
806
+ # Clean up temporary XForm file
807
+ os.unlink(temp_xform_path)
783
808
 
784
809
  except Exception as e:
785
810
  logger.error(f"CHT XLSForm validation error for {os.path.basename(xls_file)}: {str(e)}")
786
811
  all_valid = False
787
812
 
788
- return all_valid
813
+ jar_in_zip = "site-packages/pyxform/validators/odk_validate/bin/ODK_Validate.jar"
814
+ zip_ref.extract(jar_in_zip, os.path.dirname(__file__))
815
+
816
+ # Move to final location
817
+ extracted_jar = os.path.join(os.path.dirname(__file__), jar_in_zip)
818
+ shutil.move(extracted_jar, jar_path)
789
819
 
790
- def _ensure_xls2xform_medic(self):
791
- """Ensure xls2xform-medic tool is available."""
792
- # Check if it's in PATH
793
- medic_tool = shutil.which("xls2xform-medic")
794
- if medic_tool:
795
- return medic_tool
820
+ logger.info(f"Extracted ODK Validate JAR to {jar_path}")
821
+ return jar_path
796
822
 
797
- # Check if we need to download it
798
- medic_path = os.path.join(os.path.dirname(__file__), "xls2xform-medic")
799
- if os.path.exists(medic_path):
800
- return medic_path
823
+ def _ensure_odk_validate_jar(self):
824
+ """Ensure ODK Validate JAR is available by extracting from medic zip."""
825
+ jar_path = os.path.join(os.path.dirname(__file__), "ODK_Validate.jar")
826
+
827
+ # Check if JAR already exists
828
+ if os.path.exists(jar_path):
829
+ return jar_path
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
801
836
 
802
- # Try to download from the provided URL
803
837
  try:
804
- import urllib.request
805
- medic_url = "https://github.com/medic/pyxform/releases/download/v4.0.0-medic/xls2xform-medic"
806
- logger.info(f"Downloading xls2xform-medic from {medic_url}")
807
- urllib.request.urlretrieve(medic_url, medic_path)
808
- # Make executable
809
- os.chmod(medic_path, 0o755)
810
- return medic_path
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}")
848
+ return jar_path
849
+
811
850
  except Exception as e:
812
- logger.error(f"Failed to download xls2xform-medic: {str(e)}")
851
+ logger.error(f"Failed to extract ODK Validate JAR: {str(e)}")
813
852
  return None
814
853
 
815
854
  def tricc_operation_zscore(self, ref_expressions):
@@ -836,7 +875,7 @@ class XLSFormCHTStrategy(XLSFormCDSSStrategy):
836
875
  self.clean_coalesce(ref_expressions[2])
837
876
  } ,{
838
877
  self.clean_coalesce(ref_expressions[3])
839
- }, true)"""
878
+ }, true"""
840
879
 
841
880
  def tricc_operation_drug_dosage(self, ref_expressions):
842
881
  # drug name
@@ -1772,12 +1772,6 @@ def reorder_node_list(node_list, group, processed_nodes):
1772
1772
  # Check for non main activities
1773
1773
  elif activity and isinstance(activity.root, TriccNodeActivityStart):
1774
1774
  priority += NON_START_ACTIVITY_PRIORITY
1775
- # Check for display calculate and end nodes with prev_nodes
1776
- elif (
1777
- issubclass(node.__class__, TriccNodeDisplayCalculateBase) or
1778
- isinstance(node, TriccNodeEnd)
1779
- ) and not isinstance(node, TriccNodeActivityEnd) and hasattr(node, 'prev_nodes') and len(node.prev_nodes) > 0:
1780
- priority += FLOW_CALCULATE_NODE_PRIORITY
1781
1775
  # Check for active activities (lower priority)
1782
1776
  elif activity and activity in active_activities:
1783
1777
  priority += ACTIVE_ACTIVITY_LOWER_PRIORITY
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tricc-oo
3
- Version: 1.6.9
3
+ Version: 1.6.10
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
@@ -8,7 +8,7 @@ tricc_oo/converters/codesystem_to_ocl.py,sha256=Fh7Vk73OsxljZKu1k6H9uzYwz334tpQT
8
8
  tricc_oo/converters/cql_to_operation.py,sha256=PUyV_YpUY98Ox0H_F_CN3UUf_I-BhFZVOcWWKTtwecM,14492
9
9
  tricc_oo/converters/datadictionnary.py,sha256=T2HLCBo4Am1p0kFqSH1r0PqbD8AC2IGuWkbvMvSCru0,3658
10
10
  tricc_oo/converters/drawio_type_map.py,sha256=UCPiGs7Lw0bigKScmZUnmOhACBz-FiDq92jHkI7RTSQ,9113
11
- tricc_oo/converters/tricc_to_xls_form.py,sha256=wsWv4aA0QssY7ry9R7KsuuMzVfovj9fwE3i9AtCum0c,3842
11
+ tricc_oo/converters/tricc_to_xls_form.py,sha256=39hwWgYNitGE-AuKtjUwNLz39tEpwc7nd9gT_gw5wjc,3842
12
12
  tricc_oo/converters/utils.py,sha256=JZrtrvvOfXwdkw49pKauzinOcauWwsy-CVcw36TjyLo,1684
13
13
  tricc_oo/converters/xml_to_tricc.py,sha256=yqnU5xg1SVoQ8vra0gOvIPwoh80pyTI332y9qJCvcRs,39654
14
14
  tricc_oo/converters/cql/cqlLexer.py,sha256=8HArbRphcrpnAG4uogJ2rHv4tc1WLzjN0B1uFeYILAc,49141
@@ -26,27 +26,27 @@ 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=L0WF774zFt6PbdqncJGeyZzM9NiLq9NY5vO98yGTLhM,22133
29
+ tricc_oo/serializers/xls_form.py,sha256=_sYYVmJkGJeeOr8l_FzRIOuCcGzrxeFc1APXBgNNs08,22585
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
33
33
  tricc_oo/strategies/input/drawio.py,sha256=uXAUPhXOeg0Uk_BNqlCqFBW4cWNox4VfH559bj1fhC0,12767
34
34
  tricc_oo/strategies/output/base_output_strategy.py,sha256=i9L5CVUqkEAMNyBsdHJ4xA7Nptr3myHr_fHHveDX1cU,8928
35
- tricc_oo/strategies/output/dhis2_form.py,sha256=RFMUrB3TNJJi3kecBVThY6X1GF_TVk8XgXkye8fRkIc,47035
35
+ tricc_oo/strategies/output/dhis2_form.py,sha256=O5sBcwG_i6Vx3T5-Be4MmE50CsW4obikS3p8MOOJu1o,49317
36
36
  tricc_oo/strategies/output/fhir_form.py,sha256=yDDJqdkt4PvSDEy4kmgKM8V_o757CDlE7813atyyDHM,15749
37
37
  tricc_oo/strategies/output/html_form.py,sha256=qSleEZOMV_-Z04y-i-ucyd5rgAYWAyjPwMrw0IHtCRM,8604
38
38
  tricc_oo/strategies/output/openmrs_form.py,sha256=ne6TwAyhafR-WDs27QTKKFl85VD5sij_VEJtK6ZjOIE,28996
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=eKAc6LLDnvdZ5m8a2Vk6eAhvPbUvOfykgYr0ou3an9k,27164
42
+ tricc_oo/strategies/output/xlsform_cht.py,sha256=RXacGiVAib5bF_0ea564YhuJ1ASs20MuMuIeZXiP5-M,29019
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=_UzAylSHuAhfXXPUBV_PJIhta5ihbJhLDe3GJAwxQzU,110598
45
+ tricc_oo/visitors/tricc.py,sha256=9jAVSxFfklJcLzwLvZAV1_sRuD8616HSgOSl8wdqPTE,110227
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.9.dist-info/licenses/LICENSE,sha256=Pz2eACSxkhsGfW9_iN60pgy-enjnbGTj8df8O3ebnQQ,16726
49
- tricc_oo-1.6.9.dist-info/METADATA,sha256=qbIz4okrC-eeMx-8mZMt_--MUWzPcZmht_dhO11qovY,8599
50
- tricc_oo-1.6.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
51
- tricc_oo-1.6.9.dist-info/top_level.txt,sha256=NvbfMNAiy9m4b1unBsqpeOQWh4IgA1Xa33BtKA4abxk,15
52
- tricc_oo-1.6.9.dist-info/RECORD,,
48
+ tricc_oo-1.6.10.dist-info/licenses/LICENSE,sha256=Pz2eACSxkhsGfW9_iN60pgy-enjnbGTj8df8O3ebnQQ,16726
49
+ tricc_oo-1.6.10.dist-info/METADATA,sha256=kiJuIi8qGKOf5IP63NtQYJ7ReSJJHrReUl3fuWEJS18,8600
50
+ tricc_oo-1.6.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
51
+ tricc_oo-1.6.10.dist-info/top_level.txt,sha256=NvbfMNAiy9m4b1unBsqpeOQWh4IgA1Xa33BtKA4abxk,15
52
+ tricc_oo-1.6.10.dist-info/RECORD,,