Now you get an error when defining two outputs with the same name.

This commit is contained in:
Salvador E. Tropea 2021-12-02 13:21:57 -03:00
parent f3b03a4bbe
commit b9cb24c325
9 changed files with 122 additions and 14 deletions

View File

@ -49,6 +49,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The `%v/%V` expansion patterns now expand to the global variant when used in
a context not related to variants. I.e. when a `compress` target expands
`%v`.
- Now you get an error when defining two outputs with the same name.
### Fixed
- Position files now defaults to use the auxiliar origin as KiCad.

View File

@ -200,7 +200,7 @@ class CfgYamlReader(object):
return values
CfgYamlReader._config_error_import(fname, '`{}` must be a string or a list ({})'.format(kind, str(v)))
def _parse_import_outputs(self, outs, explicit_outs, fn_rel, data, outputs):
def _parse_import_outputs(self, outs, explicit_outs, fn_rel, data):
if (outs is None or len(outs) > 0) and 'outputs' in data:
i_outs = self._parse_outputs(data['outputs'])
if outs is not None:
@ -216,8 +216,11 @@ class CfgYamlReader(object):
if len(sel_outs) == 0:
logger.warning(W_NOOUTPUTS+"No outputs found in `{}`".format(fn_rel))
else:
outputs.extend(sel_outs)
logger.debug('Outputs loaded from `{}`: {}'.format(fn_rel, list(map(lambda c: c.name, sel_outs))))
try:
RegOutput.add_outputs(sel_outs, fn_rel)
except KiPlotConfigurationError as e:
config_error(str(e))
logger.debug('Outputs loaded from `{}`: {}'.format(fn_rel, list(map(lambda c: c.name, sel_outs))))
if outs is None and explicit_outs and 'outputs' not in data:
logger.warning(W_NOOUTPUTS+"No outputs found in `{}`".format(fn_rel))
@ -290,7 +293,6 @@ class CfgYamlReader(object):
config_error("Incorrect `import` section (must be a list)")
# Import the files
dir = os.path.dirname(os.path.abspath(name))
outputs = []
for entry in imp:
if isinstance(entry, str):
fn = entry
@ -335,14 +337,13 @@ class CfgYamlReader(object):
fn_rel = os.path.relpath(fn)
data = self.load_yaml(open(fn))
# Outputs
self._parse_import_outputs(outs, explicit_outs, fn_rel, data, outputs)
self._parse_import_outputs(outs, explicit_outs, fn_rel, data)
# Filters
self._parse_import_filters(fils, explicit_fils, fn_rel, data)
# Variants
self._parse_import_variants(vars, explicit_vars, fn_rel, data)
# Globals
self._parse_import_globals(globals, explicit_globals, fn_rel, data)
return outputs
def load_yaml(self, fstream):
try:
@ -368,7 +369,6 @@ class CfgYamlReader(object):
GS.global_kiauto_wait_start = GS.global_from_cli.get('kiauto_wait_start', None)
GS.global_kiauto_time_out_scale = GS.global_from_cli.get('kiauto_time_out_scale', None)
# List of outputs
outputs = []
version = None
globals_found = False
# Analize each section
@ -382,13 +382,16 @@ class CfgYamlReader(object):
self._parse_global(v)
globals_found = True
elif k == 'import':
outputs.extend(self._parse_import(v, fstream.name))
self._parse_import(v, fstream.name)
elif k == 'variants':
RegOutput.add_variants(self._parse_variants(v))
elif k == 'filters':
RegOutput.add_filters(self._parse_filters(v))
elif k == 'outputs':
outputs.extend(self._parse_outputs(v))
try:
RegOutput.add_outputs(self._parse_outputs(v))
except KiPlotConfigurationError as e:
config_error(str(e))
else:
config_error('Unknown section `{}` in config.'.format(k))
if version is None:
@ -402,7 +405,7 @@ class CfgYamlReader(object):
GS.solved_global_variant = RegOutput.check_variant(GS.global_variant)
except KiPlotConfigurationError as e:
config_error("In global section: "+str(e))
return outputs
return RegOutput.get_outputs()
def trim(docstring):

View File

