Moved some repeated code in BoM writers.
All the writers computed some stats. Now they are computed in one place avoiding repetition.
This commit is contained in:
parent
670e379f65
commit
64576e3975
|
|
@ -32,6 +32,11 @@ def write_bom(filename, ext, groups, headings, cfg):
|
|||
# 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
|
||||
# Some stats
|
||||
cfg.n_groups = len(groups)
|
||||
cfg.n_total = sum([g.get_count() for g in groups])
|
||||
cfg.n_fitted = sum([g.get_count() for g in groups if g.is_fitted()])
|
||||
cfg.n_build = cfg.n_fitted * cfg.number
|
||||
# CSV file writing
|
||||
if ext in ["csv", "tsv", "txt"]:
|
||||
result = write_csv(filename, ext, groups, headings, head_names, cfg)
|
||||
|
|
|
|||
|
|
@ -27,11 +27,6 @@ def write_csv(filename, ext, groups, headings, head_names, cfg):
|
|||
elif ext == "tsv" or ext == "txt":
|
||||
delimiter = "\t"
|
||||
|
||||
n_groups = len(groups)
|
||||
n_total = sum([g.get_count() for g in groups])
|
||||
n_fitted = sum([g.get_count() for g in groups if g.is_fitted()])
|
||||
n_build = n_fitted * cfg.number
|
||||
|
||||
with open(filename, "wt") as f:
|
||||
writer = csv.writer(f, delimiter=delimiter, lineterminator="\n")
|
||||
# Headers
|
||||
|
|
@ -63,11 +58,11 @@ def write_csv(filename, ext, groups, headings, head_names, cfg):
|
|||
for i in range(5):
|
||||
writer.writerow([])
|
||||
|
||||
writer.writerow(["Component Groups:", n_groups])
|
||||
writer.writerow(["Component Count:", n_total])
|
||||
writer.writerow(["Fitted Components:", n_fitted])
|
||||
writer.writerow(["Component Groups:", cfg.n_groups])
|
||||
writer.writerow(["Component Count:", cfg.n_total])
|
||||
writer.writerow(["Fitted Components:", cfg.n_fitted])
|
||||
writer.writerow(["Number of PCBs:", cfg.number])
|
||||
writer.writerow(["Total components:", n_build])
|
||||
writer.writerow(["Total components:", cfg.n_build])
|
||||
writer.writerow(["Schematic Revision:", cfg.revision])
|
||||
writer.writerow(["Schematic Date:", cfg.date])
|
||||
writer.writerow(["PCB Variant:", ' + '.join(cfg.variant)])
|
||||
|
|
|
|||
|
|
@ -84,11 +84,6 @@ def write_html(filename, groups, headings, head_names, cfg):
|
|||
head_names = [list of headings to display in the BoM file]
|
||||
prefs = BomPref object
|
||||
"""
|
||||
n_groups = len(groups)
|
||||
n_total = sum([g.get_count() for g in groups])
|
||||
n_fitted = sum([g.get_count() for g in groups if g.is_fitted()])
|
||||
n_build = n_fitted * cfg.number
|
||||
|
||||
link_datasheet = cfg.datasheet_as_link
|
||||
link_digikey = None
|
||||
if cfg.digikey_link:
|
||||
|
|
@ -107,18 +102,18 @@ def write_html(filename, groups, headings, head_names, cfg):
|
|||
html.write("<h2>KiBoM PCB Bill of Materials</h2>\n")
|
||||
if not cfg.hide_pcb_info:
|
||||
html.write('<table border="1">\n')
|
||||
html.write("<tr><td>Source File</td><td>{source}</td></tr>\n".format(source=cfg.source))
|
||||
html.write("<tr><td>Source File</td><td>{}</td></tr>\n".format(cfg.source))
|
||||
# html.write("<tr><td>BoM Date</td><td>{date}</td></tr>\n".format(date=cfg.date)) Same as schematic
|
||||
html.write("<tr><td>Schematic Revision</td><td>{version}</td></tr>\n".format(version=cfg.revision))
|
||||
html.write("<tr><td>Schematic Date</td><td>{date}</td></tr>\n".format(date=cfg.date))
|
||||
html.write("<tr><td>PCB Variant</td><td>{variant}</td></tr>\n".format(variant=', '.join(cfg.variant)))
|
||||
html.write("<tr><td>Schematic Revision</td><td>{}</td></tr>\n".format(cfg.revision))
|
||||
html.write("<tr><td>Schematic Date</td><td>{}</td></tr>\n".format(cfg.date))
|
||||
html.write("<tr><td>PCB Variant</td><td>{}</td></tr>\n".format(', '.join(cfg.variant)))
|
||||
# html.write("<tr><td>KiCad Version</td><td>{version}</td></tr>\n".format(version=net.getTool())) TODO?
|
||||
html.write("<tr><td>Component Groups</td><td>{n}</td></tr>\n".format(n=n_groups))
|
||||
html.write("<tr><td>Component Count (per PCB)</td><td>{n}</td></tr>\n".format(n=n_total))
|
||||
html.write("<tr><td>Fitted Components (per PCB)</td><td>{n}</td></tr>\n".format(n=n_fitted))
|
||||
html.write("<tr><td>Number of PCBs</td><td>{n}</td></tr>\n".format(n=cfg.number))
|
||||
html.write("<tr><td>Component Groups</td><td>{}</td></tr>\n".format(cfg.n_groups))
|
||||
html.write("<tr><td>Component Count (per PCB)</td><td>{}</td></tr>\n".format(cfg.n_total))
|
||||
html.write("<tr><td>Fitted Components (per PCB)</td><td>{}</td></tr>\n".format(cfg.n_fitted))
|
||||
html.write("<tr><td>Number of PCBs</td><td>{}</td></tr>\n".format(cfg.number))
|
||||
html.write("<tr><td>Total Component Count<br>(for {n} PCBs)</td><td>{t}</td></tr>\n".
|
||||
format(n=cfg.number, t=n_build))
|
||||
format(n=cfg.number, t=cfg.n_build))
|
||||
html.write("</table>\n")
|
||||
html.write("<br>\n")
|
||||
|
||||
|
|
|
|||
|
|
@ -65,11 +65,6 @@ def write_xlsx(filename, groups, col_fields, head_names, cfg):
|
|||
logger.error('Python xlsxwriter module not installed (Debian: python3-xlsxwriter)')
|
||||
return False
|
||||
|
||||
n_groups = len(groups)
|
||||
n_total = sum([g.get_count() for g in groups])
|
||||
n_fitted = sum([g.get_count() for g in groups if g.is_fitted()])
|
||||
n_build = n_fitted * cfg.number
|
||||
|
||||
workbook = Workbook(filename)
|
||||
worksheet = workbook.add_worksheet()
|
||||
|
||||
|
|
@ -136,11 +131,11 @@ def write_xlsx(filename, groups, col_fields, head_names, cfg):
|
|||
title_fmt.set_bold()
|
||||
|
||||
formats = [title_fmt, cellformat_left]
|
||||
row_count = add_info(worksheet, column_widths, row_count, formats, "Component Groups:", n_groups)
|
||||
row_count = add_info(worksheet, column_widths, row_count, formats, "Component Count:", n_total)
|
||||
row_count = add_info(worksheet, column_widths, row_count, formats, "Fitted Components:", n_fitted)
|
||||
row_count = add_info(worksheet, column_widths, row_count, formats, "Component Groups:", cfg.n_groups)
|
||||
row_count = add_info(worksheet, column_widths, row_count, formats, "Component Count:", cfg.n_total)
|
||||
row_count = add_info(worksheet, column_widths, row_count, formats, "Fitted Components:", cfg.n_fitted)
|
||||
row_count = add_info(worksheet, column_widths, row_count, formats, "Number of PCBs:", cfg.number)
|
||||
row_count = add_info(worksheet, column_widths, row_count, formats, "Total components:", n_build)
|
||||
row_count = add_info(worksheet, column_widths, row_count, formats, "Total components:", cfg.n_build)
|
||||
row_count = add_info(worksheet, column_widths, row_count, formats, "Schematic Revision:", cfg.revision)
|
||||
row_count = add_info(worksheet, column_widths, row_count, formats, "Schematic Date:", cfg.date)
|
||||
# row_count = add_info(worksheet, column_widths, row_count, formats, "BoM Date:", cfg.date) Same as sch
|
||||
|
|
|
|||
|
|
@ -17,11 +17,6 @@ def write_xml(filename, groups, headings, head_names, cfg):
|
|||
headings = [list of headings to display in the BoM file]
|
||||
cfg = BomPref object
|
||||
"""
|
||||
n_groups = len(groups)
|
||||
n_total = sum([g.get_count() for g in groups])
|
||||
n_fitted = sum([g.get_count() for g in groups if g.is_fitted()])
|
||||
n_build = n_fitted * cfg.number
|
||||
|
||||
attrib = {}
|
||||
attrib['Schematic_Source'] = cfg.source
|
||||
attrib['Schematic_Revision'] = cfg.revision
|
||||
|
|
@ -29,11 +24,11 @@ def write_xml(filename, groups, headings, head_names, cfg):
|
|||
attrib['PCB_Variant'] = ', '.join(cfg.variant)
|
||||
# attrib['BOM_Date'] = net.getDate() same as schematic
|
||||
# attrib['KiCad_Version'] = net.getTool() TODO?
|
||||
attrib['Component_Groups'] = str(n_groups)
|
||||
attrib['Component_Count'] = str(n_total)
|
||||
attrib['Fitted_Components'] = str(n_fitted)
|
||||
attrib['Component_Groups'] = str(cfg.n_groups)
|
||||
attrib['Component_Count'] = str(cfg.n_total)
|
||||
attrib['Fitted_Components'] = str(cfg.n_fitted)
|
||||
attrib['Number_of_PCBs'] = str(cfg.number)
|
||||
attrib['Total_Components'] = str(n_build)
|
||||
attrib['Total_Components'] = str(cfg.n_build)
|
||||
|
||||
xml = ElementTree.Element('KiCad_BOM', attrib=attrib, encoding='utf-8')
|
||||
for group in groups:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
"""
|
||||
KiCad configuration classes.
|
||||
|
||||
Notes about coverage:
|
||||
I'm excluding all the Darwin and Windows code from coverage.
|
||||
I don't know how to test it on GitHub CI/CD.
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
|
|
@ -14,7 +18,8 @@ from .. import log
|
|||
# Check python version to determine which version of ConfirParser to import
|
||||
if sys.version_info.major >= 3:
|
||||
import configparser as ConfigParser
|
||||
else:
|
||||
else: # pragma: no cover
|
||||
# For future Python 2 support
|
||||
import ConfigParser
|
||||
|
||||
logger = log.get_logger(__name__)
|
||||
|
|
@ -71,10 +76,10 @@ class LibAlias(object):
|
|||
lib.descr = un_quote(m.group(5))
|
||||
return lib
|
||||
|
||||
def __str__(self):
|
||||
if not self.name:
|
||||
return 'empty LibAlias'
|
||||
return self.name+' -> `'+self.uri+'`'
|
||||
# def __str__(self):
|
||||
# if not self.name:
|
||||
# return 'empty LibAlias'
|
||||
# return self.name+' -> `'+self.uri+'`'
|
||||
|
||||
|
||||
class KiConf(object):
|
||||
|
|
@ -125,7 +130,7 @@ class KiConf(object):
|
|||
cfg = os.path.join(home, '.config', 'kicad', KICAD_COMMON)
|
||||
if os.path.isfile(cfg):
|
||||
return cfg
|
||||
elif system == 'Darwin':
|
||||
elif system == 'Darwin': # pragma: no cover
|
||||
# MacOSX: ~/Library/Preferences/kicad/
|
||||
home = os.environ.get('HOME')
|
||||
if not home:
|
||||
|
|
@ -134,7 +139,7 @@ class KiConf(object):
|
|||
cfg = os.path.join(home, 'Library', 'Preferences', 'kicad', KICAD_COMMON)
|
||||
if os.path.isfile(cfg):
|
||||
return cfg
|
||||
elif system == 'Windows':
|
||||
elif system == 'Windows': # pragma: no cover
|
||||
# Windows: C:\Users\username\AppData\Roaming\kicad
|
||||
# or C:\Documents and Settings\username\Application Data\kicad
|
||||
username = os.environ.get('username')
|
||||
|
|
@ -173,7 +178,7 @@ class KiConf(object):
|
|||
dir = os.path.join(sysconfig.get_path('data', 'posix_prefix'), share)
|
||||
if os.path.isdir(dir):
|
||||
return dir
|
||||
elif system == 'Darwin':
|
||||
elif system == 'Darwin': # pragma: no cover
|
||||
app_data = os.path.join('Library', 'Application Support', 'kicad', 'library')
|
||||
home = os.environ.get('HOME')
|
||||
if home:
|
||||
|
|
@ -183,7 +188,7 @@ class KiConf(object):
|
|||
dir = os.path.join('/', app_data)
|
||||
if os.path.isdir(dir):
|
||||
return dir
|
||||
elif system == 'Windows':
|
||||
elif system == 'Windows': # pragma: no cover
|
||||
dir = os.path.join('C:', 'Program Files', 'KiCad', share)
|
||||
if os.path.isdir(dir):
|
||||
return dir
|
||||
|
|
|
|||
|
|
@ -262,6 +262,8 @@ class BoM(BaseOutput): # noqa: F821
|
|||
Used to generate the BoM in CSV, HTML, TSV, TXT, XML or XLSX format using the internal BoM.
|
||||
Is compatible with KiBoM, but doesn't need to update the XML netlist because the components
|
||||
are loaded from the schematic.
|
||||
Important differences with KiBoM output:
|
||||
- All options are in the main `options` section, not in `conf` subsection.
|
||||
This output is what you get from the 'Tools/Generate Bill of Materials' menu in eeschema. """
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
|
|
|||
Loading…
Reference in New Issue