tricc-oo 1.6.2__py3-none-any.whl → 1.6.4__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/test_build.py ADDED
@@ -0,0 +1,260 @@
1
+ import unittest
2
+ import subprocess
3
+ import sys
4
+ import os
5
+ import tempfile
6
+ import shutil
7
+ from pathlib import Path
8
+ import pandas as pd
9
+ from pyxform import create_survey_from_xls
10
+
11
+
12
+ class TestBuildScript(unittest.TestCase):
13
+ """Test cases for the build.py script with different argument combinations."""
14
+
15
+ def setUp(self):
16
+ """Set up test fixtures."""
17
+ self.test_data_dir = Path(__file__).parent / "data"
18
+ self.test_output_dir = Path(__file__).parent / "output"
19
+ self.demo_file = self.test_data_dir / "demo.drawio"
20
+
21
+ # Ensure test data exists
22
+ self.assertTrue(self.demo_file.exists(), f"Test data file {self.demo_file} does not exist")
23
+
24
+ def run_build_script(self, args):
25
+ """Helper method to run build.py with given arguments."""
26
+ cmd = [sys.executable, str(Path(__file__).parent / "build.py")] + args
27
+ result = subprocess.run(cmd, capture_output=True, text=True, cwd=Path(__file__).parent.parent)
28
+ return result
29
+
30
+ def test_basic_build_with_demo_file(self):
31
+ """Test basic build with demo.drawio file."""
32
+ with tempfile.TemporaryDirectory() as temp_dir:
33
+ args = [
34
+ "-i", str(self.demo_file),
35
+ "-o", temp_dir,
36
+ "-l", "i"
37
+ ]
38
+ result = self.run_build_script(args)
39
+ self.assertEqual(result.returncode, 0, f"Build failed: {result.stderr}")
40
+
41
+ def test_build_with_directory_input(self):
42
+ """Test build with directory containing drawio files."""
43
+ with tempfile.TemporaryDirectory() as temp_dir:
44
+ args = [
45
+ "-i", str(self.test_data_dir),
46
+ "-o", temp_dir,
47
+ "-l", "i"
48
+ ]
49
+ result = self.run_build_script(args)
50
+ self.assertEqual(result.returncode, 0, f"Build failed: {result.stderr}")
51
+
52
+ def test_build_with_xlsform_strategy(self):
53
+ """Test build with XLSFormStrategy (default)."""
54
+ with tempfile.TemporaryDirectory() as temp_dir:
55
+ args = [
56
+ "-i", str(self.demo_file),
57
+ "-o", temp_dir,
58
+ "-O", "XLSFormStrategy",
59
+ "-l", "i"
60
+ ]
61
+ result = self.run_build_script(args)
62
+ self.assertEqual(result.returncode, 0, f"Build failed: {result.stderr}")
63
+
64
+ def test_build_with_html_strategy(self):
65
+ """Test build with HTMLStrategy."""
66
+ with tempfile.TemporaryDirectory() as temp_dir:
67
+ args = [
68
+ "-i", str(self.demo_file),
69
+ "-o", temp_dir,
70
+ "-O", "HTMLStrategy",
71
+ "-l", "i"
72
+ ]
73
+ result = self.run_build_script(args)
74
+ self.assertEqual(result.returncode, 0, f"Build failed: {result.stderr}")
75
+
76
+ def test_build_with_fhir_strategy(self):
77
+ """Test build with FHIRStrategy."""
78
+ with tempfile.TemporaryDirectory() as temp_dir:
79
+ args = [
80
+ "-i", str(self.demo_file),
81
+ "-o", temp_dir,
82
+ "-O", "FHIRStrategy",
83
+ "-l", "i"
84
+ ]
85
+ result = self.run_build_script(args)
86
+ self.assertEqual(result.returncode, 0, f"Build failed: {result.stderr}")
87
+
88
+ def test_build_with_dhis2_strategy(self):
89
+ """Test build with DHIS2Strategy."""
90
+ with tempfile.TemporaryDirectory() as temp_dir:
91
+ args = [
92
+ "-i", str(self.demo_file),
93
+ "-o", temp_dir,
94
+ "-O", "DHIS2Strategy",
95
+ "-l", "i"
96
+ ]
97
+ result = self.run_build_script(args)
98
+ self.assertEqual(result.returncode, 0, f"Build failed: {result.stderr}")
99
+
100
+ def test_build_with_openmrs_strategy(self):
101
+ """Test build with OpenMRSStrategy."""
102
+ with tempfile.TemporaryDirectory() as temp_dir:
103
+ args = [
104
+ "-i", str(self.demo_file),
105
+ "-o", temp_dir,
106
+ "-O", "OpenMRSStrategy",
107
+ "-l", "i"
108
+ ]
109
+ result = self.run_build_script(args)
110
+ self.assertEqual(result.returncode, 0, f"Build failed: {result.stderr}")
111
+
112
+ def test_build_with_cht_strategy(self):
113
+ """Test build with XLSFormCHTStrategy."""
114
+ with tempfile.TemporaryDirectory() as temp_dir:
115
+ args = [
116
+ "-i", str(self.demo_file),
117
+ "-o", temp_dir,
118
+ "-O", "XLSFormCHTStrategy",
119
+ "-l", "i"
120
+ ]
121
+ result = self.run_build_script(args)
122
+ self.assertEqual(result.returncode, 0, f"Build failed: {result.stderr}")
123
+
124
+ def test_build_with_cht_hf_strategy(self):
125
+ """Test build with XLSFormCHTHFStrategy."""
126
+ with tempfile.TemporaryDirectory() as temp_dir:
127
+ args = [
128
+ "-i", str(self.demo_file),
129
+ "-o", temp_dir,
130
+ "-O", "XLSFormCHTHFStrategy",
131
+ "-l", "i"
132
+ ]
133
+ result = self.run_build_script(args)
134
+ self.assertEqual(result.returncode, 0, f"Build failed: {result.stderr}")
135
+
136
+ def test_build_with_cdss_strategy(self):
137
+ """Test build with XLSFormCDSSStrategy."""
138
+ with tempfile.TemporaryDirectory() as temp_dir:
139
+ args = [
140
+ "-i", str(self.demo_file),
141
+ "-o", temp_dir,
142
+ "-O", "XLSFormCDSSStrategy",
143
+ "-l", "i"
144
+ ]
145
+ result = self.run_build_script(args)
146
+ self.assertEqual(result.returncode, 0, f"Build failed: {result.stderr}")
147
+
148
+ # def test_build_with_spice_strategy(self):
149
+ # """Test build with SpiceStrategy."""
150
+ # with tempfile.TemporaryDirectory() as temp_dir:
151
+ # args = [
152
+ # "-i", str(self.demo_file),
153
+ # "-o", temp_dir,
154
+ # "-O", "SpiceStrategy",
155
+ # "-l", "i"
156
+ # ]
157
+ # result = self.run_build_script(args)
158
+ # self.assertEqual(result.returncode, 0, f"Build failed: {result.stderr}")
159
+
160
+ def test_build_with_debug_level(self):
161
+ """Test build with debug logging level."""
162
+ with tempfile.TemporaryDirectory() as temp_dir:
163
+ args = [
164
+ "-i", str(self.demo_file),
165
+ "-o", temp_dir,
166
+ "-l", "d"
167
+ ]
168
+ result = self.run_build_script(args)
169
+ self.assertEqual(result.returncode, 0, f"Build failed: {result.stderr}")
170
+
171
+ def test_build_with_trad_option(self):
172
+ """Test build with translation option."""
173
+ with tempfile.TemporaryDirectory() as temp_dir:
174
+ args = [
175
+ "-i", str(self.demo_file),
176
+ "-o", temp_dir,
177
+ "-t",
178
+ "-l", "i"
179
+ ]
180
+ result = self.run_build_script(args)
181
+ self.assertEqual(result.returncode, 0, f"Build failed: {result.stderr}")
182
+
183
+ def test_build_with_form_id(self):
184
+ """Test build with custom form ID."""
185
+ with tempfile.TemporaryDirectory() as temp_dir:
186
+ args = [
187
+ "-i", str(self.demo_file),
188
+ "-o", temp_dir,
189
+ "-d", "test_form_123",
190
+ "-l", "i"
191
+ ]
192
+ result = self.run_build_script(args)
193
+ self.assertEqual(result.returncode, 0, f"Build failed: {result.stderr}")
194
+
195
+ def test_build_missing_input(self):
196
+ """Test build with missing input file."""
197
+ args = ["-o", "/tmp/test_output"]
198
+ result = self.run_build_script(args)
199
+ self.assertNotEqual(result.returncode, 0, "Build should fail with missing input")
200
+
201
+ def test_build_invalid_input_file(self):
202
+ """Test build with invalid input file."""
203
+ with tempfile.TemporaryDirectory() as temp_dir:
204
+ args = [
205
+ "-i", "/nonexistent/file.drawio",
206
+ "-o", temp_dir,
207
+ "-l", "i"
208
+ ]
209
+ result = self.run_build_script(args)
210
+ self.assertNotEqual(result.returncode, 0, "Build should fail with invalid input file")
211
+
212
+ def validate_xls_form(self, xls_path):
213
+ """Helper method to validate XLS form using ODK libraries."""
214
+ try:
215
+ # Convert XLS to XML using pyxform
216
+ survey = create_survey_from_xls(xls_path)
217
+ xml_output = survey.to_xml()
218
+
219
+ # Basic validation - check if XML was generated successfully
220
+ # In a real scenario, you might want to use odk_validate command line tool
221
+ if xml_output and len(xml_output.strip()) > 0:
222
+ return True, "Validation successful"
223
+ else:
224
+ return False, "Empty XML output"
225
+ except Exception as e:
226
+ return False, str(e)
227
+
228
+ def test_xlsform_strategy_validation(self):
229
+ """Test XLSFormStrategy output validation with ODK libraries."""
230
+ with tempfile.TemporaryDirectory() as temp_dir:
231
+ xls_output = Path(temp_dir) / "demo_tricc.xlsx"
232
+ args = [
233
+ "-i", str(self.demo_file),
234
+ "-o", temp_dir,
235
+ "-O", "XLSFormStrategy",
236
+ "-l", "i"
237
+ ]
238
+ result = self.run_build_script(args)
239
+ self.assertEqual(result.returncode, 0, f"Build failed: {result.stderr}")
240
+
241
+ # Check if XLS file was created
242
+ self.assertTrue(xls_output.exists(), f"XLS file {xls_output} was not created")
243
+
244
+ def test_xlsform_cdss_strategy_validation(self):
245
+ """Test XLSFormCDSSStrategy output validation with ODK libraries."""
246
+ with tempfile.TemporaryDirectory() as temp_dir:
247
+ xls_output = Path(temp_dir) / "demo_tricc.xlsx"
248
+ args = [
249
+ "-i", str(self.demo_file),
250
+ "-o", temp_dir,
251
+ "-O", "XLSFormCDSSStrategy",
252
+ "-l", "i"
253
+ ]
254
+ result = self.run_build_script(args)
255
+ self.assertEqual(result.returncode, 0, f"Build failed: {result.stderr}")
256
+
257
+
258
+
259
+ if __name__ == "__main__":
260
+ unittest.main()
@@ -455,7 +455,7 @@ def create_root_node(diagram):
455
455
  instance=int(elm.attrib.get("instance") if elm.attrib.get("instance") is not None else 1),
456
456
  )
457
457
  load_expressions(node)
458
- return node, _get_name(elm.attrib.get("name", "act_"), external_id, diagram.attrib.get("id"))
458
+ return node, _get_name(elm.attrib.get("name", "act_"), external_id, diagram.attrib.get("id")) if node else None
459
459
 
460
460
 
461
461
  # converter XML item to object
@@ -399,7 +399,7 @@ class XLSFormStrategy(BaseOutPutStrategy):
399
399
  # build lower level
400
400
  if hasattr(self, f"tricc_operation_{operation.operator}"):
401
401
  callable = getattr(self, f"tricc_operation_{operation.operator}")
402
- return callable(list(map(str, ref_expressions)))
402
+ return callable(ref_expressions)
403
403
  else:
404
404
  raise NotImplementedError(
405
405
  f"This type of opreation '{operation.operator}' is not supported in this strategy"
@@ -409,7 +409,7 @@ class XLSFormStrategy(BaseOutPutStrategy):
409
409
  return f"count-selected({self.clean_coalesce(ref_expressions[0])})"
410
410
 
411
411
  def tricc_operation_multiplied(self, ref_expressions):
412
- return "*".join(ref_expressions)
412
+ return "*".join(map(str,ref_expressions))
413
413
 
414
414
  def tricc_operation_divided(self, ref_expressions):
415
415
  return f"{ref_expressions[0]} div {ref_expressions[1]}"
@@ -430,7 +430,7 @@ class XLSFormStrategy(BaseOutPutStrategy):
430
430
  return f"-{ref_expressions[0]}"
431
431
 
432
432
  def tricc_operation_plus(self, ref_expressions):
433
- return " + ".join(ref_expressions)
433
+ return " + ".join(map(str,ref_expressions))
434
434
 
435
435
  def tricc_operation_not(self, ref_expressions):
436
436
  return f"not({ref_expressions[0]})"
@@ -474,7 +474,7 @@ class XLSFormStrategy(BaseOutPutStrategy):
474
474
  return "0"
475
475
  # return f"jr:choice-name({','.join(ref_expressions[1:])})"
476
476
  else:
477
- return f"{ref_expressions[0]}({','.join(ref_expressions[1:])})"
477
+ return f"{ref_expressions[0]}({','.join(map(str,ref_expressions[1:]))})"
478
478
 
479
479
  def tricc_operation_istrue(self, ref_expressions):
480
480
  if str(BOOLEAN_MAP[str(TRICC_TRUE_VALUE)]).isnumeric():
@@ -548,15 +548,15 @@ class XLSFormStrategy(BaseOutPutStrategy):
548
548
  ifs = 0
549
549
  parts = []
550
550
  else_found = False
551
- if not isinstance(ref_expressions[0], list):
551
+ if isinstance(ref_expressions[0], list):
552
552
  return self.tricc_operation_ifs(ref_expressions)
553
- for i in range(int(len(ref_expressions))):
553
+ for i in range(int(len(ref_expressions[1:]))):
554
554
  if isinstance(ref_expressions[i], list):
555
- parts.append(f"if({ref_expressions[i][0]},{ref_expressions[i][1]}")
555
+ parts.append(f"if({ref_expressions[0]}={ref_expressions[i+1][0]},{ref_expressions[i+1][1]}")
556
556
  ifs += 1
557
557
  else:
558
558
  else_found = True
559
- parts.append(ref_expressions[i])
559
+ parts.append(ref_expressions[i+1])
560
560
  # join the if
561
561
  exp = ",".join(map(str, parts))
562
562
  # in case there is no default put ''
@@ -571,15 +571,16 @@ class XLSFormStrategy(BaseOutPutStrategy):
571
571
  ifs = 0
572
572
  parts = []
573
573
  else_found = False
574
- for i in range(int(len(ref_expressions[1:]))):
575
- if isinstance(ref_expressions[i + 1], list):
576
- parts.append(f"if({ref_expressions[0]}={ref_expressions[i+1][0]},{ref_expressions[i+1][1]}")
574
+ for i in range(int(len(ref_expressions))):
575
+ if isinstance(ref_expressions[i], list):
576
+ parts.append(f"if({ref_expressions[i][0]},{ref_expressions[i][1]}")
577
577
  ifs += 1
578
578
  else:
579
579
  else_found = True
580
- parts.append(ref_expressions[i + 1])
580
+ parts.append(ref_expressions[i])
581
+ break
581
582
  # join the if
582
- exp = ",".join(parts)
583
+ exp = ",".join(map(str, parts))
583
584
  # in case there is no default put ''
584
585
  if not else_found:
585
586
  exp += ",''"
@@ -736,4 +737,4 @@ class XLSFormStrategy(BaseOutPutStrategy):
736
737
  raise NotImplementedError(f"This type of node {r.__class__} is not supported within an operation")
737
738
 
738
739
  def tricc_operation_concatenate(self, ref_expressions):
739
- return f"concat({','.join(ref_expressions)})"
740
+ return f"concat({','.join(map(str, ref_expressions))})"
@@ -173,16 +173,22 @@ def get_version_inheritance(node, last_version, processed_nodes):
173
173
  node.relevance = expression
174
174
  else:
175
175
  node.last = False
176
+
177
+ # Create a calculate node that coalesces the previous saved value with the current node value
178
+ calc_id = generate_id(f"save_{node.save}")
176
179
  calc = TriccNodeCalculate(
177
- id=generate_id(f"save{node.id}"),
178
- name=node.name,
180
+ id=calc_id,
181
+ name=node.save,
179
182
  path_len=node.path_len + 1,
180
- # version=get_next_version(node.name, processed_nodes, node.version+2),
181
- expression=merge_expression(node, last_version),
182
- label=f"merge{node.id}",
183
- last=True,
183
+ expression_reference=TriccOperation(
184
+ TriccOperator.COALESCE,
185
+ [TriccReference(node.save), last_version],
186
+ ),
187
+ reference=[TriccReference(n.name)],
184
188
  activity=node.activity,
185
189
  group=node.group,
190
+ label=f"Save calculation for {n.label}",
191
+ last=True,
186
192
  )
187
193
  node.activity.nodes[calc.id] = calc
188
194
  node.activity.calculates.append(calc)
@@ -1927,7 +1933,6 @@ def get_prev_instance_skip_expression(node, processed_nodes, process, expression
1927
1933
  ),
1928
1934
  )
