Simplified the columns logic for the internal BoM.

The ColumnList class now is just a place holder for column names.
We just create the list of columns from the user preferences or
creating a good default and then we just use this list.
This commit is contained in:
Salvador E. Tropea 2020-08-01 20:15:33 -03:00
parent 71c87bf2ea
commit 547c3a22bb
5 changed files with 21 additions and 72 deletions

View File

@ -4,6 +4,7 @@ This code is adapted from https://github.com/SchrodingersGat/KiBoM by Oliver Hen
Here is all the logic to convert a list of components into the rows and columns used to create the BoM.
"""
from copy import deepcopy
from .units import compare_values, comp_match
from .bom_writer import write_bom
from .columnlist import ColumnList
@ -153,7 +154,7 @@ class ComponentGroup(object):
self.cfg = cfg
# Columns loaded from KiCad
self.fields = {c.lower(): None for c in ColumnList.COLUMNS_DEFAULT}
self.field_names = ColumnList.COLUMNS_DEFAULT
self.field_names = deepcopy(ColumnList.COLUMNS_DEFAULT)
def match_component(self, c):
""" Test if a given component fits in this group """
@ -455,21 +456,9 @@ def do_bom(file_name, ext, comps, cfg):
c.fixed = comp_is_fixed(value, config, variants)
# Group components according to group_fields
groups = group_components(cfg, comps)
# Create the columns
columns = ColumnList(cfg.columns)
# Read out all available fields
# TODO: get cached from the list?
for g in groups:
for f in g.field_names:
columns.add_column(f)
# Don't add 'boards' column if only one board is specified
# TODO: Shouldn't be the other way (add if needed)
if cfg.number <= 1:
columns.remove_column(ColumnList.COL_GRP_BUILD_QUANTITY)
logger.debug("Removing: "+ColumnList.COL_GRP_BUILD_QUANTITY)
# Give a name to empty variant
if not variants:
cfg.variant = ['default']
# Create the BoM
logger.debug("Saving BOM File: "+file_name)
write_bom(file_name, ext, groups, columns.columns, cfg)
write_bom(file_name, ext, groups, cfg.columns, cfg)

View File

@ -27,8 +27,6 @@ def write_bom(filename, ext, groups, headings, cfg):
headings = [list of fields to use as columns]
cfg = configuration data
"""
# Remove any headings that appear in the ignore[] list
headings = [h for h in headings if not h.lower() in cfg.ignore]
# Allow renaming the columns
head_names = [h if h.lower() not in cfg.column_rename else cfg.column_rename[h.lower()] for h in headings]
result = False

View File

@ -33,8 +33,6 @@ class ColumnList:
# Default columns for groups
COL_GRP_QUANTITY = 'Quantity Per PCB'
COL_GRP_QUANTITY_L = COL_GRP_QUANTITY.lower()
# COL_GRP_TOTAL_COST = 'Total Cost'
# COL_GRP_TOTAL_COST_L = COL_GRP_TOTAL_COST.lower()
COL_GRP_BUILD_QUANTITY = 'Build Quantity'
COL_GRP_BUILD_QUANTITY_L = COL_GRP_BUILD_QUANTITY.lower()
@ -84,44 +82,3 @@ class ColumnList:
COL_FP_L,
COL_FP_LIB_L,
]
def __init__(self, cols=None):
self.columns = []
self.columns_l = {}
if not cols:
cols = ColumnList.COLUMNS_DEFAULT
# Make a copy of the supplied columns
for col in cols:
self.add_column(col)
def _has_column(self, col):
return col.lower() in self.columns_l
def add_column(self, col):
""" Add a new column (if it doesn't already exist!) """
# Already exists?
if self._has_column(col):
return
# To enable fast lowercase search
self.columns_l[col.lower()] = col
# Case sensitive version
self.columns.append(col)
def remove_column(self, col):
""" Remove a column from the list. Specify either the heading or the index """
if type(col) is str:
self.remove_column_by_name(col)
elif type(col) is int and col >= 0 and col < len(self.columns):
self.remove_column_by_name(self.columns[col])
def remove_column_by_name(self, name):
name = name.lower()
# First check if this is in an immutable colum
if name in self.COLUMNS_PROTECTED_L:
return
# Column does not exist, return
if name not in self.columns_l:
return
name = self.columns_l[name]
index = self.columns.index(name)
del self.columns[index]

View File

@ -195,23 +195,29 @@ class BoMOptions(BaseOptions):
else:
for r in self.exclude_any:
r.regex = compile(r.regex, flags=IGNORECASE)
# columns
# Columns
self.column_rename = {}
self.join = []
valid_columns = self._get_columns()
if isinstance(self.columns, type):
self.columns = None
# Ignore the library part and footprint
self.ignore = [ColumnList.COL_PART_LIB_L, ColumnList.COL_FP_LIB_L, ColumnList.COL_SHEETPATH_L]
# If none specified make a list with all the possible columns.
# Here are some exceptions:
# Ignore the part and footprint library, also sheetpath and the Reference in singular
ignore = [ColumnList.COL_PART_LIB_L, ColumnList.COL_FP_LIB_L, ColumnList.COL_SHEETPATH_L,
ColumnList.COL_REFERENCE_L[:-1]]
if self.number <= 1:
# For one board avoid COL_GRP_BUILD_QUANTITY
ignore.append(ColumnList.COL_GRP_BUILD_QUANTITY_L)
# Exclude the particular columns
self.columns = [h for h in valid_columns if not h.lower() in ignore]
else:
# This is tricky
# Lower case available columns
valid_columns = self._get_columns()
valid_columns.append(ColumnList.COL_ROW_NUMBER)
# Ensure the column names are valid.
# Also create the rename and join lists.
# Lower case available columns (to check if valid)
valid_columns_l = {c.lower(): c for c in valid_columns}
logger.debug("Valid columns: "+str(valid_columns))
# Create the different lists
columns = []
columns_l = {}
for col in self.columns:
if isinstance(col, str):
# Just a string, add to the list of used
@ -229,10 +235,7 @@ class BoMOptions(BaseOptions):
if new_col.lower() not in valid_columns_l:
raise KiPlotConfigurationError('Invalid column name `{}`'.format(new_col))
columns.append(new_col)
columns_l[new_col.lower()] = new_col
# Create a list of the columns we don't want
self.ignore = [c for c in valid_columns_l.keys() if c not in columns_l]
# And this is the ordered list with the case style defined by the user
# This is the ordered list with the case style defined by the user
self.columns = columns
def run(self, output_dir, board):

View File

@ -30,6 +30,8 @@ Missing:
- number_boards
- hide_headers
- hide_pcb_info
- various boards
- stats info
For debug information use:
pytest-3 --log-cli-level debug