From f0985b2623afe25f21112ac5f71795bb6531a4c6 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 16 May 2016 13:44:42 +1000 Subject: [PATCH] Better unicode support across all output formats --- KiBOM/columns.py | 11 ++++++++++- KiBOM/component.py | 20 +++++++++++++++++--- KiBOM/csv_writer.py | 19 ++++++++++++++++--- KiBOM/html_writer.py | 23 ++++++++++++++++++----- KiBOM/xml_writer.py | 36 ++++++++++++++++++++++++------------ 5 files changed, 85 insertions(+), 24 deletions(-) diff --git a/KiBOM/columns.py b/KiBOM/columns.py index 8cceefd3..d6d803f6 100644 --- a/KiBOM/columns.py +++ b/KiBOM/columns.py @@ -12,6 +12,14 @@ class ColumnList: #default columns for groups COL_GRP_QUANTITY = 'Quantity' + COL_GRP_TOTAL_COST = 'Total Cost' #Total cost based on quantity + COL_GRP_BUILD_QUANTITY = 'Build Quantity' + + #generated columns + _COLUMNS_GEN = [ + COL_GRP_QUANTITY, + COL_GRP_BUILD_QUANTITY, + ] #default columns _COLUMNS_DEFAULT = [ @@ -23,6 +31,7 @@ class ColumnList: COL_FP, COL_FP_LIB, COL_GRP_QUANTITY, + COL_GRP_BUILD_QUANTITY, COL_DATASHEET ] @@ -71,7 +80,7 @@ class ColumnList: def RemoveColumnByName(self, name): #first check if this is in an immutable colum - if name in self._COLUMNS_DEFAULT: + if name in self._COLUMNS_PROTECTED: return #column does not exist, return diff --git a/KiBOM/component.py b/KiBOM/component.py index 8c4d4b5f..2a7526b6 100644 --- a/KiBOM/component.py +++ b/KiBOM/component.py @@ -255,9 +255,12 @@ class ComponentGroup(): #update 'global' fields self.fields[ColumnList.COL_REFERENCE] = self.getRefs() + + q = self.getCount() self.fields[ColumnList.COL_GRP_QUANTITY] = "{n}{dnf}".format( - n = self.getCount(), + n=q, dnf = " (DNF)" if not self.isFitted() else "") + self.fields[ColumnList.COL_GRP_BUILD_QUANTITY] = str(q * self.prefs.buildNumber) if self.isFitted() else "0" self.fields[ColumnList.COL_VALUE] = self.components[0].getValue() self.fields[ColumnList.COL_PART] = self.components[0].getPartName() self.fields[ColumnList.COL_PART_LIB] = self.components[0].getLibName() @@ -303,7 +306,18 @@ class ComponentGroup(): #return a dict of the KiCAD data based on the supplied columns + #NOW WITH UNICODE SUPPORT! def getRow(self, columns): - row = [self.getField(key) for key in columns] - #print(row) + row = [] + for key in columns: + val = self.getField(key) + + if val is None: + val = "" + else: + val = u'' + val + val = val.encode('utf-8') + + row.append(val) + return row \ No newline at end of file diff --git a/KiBOM/csv_writer.py b/KiBOM/csv_writer.py index edad802b..5dfc581d 100644 --- a/KiBOM/csv_writer.py +++ b/KiBOM/csv_writer.py @@ -1,3 +1,5 @@ +# _*_ coding:latin-1 _*_ + import csv import columns from component import * @@ -25,6 +27,11 @@ def WriteCSV(filename, groups, net, headings, prefs): else: return False + nGroups = len(groups) + nTotal = sum([g.getCount() for g in groups]) + nFitted = sum([g.getCount() for g in groups if g.isFitted()]) + nBuild = nFitted * prefs.buildNumber + with open(filename, "w") as f: writer = csv.writer(f, delimiter=delimiter, lineterminator="\n") @@ -43,8 +50,10 @@ def WriteCSV(filename, groups, net, headings, prefs): row = group.getRow(headings) if prefs.numberRows: - row = [rowCount] + row + row = [str(rowCount)] + row + #deal with unicode characters + #row = [el.decode('latin-1') for el in row] writer.writerow(row) try: @@ -58,8 +67,12 @@ def WriteCSV(filename, groups, net, headings, prefs): for i in range(5): writer.writerow([]) - writer.writerow(["Component Count:",sum([g.getCount() for g in groups])]) - writer.writerow(["Component Groups:",len(groups)]) + writer.writerow(["Component Groups:",nGroups]) + writer.writerow(["Component Count:",nTotal]) + writer.writerow(["Fitted Components:", nFitted]) + if prefs.buildNumber > 0: + writer.writerow(["Number of PCBs:",prefs.buildNumber]) + writer.writerow(["Total components:", nBuild]) writer.writerow(["Schematic Version:",net.getVersion()]) writer.writerow(["Schematic Date:",net.getSheetDate()]) writer.writerow(["BoM Date:",net.getDate()]) diff --git a/KiBOM/html_writer.py b/KiBOM/html_writer.py index 2dbbe405..4c2a561a 100644 --- a/KiBOM/html_writer.py +++ b/KiBOM/html_writer.py @@ -10,7 +10,7 @@ BG_USER = "#E6F9FF" #return a background color for a given column title def bgColor(col): #auto-generated columns - if col == ColumnList.COL_GRP_QUANTITY: + if col in ColumnList._COLUMNS_GEN: return BG_GEN #kicad protected columns elif col in ColumnList._COLUMNS_PROTECTED: @@ -20,7 +20,7 @@ def bgColor(col): return BG_USER def link(text): - text = u''.join((text)).encode('utf-8').strip() + for t in ["http","https","ftp","www"]: if text.startswith(t): return '{t}'.format(t=text) @@ -42,12 +42,21 @@ def WriteHTML(filename, groups, net, headings, prefs): print("{fn} is not a valid html file".format(fn=filename)) return False + nGroups = len(groups) + nTotal = sum([g.getCount() for g in groups]) + nFitted = sum([g.getCount() for g in groups if g.isFitted()]) + nBuild = nFitted * prefs.buildNumber + with open(filename,"w") as html: #header html.write("\n") + html.write("\n") + html.write('\t\n') #UTF-8 encoding for unicode support + html.write("\n") html.write("\n") + #PCB info html.write("

