Skip to content

Commit bebf4a8

Browse files
committed
Add option to normalize extra field name case
This will make "MPN" and "mpn" be same field. Lexicographically smaller one is picked, which means it favoures capital case. Fixes #79
1 parent 3434391 commit bebf4a8

File tree

7 files changed

+135
-7
lines changed

7 files changed

+135
-7
lines changed

InteractiveHtmlBom/core/config.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class Config:
5252
netlist_file = None
5353
netlist_initial_directory = '' # This is relative to pcb file directory
5454
extra_fields = []
55+
normalize_field_case = False
5556
board_variant_field = ''
5657
board_variant_whitelist = []
5758
board_variant_blacklist = []
@@ -101,6 +102,8 @@ def __init__(self):
101102
self.extra_fields = self._split(f.Read(
102103
'extra_fields',
103104
','.join(self.extra_fields)))
105+
self.normalize_field_case = f.ReadBool(
106+
'normalize_field_case', self.normalize_field_case)
104107
self.board_variant_field = f.Read(
105108
'board_variant_field', self.board_variant_field)
106109
self.board_variant_whitelist = self._split(f.Read(
@@ -143,6 +146,7 @@ def save(self):
143146

144147
f.SetPath('/extra_fields')
145148
f.Write('extra_fields', ','.join(self.extra_fields))
149+
f.WriteBool('normalize_field_case', self.normalize_field_case)
146150
f.Write('board_variant_field', self.board_variant_field)
147151
f.Write('board_variant_whitelist',
148152
','.join(self.board_variant_whitelist))
@@ -180,6 +184,7 @@ def set_from_dialog(self, dlg):
180184
# Extra fields
181185
self.netlist_file = dlg.extra.netlistFilePicker.Path
182186
self.extra_fields = list(dlg.extra.extraFieldsList.GetCheckedStrings())
187+
self.normalize_field_case = dlg.extra.normalizeCaseCheckbox.Value
183188
self.board_variant_field = dlg.extra.boardVariantFieldBox.Value
184189
if self.board_variant_field == dlg.extra.NONE_STRING:
185190
self.board_variant_field = ''
@@ -230,6 +235,7 @@ def safe_set_checked_strings(clb, strings):
230235
clb.SetCheckedStrings([s for s in strings if s in safe_strings])
231236

232237
safe_set_checked_strings(dlg.extra.extraFieldsList, self.extra_fields)
238+
dlg.extra.normalizeCaseCheckbox.Value = self.normalize_field_case
233239
dlg.extra.boardVariantFieldBox.Value = self.board_variant_field
234240
dlg.extra.OnBoardVariantFieldChange(None)
235241
safe_set_checked_strings(dlg.extra.boardVariantWhitelist,
@@ -306,6 +312,10 @@ def add_options(self, parser, file_name_format_hint):
306312
default=','.join(self.extra_fields),
307313
help='Comma separated list of extra fields to '
308314
'pull from netlist or xml file.')
315+
parser.add_argument('--normalize-field-case',
316+
help='Normalize extra field name case. E.g. "MPN" '
317+
'and "mpn" will be considered the same field.',
318+
action='store_true')
309319
parser.add_argument('--variant-field',
310320
help='Name of the extra field that stores board '
311321
'variant for component.')
@@ -348,14 +358,13 @@ def set_from_args(self, args):
348358
# Extra
349359
self.netlist_file = args.netlist_file
350360
self.extra_fields = self._split(args.extra_fields)
361+
self.normalize_field_case = args.normalize_field_case
351362
self.board_variant_field = args.variant_field
352363
self.board_variant_whitelist = args.variants_whitelist
353364
self.board_variant_blacklist = args.variants_blacklist
354365
self.dnp_field = args.dnp_field
355366

356367
def get_html_config(self):
357368
import json
358-
d = {}
359-
for f in self.html_config_fields:
360-
d[f] = getattr(self, f)
369+
d = {f: getattr(self, f) for f in self.html_config_fields}
361370
return json.dumps(d)

InteractiveHtmlBom/core/ibom.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,8 @@ def main(pcb, config, parse_schematic_data, cli=False):
569569
# Get extra field data
570570
extra_fields = None
571571
if config.netlist_file and os.path.isfile(config.netlist_file):
572-
extra_fields = parse_schematic_data(config.netlist_file)
572+
extra_fields = parse_schematic_data(
573+
config.netlist_file, config.normalize_field_case)
573574

574575
need_extra_fields = (config.extra_fields or
575576
config.board_variant_whitelist or

InteractiveHtmlBom/dialog/dialog_base.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,9 @@ def __init__( self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.
403403

404404
extraFieldsSizer.Add( bSizer4, 1, wx.EXPAND, 5 )
405405

406+
self.normalizeCaseCheckbox = wx.CheckBox( extraFieldsSizer.GetStaticBox(), wx.ID_ANY, u"Normalize field name case", wx.DefaultPosition, wx.DefaultSize, 0 )
407+
extraFieldsSizer.Add( self.normalizeCaseCheckbox, 0, wx.ALL|wx.EXPAND, 5 )
408+
406409

407410
bSizer42.Add( extraFieldsSizer, 2, wx.ALL|wx.EXPAND, 5 )
408411

@@ -477,6 +480,7 @@ def __init__( self, parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.
477480
self.netlistFilePicker.Bind( wx.EVT_FILEPICKER_CHANGED, self.OnNetlistFileChanged )
478481
self.m_button1.Bind( wx.EVT_BUTTON, self.OnExtraFieldsUp )
479482
self.m_button2.Bind( wx.EVT_BUTTON, self.OnExtraFieldsDown )
483+
self.normalizeCaseCheckbox.Bind( wx.EVT_CHECKBOX, self.OnNetlistFileChanged )
480484
self.boardVariantFieldBox.Bind( wx.EVT_COMBOBOX, self.OnBoardVariantFieldChange )
481485

482486
def __del__( self ):
@@ -496,6 +500,7 @@ def OnExtraFieldsUp( self, event ):
496500
def OnExtraFieldsDown( self, event ):
497501
event.Skip()
498502

503+
499504
def OnBoardVariantFieldChange( self, event ):
500505
event.Skip()
501506

InteractiveHtmlBom/dialog/settings_dialog.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,8 @@ def OnNetlistFileChanged(self, event):
207207
netlist_file = self.netlistFilePicker.Path
208208
if not os.path.isfile(netlist_file):
209209
return
210-
self.extra_field_data = self.extra_data_func(netlist_file)
210+
self.extra_field_data = self.extra_data_func(
211+
netlist_file, self.normalizeCaseCheckbox.Value)
211212
if self.extra_field_data is not None:
212213
field_list = list(self.extra_field_data[0])
213214
self.extraFieldsList.SetItems(field_list)

InteractiveHtmlBom/schematic_data/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@
99
}
1010

1111

12-
def parse_schematic_data(file_name):
12+
def parse_schematic_data(file_name, normalize_case):
1313
if not os.path.isfile(file_name):
1414
return None
1515
extension = os.path.splitext(file_name)[1]
1616
if extension not in PARSERS:
1717
return None
1818
else:
1919
parser = PARSERS[extension](file_name)
20-
return parser.get_extra_field_data()
20+
return parser.parse(normalize_case)
2121

2222

2323
def find_latest_schematic_data(pcb_file):

InteractiveHtmlBom/schematic_data/parser_base.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,23 @@ def __init__(self, file_name):
77
"""
88
self.file_name = file_name
99

10+
@staticmethod
11+
def normalize_field_names(data):
12+
field_map = {f.lower(): f for f in reversed(data[0])}
13+
14+
def remap(ref_fields):
15+
return {field_map[f.lower()]: v for (f, v) in
16+
sorted(ref_fields.items(), reverse=True)}
17+
18+
field_data = {r: remap(d) for (r, d) in data[1].items()}
19+
return field_map.values(), field_data
20+
21+
def parse(self, normalize_case):
22+
data = self.get_extra_field_data()
23+
if normalize_case:
24+
data = self.normalize_field_names(data)
25+
return sorted(data[0]), data[1]
26+
1027
def get_extra_field_data(self):
1128
# type: () -> tuple
1229
"""

settings_dialog.fbp

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4264,6 +4264,101 @@
42644264
</object>
42654265
</object>
42664266
</object>
4267+
<object class="sizeritem" expanded="1">
4268+
<property name="border">5</property>
4269+
<property name="flag">wxALL|wxEXPAND</property>
4270+
<property name="proportion">0</property>
4271+
<object class="wxCheckBox" expanded="1">
4272+
<property name="BottomDockable">1</property>
4273+
<property name="LeftDockable">1</property>
4274+
<property name="RightDockable">1</property>
4275+
<property name="TopDockable">1</property>
4276+
<property name="aui_layer"></property>
4277+
<property name="aui_name"></property>
4278+
<property name="aui_position"></property>
4279+
<property name="aui_row"></property>
4280+
<property name="best_size"></property>
4281+
<property name="bg"></property>
4282+
<property name="caption"></property>
4283+
<property name="caption_visible">1</property>
4284+
<property name="center_pane">0</property>
4285+
<property name="checked">0</property>
4286+
<property name="close_button">1</property>
4287+
<property name="context_help"></property>
4288+
<property name="context_menu">1</property>
4289+
<property name="default_pane">0</property>
4290+
<property name="dock">Dock</property>
4291+
<property name="dock_fixed">0</property>
4292+
<property name="docking">Left</property>
4293+
<property name="enabled">1</property>
4294+
<property name="fg"></property>
4295+
<property name="floatable">1</property>
4296+
<property name="font"></property>
4297+
<property name="gripper">0</property>
4298+
<property name="hidden">0</property>
4299+
<property name="id">wxID_ANY</property>
4300+
<property name="label">Normalize field name case</property>
4301+
<property name="max_size"></property>
4302+
<property name="maximize_button">0</property>
4303+
<property name="maximum_size"></property>
4304+
<property name="min_size"></property>
4305+
<property name="minimize_button">0</property>
4306+
<property name="minimum_size"></property>
4307+
<property name="moveable">1</property>
4308+
<property name="name">normalizeCaseCheckbox</property>
4309+
<property name="pane_border">1</property>
4310+
<property name="pane_position"></property>
4311+
<property name="pane_size"></property>
4312+
<property name="permission">protected</property>
4313+
<property name="pin_button">1</property>
4314+
<property name="pos"></property>
4315+
<property name="resize">Resizable</property>
4316+
<property name="show">1</property>
4317+
<property name="size"></property>
4318+
<property name="style"></property>
4319+
<property name="subclass">; ; forward_declare</property>
4320+
<property name="toolbar_pane">0</property>
4321+
<property name="tooltip"></property>
4322+
<property name="validator_data_type"></property>
4323+
<property name="validator_style">wxFILTER_NONE</property>
4324+
<property name="validator_type">wxDefaultValidator</property>
4325+
<property name="validator_variable"></property>
4326+
<property name="window_extra_style"></property>
4327+
<property name="window_name"></property>
4328+
<property name="window_style"></property>
4329+
<event name="OnAux1DClick"></event>
4330+
<event name="OnAux1Down"></event>
4331+
<event name="OnAux1Up"></event>
4332+
<event name="OnAux2DClick"></event>
4333+
<event name="OnAux2Down"></event>
4334+
<event name="OnAux2Up"></event>
4335+
<event name="OnChar"></event>
4336+
<event name="OnCharHook"></event>
4337+
<event name="OnCheckBox">OnNetlistFileChanged</event>
4338+
<event name="OnEnterWindow"></event>
4339+
<event name="OnEraseBackground"></event>
4340+
<event name="OnKeyDown"></event>
4341+
<event name="OnKeyUp"></event>
4342+
<event name="OnKillFocus"></event>
4343+
<event name="OnLeaveWindow"></event>
4344+
<event name="OnLeftDClick"></event>
4345+
<event name="OnLeftDown"></event>
4346+
<event name="OnLeftUp"></event>
4347+
<event name="OnMiddleDClick"></event>
4348+
<event name="OnMiddleDown"></event>
4349+
<event name="OnMiddleUp"></event>
4350+
<event name="OnMotion"></event>
4351+
<event name="OnMouseEvents"></event>
4352+
<event name="OnMouseWheel"></event>
4353+
<event name="OnPaint"></event>
4354+
<event name="OnRightDClick"></event>
4355+
<event name="OnRightDown"></event>
4356+
<event name="OnRightUp"></event>
4357+
<event name="OnSetFocus"></event>
4358+
<event name="OnSize"></event>
4359+
<event name="OnUpdateUI"></event>
4360+
</object>
4361+
</object>
42674362
</object>
42684363
</object>
42694364
<object class="sizeritem" expanded="1">

0 commit comments

Comments
 (0)