diff --git a/CHANGELOG.md b/CHANGELOG.md index 3850067b..a3d65065 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,7 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Another experimental mechanism to change 3D models according to the variant. (#103) - A mechanism to avoid running some outputs by default. (#112) -- New pre-flight command to replace tags in the schematic. (#93) +- New pre-flight commands to replace tags in the schematic and PCB. (#93) ### Changed - Internal BoM: now components with different Tolerance, Voltage, Current diff --git a/README.md b/README.md index 083848e0..89f37af6 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,23 @@ This section is used to specify tasks that will be executed before generating an - `regex`: [string='None'] Regular expression to match the text for the error we want to exclude. - *regexp*: Alias for regex. - `ignore_unconnected`: [boolean=false] Option for `run_drc`. Ignores the unconnected nets. Useful if you didn't finish the routing. +- `pcb_replace`: [dict] Replaces tags in the schematic. I.e. to insert the git hash or last revision date. + * Valid keys: + - `date_command`: [string=''] Command to get the date to use in the schematic. + git log -1 --format='%as' -- $KIBOT_PCB_NAME + Will return the date in YYYY-MM-DD format. + date -d @`git log -1 --format='%at' -- $KIBOT_PCB_NAME` +%Y-%m-%d_%H-%M-%S + Will return the date in YYYY-MM-DD_HH-MM-SS format. + - `replace_tags`: [dict|list(dict)] Tag or tags to replace. + * Valid keys: + - `after`: [string=''] Text to add after the output of `command`. + - `before`: [string=''] Text to add before the output of `command`. + - `command`: [string=''] Command to execute to get the text, will be used only if `text` is empty. + KIBOT_PCB_NAME variable is the name of the current PCB. + - `tag`: [string=''] Name of the tag to replace. Use `version` for a tag named `@version@`. + - `tag_delimiter`: [string='@'] Character used to indicate the beginning and the end of a tag. + Don't change it unless you really know about KiCad's file formats. + - `text`: [string=''] Text to insert instead of the tag. - `run_drc`: [boolean=false] Runs the DRC (Distance Rules Check). To ensure we have a valid PCB. The report file name is controlled by the global output pattern (%i=drc %x=txt). - `run_erc`: [boolean=false] Runs the ERC (Electrical Rules Check). To ensure the schematic is electrically correct. diff --git a/docs/samples/generic_plot.kibot.yaml b/docs/samples/generic_plot.kibot.yaml index 0f5359ab..6b6e9a0c 100644 --- a/docs/samples/generic_plot.kibot.yaml +++ b/docs/samples/generic_plot.kibot.yaml @@ -17,6 +17,15 @@ preflight: regex: 'Regular expression to match' # [boolean=false] Option for `run_drc`. Ignores the unconnected nets. Useful if you didn't finish the routing. ignore_unconnected: false + # [dict] Replaces tags in the schematic. I.e. to insert the git hash or last revision date. + pcb_replace: + date_command: "git log -1 --format='%as' -- $KIBOT_PCB_NAME" + replace_tags: + - tag: '@git_hash@' + command: 'git log -1 --format="%h" $KIBOT_PCB_NAME' + before: 'Git hash: <' + after: '>' + # [boolean=false] Runs the DRC (Distance Rules Check). To ensure we have a valid PCB. # The report file name is controlled by the global output pattern (%i=drc %x=txt). run_drc: true diff --git a/kibot/misc.py b/kibot/misc.py index 9f891e2b..18994bf9 100644 --- a/kibot/misc.py +++ b/kibot/misc.py @@ -211,6 +211,7 @@ W_NOENDLIB = '(W070) ' W_NEEDSPCB = '(W071) ' W_NOGLOBALS = '(W072) ' W_EMPTREP = '(W073) ' +W_BADCHARS = '(W074) ' class Rect(object): diff --git a/kibot/pre_sch_replace.py b/kibot/pre_sch_replace.py index d67d4b5b..dd736445 100644 --- a/kibot/pre_sch_replace.py +++ b/kibot/pre_sch_replace.py @@ -11,7 +11,7 @@ from .gs import GS from .error import KiPlotConfigurationError from .optionable import Optionable from .kiplot import load_sch -from .misc import W_EMPTREP, FAILED_EXECUTE +from .misc import W_EMPTREP, FAILED_EXECUTE, W_BADCHARS from .macros import macros, document, pre_class # noqa: F401 from . import log @@ -39,6 +39,7 @@ class TagReplace(Optionable): """ Text to add before the output of `command` """ self.after = '' """ Text to add after the output of `command` """ + self._relax_check = False def config(self, parent): super().config(parent) @@ -110,6 +111,12 @@ class SCH_Replace(BasePreFlight): # noqa: F821 continue text = result.stdout.strip() text = r.before + text + r.after + if not r._relax_check: + new_text = re.sub(r'["\\\\\s]', '_', text) + if new_text != text: + logger.warning(W_BADCHARS+"Replace text can't contain double quotes, backslashes or white spaces ({})". + format(text)) + text = new_text logger.debug('- ' + r.tag + ' -> ' + text) content = re.sub(r.tag, text, content, flags=re.MULTILINE) os.rename(file, file + '-bak') @@ -125,6 +132,7 @@ class SCH_Replace(BasePreFlight): # noqa: F821 t.command = o.date_command t.before = 'Date "' t.after = '"' + t._relax_check = True o.replace_tags.append(t) load_sch() os.environ['KIBOT_TOP_SCH_NAME'] = GS.sch_file diff --git a/tests/test_plot/test_preflight.py b/tests/test_plot/test_preflight.py index a0b4f585..0c6026e4 100644 --- a/tests/test_plot/test_preflight.py +++ b/tests/test_plot/test_preflight.py @@ -189,10 +189,40 @@ def test_sch_replace_1(test_dir): if 'test_v5' in k: cmd = ['/bin/bash', '-c', "git log -1 --format='%h' " + k] text = run(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True).stdout.strip() - m = re.search("Git hash: '(.*)'", c) + m = re.search("Git_hash:'(.*)'", c) logging.debug('Hash: ' + text) assert m is not None assert m.group(1) == text finally: for k, v in files.items(): os.rename(v, k) + + +def test_pcb_replace_1(test_dir): + """ Tags replacements in a PCB """ + prj = 'light_control' + ctx = context.TestContext(test_dir, 'test_pcb_replace_1', prj, 'pcb_replace_1', '') + ctx.run(extra=[]) + files = {} + file = ctx.board_file + file_back = file + '-bak' + assert os.path.isfile(file_back), v + assert os.path.getsize(file_back) > 0 + try: + logging.debug(file) + cmd = ['/bin/bash', '-c', "date -d @`git log -1 --format='%at' -- " + file + "` +%Y-%m-%d_%H-%M-%S"] + text = run(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True).stdout.strip() + with open(file, 'rt') as f: + c = f.read() + m = re.search(r'^ \(date (\S+|"(?:[^"]|\\")+")\)$', c, re.MULTILINE) + logging.debug('Date: ' + text) + assert m is not None + assert m.group(1) == '"' + text + '"' + cmd = ['/bin/bash', '-c', "git log -1 --format='%h' " + file] + text = run(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True).stdout.strip() + m = re.search("Git_hash:'(.*)'", c) + logging.debug('Hash: ' + text) + assert m is not None + assert m.group(1) == text + finally: + os.rename(file_back, file) diff --git a/tests/yaml_samples/pcb_replace_1.kibot.yaml b/tests/yaml_samples/pcb_replace_1.kibot.yaml new file mode 100644 index 00000000..529e7a06 --- /dev/null +++ b/tests/yaml_samples/pcb_replace_1.kibot.yaml @@ -0,0 +1,12 @@ +# Example KiBot config file +kibot: + version: 1 + +preflight: + pcb_replace: + date_command: date -d @`git log -1 --format='%at' -- $KIBOT_PCB_NAME` +%Y-%m-%d_%H-%M-%S + replace_tags: + - tag: "Comment4" + command: git log -1 --format="%h" $KIBOT_PCB_NAME + before: "Git_hash:'" + after: "'" diff --git a/tests/yaml_samples/sch_replace_1.kibot.yaml b/tests/yaml_samples/sch_replace_1.kibot.yaml index f11a73c6..101c437e 100644 --- a/tests/yaml_samples/sch_replace_1.kibot.yaml +++ b/tests/yaml_samples/sch_replace_1.kibot.yaml @@ -8,5 +8,5 @@ preflight: replace_tags: - tag: "Comment4" command: git log -1 --format="%h" $KIBOT_SCH_NAME - before: "Git hash: '" + before: "Git_hash:'" after: "'"