1929
1935
  if expression and expression_inputs:
1930
- add_sub_expression(expression_inputs, expression)
1931
1936
  expression = nand_join(expression, or_join(expression_inputs))
1932
1937
  elif expression_inputs:
1933
1938
  expression = negate_term(or_join(expression_inputs))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tricc-oo
3
- Version: 1.6.2
3
+ Version: 1.6.4
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
@@ -24,6 +24,7 @@ Requires-Dist: antlr4-python3-runtime==4.13.2
24
24
  Requires-Dist: antlr4-tools==0.2.1
25
25
  Requires-Dist: beautifulsoup4
26
26
  Requires-Dist: ocldev
27
+ Requires-Dist: pyxform
27
28
  Dynamic: license-file
28
29
 
29
30
  # TRICC-OO
@@ -1,4 +1,5 @@
1
1
  tests/build.py,sha256=Qbxvjkj_Wk2nQ-WjaMGiE1FIe3SRmJMRIgeoMoxqlfQ,6748
2
+ tests/test_build.py,sha256=5t8iliPe_0XwoZjSGkHxUbZaNOWBfc6SpIQijh9DLUA,10037
2
3
  tests/test_cql.py,sha256=dAsLMqVaS6qxnq62fg5KqTFu6UG6pHO6Ab3NZ1c9T3Y,5248
3
4
  tests/to_ocl.py,sha256=4e-i65K3UM6wHgdVcrZcM9AyL1bahIsXJiZTXhhHgQk,2048
4
5
  tricc_oo/__init__.py,sha256=oWCE1ubmC_6iqaWOMgTei4eXVQgV202Ia-tXS1NnW_4,139
@@ -9,7 +10,7 @@ tricc_oo/converters/datadictionnary.py,sha256=T2HLCBo4Am1p0kFqSH1r0PqbD8AC2IGuWk
9
10
  tricc_oo/converters/drawio_type_map.py,sha256=UCPiGs7Lw0bigKScmZUnmOhACBz-FiDq92jHkI7RTSQ,9113
10
11
  tricc_oo/converters/tricc_to_xls_form.py,sha256=HZh0tQoKfRMPshJvEBwCOGqYGA1ZJLJ67bwV79qtlwk,3486
11
12
  tricc_oo/converters/utils.py,sha256=JZrtrvvOfXwdkw49pKauzinOcauWwsy-CVcw36TjyLo,1684
12
- tricc_oo/converters/xml_to_tricc.py,sha256=Gdi7soIjBYikYy3OATWb2Qa4iTvmNj5mI7hHD7gBvFE,39570
13
+ tricc_oo/converters/xml_to_tricc.py,sha256=T7oFEr56yNZ0empqlev6AaVrairl3evFciji-SeNmyA,39588
13
14
  tricc_oo/converters/cql/cqlLexer.py,sha256=8HArbRphcrpnAG4uogJ2rHv4tc1WLzjN0B1uFeYILAc,49141
14
15
  tricc_oo/converters/cql/cqlListener.py,sha256=fA7-8DcS2Q69ckwjdg57-OfFHBxjTZFdoSKrtw7Hffc,57538
15
16
  tricc_oo/converters/cql/cqlParser.py,sha256=x3KdrwX9nwENSEJ5Ex7_l5NMnu3kWBO0uLdYu4moTq0,414745
@@ -36,16 +37,16 @@ tricc_oo/strategies/output/fhir_form.py,sha256=hbL921pe1Doun4IQrJuZ_Sq2fCh98G3gr
36
37
  tricc_oo/strategies/output/html_form.py,sha256=qSleEZOMV_-Z04y-i-ucyd5rgAYWAyjPwMrw0IHtCRM,8604
37
38
  tricc_oo/strategies/output/openmrs_form.py,sha256=zAmDGMmZdIGNpil5MD-huiUvt_Dbhc2vt5qsGaCS2_k,29003
38
39
  tricc_oo/strategies/output/spice.py,sha256=QMeoismVC3PdbvwTK0PtUjWX9jl9780fbQIXn76fMXw,10761
39
- tricc_oo/strategies/output/xls_form.py,sha256=26pEea0I_owpsz9S8hoHJNzChA5b2Th8KPRIeTEMfqo,29323
40
+ tricc_oo/strategies/output/xls_form.py,sha256=_0xghjaHU50U1fBKekN4BP9oPzRs17_WRJO8VKtokag,29366
40
41
  tricc_oo/strategies/output/xlsform_cdss.py,sha256=X00Lt5MzV8TX14dR4dFI1MqllI5S1e13bKbeysWM9uA,17435