KiBoM PCB Bill of Materials

\n") html.write('\n') @@ -56,8 +65,12 @@ def WriteHTML(filename, groups, net, headings, prefs): html.write("\n".format(version=net.getVersion())) html.write("\n".format(date=net.getSheetDate())) html.write("\n".format(version=net.getTool())) - html.write("\n".format(n = sum([g.getCount() for g in groups]))) - html.write("\n".format(n=len(groups))) + html.write("\n".format(n=nGroups)) + html.write("\n".format(n=nTotal)) + html.write("\n".format(n=nFitted)) + if prefs.buildNumber > 0: + html.write("\n".format(n=prefs.buildNumber)) + html.write("\n".format(n=prefs.buildNumber, t=nBuild)) html.write("
Schematic Version{version}
Schematic Date{date}
KiCad Version{version}
Total Components{n}
Component Groups{n}
Component Groups{n}
Component Count (per PCB){n}
Fitted Components (per PCB){n}
Number of PCBs{n}
Total Component Count
(for {n} PCBs)
{t}
\n") html.write("
\n") html.write("

Component Groups

\n") @@ -94,7 +107,7 @@ def WriteHTML(filename, groups, net, headings, prefs): html.write("\n") if prefs.numberRows: - html.write('\t{n}'.format(n=rowCount)) + html.write('\t{n}\n'.format(n=rowCount)) for n, r in enumerate(row): bg = bgColor(headings[n]) diff --git a/KiBOM/xml_writer.py b/KiBOM/xml_writer.py index 58f1c1db..5ffe418c 100644 --- a/KiBOM/xml_writer.py +++ b/KiBOM/xml_writer.py @@ -18,19 +18,32 @@ def WriteXML(filename, groups, net, headings, prefs): if not filename.endswith(".xml"): return False - xml = ElementTree.Element('KiCAD_BOM', attrib = { - 'Schematic_Source' : net.getSource(), - 'Schematic_Version' : net.getVersion(), - 'Schematic_Date' : net.getSheetDate(), - 'BOM_Date' : net.getDate(), - 'KiCad_Version' : net.getTool(), - 'groups' : str(len(groups)), - 'components' : str(sum([group.getCount() for group in groups])) - }) + nGroups = len(groups) + nTotal = sum([g.getCount() for g in groups]) + nFitted = sum([g.getCount() for g in groups if g.isFitted()]) + nBuild = nFitted * prefs.buildNumber + + attrib = {} + + attrib['Schematic_Source'] = net.getSource() + attrib['Schematic_Version'] = net.getVersion() + attrib['Schematic_Date'] = net.getSheetDate() + attrib['BOM_Date'] = net.getDate() + attrib['KiCad_Version'] = net.getTool() + attrib['Component_Groups'] = str(nGroups) + attrib['Component_Count'] = str(nTotal) + attrib['Fitted_Components'] = str(nFitted) + + if prefs.buildNumber > 0: + attrib['Number_of_PCBs'] = str(prefs.buildNumber) + attrib['Total_Components'] = str(nBuild) + + xml = ElementTree.Element('KiCAD_BOM', attrib = attrib, encoding='utf-8') for group in groups: if prefs.ignoreDNF and not group.isFitted(): continue + row = group.getRow(headings) attrib = {} @@ -40,13 +53,12 @@ def WriteXML(filename, groups, net, headings, prefs): h = h.replace('"','') h = h.replace("'",'') - attrib[h] = row[i] + attrib[h] = str(row[i]).decode('ascii',errors='ignore') sub = ElementTree.SubElement(xml, "group", attrib=attrib) with open(filename,"w") as output: - out = ElementTree.tostring(xml, 'utf-8') - + out = ElementTree.tostring(xml, encoding="utf-8") output.write(minidom.parseString(out).toprettyxml(indent="\t")) return True