Explicitly call out DNP in BOM

Add DNP column and group output based on DNP

Fixes https://gitlab.com/kicad/code/kicad/issues/13466
This commit is contained in:
Seth Hillbrand 2023-01-10 15:21:31 -08:00
parent 3003d9476a
commit 786fc14df3
8 changed files with 38 additions and 45 deletions

View File

@ -45,6 +45,8 @@ def myEqu(self, other):
result = False result = False
elif self.getFootprint() != other.getFootprint(): elif self.getFootprint() != other.getFootprint():
result = False result = False
elif self.getDNP() != other.getDNP():
result = False
return result return result
@ -84,7 +86,7 @@ partfields -= set( ['Reference', 'Value', 'Datasheet', 'Footprint'] )
columnset = compfields | partfields # union columnset = compfields | partfields # union
# prepend an initial 'hard coded' list and put the enchillada into list 'columns' # prepend an initial 'hard coded' list and put the enchillada into list 'columns'
columns = ['Item', 'Qty', 'Reference(s)', 'Value', 'LibPart', 'Footprint', 'Datasheet'] + sorted(list(columnset)) columns = ['Item', 'Qty', 'Reference(s)', 'Value', 'LibPart', 'Footprint', 'Datasheet', 'DNP'] + sorted(list(columnset))
# Create a new csv writer object to use as the output formatter # Create a new csv writer object to use as the output formatter
out = csv.writer( f, lineterminator='\n', delimiter=',', quotechar='\"', quoting=csv.QUOTE_ALL ) out = csv.writer( f, lineterminator='\n', delimiter=',', quotechar='\"', quoting=csv.QUOTE_ALL )
@ -103,39 +105,12 @@ writerow( out, ['Tool:', net.getTool()] )
writerow( out, ['Generator:', sys.argv[0]] ) writerow( out, ['Generator:', sys.argv[0]] )
writerow( out, ['Component Count:', len(components)] ) writerow( out, ['Component Count:', len(components)] )
writerow( out, [] ) writerow( out, [] )
writerow( out, ['Individual Components:'] )
writerow( out, [] ) # blank line
writerow( out, columns )
# Output all the interesting components individually first:
row = []
for c in components:
del row[:]
row.append('') # item is blank in individual table
row.append('') # Qty is always 1, why print it
row.append( c.getRef() ) # Reference
row.append( c.getValue() ) # Value
row.append( c.getLibName() + ":" + c.getPartName() ) # LibPart
#row.append( c.getDescription() )
row.append( c.getFootprint() )
row.append( c.getDatasheet() )
# from column 7 upwards, use the fieldnames to grab the data
for field in columns[7:]:
row.append( c.getField( field ) );
writerow( out, row )
writerow( out, [] ) # blank line
writerow( out, [] ) # blank line
writerow( out, [] ) # blank line
writerow( out, ['Collated Components:'] ) writerow( out, ['Collated Components:'] )
writerow( out, [] ) # blank line writerow( out, [] ) # blank line
writerow( out, columns ) # reuse same columns writerow( out, columns ) # reuse same columns
row=[]
# Get all of the components in groups of matching parts + values # Get all of the components in groups of matching parts + values
# (see kicad_netlist_reader.py) # (see kicad_netlist_reader.py)
@ -147,7 +122,7 @@ item = 0
for group in grouped: for group in grouped:
del row[:] del row[:]
refs = "" refs = ""
# Add the reference of every component in the group and keep a reference # Add the reference of every component in the group and keep a reference
# to the component so that the other data can be filled in once per group # to the component so that the other data can be filled in once per group
for component in group: for component in group:
@ -157,7 +132,7 @@ for group in grouped:
c = component c = component
# Fill in the component groups common data # Fill in the component groups common data
# columns = ['Item', 'Qty', 'Reference(s)', 'Value', 'LibPart', 'Footprint', 'Datasheet'] + sorted(list(columnset)) # columns = ['Item', 'Qty', 'Reference(s)', 'Value', 'LibPart', 'Footprint', 'Datasheet', 'DNP'] + sorted(list(columnset))
item += 1 item += 1
row.append( item ) row.append( item )
row.append( len(group) ) row.append( len(group) )
@ -166,6 +141,7 @@ for group in grouped:
row.append( c.getLibName() + ":" + c.getPartName() ) row.append( c.getLibName() + ":" + c.getPartName() )
row.append( net.getGroupFootprint(group) ) row.append( net.getGroupFootprint(group) )
row.append( net.getGroupDatasheet(group) ) row.append( net.getGroupDatasheet(group) )
row.append( c.getDNPString() )
# from column 7 upwards, use the fieldnames to grab the data # from column 7 upwards, use the fieldnames to grab the data
for field in columns[7:]: for field in columns[7:]:

View File