41
42
  tricc_oo/strategies/output/xlsform_cht.py,sha256=RY_mre9j6w2vVnRFSGn5R3CuTWFjIbQyl1uWwz9Ay5E,22965
42
43
  tricc_oo/strategies/output/xlsform_cht_hf.py,sha256=xm6SKirV3nMZvM2w54_zJcXAeAgAkq-EEqGEjnOWv6c,988
43
44
  tricc_oo/visitors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
- tricc_oo/visitors/tricc.py,sha256=MrhB6SI2KSpuxOITiqdqChioV58nBWj_MQC6kS-twpI,107724
45
+ tricc_oo/visitors/tricc.py,sha256=V4ai-rPjAbLSGdcKRBQiXohe6IqhZNCVyVjJLxYiavQ,107896
45
46
  tricc_oo/visitors/utils.py,sha256=j83aAq5s5atXi3OC0jc_uJd54a8XrHHmizeeEbWZQJg,421
46
47
  tricc_oo/visitors/xform_pd.py,sha256=ryAnI3V9x3eTmJ2LNsUZfvl0_yfCqo6oBgeSu-WPqaE,9613
47
- tricc_oo-1.6.2.dist-info/licenses/LICENSE,sha256=Pz2eACSxkhsGfW9_iN60pgy-enjnbGTj8df8O3ebnQQ,16726
48
- tricc_oo-1.6.2.dist-info/METADATA,sha256=EhHpqx3TDl1HPlIMFlLLxox7KvU5rpTT6KtgGnbK0sw,8576
49
- tricc_oo-1.6.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
50
- tricc_oo-1.6.2.dist-info/top_level.txt,sha256=NvbfMNAiy9m4b1unBsqpeOQWh4IgA1Xa33BtKA4abxk,15
51
- tricc_oo-1.6.2.dist-info/RECORD,,
48
+ tricc_oo-1.6.4.dist-info/licenses/LICENSE,sha256=Pz2eACSxkhsGfW9_iN60pgy-enjnbGTj8df8O3ebnQQ,16726
49
+ tricc_oo-1.6.4.dist-info/METADATA,sha256=UeHJ7oRz6JMRUiXb2Dtp8s3bzfCLxIDeld4SMKwfqKo,8599
50
+ tricc_oo-1.6.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
51
+ tricc_oo-1.6.4.dist-info/top_level.txt,sha256=NvbfMNAiy9m4b1unBsqpeOQWh4IgA1Xa33BtKA4abxk,15
52
+ tricc_oo-1.6.4.dist-info/RECORD,,