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:
parent
71c87bf2ea
commit
547c3a22bb
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue