Internal BoM: Added customizable extra info after the title
Closes #199
This commit is contained in:
parent
fb082fcbb3
commit
bb6e962f3d
|
|
@ -10,7 +10,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- New outputs:
|
||||
- KiCad netlist generation
|
||||
- IPC-D-356 netlist generation (#197)
|
||||
- Pattern and text variables expansion on internal BoM title (#198)
|
||||
- Internal BoM:
|
||||
- Pattern and text variables expansion in the title (#198)
|
||||
- Customizable extra info after the title (#199)
|
||||
|
||||
### Fixed
|
||||
- Already configured outputs not created (i.e. when creating reports)
|
||||
|
|
|
|||
|
|
@ -137,13 +137,13 @@ Notes:
|
|||
|
||||
[**ImageMagick**](https://imagemagick.org/) (tool) [Debian](https://packages.debian.org/bullseye/imagemagick)
|
||||
- Optional to:
|
||||
- Create monochrome prints for `pcb_print`
|
||||
- Create JPG images for `pcbdraw`
|
||||
- Create monochrome prints for `pcb_print`
|
||||
|
||||
[**RSVG tools**](https://cran.r-project.org/web/packages/rsvg/index.html) (tool) [Debian](https://packages.debian.org/bullseye/librsvg2-bin)
|
||||
- Optional to:
|
||||
- Create PDF, PNG, EPS and PS formats for `pcb_print`
|
||||
- Create PNG and JPG images for `pcbdraw`
|
||||
- Create PDF, PNG, EPS and PS formats for `pcb_print`
|
||||
|
||||
[**Ghostscript**](https://www.ghostscript.com/) (tool) [Debian](https://packages.debian.org/bullseye/ghostscript)
|
||||
- Optional to create PS files for `pcb_print`
|
||||
|
|
@ -1263,6 +1263,7 @@ Next time you need this list just use an alias, like this:
|
|||
- `col_colors`: [boolean=true] Use colors to show the field type.
|
||||
- `datasheet_as_link`: [string=''] Column with links to the datasheet.
|
||||
- `digikey_link`: [string|list(string)=''] Column/s containing Digi-Key part numbers, will be linked to web page.
|
||||
- `extra_info`: [string|list(string)=''] Information to put after the title and before the pcb and stats info.
|
||||
- `generate_dnf`: [boolean=true] Generate a separated section for DNF (Do Not Fit) components.
|
||||
- `hide_pcb_info`: [boolean=false] Hide project information.
|
||||
- `hide_stats_info`: [boolean=false] Hide statistics information.
|
||||
|
|
@ -1299,6 +1300,7 @@ Next time you need this list just use an alias, like this:
|
|||
- `col_colors`: [boolean=true] Use colors to show the field type.
|
||||
- `datasheet_as_link`: [string=''] Column with links to the datasheet.
|
||||
- `digikey_link`: [string|list(string)=''] Column/s containing Digi-Key part numbers, will be linked to web page.
|
||||
- `extra_info`: [string|list(string)=''] Information to put after the title and before the pcb and stats info.
|
||||
- `generate_dnf`: [boolean=true] Generate a separated section for DNF (Do Not Fit) components.
|
||||
- `hide_pcb_info`: [boolean=false] Hide project information.
|
||||
- `hide_stats_info`: [boolean=false] Hide statistics information.
|
||||
|
|
|
|||
|
|
@ -239,6 +239,8 @@ outputs:
|
|||
datasheet_as_link: ''
|
||||
# [string|list(string)=''] Column/s containing Digi-Key part numbers, will be linked to web page
|
||||
digikey_link: ''
|
||||
# [string|list(string)=''] Information to put after the title and before the pcb and stats info
|
||||
extra_info: ''
|
||||
# [boolean=true] Generate a separated section for DNF (Do Not Fit) components
|
||||
generate_dnf: true
|
||||
# [boolean=false] Hide project information
|
||||
|
|
@ -303,6 +305,8 @@ outputs:
|
|||
datasheet_as_link: ''
|
||||
# [string|list(string)=''] Column/s containing Digi-Key part numbers, will be linked to web page
|
||||
digikey_link: ''
|
||||
# [string|list(string)=''] Information to put after the title and before the pcb and stats info
|
||||
extra_info: ''
|
||||
# [boolean=true] Generate a separated section for DNF (Do Not Fit) components
|
||||
generate_dnf: true
|
||||
# [boolean=false] Hide project information
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ HEAD_COLOR_B = "#0e4e8e"
|
|||
HEAD_COLOR_B_L = "#3e7ebe"
|
||||
STYLE_COMMON = (" .cell-title { vertical-align: bottom; }\n"
|
||||
" .cell-info { vertical-align: top; padding: 1em;}\n"
|
||||
" .cell-extra-info { vertical-align: top; padding: 1em;}\n"
|
||||
" .cell-stats { vertical-align: top; padding: 1em;}\n"
|
||||
" .title { font-size:2.5em; font-weight: bold; }\n"
|
||||
" .subtitle { font-size:1.5em; font-weight: bold; }\n"
|
||||
|
|
@ -344,6 +345,17 @@ def write_stats(html, cfg):
|
|||
html.write('</tr>\n')
|
||||
|
||||
|
||||
def write_extra_info(html, cfg):
|
||||
if not cfg.html.extra_info:
|
||||
return
|
||||
html.write('<tr>\n')
|
||||
html.write(' <td colspan="2" class="cell-extra-info">\n')
|
||||
for e in cfg.html.extra_info:
|
||||
html.write(" <b>{}</b><br>\n".format(e))
|
||||
html.write(' </td>\n')
|
||||
html.write('</tr>\n')
|
||||
|
||||
|
||||
def write_html(filename, groups, headings, head_names, cfg):
|
||||
"""
|
||||
Write BoM out to a HTML file
|
||||
|
|
@ -413,6 +425,8 @@ def write_html(filename, groups, headings, head_names, cfg):
|
|||
n = 2
|
||||
if len(cfg.aggregate) > 1:
|
||||
n += 2*len(cfg.aggregate)
|
||||
if len(cfg.html.extra_info):
|
||||
n += 1
|
||||
html.write(' <td rowspan="{}">\n'.format(n))
|
||||
if img:
|
||||
html.write(' <img src="'+img+'" alt="Logo" width="'+str(img_w)+'" height="'+str(img_h)+'">\n')
|
||||
|
|
@ -422,6 +436,7 @@ def write_html(filename, groups, headings, head_names, cfg):
|
|||
html.write(' <div class="title">'+cfg.html.title+'</div>\n')
|
||||
html.write(' </td>\n')
|
||||
html.write('</tr>\n')
|
||||
write_extra_info(html, cfg)
|
||||
write_stats(html, cfg)
|
||||
html.write('</table>\n')
|
||||
|
||||
|
|
|
|||
|
|
@ -110,9 +110,13 @@ def add_info(worksheet, column_widths, row, col_offset, formats, text, value):
|
|||
return row + 1
|
||||
|
||||
|
||||
def title_rows(cfg):
|
||||
return (1 if cfg.xlsx.title else 0)+len(cfg.xlsx.extra_info)
|
||||
|
||||
|
||||
def compute_head_size(cfg):
|
||||
col_logo = 0 if cfg.xlsx.logo is None else 6
|
||||
col_info = 1 if cfg.xlsx.title else 0
|
||||
col_info = title_rows(cfg)
|
||||
if not (cfg.xlsx.hide_pcb_info and cfg.xlsx.hide_stats_info):
|
||||
col_info += 5
|
||||
if len(cfg.aggregate) > 1:
|
||||
|
|
@ -548,6 +552,16 @@ def dis_enable_apis(api_options, cfg):
|
|||
api_options[api]['enable'] = True
|
||||
|
||||
|
||||
def do_title(cfg, worksheet, col1, length, fmt_title, fmt_info):
|
||||
r_extra = 0
|
||||
if cfg.xlsx.title:
|
||||
worksheet.set_row(0, 32)
|
||||
worksheet.merge_range(0, col1, 0, length, cfg.xlsx.title, fmt_title)
|
||||
r_extra = 1
|
||||
for c, text in enumerate(cfg.xlsx.extra_info):
|
||||
worksheet.merge_range(c+r_extra, col1, c+r_extra, length, text, fmt_info)
|
||||
|
||||
|
||||
def _create_kicost_sheet(workbook, groups, image_data, fmt_title, fmt_info, fmt_subtitle, fmt_head, fmt_cols, cfg):
|
||||
if not KICOST_SUPPORT:
|
||||
logger.warning(W_NOKICOST+'KiCost sheet requested but failed to load KiCost support')
|
||||
|
|
@ -571,7 +585,7 @@ def _create_kicost_sheet(workbook, groups, image_data, fmt_title, fmt_info, fmt_
|
|||
# Create the worksheets
|
||||
ws_names = ['Costs', 'Costs (DNF)']
|
||||
Spreadsheet.PRJ_INFO_ROWS = 5 if len(cfg.aggregate) == 1 else 6
|
||||
Spreadsheet.PRJ_INFO_START = 1 if len(cfg.aggregate) == 1 else 4
|
||||
Spreadsheet.PRJ_INFO_START = (1 if len(cfg.aggregate) == 1 else 4)+len(cfg.xlsx.extra_info)
|
||||
Spreadsheet.ADJUST_ROW_AND_COL_SIZE = True
|
||||
Spreadsheet.MAX_COL_WIDTH = cfg.xlsx.max_col_width
|
||||
Spreadsheet.PART_NSEQ_SEPRTR = cfg.ref_separator
|
||||
|
|
@ -648,7 +662,7 @@ def _create_kicost_sheet(workbook, groups, image_data, fmt_title, fmt_info, fmt_
|
|||
col1 += 1
|
||||
# PCB & Stats Info
|
||||
if not (cfg.xlsx.hide_pcb_info and cfg.xlsx.hide_stats_info):
|
||||
r_info_start = 1 if cfg.xlsx.title else 0
|
||||
r_info_start = title_rows(cfg)
|
||||
column_widths = [0]*5 # Column 1 to 5
|
||||
old_stats = cfg.xlsx.hide_stats_info
|
||||
cfg.xlsx.hide_stats_info = True
|
||||
|
|
@ -659,9 +673,7 @@ def _create_kicost_sheet(workbook, groups, image_data, fmt_title, fmt_info, fmt_
|
|||
# Add a worksheet with costs to the spreadsheet
|
||||
create_worksheet(ss, parts)
|
||||
# Title
|
||||
if cfg.xlsx.title:
|
||||
wks.set_row(0, 32)
|
||||
wks.merge_range(0, col1, 0, ss.globals_width, cfg.xlsx.title, fmt_title)
|
||||
do_title(cfg, wks, col1, ss.globals_width, fmt_title, fmt_info[0])
|
||||
used_parts.append(parts)
|
||||
# Specs sheets
|
||||
create_meta_sheets(workbook, used_parts, fmt_head, fmt_cols, cfg, ss)
|
||||
|
|
@ -698,6 +710,7 @@ def write_xlsx(filename, groups, col_fields, head_names, cfg):
|
|||
"""
|
||||
if not XLSX_SUPPORT:
|
||||
logger.error('Python xlsxwriter module not installed (Debian: python3-xlsxwriter)')
|
||||
logger.error(TRY_INSTALL_CHECK)
|
||||
return False
|
||||
|
||||
link_datasheet = -1
|
||||
|
|
@ -712,8 +725,8 @@ def write_xlsx(filename, groups, col_fields, head_names, cfg):
|
|||
|
||||
# Leave space for the logo, title and info
|
||||
head_size = compute_head_size(cfg)
|
||||
# First rowe for the information
|
||||
r_info_start = 1 if cfg.xlsx.title else 0
|
||||
# First row for the information
|
||||
r_info_start = title_rows(cfg)
|
||||
max_width = cfg.xlsx.max_col_width
|
||||
|
||||
# #######################
|
||||
|
|
@ -793,9 +806,7 @@ def write_xlsx(filename, groups, col_fields, head_names, cfg):
|
|||
# Logo
|
||||
col1 = insert_logo(worksheet, image_data, cfg.xlsx.logo_scale)
|
||||
# Title
|
||||
if cfg.xlsx.title:
|
||||
worksheet.set_row(0, 32)
|
||||
worksheet.merge_range(0, col1, 0, len(column_widths)-1, cfg.xlsx.title, fmt_title)
|
||||
do_title(cfg, worksheet, col1, len(column_widths)-1, fmt_title, fmt_info[0])
|
||||
# PCB & Stats Info
|
||||
if not (cfg.xlsx.hide_pcb_info and cfg.xlsx.hide_stats_info):
|
||||
write_info(cfg, r_info_start, worksheet, column_widths, col1, fmt_info, fmt_subtitle)
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ class Optionable(object):
|
|||
return Optionable.expand_filename_both(self, name)
|
||||
|
||||
@staticmethod
|
||||
def force_list(val):
|
||||
def force_list(val, comma_sep=True):
|
||||
""" Used for values that accept a string or a list of strings.
|
||||
The string can be a comma separated list """
|
||||
if isinstance(val, type):
|
||||
|
|
@ -339,7 +339,10 @@ class Optionable(object):
|
|||
elif isinstance(val, str):
|
||||
# A string
|
||||
if val:
|
||||
val = [v.strip() for v in val.split(',')]
|
||||
if comma_sep:
|
||||
val = [v.strip() for v in val.split(',')]
|
||||
else:
|
||||
val = [val]
|
||||
else:
|
||||
# Empty string
|
||||
val = []
|
||||
|
|
|
|||
|
|
@ -175,6 +175,8 @@ class BoMLinkable(Optionable):
|
|||
""" [string|boolean=''] PNG file to use as logo, use false to remove """
|
||||
self.title = 'KiBot Bill of Materials'
|
||||
""" BoM title """
|
||||
self.extra_info = Optionable
|
||||
""" [string|list(string)=''] Information to put after the title and before the pcb and stats info """
|
||||
|
||||
def config(self, parent):
|
||||
super().config(parent)
|
||||
|
|
@ -192,6 +194,8 @@ class BoMLinkable(Optionable):
|
|||
self.logo = os.path.abspath(self.logo)
|
||||
if not os.path.isfile(self.logo):
|
||||
raise KiPlotConfigurationError('Missing logo file `{}`'.format(self.logo))
|
||||
# Extra info lines
|
||||
self.extra_info = Optionable.force_list(self.extra_info, comma_sep=False)
|
||||
# Datasheet as link
|
||||
self.datasheet_as_link = self.datasheet_as_link.lower()
|
||||
|
||||
|
|
@ -313,14 +317,8 @@ class BoMXLSX(BoMLinkable):
|
|||
if not self.kicost_config:
|
||||
self.kicost_config = None
|
||||
# KiCost APIs
|
||||
if isinstance(self.kicost_api_enable, type):
|
||||
self.kicost_api_enable = []
|
||||
elif isinstance(self.kicost_api_enable, str):
|
||||
self.kicost_api_enable = [self.kicost_api_enable]
|
||||
if isinstance(self.kicost_api_disable, type):
|
||||
self.kicost_api_disable = []
|
||||
elif isinstance(self.kicost_api_disable, str):
|
||||
self.kicost_api_disable = [self.kicost_api_disable]
|
||||
self.kicost_api_enable = Optionable.force_list(self.kicost_api_enable)
|
||||
self.kicost_api_disable = Optionable.force_list(self.kicost_api_disable)
|
||||
# Specs columns
|
||||
(self.s_columns, self.s_levels, self.s_comments, self.s_rename,
|
||||
self.s_join) = self.process_columns_config(self.specs_columns)
|
||||
|
|
@ -604,8 +602,10 @@ class BoMOptions(BaseOptions):
|
|||
# Here because some variables needs our parent
|
||||
if self.format == 'html' and self.html.title:
|
||||
self.html.title = self.expand_filename_both(self.html.title, make_safe=False)
|
||||
self.html.extra_info = [self.expand_filename_both(t, make_safe=False) for t in self.html.extra_info]
|
||||
if self.format == 'xlsx' and self.xlsx.title:
|
||||
self.xlsx.title = self.expand_filename_both(self.xlsx.title, make_safe=False)
|
||||
self.xlsx.extra_info = [self.expand_filename_both(t, make_safe=False) for t in self.xlsx.extra_info]
|
||||
# group_fields
|
||||
if isinstance(self.group_fields, type):
|
||||
self.group_fields = GroupFields.get_default()
|
||||
|
|
|
|||
160
src/kibot-check
160
src/kibot-check
|
|
@ -147,21 +147,21 @@ deps = '{\
|
|||
"name": "ImageMagick",\
|
||||
"no_cmd_line_version": false,\
|
||||
"no_cmd_line_version_old": false,\
|
||||
"output": "pcb_print",\
|
||||
"output": "pcbdraw",\
|
||||
"plugin_dirs": null,\
|
||||
"pypi_name": "ImageMagick",\
|
||||
"roles": [\
|
||||
{\
|
||||
"desc": "Create monochrome prints",\
|
||||
"mandatory": false,\
|
||||
"output": "pcb_print",\
|
||||
"version": null\
|
||||
},\
|
||||
{\
|
||||
"desc": "Create JPG images",\
|
||||
"mandatory": false,\
|
||||
"output": "pcbdraw",\
|
||||
"version": null\
|
||||
},\
|
||||
{\
|
||||
"desc": "Create monochrome prints",\
|
||||
"mandatory": false,\
|
||||
"output": "pcb_print",\
|
||||
"version": null\
|
||||
}\
|
||||
],\
|
||||
"url": "https://imagemagick.org/",\
|
||||
|
|
@ -243,62 +243,10 @@ deps = '{\
|
|||
"name": "KiCad Automation tools",\
|
||||
"no_cmd_line_version": false,\
|
||||
"no_cmd_line_version_old": false,\
|
||||
"output": "step",\
|
||||
"output": "svg_pcb_print",\
|
||||
"plugin_dirs": null,\
|
||||
"pypi_name": "kiauto",\
|
||||
"roles": [\
|
||||
{\
|
||||
"desc": null,\
|
||||
"mandatory": true,\
|
||||
"output": "step",\
|
||||
"version": [\
|
||||
1,\
|
||||
6,\
|
||||
1\
|
||||
]\
|
||||
},\
|
||||
{\
|
||||
"desc": null,\
|
||||
"mandatory": true,\
|
||||
"output": "netlist",\
|
||||
"version": [\
|
||||
1,\
|
||||
6,\
|
||||
11\
|
||||
]\
|
||||
},\
|
||||
{\
|
||||
"desc": null,\
|
||||
"mandatory": true,\
|
||||
"output": "render_3d",\
|
||||
"version": [\
|
||||
1,\
|
||||
6,\
|
||||
8\
|
||||
]\
|
||||
},\
|
||||
{\
|
||||
"desc": null,\
|
||||
"mandatory": true,\
|
||||
"output": "svg_sch_print",\
|
||||
"version": null\
|
||||
},\
|
||||
{\
|
||||
"desc": null,\
|
||||
"mandatory": true,\
|
||||
"output": "pdf_pcb_print",\
|
||||
"version": [\
|
||||
1,\
|
||||
6,\
|
||||
7\
|
||||
]\
|
||||
},\
|
||||
{\
|
||||
"desc": null,\
|
||||
"mandatory": true,\
|
||||
"output": "pdf_sch_print",\
|
||||
"version": null\
|
||||
},\
|
||||
{\
|
||||
"desc": null,\
|
||||
"mandatory": true,\
|
||||
|
|
@ -319,6 +267,58 @@ deps = '{\
|
|||
5\
|
||||
]\
|
||||
},\
|
||||
{\
|
||||
"desc": null,\
|
||||
"mandatory": true,\
|
||||
"output": "svg_sch_print",\
|
||||
"version": null\
|
||||
},\
|
||||
{\
|
||||
"desc": null,\
|
||||
"mandatory": true,\
|
||||
"output": "pdf_sch_print",\
|
||||
"version": null\
|
||||
},\
|
||||
{\
|
||||
"desc": null,\
|
||||
"mandatory": true,\
|
||||
"output": "pdf_pcb_print",\
|
||||
"version": [\
|
||||
1,\
|
||||
6,\
|
||||
7\
|
||||
]\
|
||||
},\
|
||||
{\
|
||||
"desc": null,\
|
||||
"mandatory": true,\
|
||||
"output": "netlist",\
|
||||
"version": [\
|
||||
1,\
|
||||
6,\
|
||||
11\
|
||||
]\
|
||||
},\
|
||||
{\
|
||||
"desc": null,\
|
||||
"mandatory": true,\
|
||||
"output": "step",\
|
||||
"version": [\
|
||||
1,\
|
||||
6,\
|
||||
1\
|
||||
]\
|
||||
},\
|
||||
{\
|
||||
"desc": null,\
|
||||
"mandatory": true,\
|
||||
"output": "render_3d",\
|
||||
"version": [\
|
||||
1,\
|
||||
6,\
|
||||
8\
|
||||
]\
|
||||
},\
|
||||
{\
|
||||
"desc": null,\
|
||||
"mandatory": true,\
|
||||
|
|
@ -328,13 +328,13 @@ deps = '{\
|
|||
{\
|
||||
"desc": null,\
|
||||
"mandatory": true,\
|
||||
"output": "run_drc",\
|
||||
"output": "update_xml",\
|
||||
"version": null\
|
||||
},\
|
||||
{\
|
||||
"desc": null,\
|
||||
"mandatory": true,\
|
||||
"output": "update_xml",\
|
||||
"output": "run_drc",\
|
||||
"version": null\
|
||||
}\
|
||||
],\
|
||||
|
|
@ -353,20 +353,10 @@ deps = '{\
|
|||
"name": "KiCost",\
|
||||
"no_cmd_line_version": false,\
|
||||
"no_cmd_line_version_old": false,\
|
||||
"output": "bom",\
|
||||
"output": "kicost",\
|
||||
"plugin_dirs": null,\
|
||||
"pypi_name": "KiCost",\
|
||||
"roles": [\
|
||||
{\
|
||||
"desc": "Find components costs and specs",\
|
||||
"mandatory": false,\
|
||||
"output": "bom",\
|
||||
"version": [\
|
||||
1,\
|
||||
1,\
|
||||
8\
|
||||
]\
|
||||
},\
|
||||
{\
|
||||
"desc": null,\
|
||||
"mandatory": true,\
|
||||
|
|
@ -376,6 +366,16 @@ deps = '{\
|
|||
1,\
|
||||
7\
|
||||
]\
|
||||
},\
|
||||
{\
|
||||
"desc": "Find components costs and specs",\
|
||||
"mandatory": false,\
|
||||
"output": "bom",\
|
||||
"version": [\
|
||||
1,\
|
||||
1,\
|
||||
8\
|
||||
]\
|
||||
}\
|
||||
],\
|
||||
"url": "https://github.com/INTI-CMNB/KiCost",\
|
||||
|
|
@ -559,21 +559,21 @@ deps = '{\
|
|||
"name": "RSVG tools",\
|
||||
"no_cmd_line_version": false,\
|
||||
"no_cmd_line_version_old": false,\
|
||||
"output": "pcb_print",\
|
||||
"output": "pcbdraw",\
|
||||
"plugin_dirs": null,\
|
||||
"pypi_name": "RSVG tools",\
|
||||
"roles": [\
|
||||
{\
|
||||
"desc": "Create PDF, PNG, EPS and PS formats",\
|
||||
"mandatory": false,\
|
||||
"output": "pcb_print",\
|
||||
"version": null\
|
||||
},\
|
||||
{\
|
||||
"desc": "Create PNG and JPG images",\
|
||||
"mandatory": false,\
|
||||
"output": "pcbdraw",\
|
||||
"version": null\
|
||||
},\
|
||||
{\
|
||||
"desc": "Create PDF, PNG, EPS and PS formats",\
|
||||
"mandatory": false,\
|
||||
"output": "pcb_print",\
|
||||
"version": null\
|
||||
}\
|
||||
],\
|
||||
"url": "https://cran.r-project.org/web/packages/rsvg/index.html",\
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
,,,KiBot Bill of Materials,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,,kibom-variant_2c,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,, 2021-04-06,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,,Schematic:,kibom-variant_2c,,,,,Board Qty:,50,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,,Variant:,default,,,,,Unit Cost:,0.002,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,,Revision:,A,,,,,Total Cost:,0.1,,,,,0,0 of 1 parts found,,,,,0.61,1 of 1 parts found,,,,,0.7292,1 of 1 parts found,,,,,0,0 of 1 parts found,,,,,0.5,1 of 1 parts found,,,,,0.1,1 of 1 parts found,,,,,0,0 of 1 parts found,,,,,0,0 of 1 parts found,,,,,0,0 of 1 parts found
|
||||
|
|
|
|||
|
|
|
@ -1,4 +1,6 @@
|
|||
,,,KiBot Bill of Materials,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,,kibom-variant_2c,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,, 2021-04-06,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,,Schematic:,kibom-variant_2c,,,,,Board Qty:,50,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,,Variant:,default,,,,,Unit Cost:,0.0098,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,,Revision:,A,,,,,Total Cost:,0.49,,,,,0,0 of 1 parts found,,,,,1.66,1 of 1 parts found,,,,,2.0089,1 of 1 parts found,,,,,0.49,1 of 1 parts found,,,,,1.8,1 of 1 parts found,,,,,1.8,1 of 1 parts found,,,,,0,1 of 1 parts found,,,,,2.2725,1 of 1 parts found,,,,,0,0 of 1 parts found
|
||||
|
|
|
|||
|
|
|
@ -156,13 +156,18 @@ def check_path(rows, comp, ref, sp, val):
|
|||
return
|
||||
|
||||
|
||||
def check_head_xlsx(r, info, stats, title=DEF_TITLE):
|
||||
def check_head_xlsx(r, info, stats, title=DEF_TITLE, extra_info=None):
|
||||
rn = 0
|
||||
if title:
|
||||
# First row is just the title
|
||||
assert r[rn][0] == title
|
||||
rn += 1
|
||||
logging.debug('Title Ok')
|
||||
if extra_info:
|
||||
for e in extra_info:
|
||||
assert r[rn][0] == e
|
||||
rn += 1
|
||||
logging.debug('Extra `{}` Ok'.format(e))
|
||||
if info:
|
||||
info_col = 0
|
||||
for i, txt in enumerate(info):
|
||||
|
|
@ -180,7 +185,7 @@ def check_head_xlsx(r, info, stats, title=DEF_TITLE):
|
|||
logging.debug('Stats block Ok')
|
||||
|
||||
|
||||
def check_head_html(r, info, stats, title, logo):
|
||||
def check_head_html(r, info, stats, title, logo, extra_info):
|
||||
if title:
|
||||
assert 'title' in r
|
||||
assert r['title'] == title
|
||||
|
|
@ -194,6 +199,15 @@ def check_head_html(r, info, stats, title, logo):
|
|||
else:
|
||||
assert 'logo' not in r
|
||||
logging.debug('No logo Ok')
|
||||
if extra_info:
|
||||
assert 'extra_info' in r
|
||||
extra = r['extra_info']
|
||||
for i, val in enumerate(extra_info):
|
||||
assert extra[i] == val
|
||||
logging.debug('Extra info Ok')
|
||||
else:
|
||||
assert 'extra_info' not in r
|
||||
logging.debug('No extra info Ok')
|
||||
if info:
|
||||
assert 'info' in r
|
||||
for i, tit in enumerate(INFO_ROWS):
|
||||
|
|
@ -323,13 +337,13 @@ def test_int_bom_simple_txt(test_dir):
|
|||
|
||||
|
||||
def simple_html_test(ctx, rows, headers, sh_head, prj, do_title=True, do_logo=True, do_info=True, do_stats=True,
|
||||
a_title=DEF_TITLE):
|
||||
a_title=DEF_TITLE, extra_info=None):
|
||||
title = a_title if do_title else None
|
||||
info = KIBOM_PRJ_INFO if do_info else None
|
||||
stats = None
|
||||
if do_stats:
|
||||
stats = KIBOM_STATS
|
||||
check_head_html(sh_head, info, stats, title=title, logo=do_logo)
|
||||
check_head_html(sh_head, info, stats, title=title, logo=do_logo, extra_info=extra_info)
|
||||
# Test we got the normal and DNF tables
|
||||
assert len(rows) == 2
|
||||
assert len(headers) == 2
|
||||
|
|
@ -362,7 +376,7 @@ def simple_html_setup(test_dir, name, ret_val=0):
|
|||
|
||||
def test_int_bom_simple_html_1(test_dir):
|
||||
(rows, headers, sh_head), prj, ctx = simple_html_setup(test_dir, 'int_bom_simple_html_1')
|
||||
simple_html_test(ctx, rows, headers, sh_head, prj)
|
||||
simple_html_test(ctx, rows, headers, sh_head, prj, extra_info=['Extra 1: '+prj, 'Extra 2: 2020-03-12'])
|
||||
|
||||
|
||||
def test_int_bom_simple_html_2(test_dir):
|
||||
|
|
@ -442,12 +456,12 @@ def test_int_bom_simple_xml(test_dir):
|
|||
ctx.clean_up()
|
||||
|
||||
|
||||
def simple_xlsx_verify(ctx, prj, dnf=True, title=DEF_TITLE):
|
||||
def simple_xlsx_verify(ctx, prj, dnf=True, title=DEF_TITLE, extra_info=None):
|
||||
ext = 'xlsx'
|
||||
ctx.run()
|
||||
out = prj + '-bom.' + ext
|
||||
rows, header, sh_head = ctx.load_xlsx(out)
|
||||
check_head_xlsx(sh_head, KIBOM_PRJ_INFO, KIBOM_STATS, title=title)
|
||||
check_head_xlsx(sh_head, KIBOM_PRJ_INFO, KIBOM_STATS, title=title, extra_info=extra_info)
|
||||
assert header == KIBOM_TEST_HEAD
|
||||
ref_column = header.index(REF_COLUMN_NAME)
|
||||
status_column = header.index(STATUS_COLUMN_NAME)
|
||||
|
|
@ -464,7 +478,7 @@ def simple_xlsx_verify(ctx, prj, dnf=True, title=DEF_TITLE):
|
|||
def test_int_bom_simple_xlsx_1(test_dir):
|
||||
prj = 'kibom-test'
|
||||
ctx = context.TestContextSCH(test_dir, 'test_int_bom_simple_xlsx', prj, 'int_bom_simple_xlsx', BOM_DIR)
|
||||
simple_xlsx_verify(ctx, prj)
|
||||
simple_xlsx_verify(ctx, prj, extra_info=['Extra 1: '+prj, 'Extra 2: 2020-03-12'])
|
||||
|
||||
|
||||
def get_column(rows, col, split=True):
|
||||
|
|
|
|||
|
|
@ -591,6 +591,15 @@ class TestContext(object):
|
|||
inf_entries.append(val)
|
||||
if inf_entries:
|
||||
sh_head['info'] = inf_entries
|
||||
# Extract extra info
|
||||
m = re.search(r'<td colspan="2" class="cell-extra-info">((?:\s+.*?)+)</td>', body, re.MULTILINE)
|
||||
if m:
|
||||
info = m.group(1)
|
||||
inf_entries = []
|
||||
for val in re.findall('<b>(.*?)</b><br>', info):
|
||||
inf_entries.append(val)
|
||||
if inf_entries:
|
||||
sh_head['extra_info'] = inf_entries
|
||||
# Extract stats
|
||||
m = re.search(r'<td class="cell-stats">((?:\s+.*?)+)</td>', body, re.MULTILINE)
|
||||
if m:
|
||||
|
|
|
|||
|
|
@ -37,3 +37,4 @@ outputs:
|
|||
xlsx:
|
||||
kicost: true
|
||||
kicost_config: tests/data/kicost_default_config.yaml
|
||||
extra_info: ['%f', ' %d']
|
||||
|
|
|
|||
|
|
@ -8,5 +8,8 @@ outputs:
|
|||
type: bom
|
||||
dir: BoM
|
||||
options:
|
||||
format: HTML
|
||||
variant: ''
|
||||
html:
|
||||
extra_info:
|
||||
- 'Extra 1: %f'
|
||||
- 'Extra 2: %d'
|
||||
|
|
|
|||
|
|
@ -8,4 +8,7 @@ outputs:
|
|||
type: bom
|
||||
dir: BoM
|
||||
options:
|
||||
format: XLSX
|
||||
xlsx:
|
||||
extra_info:
|
||||
- 'Extra 1: %f'
|
||||
- 'Extra 2: %d'
|
||||
|
|
|
|||
Loading…
Reference in New Issue