@ -1,8 +1,9 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020 Salvador E. Tropea
# Copyright (c) 2020 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2020-2021 Salvador E. Tropea
# Copyright (c) 2020-2021 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
from collections import OrderedDict
from .optionable import Optionable
from .error import KiPlotConfigurationError
@ -41,6 +42,8 @@ class RegOutput(Optionable, Registrable):
_def_filters = {}
# List of defined variants
_def_variants = {}
# List of defined outputs
_def_outputs = OrderedDict()
def __init__(self):
super().__init__()
@ -73,6 +76,24 @@ class RegOutput(Optionable, Registrable):
def add_filter(obj):
RegOutput._def_filters[obj.name] = obj
@staticmethod
def add_output(obj, file=None):
if obj.name in RegOutput._def_outputs:
msg = "Output name `{}` already defined".format(obj.name)
if file:
msg += ", while importing from `{}`".format(file)
raise KiPlotConfigurationError(msg)
RegOutput._def_outputs[obj.name] = obj
@staticmethod
def add_outputs(objs, file=None):
for o in objs:
RegOutput.add_output(o, file)
@staticmethod
def get_outputs():
return RegOutput._def_outputs.values()
@staticmethod
def check_variant(variant):
if variant:

View File

@ -696,3 +696,27 @@ def test_error_import_no_outputs(test_dir):
ctx.run()
assert ctx.search_err(r"No outputs found in `(.*)drc.kibot.yaml`")
ctx.clean_up()
def test_same_name_1(test_dir):
""" 2 outputs with the same name in the same file """
ctx = context.TestContext(test_dir, 'test_same_name_1', PRJ, 'error_same_name_1', '')
ctx.run(EXIT_BAD_CONFIG)
assert ctx.search_err(r"Output name `position` already defined")
ctx.clean_up()
def test_same_name_2(test_dir):
""" Using import, but the 2nd is in the main file """
ctx = context.TestContext(test_dir, 'test_same_name_2', PRJ, 'error_same_name_2', '')
ctx.run(EXIT_BAD_CONFIG)
assert ctx.search_err(r"Output name `position` already defined")
ctx.clean_up()
def test_same_name_3(test_dir):
""" Using import and the 2nd is from the import """
ctx = context.TestContext(test_dir, 'test_same_name_3', PRJ, 'error_same_name_3', '')
ctx.run(EXIT_BAD_CONFIG)
assert ctx.search_err(r"Output name `position` already defined, while importing from")
ctx.clean_up()

View File

@ -0,0 +1,24 @@
# Example KiBot config file for a basic 2-layer board
kibot:
version: 1
outputs:
- name: 'position'
comment: "Pick and place file"
type: position
dir: positiondir
options:
format: ASCII # CSV or ASCII format
units: millimeters # millimeters or inches
separate_files_for_front_and_back: true
only_smd: true
- name: 'position'
comment: "Pick and place file"
type: position
dir: positiondir
options:
format: ASCII # CSV or ASCII format
units: millimeters # millimeters or inches
separate_files_for_front_and_back: true
only_smd: true

View File

@ -0,0 +1,17 @@
# Example KiBot config file for a basic 2-layer board
kibot:
version: 1
import:
- simple_position.kibot.yaml
outputs:
- name: 'position'
comment: "Pick and place file"
type: position
dir: positiondir
options:
format: ASCII # CSV or ASCII format
units: millimeters # millimeters or inches
separate_files_for_front_and_back: true
only_smd: true

View File

@ -0,0 +1,18 @@
# Example KiBot config file for a basic 2-layer board
kibot:
version: 1
outputs:
- name: 'position'
comment: "Pick and place file"
type: position
dir: positiondir
options:
format: ASCII # CSV or ASCII format
units: millimeters # millimeters or inches
separate_files_for_front_and_back: true
only_smd: true
import:
- simple_position.kibot.yaml

View File

@ -47,7 +47,7 @@ outputs:
warnings: visible
dpi: 600
- name: PcbDraw
- name: PcbDraw2
comment: "PcbDraw test bottom"
type: pcbdraw
dir: PcbDraw

View File

@ -15,7 +15,7 @@ outputs:
warnings: all
show_components: all
- name: PcbDraw
- name: PcbDraw2
comment: "PcbDraw test bottom"
type: pcbdraw
dir: PcbDraw