Move BOM sorting above grouping to use groupby()

- Use one common entry loop to consume iterator only once.
- Use same key function for sort() and groupby(),
  except replace None with empty string when sorting.
This commit is contained in:
KV 2020-11-27 01:16:26 +01:00
parent 10b1198b77
commit cdca708da9

View File

@ -1,8 +1,8 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from collections import Counter
from dataclasses import asdict from dataclasses import asdict
from itertools import groupby
from typing import Any, List, Tuple, Union from typing import Any, List, Tuple, Union
from wireviz.DataClasses import AdditionalComponent, Connector, Cable from wireviz.DataClasses import AdditionalComponent, Connector, Cable
@ -100,17 +100,20 @@ def generate_bom(harness):
# remove line breaks if present and cleanup any resulting whitespace issues # remove line breaks if present and cleanup any resulting whitespace issues
bom_entries = [{k: clean_whitespace(v) for k, v in entry.items()} for entry in bom_entries] bom_entries = [{k: clean_whitespace(v) for k, v in entry.items()} for entry in bom_entries]
# Sort entries to prepare grouping on the same key function.
bom_entries.sort(key=lambda entry: tuple(attr or '' for attr in bom_types_group(entry)))
# deduplicate bom # deduplicate bom
bom = [] bom = []
for group in Counter([bom_types_group(v) for v in bom_entries]): for _, group in groupby(bom_entries, bom_types_group):
group_entries = [v for v in bom_entries if bom_types_group(v) == group] last_entry = None
total_qty = 0
designators = [] designators = []
for group_entry in group_entries: for group_entry in group:
designators.extend(make_list(group_entry.get('designators'))) designators.extend(make_list(group_entry.get('designators')))
total_qty = sum(entry['qty'] for entry in group_entries) total_qty += group_entry['qty']
bom.append({**group_entries[0], 'qty': round(total_qty, 3), 'designators': sorted(set(designators))}) last_entry = group_entry
bom.append({**last_entry, 'qty': round(total_qty, 3), 'designators': sorted(set(designators))})
bom = sorted(bom, key=lambda k: k['item']) # sort list of dicts by their values (https://stackoverflow.com/a/73050)
# add an incrementing id to each bom item # add an incrementing id to each bom item
return [{**entry, 'id': index} for index, entry in enumerate(bom, 1)] return [{**entry, 'id': index} for index, entry in enumerate(bom, 1)]