diff --git a/kibot/bom/bom.py b/kibot/bom/bom.py
index 2b6c0530..72a457e7 100644
--- a/kibot/bom/bom.py
+++ b/kibot/bom/bom.py
@@ -14,33 +14,10 @@ from copy import deepcopy
from .units import compare_values, comp_match
from .bom_writer import write_bom
from .columnlist import ColumnList
+from ..misc import DNF
from .. import log
logger = log.get_logger(__name__)
-# Supported values for "do not fit"
-DNF = {
- "dnf": 1,
- "dnl": 1,
- "dnp": 1,
- "do not fit": 1,
- "do not place": 1,
- "do not load": 1,
- "nofit": 1,
- "nostuff": 1,
- "noplace": 1,
- "noload": 1,
- "not fitted": 1,
- "not loaded": 1,
- "not placed": 1,
- "no stuff": 1,
-}
-# String matches for marking a component as "do not change" or "fixed"
-DNC = {
- "dnc": 1,
- "do not change": 1,
- "no change": 1,
- "fixed": 1
-}
# RV == Resistor Variable or Varistor
# RN == Resistor 'N'(Pack)
# RT == Thermistor
@@ -412,88 +389,11 @@ def group_components(cfg, components):
return groups
-def comp_is_fixed(value, config, variants):
- """ Determine if a component is FIXED or not.
- Fixed components shouldn't be replaced without express authorization.
- value: component value (lowercase).
- config: content of the 'Config' field (lowercase).
- variants: list of variants to match. """
- # Check the value field first
- if value in DNC:
- return True
- # Empty is not fixed
- if not config:
- return False
- # Also support space separated list (simple cases)
- opts = config.split(" ")
- for opt in opts:
- if opt in DNC:
- return True
- # Normal separator is ","
- opts = config.split(",")
- for opt in opts:
- if opt in DNC:
- return True
- return False
-
-
-def comp_is_fitted(value, config, variants):
- """ Determine if a component will be or not.
- value: component value (lowercase).
- config: content of the 'Config' field (lowercase).
- variants: list of variants to match. """
- # Check the value field first
- if value in DNF:
- return False
- # Empty value means part is fitted
- if not config:
- return True
- # Also support space separated list (simple cases)
- opts = config.split(" ")
- for opt in opts:
- if opt in DNF:
- return False
- # Variants logic
- opts = config.split(",")
- # Only fit for ...
- exclusive = False
- for opt in opts:
- opt = opt.strip()
- # Any option containing a DNF is not fitted
- if opt in DNF:
- return False
- # Options that start with '-' are explicitly removed from certain configurations
- if opt.startswith("-") and opt[1:] in variants:
- return False
- # Options that start with '+' are fitted only for certain configurations
- if opt.startswith("+"):
- exclusive = True
- if opt[1:] in variants:
- return True
- # No match
- return not exclusive
-
-
def do_bom(file_name, ext, comps, cfg):
- # Make the config field name lowercase
- cfg.fit_field = cfg.fit_field.lower()
- f_config = cfg.fit_field
- # Make the variants lowercase
- variants = [v.lower() for v in cfg.variant]
# Solve `fixed` and `fitted` attributes for all components
- for c in comps:
- value = c.value.lower()
- config = c.get_field_value(f_config).lower()
- c.fitted = comp_is_fitted(value, config, variants)
- if cfg.debug_level > 2:
- logger.debug('ref: {} value: {} config: {} variants: {} -> fitted {}'.
- format(c.ref, value, config, variants, c.fitted))
- c.fixed = comp_is_fixed(value, config, variants)
+ cfg.variant.filter(comps)
# Group components according to group_fields
groups = group_components(cfg, comps)
- # Give a name to empty variant
- if not variants:
- cfg.variant = ['default']
# Create the BoM
logger.debug("Saving BOM File: "+file_name)
write_bom(file_name, ext, groups, cfg.columns, cfg)
diff --git a/kibot/bom/csv_writer.py b/kibot/bom/csv_writer.py
index 748dc85c..dca72765 100644
--- a/kibot/bom/csv_writer.py
+++ b/kibot/bom/csv_writer.py
@@ -53,7 +53,7 @@ def write_csv(filename, ext, groups, headings, head_names, cfg):
if not cfg.csv.hide_pcb_info:
writer.writerow(["Project info:"])
writer.writerow(["Schematic:", cfg.source])
- writer.writerow(["Variant:", ' + '.join(cfg.variant)])
+ writer.writerow(["Variant:", cfg.variant.name])
writer.writerow(["Revision:", cfg.revision])
writer.writerow(["Date:", cfg.date])
writer.writerow(["KiCad Version:", cfg.kicad_version])
diff --git a/kibot/bom/html_writer.py b/kibot/bom/html_writer.py
index 93778fc0..cf13eff4 100644
--- a/kibot/bom/html_writer.py
+++ b/kibot/bom/html_writer.py
@@ -213,7 +213,7 @@ def write_html(filename, groups, headings, head_names, cfg):
html.write('
\n')
if not cfg.html.hide_pcb_info:
html.write(" Schematic: {} \n".format(cfg.source))
- html.write(" Variant: {} \n".format(', '.join(cfg.variant)))
+ html.write(" Variant: {} \n".format(cfg.variant.name))
html.write(" Revision: {} \n".format(cfg.revision))
html.write(" Date: {} \n".format(cfg.date))
html.write(" KiCad Version: {} \n".format(cfg.kicad_version))
diff --git a/kibot/bom/xlsx_writer.py b/kibot/bom/xlsx_writer.py
index 551e65a0..5874f9f1 100644
--- a/kibot/bom/xlsx_writer.py
+++ b/kibot/bom/xlsx_writer.py
@@ -313,7 +313,7 @@ def write_xlsx(filename, groups, col_fields, head_names, cfg):
rc = r_info_start
if not cfg.xlsx.hide_pcb_info:
rc = add_info(worksheet, column_widths, rc, col1, fmt_info, "Schematic:", cfg.source)
- rc = add_info(worksheet, column_widths, rc, col1, fmt_info, "Variant:", ' + '.join(cfg.variant))
+ rc = add_info(worksheet, column_widths, rc, col1, fmt_info, "Variant:", cfg.variant.name)
rc = add_info(worksheet, column_widths, rc, col1, fmt_info, "Revision:", cfg.revision)
rc = add_info(worksheet, column_widths, rc, col1, fmt_info, "Date:", cfg.date)
rc = add_info(worksheet, column_widths, rc, col1, fmt_info, "KiCad Version:", cfg.kicad_version)
diff --git a/kibot/bom/xml_writer.py b/kibot/bom/xml_writer.py
index 5bb2f3e0..fa514896 100644
--- a/kibot/bom/xml_writer.py
+++ b/kibot/bom/xml_writer.py
@@ -26,7 +26,7 @@ def write_xml(filename, groups, headings, head_names, cfg):
attrib['Schematic_Source'] = cfg.source
attrib['Schematic_Revision'] = cfg.revision
attrib['Schematic_Date'] = cfg.date
- attrib['PCB_Variant'] = ', '.join(cfg.variant)
+ attrib['PCB_Variant'] = cfg.variant.name
attrib['KiCad_Version'] = cfg.kicad_version
attrib['Component_Groups'] = str(cfg.n_groups)
attrib['Component_Count'] = str(cfg.n_total)
diff --git a/kibot/misc.py b/kibot/misc.py
index 515d7436..8947524e 100644
--- a/kibot/misc.py
+++ b/kibot/misc.py
@@ -45,3 +45,28 @@ PCBDRAW = 'pcbdraw'
URL_PCBDRAW = 'https://github.com/INTI-CMNB/pcbdraw'
EXAMPLE_CFG = 'example.kibot.yaml'
AUTO_SCALE = 0
+
+# Supported values for "do not fit"
+DNF = {
+ "dnf": 1,
+ "dnl": 1,
+ "dnp": 1,
+ "do not fit": 1,
+ "do not place": 1,
+ "do not load": 1,
+ "nofit": 1,
+ "nostuff": 1,
+ "noplace": 1,
+ "noload": 1,
+ "not fitted": 1,
+ "not loaded": 1,
+ "not placed": 1,
+ "no stuff": 1,
+}
+# String matches for marking a component as "do not change" or "fixed"
+DNC = {
+ "dnc": 1,
+ "do not change": 1,
+ "no change": 1,
+ "fixed": 1
+}
diff --git a/kibot/out_bom.py b/kibot/out_bom.py
index 81557193..615e3866 100644
--- a/kibot/out_bom.py
+++ b/kibot/out_bom.py
@@ -11,10 +11,12 @@ import os
from re import compile, IGNORECASE
from .gs import GS
from .optionable import Optionable, BaseOptions
+from .registrable import RegOutput
from .error import KiPlotConfigurationError
from .macros import macros, document, output_class # noqa: F401
from .bom.columnlist import ColumnList, BoMError
from .bom.bom import do_bom
+from .var_kibom import KiBoM
from . import log
logger = log.get_logger(__name__)
@@ -207,8 +209,8 @@ class BoMOptions(BaseOptions):
with document:
self.number = 1
""" Number of boards to build (components multiplier) """
- self.variant = Optionable
- """ [string|list(string)=''] Board variant(s), used to determine which components
+ self.variant = ''
+ """ Board variant(s), used to determine which components
are output to the BoM. """
self.output = GS.def_global_output
""" filename for the output (%i=bom)"""
@@ -228,7 +230,8 @@ class BoMOptions(BaseOptions):
self.merge_blank_fields = True
""" Component groups with blank fields will be merged into the most compatible group, where possible """
self.fit_field = 'Config'
- """ Field name used to determine if a particular part is to be fitted (also DNC and variants) """
+ """ Field name used to determine if a particular part is to be fitted (also DNC, not for variants).
+ This value is used only when no variants are specified """
self.group_fields = GroupFields
""" [list(string)] List of fields used for sorting individual components into groups.
Components which match (comparing *all* fields) will be grouped together.
@@ -316,16 +319,18 @@ class BoMOptions(BaseOptions):
col = col[:-1]
return col
- @staticmethod
- def _normalize_variant(variant):
- if isinstance(variant, type):
- variant = []
- elif isinstance(variant, str):
- if variant:
- variant = [variant]
- else:
- variant = []
- return variant
+ def _normalize_variant(self):
+ """ Replaces the name of the variant by an object handling it. """
+ if self.variant:
+ if self.variant not in RegOutput._def_variants:
+ raise KiPlotConfigurationError("Unknown variant name `{}`".format(self.variant))
+ self.variant = RegOutput._def_variants[self.variant]
+ else:
+ # If no variant is specified use the KiBoM variant class with basic functionality
+ self.variant = KiBoM()
+ self.variant.config_field = self.fit_field
+ self.variant.variant = []
+ self.variant.name = 'default'
def config(self):
super().config()
@@ -372,8 +377,10 @@ class BoMOptions(BaseOptions):
for r in self.exclude_any:
r.column = self._fix_ref_field(r.column)
r.regex = compile(r.regex, flags=IGNORECASE)
- # Variants, ensure a list
- self.variant = self._normalize_variant(self.variant)
+ # Make the config field name lowercase
+ self.fit_field = self.fit_field.lower()
+ # Variants, make it an object
+ self._normalize_variant()
# Columns
self.column_rename = {}
self.join = []
diff --git a/kibot/var_kibom.py b/kibot/var_kibom.py
new file mode 100644
index 00000000..2b606c4a
--- /dev/null
+++ b/kibot/var_kibom.py
@@ -0,0 +1,141 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020 Salvador E. Tropea
+# Copyright (c) 2020 Instituto Nacional de TecnologĂa Industrial
+# License: GPL-3.0
+# Project: KiBot (formerly KiPlot)
+"""
+Implements the KiBoM variants mechanism.
+"""
+from .optionable import Optionable
+from .gs import GS
+from .misc import DNF, DNC
+from .macros import macros, document, variant_class # noqa: F401
+from . import log
+
+logger = log.get_logger(__name__)
+
+
+@variant_class
+class KiBoM(BaseVariant): # noqa: F821
+ """ KiBoM variant style
+ The Config field (configurable) contains a comma separated list of variant directives.
+ -VARIANT excludes a component from VARIANT.
+ +VARIANT includes the component only if we are using this variant. """
+ def __init__(self):
+ super().__init__()
+ with document:
+ self.config_field = 'Config'
+ """ Name of the field used to clasify components """
+ self.variant = Optionable
+ """ [string|list(string)=''] Board variant(s) """
+
+ def config(self):
+ super().config()
+ # Variants, ensure a list
+ if isinstance(self.variant, type):
+ self.variant = []
+ elif isinstance(self.variant, str):
+ if self.variant:
+ self.variant = [self.variant]
+ else:
+ self.variant = []
+ self.variant = [v.lower() for v in self.variant]
+ # Config field must be lowercase
+ self.config_field = self.config_field.lower()
+
+ @staticmethod
+ def basic_comp_is_fitted(value, config):
+ """ Basic `fitted` criteria, no variants.
+ value: component value (lowercase).
+ config: content of the 'Config' field (lowercase). """
+ # Check the value field first
+ if value in DNF:
+ return False
+ # Empty value means part is fitted
+ if not config:
+ return True
+ # Also support space separated list (simple cases)
+ opts = config.split(" ")
+ for opt in opts:
+ if opt in DNF:
+ return False
+ # Normal separator is ","
+ opts = config.split(",")
+ for opt in opts:
+ if opt in DNF:
+ return False
+ return True
+
+ @staticmethod
+ def basic_comp_is_fixed(value, config):
+ """ Basic `fixed` criteria, no variants
+ Fixed components shouldn't be replaced without express authorization.
+ value: component value (lowercase).
+ config: content of the 'Config' field (lowercase). """
+ # Check the value field first
+ if value in DNC:
+ return True
+ # Empty is not fixed
+ if not config:
+ return False
+ # Also support space separated list (simple cases)
+ opts = config.split(" ")
+ for opt in opts:
+ if opt in DNC:
+ return True
+ # Normal separator is ","
+ opts = config.split(",")
+ for opt in opts:
+ if opt in DNC:
+ return True
+ return False
+
+ @staticmethod
+ def _base_filter(comps, f_config):
+ """ Fill the `fixed` and `fitted` using the basic criteria.
+ No variant is applied in this step. """
+ logger.debug("- Generic KiBoM rules")
+ for c in comps:
+ value = c.value.lower()
+ config = c.get_field_value(f_config).lower()
+ c.fitted = KiBoM.basic_comp_is_fitted(value, config)
+ if GS.debug_level > 2:
+ logger.debug('ref: {} value: {} config: {} -> fitted {}'.
+ format(c.ref, value, config, c.fitted))
+ c.fixed = KiBoM.basic_comp_is_fixed(value, config)
+
+ def variant_comp_is_fitted(self, value, config):
+ """ Apply the variants to determine if this component will be fitted.
+ value: component value (lowercase).
+ config: content of the 'Config' field (lowercase). """
+ # Variants logic
+ opts = config.split(",")
+ # Only fit for ...
+ exclusive = False
+ for opt in opts:
+ opt = opt.strip()
+ # Options that start with '-' are explicitly removed from certain configurations
+ if opt.startswith("-") and opt[1:] in self.variant:
+ return False
+ # Options that start with '+' are fitted only for certain configurations
+ if opt.startswith("+"):
+ exclusive = True
+ if opt[1:] in self.variant:
+ return True
+ # No match
+ return not exclusive
+
+ def filter(self, comps):
+ logger.debug("Applying KiBoM style filter `{}`".format(self.name))
+ self._base_filter(comps, self.config_field)
+ logger.debug("- Variant specific rules")
+ for c in comps:
+ if not c.fitted:
+ # Don't check if we already discarded it during the basic test
+ continue
+ value = c.value.lower()
+ config = c.get_field_value(self.config_field).lower()
+ c.fitted = self.variant_comp_is_fitted(value, config)
+ if not c.fitted and GS.debug_level > 2:
+ logger.debug('ref: {} value: {} config: {} variant: {} -> False'.
+ format(c.ref, value, config, self.variant))
diff --git a/tests/test_plot/test_int_bom.py b/tests/test_plot/test_int_bom.py
index fa4e5bac..f80f536f 100644
--- a/tests/test_plot/test_int_bom.py
+++ b/tests/test_plot/test_int_bom.py
@@ -81,6 +81,7 @@ KIBOM_STATS = [KIBOM_TEST_GROUPS+len(KIBOM_TEST_EXCLUDE),
len(KIBOM_TEST_COMPONENTS),
1,
len(KIBOM_TEST_COMPONENTS)]
+VARIANTE_PRJ_INFO = ['kibom-variante', 'default', 'A', '2020-03-12', None]
LINK_HEAD = ['References', 'Part', 'Value', 'Quantity Per PCB', 'digikey#', 'digikey_alt#', 'manf#']
LINKS_COMPONENTS = ['J1', 'J2', 'R1']
LINKS_EXCLUDE = ['C1']
@@ -1158,82 +1159,54 @@ def test_int_bom_missing_lib():
ctx.clean_up()
-def test_int_bom_variant_t1_1():
+def test_int_bom_variant_t1():
prj = 'kibom-variante'
- ctx = context.TestContextSCH('test_int_bom_variant_t1_1', prj, 'int_bom_var_v1_csv', BOM_DIR)
- ctx.run()
- rows, header, info = ctx.load_csv(prj+'-bom.csv')
- ref_column = header.index(REF_COLUMN_NAME)
- check_kibom_test_netlist(rows, ref_column, 2, ['R3', 'R4'], ['R1', 'R2'])
- ctx.search_err(r'Field Config of component (.*) contains extra spaces')
- ctx.clean_up()
-
-
-def test_int_bom_variant_t1_2():
- prj = 'kibom-variante'
- ctx = context.TestContextSCH('test_int_bom_variant_t1_2', prj, 'int_bom_var_v2_csv', BOM_DIR)
- ctx.run()
- rows, header, info = ctx.load_csv(prj+'-bom.csv')
- ref_column = header.index(REF_COLUMN_NAME)
- check_kibom_test_netlist(rows, ref_column, 1, ['R2', 'R4'], ['R1', 'R3'])
- ctx.clean_up()
-
-
-def test_int_bom_variant_t1_3():
- prj = 'kibom-variante'
- ctx = context.TestContextSCH('test_int_bom_variant_t1_3', prj, 'int_bom_var_v3_csv', BOM_DIR)
- ctx.run()
- rows, header, info = ctx.load_csv(prj+'-bom.csv')
- ref_column = header.index(REF_COLUMN_NAME)
- check_kibom_test_netlist(rows, ref_column, 1, ['R2', 'R3'], ['R1', 'R4'])
- ctx.clean_up()
-
-
-def test_int_bom_variant_t1_4():
- prj = 'kibom-variante'
- ctx = context.TestContextSCH('test_int_bom_variant_t1_4', prj, 'int_bom_simple_csv', BOM_DIR)
+ ctx = context.TestContextSCH('test_int_bom_variant_t1', prj, 'int_bom_var_t1_csv', BOM_DIR)
ctx.run()
+ # No variant
+ logging.debug("* No variant")
rows, header, info = ctx.load_csv(prj+'-bom.csv')
ref_column = header.index(REF_COLUMN_NAME)
check_kibom_test_netlist(rows, ref_column, 2, ['R4'], ['R1', 'R2', 'R3'])
- ctx.clean_up()
-
-
-def test_int_bom_variant_t1_5():
- prj = 'kibom-variante'
- ctx = context.TestContextSCH('test_int_bom_variant_t1_5', prj, 'int_bom_var_v1v3_csv', BOM_DIR)
- ctx.run()
- rows, header, info = ctx.load_csv(prj+'-bom.csv')
- ref_column = header.index(REF_COLUMN_NAME)
+ VARIANTE_PRJ_INFO[1] = 'default'
+ check_csv_info(info, VARIANTE_PRJ_INFO, [4, 20, 3, 1, 3])
+ # V1
+ logging.debug("* t1_v1 variant")
+ rows, header, info = ctx.load_csv(prj+'-bom_(V1).csv')
+ check_kibom_test_netlist(rows, ref_column, 2, ['R3', 'R4'], ['R1', 'R2'])
+ ctx.search_err(r'Field Config of component (.*) contains extra spaces')
+ VARIANTE_PRJ_INFO[1] = 't1_v1'
+ check_csv_info(info, VARIANTE_PRJ_INFO, [4, 20, 2, 1, 2])
+ # V2
+ logging.debug("* t1_v2 variant")
+ rows, header, info = ctx.load_csv(prj+'-bom_(V2).csv')
+ check_kibom_test_netlist(rows, ref_column, 1, ['R2', 'R4'], ['R1', 'R3'])
+ VARIANTE_PRJ_INFO[1] = 't1_v2'
+ check_csv_info(info, VARIANTE_PRJ_INFO, [3, 20, 2, 1, 2])
+ # V3
+ logging.debug("* t1_v3 variant")
+ rows, header, info = ctx.load_csv(prj+'-bom_V3.csv')
check_kibom_test_netlist(rows, ref_column, 1, ['R2', 'R3'], ['R1', 'R4'])
+ VARIANTE_PRJ_INFO[1] = 't1_v3'
+ check_csv_info(info, VARIANTE_PRJ_INFO, [3, 20, 2, 1, 2])
+ # V1,V3
+ logging.debug("* `bla bla` variant")
+ rows, header, info = ctx.load_csv(prj+'-bom_bla_bla.csv')
+ check_kibom_test_netlist(rows, ref_column, 1, ['R2', 'R3'], ['R1', 'R4'])
+ VARIANTE_PRJ_INFO[1] = 'bla bla'
+ check_csv_info(info, VARIANTE_PRJ_INFO, [3, 20, 2, 1, 2])
ctx.clean_up()
-def test_int_bom_variant_t2_1():
+def test_int_bom_variant_t2():
prj = 'kibom-variant_2'
- ctx = context.TestContextSCH('test_int_bom_variant_t2_1', prj, 'int_bom_var_production_csv', BOM_DIR)
- ctx.run()
- rows, header, info = ctx.load_csv(prj+'-bom.csv')
- ref_column = header.index(REF_COLUMN_NAME)
- check_kibom_test_netlist(rows, ref_column, 2, ['C1'], ['R1', 'R2', 'C2'])
- ctx.clean_up()
-
-
-def test_int_bom_variant_t2_2():
- prj = 'kibom-variant_2'
- ctx = context.TestContextSCH('test_int_bom_variant_t2_2', prj, 'int_bom_var_test_csv', BOM_DIR)
- ctx.run()
- rows, header, info = ctx.load_csv(prj+'-bom.csv')
- ref_column = header.index(REF_COLUMN_NAME)
- check_kibom_test_netlist(rows, ref_column, 2, ['R2'], ['R1', 'C1', 'C2'])
- ctx.clean_up()
-
-
-def test_int_bom_variant_t2_3():
- prj = 'kibom-variant_2'
- ctx = context.TestContextSCH('test_int_bom_variant_t2_3', prj, 'int_bom_simple_csv', BOM_DIR)
+ ctx = context.TestContextSCH('test_int_bom_variant_t2', prj, 'int_bom_var_t2_csv', BOM_DIR)
ctx.run()
rows, header, info = ctx.load_csv(prj+'-bom.csv')
ref_column = header.index(REF_COLUMN_NAME)
check_kibom_test_netlist(rows, ref_column, 1, ['C1', 'C2'], ['R1', 'R2'])
+ rows, header, info = ctx.load_csv(prj+'-bom_(production).csv')
+ check_kibom_test_netlist(rows, ref_column, 2, ['C1'], ['R1', 'R2', 'C2'])
+ rows, header, info = ctx.load_csv(prj+'-bom_(test).csv')
+ check_kibom_test_netlist(rows, ref_column, 2, ['R2'], ['R1', 'C1', 'C2'])
ctx.clean_up()
diff --git a/tests/yaml_samples/int_bom_var_production_csv.kibot.yaml b/tests/yaml_samples/int_bom_var_production_csv.kibot.yaml
deleted file mode 100644
index 08696d29..00000000
--- a/tests/yaml_samples/int_bom_var_production_csv.kibot.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
-# Example KiBot config file
-kibot:
- version: 1
-
-outputs:
- - name: 'bom_internal'
- comment: "Bill of Materials in CSV format"
- type: bom
- dir: BoM
- options:
- variant: production
-
diff --git a/tests/yaml_samples/int_bom_var_t1_csv.kibot.yaml b/tests/yaml_samples/int_bom_var_t1_csv.kibot.yaml
new file mode 100644
index 00000000..aa9974d2
--- /dev/null
+++ b/tests/yaml_samples/int_bom_var_t1_csv.kibot.yaml
@@ -0,0 +1,63 @@
+# Example KiBot config file
+kibot:
+ version: 1
+
+
+variants:
+ - name: 't1_v1'
+ comment: 'Test 1 Variant V1'
+ type: kibom
+ file_id: '_(V1)'
+ variant: V1
+
+ - name: 't1_v2'
+ comment: 'Test 1 Variant V2'
+ type: kibom
+ file_id: '_(V2)'
+ variant: V2
+
+ - name: 't1_v3'
+ comment: 'Test 1 Variant V3'
+ type: kibom
+ file_id: '_V3'
+ variant: V3
+
+ - name: 'bla bla'
+ comment: 'Test 1 Variant V1+V3'
+ type: kibom
+ file_id: '_bla_bla'
+ variant: ['V1', 'V3']
+
+outputs:
+ - name: 'bom_internal'
+ comment: "Bill of Materials in CSV format"
+ type: bom
+ dir: BoM
+
+ - name: 'bom_internal_v1'
+ comment: "Bill of Materials in CSV format for variant t1_v1"
+ type: bom
+ dir: BoM
+ options:
+ variant: t1_v1
+
+ - name: 'bom_internal_v2'
+ comment: "Bill of Materials in CSV format for variant t1_v2"
+ type: bom
+ dir: BoM
+ options:
+ variant: t1_v2
+
+ - name: 'bom_internal_v3'
+ comment: "Bill of Materials in CSV format for variant t1_v3"
+ type: bom
+ dir: BoM
+ options:
+ variant: t1_v3
+
+ - name: 'bom_internal_bla_bla'
+ comment: "Bill of Materials in CSV format for variant `bla bla`"
+ type: bom
+ dir: BoM
+ options:
+ variant: 'bla bla'
diff --git a/tests/yaml_samples/int_bom_var_t2_csv.kibot.yaml b/tests/yaml_samples/int_bom_var_t2_csv.kibot.yaml
new file mode 100644
index 00000000..0c79bfbc
--- /dev/null
+++ b/tests/yaml_samples/int_bom_var_t2_csv.kibot.yaml
@@ -0,0 +1,36 @@
+# Example KiBot config file
+kibot:
+ version: 1
+
+variants:
+ - name: 'production'
+ comment: 'Production variant'
+ type: kibom
+ file_id: '_(production)'
+ variant: production
+
+ - name: 'test'
+ comment: 'Test variant'
+ type: kibom
+ file_id: '_(test)'
+ variant: test
+
+outputs:
+ - name: 'bom_internal'
+ comment: "Bill of Materials in CSV format"
+ type: bom
+ dir: BoM
+
+ - name: 'bom_internal_production'
+ comment: "Bill of Materials in CSV format for production"
+ type: bom
+ dir: BoM
+ options:
+ variant: production
+
+ - name: 'bom_internal_test'
+ comment: "Bill of Materials in CSV format for test"
+ type: bom
+ dir: BoM
+ options:
+ variant: test
diff --git a/tests/yaml_samples/int_bom_var_test_csv.kibot.yaml b/tests/yaml_samples/int_bom_var_test_csv.kibot.yaml
deleted file mode 100644
index 8f857ba7..00000000
--- a/tests/yaml_samples/int_bom_var_test_csv.kibot.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
-# Example KiBot config file
-kibot:
- version: 1
-
-outputs:
- - name: 'bom_internal'
- comment: "Bill of Materials in CSV format"
- type: bom
- dir: BoM
- options:
- variant: test
-
diff --git a/tests/yaml_samples/int_bom_var_v1_csv.kibot.yaml b/tests/yaml_samples/int_bom_var_v1_csv.kibot.yaml
deleted file mode 100644
index 9a2cbf12..00000000
--- a/tests/yaml_samples/int_bom_var_v1_csv.kibot.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
-# Example KiBot config file
-kibot:
- version: 1
-
-outputs:
- - name: 'bom_internal'
- comment: "Bill of Materials in CSV format"
- type: bom
- dir: BoM
- options:
- variant: V1
-
diff --git a/tests/yaml_samples/int_bom_var_v1v3_csv.kibot.yaml b/tests/yaml_samples/int_bom_var_v1v3_csv.kibot.yaml
deleted file mode 100644
index f1b0b8af..00000000
--- a/tests/yaml_samples/int_bom_var_v1v3_csv.kibot.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
-# Example KiBot config file
-kibot:
- version: 1
-
-outputs:
- - name: 'bom_internal'
- comment: "Bill of Materials in CSV format"
- type: bom
- dir: BoM
- options:
- variant: ['V1', 'V3']
-
diff --git a/tests/yaml_samples/int_bom_var_v2_csv.kibot.yaml b/tests/yaml_samples/int_bom_var_v2_csv.kibot.yaml
deleted file mode 100644
index 1c739682..00000000
--- a/tests/yaml_samples/int_bom_var_v2_csv.kibot.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
-# Example KiBot config file
-kibot:
- version: 1
-
-outputs:
- - name: 'bom_internal'
- comment: "Bill of Materials in CSV format"
- type: bom
- dir: BoM
- options:
- variant: V2
-
diff --git a/tests/yaml_samples/int_bom_var_v3_csv.kibot.yaml b/tests/yaml_samples/int_bom_var_v3_csv.kibot.yaml
deleted file mode 100644
index 707cbf58..00000000
--- a/tests/yaml_samples/int_bom_var_v3_csv.kibot.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
-# Example KiBot config file
-kibot:
- version: 1
-
-outputs:
- - name: 'bom_internal'
- comment: "Bill of Materials in CSV format"
- type: bom
- dir: BoM
- options:
- variant: V3
-
|