diff --git a/mlx/traceability/directives/item_pie_chart_directive.py b/mlx/traceability/directives/item_pie_chart_directive.py index f0250e65..e52eccbe 100644 --- a/mlx/traceability/directives/item_pie_chart_directive.py +++ b/mlx/traceability/directives/item_pie_chart_directive.py @@ -72,6 +72,7 @@ def __init__(self, *args, **kwargs): self.target_relationships = [] self.relationship_to_string = {} self.priorities = [] # default priority order is 'uncovered', 'covered', 'executed' + self.labels = [] self.nested_target_regex = re.compile('') self.matches = {} # source_id (str): Match @@ -91,7 +92,7 @@ def perform_replacement(self, app, collection): self.source_relationships = self['sourcetype'] if self['sourcetype'] else self.collection.iter_relations() self.target_relationships = self['targettype'] if self['targettype'] else self.collection.iter_relations() self.relationship_to_string = app.config.traceability_relationship_to_string - self._set_priorities() + self._store_labels() self._set_nested_target_regex() target_regex = re.compile(self['id_set'][1]) for source_id in self.collection.get_items(self['id_set'][0], self['filter-attributes']): @@ -107,8 +108,7 @@ def perform_replacement(self, app, collection): report_warning("item-piechart can contain up to {} slices but only {} colors have been provided: some " "colors may be reused".format(len(self.priorities), len(self['colors'])), self['document'], self['line']) - data, statistics = self._prepare_labels_and_values(self.priorities, - [x.label for x in self.matches.values()], + data, statistics = self._prepare_labels_and_values([x.label for x in self.matches.values()], self['colors']) if data['labels']: top_node += self.build_pie_chart(data['sizes'], data['labels'], data['colors'], env) @@ -139,17 +139,23 @@ def _relationships_to_labels(self, relationships): labels.append(self.relationship_to_string[reverse_relationship].lower()) return labels - def _set_priorities(self): - """ Initializes the priorities list with labels, sort by priority from low to high. """ + def _store_labels(self): + """ Stores all labels """ self.priorities = list(self['label_set']) + self.labels = list(self['label_set']) if self['splitsourcetype'] and self['sourcetype']: - self.priorities.extend(reversed(self._relationships_to_labels(self['sourcetype']))) + sourcetype_labels = self._relationships_to_labels(self['sourcetype']) + self.priorities.extend(sourcetype_labels) + self.labels.extend(sourcetype_labels) + custom_labels = [] if self['attr_values']: - self.priorities.extend(reversed([val.lower() for val in self['attr_values']])) + custom_labels.extend([val.lower() for val in self['attr_values']]) elif self['targettype']: - self.priorities.extend(reversed(self._relationships_to_labels(self['targettype']))) + custom_labels.extend(self._relationships_to_labels(self['targettype'])) + self.priorities.extend(reversed(custom_labels)) + self.labels.extend(custom_labels) def _set_nested_target_regex(self): """ Sets the ``nested_target_regex`` if a third item ID in the id_set option is given. """ @@ -273,12 +279,11 @@ def _match_attribute_values(self, top_source_id, nested_target_item, *_, **__): self._store_linked_label(top_source_id, attribute_value) return True - def _prepare_labels_and_values(self, ordered_labels, discovered_labels, colors): + def _prepare_labels_and_values(self, discovered_labels, colors): """ Keeps case-sensitivity of :<>: arguments in labels and calculates slice size based on the highest-priority label for each relevant item. Args: - ordered_labels (list): List of unique labels (str), ordered by priority from low to high. discovered_labels (list): List of labels with the highest priority for each relevant item. colors (list): List of colors in the order as they are defined @@ -287,16 +292,10 @@ def _prepare_labels_and_values(self, ordered_labels, discovered_labels, colors): (str) Coverage statistics. """ # initialize dictionary for each possible value, and count label occurences - ordered_colors = colors[:len(ordered_labels)] - if len(colors) > 3: - # reverse order for labels specified by :sourcetype: or :<>: or :targettype: - sourcetypes = len(self['sourcetype']) if self['splitsourcetype'] else 0 - ordered_colors[3:3+sourcetypes] = reversed(ordered_colors[3:3+sourcetypes]) - ordered_colors[3+sourcetypes:] = reversed(ordered_colors[3+sourcetypes:]) - + ordered_colors = colors[:len(self.labels)] pie_data = { - 'labels': ordered_labels, - 'sizes': [0] * len(ordered_labels), + 'labels': self.labels, + 'sizes': [0] * len(self.labels), 'colors': ordered_colors, } labels = pie_data['labels'] @@ -412,7 +411,7 @@ def build_table(self, app): """ table = nodes.table() if self['matrix'] == ['']: - self['matrix'] = self.priorities + self['matrix'] = self.labels self['nocaptions'] = True table = nodes.table() if self.get('classes'): diff --git a/mlx/traceability/traceable_collection.py b/mlx/traceability/traceable_collection.py index e5e31502..e56f17ba 100644 --- a/mlx/traceability/traceable_collection.py +++ b/mlx/traceability/traceable_collection.py @@ -206,8 +206,7 @@ def self_test(self, notification_item_id, docname=None): if not self.relations: raise TraceabilityException('No relations configured', 'configuration') # Validate each item - for itemid in self.items: - item = self.get_item(itemid) + for itemid, item in self.items.items(): # Only for relevant items, filtered on document name if docname is not None and item.docname != docname and item.docname is not None: continue