@ -48,7 +48,7 @@ out.writerow(['Date:', net.getDate()])
out.writerow(['Tool:', net.getTool()]) out.writerow(['Tool:', net.getTool()])
out.writerow( ['Generator:', sys.argv[0]] ) out.writerow( ['Generator:', sys.argv[0]] )
out.writerow(['Component Count:', len(net.components)]) out.writerow(['Component Count:', len(net.components)])
out.writerow(['Ref', 'Qnty', 'Value', 'Cmp name', 'Footprint', 'Description', 'Vendor']) out.writerow(['Ref', 'Qnty', 'Value', 'Cmp name', 'Footprint', 'Description', 'Vendor', 'DNP'])
# Get all of the components in groups of matching parts + values # Get all of the components in groups of matching parts + values
@ -74,6 +74,7 @@ for group in grouped:
fromNetlistText( c.getPartName() ), fromNetlistText( c.getPartName() ),
fromNetlistText( c.getFootprint() ), fromNetlistText( c.getFootprint() ),
fromNetlistText( c.getDescription() ), fromNetlistText( c.getDescription() ),
fromNetlistText( c.getField("Vendor") )]) fromNetlistText( c.getField("Vendor") ),
c.getDNPString()])

View File

@ -43,6 +43,8 @@ def myEqu(self, other):
result = False result = False
elif self.getFootprint() != other.getFootprint(): elif self.getFootprint() != other.getFootprint():
result = False result = False
elif self.getDNP() != other.getDNP():
result = False
else: else:
for field_name in extra_fields: for field_name in extra_fields:
if self.getField(field_name) != other.getField(field_name): if self.getField(field_name) != other.getField(field_name):
@ -72,7 +74,7 @@ except IOError:
out = csv.writer(f, lineterminator='\n', delimiter=',', quotechar='\"', quoting=csv.QUOTE_ALL) out = csv.writer(f, lineterminator='\n', delimiter=',', quotechar='\"', quoting=csv.QUOTE_ALL)
# Output a CSV header # Output a CSV header
out.writerow(['#', 'Reference', 'Qty', 'Value', 'Footprint'] + extra_fields) out.writerow(['#', 'Reference', 'Qty', 'Value', 'Footprint', 'DNP'] + extra_fields)
# Get all of the components in groups of matching parts + values # Get all of the components in groups of matching parts + values
# (see kicad_netlist_reader.py) # (see kicad_netlist_reader.py)
@ -99,6 +101,7 @@ for group in grouped:
row.append( len(group) ) row.append( len(group) )
row.append( c.getValue() ) row.append( c.getValue() )
row.append( c.getFootprint() ) row.append( c.getFootprint() )
row.append( c.getDNPString() )
# Add the values of extra fields # Add the values of extra fields
for field_name in extra_fields: for field_name in extra_fields:

View File

@ -58,10 +58,10 @@ writerow( out, ['Source:', net.getSource()] )
writerow( out, ['Date:', net.getDate()] ) writerow( out, ['Date:', net.getDate()] )
writerow( out, ['Tool:', net.getTool()] ) writerow( out, ['Tool:', net.getTool()] )
writerow( out, ['Component Count:', len(components)] ) writerow( out, ['Component Count:', len(components)] )
writerow( out, ['Ref', 'Value', 'Footprint', 'Datasheet', 'Manufacturer', 'Vendor'] ) writerow( out, ['Ref', 'Value', 'Footprint', 'Datasheet', 'Manufacturer', 'Vendor', 'DNP'] )
# Output all of the component information (One component per row) # Output all of the component information (One component per row)
for c in components: for c in components:
writerow( out, [c.getRef(), c.getValue(), c.getFootprint(), c.getDatasheet(), writerow( out, [c.getRef(), c.getValue(), c.getFootprint(), c.getDatasheet(),
c.getField("Manufacturer"), c.getField("Vendor")]) c.getField("Manufacturer"), c.getField("Vendor"), c.getDNPString()])

View File

@ -69,7 +69,7 @@ row =""
row += "<tr><th>Ref</th>" row += "<tr><th>Ref</th>"
row += "<th>Qnty</th>" row += "<th>Qnty</th>"
row += "<th>Value</th>" + "<th>Part</th>" + "<th>Datasheet</th>" row += "<th>Value</th>" + "<th>Part</th>" + "<th>Datasheet</th>"
row += "<th>Description</th>" + "<th>Vendor</th></tr>" row += "<th>Description</th>" + "<th>Vendor</th>" + "<th>DNP</th></tr>"
html = html.replace('<!--TABLEROW-->', row + "<!--TABLEROW-->") html = html.replace('<!--TABLEROW-->', row + "<!--TABLEROW-->")
@ -94,7 +94,8 @@ for group in grouped:
row += "</td><td>" + c.getLibName() + ":" + c.getPartName() row += "</td><td>" + c.getLibName() + ":" + c.getPartName()
row += "</td><td>" + c.getDatasheet() row += "</td><td>" + c.getDatasheet()
row += "</td><td>" + c.getDescription() row += "</td><td>" + c.getDescription()
row += "</td><td>" + c.getField("Vendor")+ "</td></tr>" row += "</td><td>" + c.getField("Vendor")
row += "</td><td>" + c.getDNPString() + "</td></tr>"
row += "\n" row += "\n"
html = html.replace('<!--TABLEROW-->', row + "<!--TABLEROW-->") html = html.replace('<!--TABLEROW-->', row + "<!--TABLEROW-->")

View File

@ -69,6 +69,8 @@ def myEqu(self, other):
result = False result = False
elif self.getField("Voltage") != other.getField("Voltage"): elif self.getField("Voltage") != other.getField("Voltage"):
result = False result = False
elif self.getDNP() != other.getDNP():
result = False
return result return result
@ -99,7 +101,7 @@ html = html.replace('<!--COMPCOUNT-->', "<b>Component Count:</b>" + \
row = "<tr><th style='width:640px'>Ref</th>" + "<th>Qnty</th>" row = "<tr><th style='width:640px'>Ref</th>" + "<th>Qnty</th>"
row += "<th>Value</th>" + "<th>Part</th>" + "<th>Footprint</th>" row += "<th>Value</th>" + "<th>Part</th>" + "<th>Footprint</th>"
row += "<th>Description</th>" + "<th>Vendor</th></tr>" row += "<th>Description</th>" + "<th>Vendor</th> + "<th>DNP</th></tr>"
html = html.replace('<!--TABLEROW-->', row + "<!--TABLEROW-->") html = html.replace('<!--TABLEROW-->', row + "<!--TABLEROW-->")
@ -125,7 +127,8 @@ for group in grouped:
row += "<tr><td>" + refs +"</td><td>" + str(len(group)) row += "<tr><td>" + refs +"</td><td>" + str(len(group))
row += "</td><td>" + c.getValue() + "</td><td>" + c.getLibName() + ":" row += "</td><td>" + c.getValue() + "</td><td>" + c.getLibName() + ":"
row += c.getPartName() + "</td><td>" + c.getFootprint() + "</td><td>" row += c.getPartName() + "</td><td>" + c.getFootprint() + "</td><td>"
row += c.getDescription() + "</td><td>" + c.getField("Vendor") row += c.getDescription() + "</td><td>" + c.getField("Vendor") + "</td><td>"
row += c.getDNPString()
row += "</td></tr>" row += "</td></tr>"
html = html.replace('<!--TABLEROW-->', row + "<!--TABLEROW-->") html = html.replace('<!--TABLEROW-->', row + "<!--TABLEROW-->")

View File

@ -59,9 +59,9 @@ writerow( out, ['Source:', net.getSource()] )
writerow( out, ['Date:', net.getDate()] ) writerow( out, ['Date:', net.getDate()] )
writerow( out, ['Tool:', net.getTool()] ) writerow( out, ['Tool:', net.getTool()] )
writerow( out, ['Component Count:', len(components)] ) writerow( out, ['Component Count:', len(components)] )
writerow( out, ['Ref', 'Value', 'Part', 'Footprint', 'Description', 'Vendor'] ) writerow( out, ['Ref', 'Value', 'Part', 'Footprint', 'Description', 'Vendor', 'DNP'] )
# Output all of the component information # Output all of the component information
for c in components: for c in components:
writerow( out, [c.getRef(), c.getValue(), c.getLibName() + ":" + c.getPartName(), writerow( out, [c.getRef(), c.getValue(), c.getLibName() + ":" + c.getPartName(),
c.getFootprint(), c.getDescription(), c.getField("Vendor")]) c.getFootprint(), c.getDescription(), c.getField("Vendor"), c.getDNPString()])

View File

@ -331,7 +331,7 @@ class comp():
def __eq__(self, other): def __eq__(self, other):
""" Equivalency operator, remember this can be easily overloaded """ Equivalency operator, remember this can be easily overloaded
2 components are equivalent ( i.e. can be grouped 2 components are equivalent ( i.e. can be grouped
if they have same value and same footprint if they have same value and same footprint and are both set to be populated
Override the component equivalence operator must be done before Override the component equivalence operator must be done before
loading the netlist, otherwise all components will have the original loading the netlist, otherwise all components will have the original
@ -347,7 +347,8 @@ class comp():
if self.getValue() == other.getValue(): if self.getValue() == other.getValue():
if self.getFootprint() == other.getFootprint(): if self.getFootprint() == other.getFootprint():
if self.getRef().rstrip(string.digits) == other.getRef().rstrip(string.digits): if self.getRef().rstrip(string.digits) == other.getRef().rstrip(string.digits):
result = True if self.getDNP() == other.getDNP():
result = True
return result return result
def setLibPart(self, part): def setLibPart(self, part):
@ -418,6 +419,15 @@ class comp():
return False return False
'''
Return 'DNP' if the component has the DNP property set
'''
def getDNPString(self):
if self.getDNP():
return 'DNP'
return ''
''' '''
Return true if the component has the exclude from BOM property set Return true if the component has the exclude from BOM property set
''' '''
@ -758,7 +768,6 @@ class netlist():
# Make sure to start off will all components ungrouped to begin with # Make sure to start off will all components ungrouped to begin with
for c in components: for c in components:
c.grouped = False c.grouped = False
c.getExcludeFromBOM()
# Group components based on the value, library and part identifiers # Group components based on the value, library and part identifiers
for c in components: for c in components: