tricc-oo 1.6.8__py3-none-any.whl → 1.6.9__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.
- tricc_oo/converters/xml_to_tricc.py +2 -0
- tricc_oo/strategies/output/dhis2_form.py +166 -11
- tricc_oo/strategies/output/fhir_form.py +1 -1
- tricc_oo/visitors/tricc.py +5 -0
- {tricc_oo-1.6.8.dist-info → tricc_oo-1.6.9.dist-info}/METADATA +1 -1
- {tricc_oo-1.6.8.dist-info → tricc_oo-1.6.9.dist-info}/RECORD +9 -9
- {tricc_oo-1.6.8.dist-info → tricc_oo-1.6.9.dist-info}/WHEEL +0 -0
- {tricc_oo-1.6.8.dist-info → tricc_oo-1.6.9.dist-info}/licenses/LICENSE +0 -0
- {tricc_oo-1.6.8.dist-info → tricc_oo-1.6.9.dist-info}/top_level.txt +0 -0
|
@@ -16,7 +16,7 @@ import datetime
|
|
|
16
16
|
from tricc_oo.strategies.output.base_output_strategy import BaseOutPutStrategy
|
|
17
17
|
from tricc_oo.models.base import (
|
|
18
18
|
not_clean, TriccOperation,
|
|
19
|
-
TriccStatic, TriccReference
|
|
19
|
+
TriccStatic, TriccReference, TriccOperator
|
|
20
20
|
)
|
|
21
21
|
from tricc_oo.models.tricc import (
|
|
22
22
|
TriccNodeSelectOption,
|
|
@@ -27,6 +27,8 @@ from tricc_oo.models.tricc import (
|
|
|
27
27
|
TriccNodeActivity,
|
|
28
28
|
TriccNodeSelect,
|
|
29
29
|
TriccNodeSelectYesNo,
|
|
30
|
+
TriccNodeNote,
|
|
31
|
+
TriccNodeMoreInfo,
|
|
30
32
|
)
|
|
31
33
|
from tricc_oo.models.calculate import TriccNodeDisplayCalculateBase
|
|
32
34
|
from tricc_oo.models.ordered_set import OrderedSet
|
|
@@ -44,7 +46,7 @@ class DHIS2Strategy(BaseOutPutStrategy):
|
|
|
44
46
|
|
|
45
47
|
def __init__(self, project, output_path):
|
|
46
48
|
super().__init__(project, output_path)
|
|
47
|
-
form_id = getattr(self.project.start_pages["main"], 'form_id', 'dhis2_program')
|
|
49
|
+
form_id = getattr(self.project.start_pages["main"].root, 'form_id', 'dhis2_program')
|
|
48
50
|
self.program_metadata = {
|
|
49
51
|
"id": self.generate_id(form_id),
|
|
50
52
|
"name": form_id,
|
|
@@ -204,6 +206,10 @@ class DHIS2Strategy(BaseOutPutStrategy):
|
|
|
204
206
|
return False
|
|
205
207
|
|
|
206
208
|
if node not in processed_nodes:
|
|
209
|
+
# Skip relevance generation for TriccNodeMoreInfo as they don't create DataElements
|
|
210
|
+
if isinstance(node, TriccNodeMoreInfo):
|
|
211
|
+
return True
|
|
212
|
+
|
|
207
213
|
relevance = None
|
|
208
214
|
if hasattr(node, 'relevance') and node.relevance:
|
|
209
215
|
relevance = node.relevance
|
|
@@ -225,8 +231,10 @@ class DHIS2Strategy(BaseOutPutStrategy):
|
|
|
225
231
|
"activity_ref": node, # Temporary reference to be replaced with section ID
|
|
226
232
|
"programRule": {"id": rule_id},
|
|
227
233
|
}
|
|
228
|
-
|
|
229
|
-
|
|
234
|
+
self.program_rule_actions.append(program_rule_action)
|
|
235
|
+
elif not issubclass(node.__class__, TriccNodeCalculateBase) and not isinstance(node, (TriccNodeNote, TriccNodeMoreInfo)):
|
|
236
|
+
# For regular nodes that get DataElements, use HIDEFIELD action
|
|
237
|
+
# Exclude TriccNodeNote and TriccNodeMoreInfo as they don't get DataElements
|
|
230
238
|
program_rule_action = {
|
|
231
239
|
"id": action_id,
|
|
232
240
|
"programRuleActionType": "HIDEFIELD",
|
|
@@ -235,18 +243,45 @@ class DHIS2Strategy(BaseOutPutStrategy):
|
|
|
235
243
|
},
|
|
236
244
|
"programRule": {"id": rule_id}
|
|
237
245
|
}
|
|
238
|
-
|
|
246
|
+
self.program_rule_actions.append(program_rule_action)
|
|
239
247
|
|
|
240
248
|
# Create program rule referencing the action
|
|
241
|
-
condition = self.simplify_expression(f"
|
|
249
|
+
condition = self.simplify_expression(f"({relevance_str})==false") # Negate for hide when true
|
|
242
250
|
condition = self.simplify_expression(condition)
|
|
243
251
|
self.program_rules.append({
|
|
244
252
|
"id": rule_id,
|
|
245
253
|
"name": f"Hide `{self.get_export_name(node)}` when condition met",
|
|
246
|
-
"description": f"Hide `{self.get_display(node)}` based on relevance",
|
|
254
|
+
"description": f"Hide `{self.get_display(node)[:128]}` based on relevance",
|
|
247
255
|
"condition": condition,
|
|
248
256
|
"programRuleActions": [{"id": action_id}]
|
|
249
257
|
})
|
|
258
|
+
|
|
259
|
+
# Check if field should be mandatory based on 'required' attribute
|
|
260
|
+
if bool(getattr(node, 'required', False)):
|
|
261
|
+
# Create program rule for mandatory field using relevance function
|
|
262
|
+
mandatory_rule_id = self.generate_id(f"rule_{node.get_name()}_mandatory")
|
|
263
|
+
mandatory_action_id = self.generate_id(f"action_{mandatory_rule_id}")
|
|
264
|
+
|
|
265
|
+
mandatory_program_rule_action = {
|
|
266
|
+
"id": mandatory_action_id,
|
|
267
|
+
"programRuleActionType": "SETMANDATORYFIELD",
|
|
268
|
+
"dataElement": {
|
|
269
|
+
"id": self.generate_id(self.get_export_name(node))
|
|
270
|
+
},
|
|
271
|
+
"programRule": {"id": mandatory_rule_id}
|
|
272
|
+
}
|
|
273
|
+
self.program_rule_actions.append(mandatory_program_rule_action)
|
|
274
|
+
|
|
275
|
+
# Create program rule for mandatory field - use relevance condition if available
|
|
276
|
+
mandatory_condition = relevance_str if relevance_str and relevance_str != 'false' else "true"
|
|
277
|
+
self.program_rules.append({
|
|
278
|
+
"id": mandatory_rule_id,
|
|
279
|
+
"name": f"Make `{self.get_export_name(node)}` mandatory",
|
|
280
|
+
"description": f"Set `{self.get_display(node)[:128]}` as mandatory field",
|
|
281
|
+
"condition": mandatory_condition,
|
|
282
|
+
"programRuleActions": [{"id": mandatory_action_id}]
|
|
283
|
+
})
|
|
284
|
+
|
|
250
285
|
return True
|
|
251
286
|
|
|
252
287
|
def generate_data_element(self, node):
|
|
@@ -512,8 +547,16 @@ class DHIS2Strategy(BaseOutPutStrategy):
|
|
|
512
547
|
return False
|
|
513
548
|
|
|
514
549
|
if node not in processed_nodes:
|
|
550
|
+
logger.debug(f"generate_export processing node: {node.get_name()} type: {type(node)}")
|
|
551
|
+
# Special handling for TriccNodeNote - transform into section description
|
|
552
|
+
if isinstance(node, TriccNodeNote):
|
|
553
|
+
logger.info(f"Found TriccNodeNote: {node.get_name()}")
|
|
554
|
+
self.handle_note_as_section_description(node, processed_nodes, **kwargs)
|
|
555
|
+
elif isinstance(node, TriccNodeMoreInfo):
|
|
556
|
+
logger.info(f"Found TriccNodeMoreInfo: {node.get_name()}")
|
|
557
|
+
self.handle_note_as_section_description(node, processed_nodes, **kwargs)
|
|
515
558
|
# Skip creating data elements for calculate nodes - they should only be program rule variables
|
|
516
|
-
|
|
559
|
+
elif not issubclass(node.__class__, TriccNodeCalculateBase):
|
|
517
560
|
data_element = self.generate_data_element(node)
|
|
518
561
|
if data_element:
|
|
519
562
|
# Add to program stage
|
|
@@ -522,7 +565,7 @@ class DHIS2Strategy(BaseOutPutStrategy):
|
|
|
522
565
|
psde = {
|
|
523
566
|
"id": psde_id,
|
|
524
567
|
"dataElement": {"id": data_element["id"]},
|
|
525
|
-
"compulsory":
|
|
568
|
+
"compulsory": False
|
|
526
569
|
}
|
|
527
570
|
self.program_metadata["programStages"][-1]["programStageDataElements"].append(psde)
|
|
528
571
|
|
|
@@ -532,6 +575,115 @@ class DHIS2Strategy(BaseOutPutStrategy):
|
|
|
532
575
|
|
|
533
576
|
return True
|
|
534
577
|
|
|
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"""
|
|
580
|
+
logger.info(f"Processing note {node.get_name()} for section description")
|
|
581
|
+
if not self.current_section or self.current_section not in self.sections:
|
|
582
|
+
logger.warning(f"No current section found for note {node.get_name()}")
|
|
583
|
+
return
|
|
584
|
+
|
|
585
|
+
# 1. Duplicate the previous section with incremented ID (like XLS form group numbering)
|
|
586
|
+
original_section = self.sections[self.current_section]
|
|
587
|
+
section_name = f"{original_section['name']}_{node.name}"
|
|
588
|
+
duplicated_section_id = self.generate_id(section_name)
|
|
589
|
+
duplicated_section = {
|
|
590
|
+
"id": duplicated_section_id,
|
|
591
|
+
"name": section_name, # Use incremented naming pattern
|
|
592
|
+
"sortOrder": len(self.sections),
|
|
593
|
+
"programStage": {"id": self.program_metadata["programStages"][-1]["id"]},
|
|
594
|
+
"dataElements": original_section.get("dataElements", []).copy(), # Copy data elements
|
|
595
|
+
"activity_ref": original_section.get("activity_ref")
|
|
596
|
+
}
|
|
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
|
+
|
|
605
|
+
# 2. Create a new section for the note/moreinfo with name and ID from the node
|
|
606
|
+
note_section_id = self.generate_id(self.get_export_name(node))
|
|
607
|
+
note_section_name = self.get_export_name(node)
|
|
608
|
+
|
|
609
|
+
note_section = {
|
|
610
|
+
"id": note_section_id,
|
|
611
|
+
"name": note_section_name,
|
|
612
|
+
"sortOrder": len(self.sections),
|
|
613
|
+
"programStage": {"id": self.program_metadata["programStages"][-1]["id"]},
|
|
614
|
+
"dataElements": [],
|
|
615
|
+
"activity_ref": original_section.get("activity_ref") # Same activity reference
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
# Set section description to the note's label
|
|
619
|
+
if hasattr(node, 'label') and node.label:
|
|
620
|
+
note_section["description"] = node.label.replace('\u00a0', ' ').strip()
|
|
621
|
+
logger.info(f"Set note section {note_section_id} description to: {note_section['description']}")
|
|
622
|
+
elif hasattr(node, 'name') and node.name:
|
|
623
|
+
note_section["description"] = node.name.replace('\u00a0', ' ').strip()
|
|
624
|
+
logger.info(f"Set note section {note_section_id} description to: {note_section['description']}")
|
|
625
|
+
else:
|
|
626
|
+
note_section["description"] = str(node.id)
|
|
627
|
+
logger.info(f"Set note section {note_section_id} description to: {note_section['description']}")
|
|
628
|
+
|
|
629
|
+
self.sections[note_section_id] = note_section
|
|
630
|
+
|
|
631
|
+
# Add note section to program stage
|
|
632
|
+
if self.program_metadata["programStages"]:
|
|
633
|
+
self.program_metadata["programStages"][-1]["programStageSections"].append({"id": note_section_id})
|
|
634
|
+
|
|
635
|
+
logger.info(f"Created note section {note_section_id} with name '{note_section_name}'")
|
|
636
|
+
|
|
637
|
+
# 3. Inject the duplicated section as the new current section
|
|
638
|
+
self.current_section = duplicated_section_id
|
|
639
|
+
logger.info(f"Set current section to duplicated section {duplicated_section_id}")
|
|
640
|
+
|
|
641
|
+
# Create hide logic for the note section based on combined relevance
|
|
642
|
+
combined_relevance = None
|
|
643
|
+
|
|
644
|
+
# Get parent activity relevance from the original section's activity_ref
|
|
645
|
+
parent_activity = original_section.get("activity_ref")
|
|
646
|
+
if parent_activity and hasattr(parent_activity, 'relevance') and parent_activity.relevance:
|
|
647
|
+
combined_relevance = parent_activity.relevance
|
|
648
|
+
|
|
649
|
+
# Combine with note relevance if it exists
|
|
650
|
+
if hasattr(node, 'relevance') and node.relevance:
|
|
651
|
+
if combined_relevance:
|
|
652
|
+
# Combine using AND operation
|
|
653
|
+
combined_relevance = TriccOperation(
|
|
654
|
+
TriccOperator.AND,
|
|
655
|
+
[combined_relevance, node.relevance]
|
|
656
|
+
)
|
|
657
|
+
else:
|
|
658
|
+
combined_relevance = node.relevance
|
|
659
|
+
|
|
660
|
+
# Create hide logic if there's relevance - applied to the note section
|
|
661
|
+
if combined_relevance:
|
|
662
|
+
relevance_str = self.convert_expression_to_string(not_clean(combined_relevance))
|
|
663
|
+
if relevance_str and relevance_str != 'false':
|
|
664
|
+
# Create program rule action for hiding the note section
|
|
665
|
+
rule_id = self.generate_id(f"rule_{node.get_name()}_note_hide_section")
|
|
666
|
+
action_id = self.generate_id(f"action_{rule_id}")
|
|
667
|
+
|
|
668
|
+
program_rule_action = {
|
|
669
|
+
"id": action_id,
|
|
670
|
+
"programRuleActionType": "HIDESECTION",
|
|
671
|
+
"activity_ref": parent_activity, # Use activity reference like other HIDESECTION actions
|
|
672
|
+
"programRule": {"id": rule_id},
|
|
673
|
+
}
|
|
674
|
+
self.program_rule_actions.append(program_rule_action)
|
|
675
|
+
|
|
676
|
+
# Create program rule referencing the action
|
|
677
|
+
condition = self.simplify_expression(f"({relevance_str})==false") # Negate for hide when true
|
|
678
|
+
condition = self.simplify_expression(condition)
|
|
679
|
+
self.program_rules.append({
|
|
680
|
+
"id": rule_id,
|
|
681
|
+
"name": f"Hide note section `{note_section_name}` based on relevance",
|
|
682
|
+
"description": f"Hide note section `{self.get_display(node)[:128]}` based on combined relevance",
|
|
683
|
+
"condition": condition,
|
|
684
|
+
"programRuleActions": [{"id": action_id}]
|
|
685
|
+
})
|
|
686
|
+
|
|
535
687
|
def clean_section(self, program_stages_payload):
|
|
536
688
|
"""Clean sections by removing empty ones and merging sections with same activity_ref"""
|
|
537
689
|
sections_to_remove = set()
|
|
@@ -542,11 +694,11 @@ class DHIS2Strategy(BaseOutPutStrategy):
|
|
|
542
694
|
section_id = section["id"]
|
|
543
695
|
activity_ref = section.get("activity_ref")
|
|
544
696
|
# Remove empty sections
|
|
545
|
-
if not section.get("dataElements"):
|
|
697
|
+
if not section.get("dataElements") and not section.get("description"):
|
|
546
698
|
sections_to_remove.add(section_id)
|
|
547
699
|
|
|
548
700
|
# Check for sections with same activity_ref
|
|
549
|
-
elif activity_ref == prev_activity_ref:
|
|
701
|
+
elif activity_ref == prev_activity_ref and not section.get("description"):
|
|
550
702
|
# Merge this section into the existing one
|
|
551
703
|
existing_section = self.sections[prev_section_id]
|
|
552
704
|
|
|
@@ -645,6 +797,8 @@ class DHIS2Strategy(BaseOutPutStrategy):
|
|
|
645
797
|
# Non-activity actions (HIDEFIELD) can be added directly
|
|
646
798
|
program_rule_actions_payload.append(action)
|
|
647
799
|
|
|
800
|
+
# Filter out rules that reference non-existent actions
|
|
801
|
+
valid_action_ids = {action["id"] for action in program_rule_actions_payload}
|
|
648
802
|
if self.program_rules:
|
|
649
803
|
program_rules_payload = [
|
|
650
804
|
{
|
|
@@ -652,6 +806,7 @@ class DHIS2Strategy(BaseOutPutStrategy):
|
|
|
652
806
|
"program": {"id": self.program_metadata["id"]}
|
|
653
807
|
}
|
|
654
808
|
for rule in self.program_rules
|
|
809
|
+
if all(action_ref["id"] in valid_action_ids for action_ref in rule["programRuleActions"])
|
|
655
810
|
]
|
|
656
811
|
|
|
657
812
|
if self.program_rule_variables:
|
|
@@ -97,7 +97,7 @@ class FHIRStrategy(BaseOutPutStrategy):
|
|
|
97
97
|
"type": self.map_tricc_type_to_fhir(node.tricc_type if hasattr(node, 'tricc_type') else 'text')
|
|
98
98
|
}
|
|
99
99
|
if hasattr(node, 'options') and node.options:
|
|
100
|
-
item["answerOption"] = [{"valueString": opt.name} for opt in node.options]
|
|
100
|
+
item["answerOption"] = [{"valueString": opt.name} for opt in node.options.values()]
|
|
101
101
|
self.questionnaires[segment]["item"].append(item)
|
|
102
102
|
return True
|
|
103
103
|
|
tricc_oo/visitors/tricc.py
CHANGED
|
@@ -1758,6 +1758,11 @@ def reorder_node_list(node_list, group, processed_nodes):
|
|
|
1758
1758
|
# Check for same group
|
|
1759
1759
|
if group is not None and node_group and node_group.id == group.id:
|
|
1760
1760
|
priority += SAME_GROUP_PRIORITY
|
|
1761
|
+
elif (
|
|
1762
|
+
issubclass(node.__class__, TriccNodeDisplayCalculateBase) or
|
|
1763
|
+
isinstance(node, TriccNodeEnd)
|
|
1764
|
+
) and not isinstance(node, TriccNodeActivityEnd) and hasattr(node, 'prev_nodes') and len(node.prev_nodes) > 0:
|
|
1765
|
+
priority += FLOW_CALCULATE_NODE_PRIORITY
|
|
1761
1766
|
# Check for parent group
|
|
1762
1767
|
elif hasattr(group, "group") and group.group and node_group and node_group.id == group.group.id:
|
|
1763
1768
|
priority += PARENT_GROUP_PRIORITY
|
|
@@ -10,7 +10,7 @@ tricc_oo/converters/datadictionnary.py,sha256=T2HLCBo4Am1p0kFqSH1r0PqbD8AC2IGuWk
|
|
|
10
10
|
tricc_oo/converters/drawio_type_map.py,sha256=UCPiGs7Lw0bigKScmZUnmOhACBz-FiDq92jHkI7RTSQ,9113
|
|
11
11
|
tricc_oo/converters/tricc_to_xls_form.py,sha256=wsWv4aA0QssY7ry9R7KsuuMzVfovj9fwE3i9AtCum0c,3842
|
|
12
12
|
tricc_oo/converters/utils.py,sha256=JZrtrvvOfXwdkw49pKauzinOcauWwsy-CVcw36TjyLo,1684
|
|
13
|
-
tricc_oo/converters/xml_to_tricc.py,sha256=
|
|
13
|
+
tricc_oo/converters/xml_to_tricc.py,sha256=yqnU5xg1SVoQ8vra0gOvIPwoh80pyTI332y9qJCvcRs,39654
|
|
14
14
|
tricc_oo/converters/cql/cqlLexer.py,sha256=8HArbRphcrpnAG4uogJ2rHv4tc1WLzjN0B1uFeYILAc,49141
|
|
15
15
|
tricc_oo/converters/cql/cqlListener.py,sha256=fA7-8DcS2Q69ckwjdg57-OfFHBxjTZFdoSKrtw7Hffc,57538
|
|
16
16
|
tricc_oo/converters/cql/cqlParser.py,sha256=x3KdrwX9nwENSEJ5Ex7_l5NMnu3kWBO0uLdYu4moTq0,414745
|
|
@@ -32,8 +32,8 @@ tricc_oo/strategies/input/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
|
|
|
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=
|
|
36
|
-
tricc_oo/strategies/output/fhir_form.py,sha256=
|
|
35
|
+
tricc_oo/strategies/output/dhis2_form.py,sha256=RFMUrB3TNJJi3kecBVThY6X1GF_TVk8XgXkye8fRkIc,47035
|
|
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
|
|
@@ -42,11 +42,11 @@ tricc_oo/strategies/output/xlsform_cdss.py,sha256=X00Lt5MzV8TX14dR4dFI1MqllI5S1e
|
|
|
42
42
|
tricc_oo/strategies/output/xlsform_cht.py,sha256=eKAc6LLDnvdZ5m8a2Vk6eAhvPbUvOfykgYr0ou3an9k,27164
|
|
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=
|
|
45
|
+
tricc_oo/visitors/tricc.py,sha256=_UzAylSHuAhfXXPUBV_PJIhta5ihbJhLDe3GJAwxQzU,110598
|
|
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.
|
|
49
|
-
tricc_oo-1.6.
|
|
50
|
-
tricc_oo-1.6.
|
|
51
|
-
tricc_oo-1.6.
|
|
52
|
-
tricc_oo-1.6.
|
|
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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|