Simplified the KiAuto use

- Temporal video remove
- Other temporals
- Messages on execution error
This commit is contained in:
Salvador E. Tropea 2023-01-03 10:04:44 -03:00
parent cfee399110
commit f7b9092a2a
19 changed files with 176 additions and 246 deletions

View File

@ -1,5 +1,5 @@
__author__ = 'Salvador E. Tropea, John Beard'
__copyright__ = 'Copyright 2018-2022, Salvador E. Tropea/INTI/John Beard'
__copyright__ = 'Copyright 2018-2023, Salvador E. Tropea/INTI/John Beard'
__credits__ = ['Salvador E. Tropea', 'John Beard']
__license__ = 'GPL v3+'
__email__ = 'stropea@inti.gob.ar'

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2022 Salvador E. Tropea
# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2020-2023 Salvador E. Tropea
# Copyright (c) 2020-2023 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
import os
@ -498,3 +498,31 @@ class GS(object):
if shape == pcbnew.S_CIRCLE:
return g.GetArcStart()
return g.GetEnd()
@staticmethod
def get_kiauto_video_name(cmd):
""" Compute the name for the video captured by KiAuto """
command = os.path.basename(cmd[0])[:-3]
subcommand = next(filter(lambda x: x[0] != '-' and (not x[0].isdigit() or x[1] == 'd'), cmd[1:]))
if command == 'pcbnew':
return command+'_'+subcommand+'_screencast.ogv'
if command == 'eeschema':
return subcommand+'_'+command+'_screencast.ogv'
return command+'_screencast.ogv'
@staticmethod
def add_extra_options(cmd):
is_gitlab_ci = 'GITLAB_CI' in os.environ
video_remove = (not GS.debug_enabled) and is_gitlab_ci
if GS.debug_enabled:
cmd.insert(1, '-'+'v'*GS.debug_level)
if GS.debug_enabled or is_gitlab_ci:
# Forcing record on GitLab CI/CD (black magic)
cmd.insert(1, '-r')
if GS.global_kiauto_time_out_scale:
cmd.insert(1, str(GS.global_kiauto_time_out_scale))
cmd.insert(1, '--time_out_scale')
if GS.global_kiauto_wait_start:
cmd.insert(1, str(GS.global_kiauto_wait_start))
cmd.insert(1, '--wait_start')
return cmd, video_remove

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2022 Salvador E. Tropea
# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2020-2023 Salvador E. Tropea
# Copyright (c) 2020-2023 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2018 John Beard
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
@ -171,7 +171,7 @@ def run_command(command, change_to=None, just_raise=False, use_x11=False):
return res.stdout.decode().rstrip()
def exec_with_retry(cmd):
def exec_with_retry(cmd, exit_with=None):
cmd_str = shlex.join(cmd)
logger.debug('Executing: '+cmd_str)
if GS.debug_level > 2:
@ -191,26 +191,12 @@ def exec_with_retry(cmd):
if 'Timed out' in err:
logger.warning(W_TIMEOUT+'Time out detected, on slow machines or complex projects try:')
logger.warning(W_TIMEOUT+'`kiauto_time_out_scale` and/or `kiauto_wait_start` global options')
if exit_with is not None and ret:
logger.error(cmd[0]+' returned %d', ret)
exit(exit_with)
return ret
def add_extra_options(cmd):
is_gitlab_ci = 'GITLAB_CI' in os.environ
video_remove = (not GS.debug_enabled) and is_gitlab_ci
if GS.debug_enabled:
cmd.insert(1, '-'+'v'*GS.debug_level)
if GS.debug_enabled or is_gitlab_ci:
# Forcing record on GitLab CI/CD (black magic)
cmd.insert(1, '-r')
if GS.global_kiauto_time_out_scale:
cmd.insert(1, str(GS.global_kiauto_time_out_scale))
cmd.insert(1, '--time_out_scale')
if GS.global_kiauto_wait_start:
cmd.insert(1, str(GS.global_kiauto_wait_start))
cmd.insert(1, '--wait_start')
return cmd, video_remove
def load_board(pcb_file=None, forced=False):
if GS.board is not None and not forced:
# Already loaded

View File

@ -1,13 +1,12 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2022 Salvador E. Tropea
# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2020-2023 Salvador E. Tropea
# Copyright (c) 2020-2023 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
import os
from shutil import rmtree
from .pre_base import BasePreFlight
from .gs import GS
from .kiplot import exec_with_retry, add_extra_options
from .kiplot import exec_with_retry
from .misc import PDF_PCB_PRINT
from .out_base import VariantOptions
from .macros import macros, document, output_class # noqa: F401
@ -56,14 +55,15 @@ class Any_PCB_PrintOptions(VariantOptions):
def filter_components(self):
if not self.will_filter_pcb_components() and self.title == '':
return GS.pcb_file, None
return GS.pcb_file
self.filter_pcb_components()
self.set_title(self.title)
# Save the PCB to a temporal dir
fname, pcb_dir = self.save_tmp_dir_board('pdf_pcb_print')
self.restore_title()
self.unfilter_pcb_components()
return fname, pcb_dir
self._files_to_remove.append(pcb_dir)
return fname
def get_targets(self, out_dir):
return [self._parent.expand_filename(out_dir, self.output)]
@ -88,26 +88,17 @@ class Any_PCB_PrintOptions(VariantOptions):
cmd.extend(['--color_theme', self.color_theme])
if svg:
cmd.append('--svg')
board_name, board_dir = self.filter_components()
board_name = self.filter_components()
cmd.extend([board_name, os.path.dirname(output)])
cmd, video_remove = add_extra_options(cmd)
# Add the extra options before the layers (so the output dir is the last option)
cmd = self.add_extra_options(cmd)
# Add the layers
cmd.extend([la.layer for la in self._layers])
if GS.ki6 and self.force_edge_cuts and not self.separated:
cmd.append('Edge.Cuts')
# Execute it
ret = exec_with_retry(cmd)
# Remove the temporal PCB
if board_dir:
logger.debug('Removing temporal variant dir `{}`'.format(board_dir))
rmtree(board_dir)
if ret:
logger.error(command+' returned %d', ret)
exit(PDF_PCB_PRINT)
if video_remove:
video_name = os.path.join(self.expand_filename_pcb(GS.out_dir), 'pcbnew_export_screencast.ogv')
if os.path.isfile(video_name):
os.remove(video_name)
exec_with_retry(cmd, PDF_PCB_PRINT)
self.remove_temporals()
def set_layers(self, layers):
layers = Layer.solve(layers)

View File

@ -1,13 +1,13 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2022 Salvador E. Tropea
# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2020-2023 Salvador E. Tropea
# Copyright (c) 2020-2023 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
import os
from tempfile import mkdtemp
from shutil import rmtree, copy2
from shutil import copy2
from .gs import GS
from .kiplot import add_extra_options, exec_with_retry
from .kiplot import exec_with_retry
from .out_base import VariantOptions
from .kicad.config import KiConf
from .macros import macros, document, output_class # noqa: F401
@ -50,17 +50,15 @@ class Any_SCH_PrintOptions(VariantOptions):
def run(self, name):
super().run(name)
output_dir = os.path.dirname(name)
our_name = self._expand_ext+'_sch_print'
command = self.ensure_tool('KiAuto')
if self._comps:
# Save it to a temporal dir
sch_dir = mkdtemp(prefix='tmp-kibot-'+our_name+'-')
sch_dir = mkdtemp(prefix='tmp-kibot-'+self._expand_ext+'_sch_print-')
copy_project(sch_dir)
fname = GS.sch.save_variant(sch_dir)
sch_file = os.path.join(sch_dir, fname)
self._files_to_remove.append(sch_dir)
else:
sch_dir = None
sch_file = GS.sch_file
cmd = [command, 'export', '--file_format', self._expand_ext, '-o', name]
if self.monochrome:
@ -69,17 +67,6 @@ class Any_SCH_PrintOptions(VariantOptions):
cmd.append('--no_frame')
if self.all_pages:
cmd.append('--all_pages')
cmd.extend([sch_file, output_dir])
cmd, video_remove = add_extra_options(cmd)
ret = exec_with_retry(cmd)
if ret:
logger.error(command+' returned %d', ret)
exit(self._exit_error)
# Remove the temporal dir if needed
if sch_dir:
logger.debug('Removing temporal variant dir `{}`'.format(sch_dir))
rmtree(sch_dir)
if video_remove:
video_name = os.path.join(output_dir, 'export_eeschema_screencast.ogv')
if os.path.isfile(video_name):
os.remove(video_name)
cmd.extend([sch_file, os.path.dirname(name)])
exec_with_retry(self.add_extra_options(cmd), self._exit_error)
self.remove_temporals()

View File

@ -1,13 +1,13 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2022 Salvador E. Tropea
# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2020-2023 Salvador E. Tropea
# Copyright (c) 2020-2023 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
from copy import deepcopy
from glob import glob
import math
import os
import re
from shutil import rmtree
from tempfile import NamedTemporaryFile, mkdtemp
from .gs import GS
from .kiplot import load_sch, get_board_comps_data
@ -650,6 +650,7 @@ class VariantOptions(BaseOptions):
return
with NamedTemporaryFile(mode='w', suffix='.wrl', delete=False) as f:
self._highlight_3D_file = f.name
self._files_to_remove.append(f.name)
logger.debug('Creating temporal highlight file '+f.name)
f.write(HIGHLIGHT_3D_WRL)
@ -772,12 +773,6 @@ class VariantOptions(BaseOptions):
if self._sub_pcb:
self._sub_pcb.revert(self.comps_hash)
def remove_highlight_3D_file(self):
# Remove the highlight 3D file if it was created
if self._highlight_3D_file:
os.remove(self._highlight_3D_file)
self._highlight_3D_file = None
def set_title(self, title, sch=False):
self.old_title = None
if title:
@ -848,8 +843,7 @@ class VariantOptions(BaseOptions):
else:
m.SetValue(data)
@staticmethod
def save_tmp_board(dir=None):
def save_tmp_board(self, dir=None):
""" Save the PCB to a temporal file.
Advantage: all relative paths inside the file remains valid
Disadvantage: the name of the file gets altered """
@ -860,9 +854,10 @@ class VariantOptions(BaseOptions):
logger.debug('Storing modified PCB to `{}`'.format(fname))
GS.board.Save(fname)
GS.copy_project(fname)
self._files_to_remove.extend(GS.get_pcb_and_pro_names(fname))
return fname
def save_tmp_board_if_variant(self, to_remove, new_title='', dir=None, do_3D=False):
def save_tmp_board_if_variant(self, new_title='', dir=None, do_3D=False):
""" If we have a variant apply it and save the PCB to a file """
if not self.will_filter_pcb_components() and not new_title:
return GS.pcb_file
@ -872,7 +867,6 @@ class VariantOptions(BaseOptions):
fname = self.save_tmp_board()
self.restore_title()
self.unfilter_pcb_components(do_3D=do_3D)
to_remove.extend(GS.get_pcb_and_pro_names(fname))
logger.debug('- Modified PCB: '+fname)
return fname
@ -889,13 +883,6 @@ class VariantOptions(BaseOptions):
KiConf.fix_page_layout(pro_name)
return fname, pcb_dir
def remove_tmp_board(self, board_name):
# Remove the temporal PCB
if board_name != GS.pcb_file:
# KiCad likes to create project files ...
for f in glob(board_name.replace('.kicad_pcb', '.*')):
os.remove(f)
def solve_kf_filters(self, components):
""" Solves references to KiBot filters in the list of components to show.
They are not yet expanded, just solved to filter objects """
@ -944,8 +931,27 @@ class VariantOptions(BaseOptions):
new_list += ext_list
return new_list
def remove_temporals(self):
logger.debug('Removing temporal files')
for f in self._files_to_remove:
if os.path.isfile(f):
logger.debug('- File `{}`'.format(f))
os.remove(f)
elif os.path.isdir(f):
logger.debug('- Dir `{}`'.format(f))
rmtree(f)
self._files_to_remove = []
self._highlight_3D_file = None
def add_extra_options(self, cmd, dir=None):
cmd, video_remove = GS.add_extra_options(cmd)
if video_remove:
self._files_to_remove.append(os.path.join(dir or cmd[-1], GS.get_kiauto_video_name(cmd)))
return cmd
def run(self, output_dir):
""" Makes the list of components available """
self._files_to_remove = []
if not self.dnf_filter and not self.variant and not self.pre_transform:
return
load_sch()

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2022 Salvador E. Tropea
# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2020-2023 Salvador E. Tropea
# Copyright (c) 2020-2023 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
from fnmatch import fnmatch
@ -82,6 +82,7 @@ class Base3DOptions(VariantOptions):
return None
if self._tmp_dir is None:
self._tmp_dir = tempfile.mkdtemp()
self._files_to_remove.append(self._tmp_dir)
rel_dirs.append(self._tmp_dir)
logger.debug('Using `{}` as temporal dir for downloaded files'.format(self._tmp_dir))
dest = os.path.join(self._tmp_dir, fname)
@ -210,6 +211,10 @@ class Base3DOptions(VariantOptions):
def get_targets(self, out_dir):
return [self._parent.expand_filename(out_dir, self.output)]
def remove_temporals(self):
super().remove_temporals()
self._tmp_dir = None
class Base3D(BaseOutput):
def __init__(self):

View File

@ -7,7 +7,7 @@ import fnmatch
import glob
import os
import re
from shutil import copy2, rmtree
from shutil import copy2
from sys import exit
from .error import KiPlotConfigurationError
from .gs import GS
@ -197,15 +197,12 @@ class Copy_FilesOptions(Base3DOptions):
dest = os.path.relpath(dest, d)
break
else:
logger.error(fname)
logger.error(self.rel_dirs)
dest = os.path.basename(fname)
if mode_3d_append:
dest = os.path.join(f.dest[:-1], dest)
else:
dest = os.path.relpath(dest, src_dir)
files.append((fname_real, dest))
return files
def get_targets(self, out_dir):
@ -242,9 +239,7 @@ class Copy_FilesOptions(Base3DOptions):
copy2(src, dest)
copied[dest] = src
# Remove the downloaded 3D models
if self._tmp_dir:
rmtree(self._tmp_dir)
self._tmp_dir = None
self.remove_temporals()
@output_class

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2022 Salvador E. Tropea
# Copyright (c) 2022 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2022-2023 Salvador E. Tropea
# Copyright (c) 2022-2023 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
"""
@ -13,7 +13,7 @@ import os
from .gs import GS
from .out_base import VariantOptions
from .misc import FAILED_EXECUTE
from .kiplot import exec_with_retry, add_extra_options
from .kiplot import exec_with_retry
from .macros import macros, document, output_class # noqa: F401
from . import log
@ -46,9 +46,8 @@ class GenCADOptions(VariantOptions):
def run(self, name):
command = self.ensure_tool('KiAuto')
super().run(name)
to_remove = []
board_name = self.save_tmp_board_if_variant(to_remove)
# Output file name
board_name = self.save_tmp_board_if_variant()
# Create the command line
cmd = [command, 'export_gencad', '--output_name', os.path.basename(name)]
if self.flip_bottom_padstacks:
cmd.append('--flip_bottom_padstacks')
@ -61,17 +60,10 @@ class GenCADOptions(VariantOptions):
if self.save_origin:
cmd.append('--save_origin')
cmd.extend([board_name, os.path.dirname(name)])
cmd, video_remove = add_extra_options(cmd)
if video_remove:
to_remove.append(os.path.join(self.expand_filename_pcb(GS.out_dir), 'pcbnew_export_gencad_screencast.ogv'))
cmd = self.add_extra_options(cmd)
# Execute it
ret = exec_with_retry(cmd)
if ret:
logger.error(command+' returned %d', ret)
exit(FAILED_EXECUTE)
for f in to_remove:
if os.path.isfile(f):
os.remove(f)
exec_with_retry(cmd, FAILED_EXECUTE)
self.remove_temporals()
@output_class

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2022 Salvador E. Tropea
# Copyright (c) 2022 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2022-2023 Salvador E. Tropea
# Copyright (c) 2022-2023 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
"""
@ -14,7 +14,7 @@ import os
from .gs import GS
from .out_base import VariantOptions
from .misc import FAILED_EXECUTE
from .kiplot import exec_with_retry, add_extra_options
from .kiplot import exec_with_retry
from .macros import macros, document, output_class # noqa: F401
from . import log
@ -50,28 +50,18 @@ class NetlistOptions(VariantOptions):
def run(self, name):
command = self.ensure_tool('KiAuto')
super().run(name)
to_remove = []
if self.format == 'ipc':
command = command.replace('eeschema_do', 'pcbnew_do')
subcommand = 'ipc_netlist'
file = self.save_tmp_board_if_variant(to_remove)
file = self.save_tmp_board_if_variant()
else:
subcommand = 'netlist'
file = GS.sch_file
output_dir = os.path.dirname(name)
# Output file name
cmd = [command, subcommand, '--output_name', name, file, output_dir]
cmd, video_remove = add_extra_options(cmd)
if video_remove:
to_remove.append(os.path.join(self.expand_filename_pcb(GS.out_dir), command[:-3]+'_'+subcommand+'_screencast.ogv'))
# Create the command line
cmd = self.add_extra_options([command, subcommand, '--output_name', name, file, os.path.dirname(name)])
# Execute it
ret = exec_with_retry(cmd)
if ret:
logger.error(command+' returned %d', ret)
exit(FAILED_EXECUTE)
for f in to_remove:
if os.path.isfile(f):
os.remove(f)
exec_with_retry(cmd, FAILED_EXECUTE)
self.remove_temporals()
@output_class

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2022 Salvador E. Tropea
# Copyright (c) 2022 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2022-2023 Salvador E. Tropea
# Copyright (c) 2022-2023 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
"""
@ -692,9 +692,7 @@ class PanelizeOptions(VariantOptions):
if GS.ki5 and version >= (1, 1, 0):
raise KiPlotConfigurationError("Installed KiKit doesn't support KiCad 5")
super().run(output)
to_remove = []
fname = self.save_tmp_board_if_variant(to_remove, new_title=self.title, do_3D=True)
fname = self.save_tmp_board_if_variant(new_title=self.title, do_3D=True)
# Create the command
cmd = [cmd_kikit, 'panelize'] # , '--dump', 'test.json'
# Add all the configurations
@ -706,7 +704,7 @@ class PanelizeOptions(VariantOptions):
cmd.append(cfg)
else:
cfg_f = self.create_config(cfg)
to_remove.append(cfg_f)
self._files_to_remove.append(cfg_f)
cmd.append(cfg_f)
# Add the PCB and output
cmd.append(fname)
@ -715,10 +713,7 @@ class PanelizeOptions(VariantOptions):
run_command(cmd)
self.create_preview_file(output)
finally:
# Remove temporals
for f in to_remove:
if os.path.isfile(f):
os.remove(f)
self.remove_temporals()
def get_targets(self, out_dir):
pcb_name = self._parent.expand_filename(out_dir, self.output)

View File

@ -46,7 +46,7 @@ from .kicad.config import KiConf
from .kicad.v5_sch import SchError
from .kicad.pcb import PCB
from .misc import PDF_PCB_PRINT, W_PDMASKFAIL, KICAD5_SVG_SCALE, W_MISSTOOL, PCBDRAW_ERR, W_PCBDRAW
from .kiplot import exec_with_retry, add_extra_options
from .kiplot import exec_with_retry
from .create_pdf import create_pdf_from_pages
from .macros import macros, document, output_class # noqa: F401
from .drill_marks import DRILL_MARKS_MAP, add_drill_marks
@ -473,28 +473,23 @@ class PCB_PrintOptions(VariantOptions):
# Move all the drawings away
# KiCad 5 always prints Edge.Cuts, so we make it empty
self.clear_layer(layer)
# Start with a fresh list of files to remove
cur_files_to_remove = self._files_to_remove
self._files_to_remove = []
# Save the PCB
pcb_name, pcb_dir = self.save_tmp_dir_board('pcb_print')
self._files_to_remove.append(pcb_dir)
# Restore the layer
self.restore_layer()
# Output file name
cmd = [command, 'export', '--output_name', output, '--monochrome', '--svg', '--pads', '0',
pcb_name, dir_name, layer]
cmd, video_remove = add_extra_options(cmd)
# Execute it
ret = exec_with_retry(cmd)
# Remove the temporal PCB
logger.debug('Removing temporal PCB used for frame `{}`'.format(pcb_dir))
rmtree(pcb_dir)
if ret:
logger.error(command+' returned %d', ret)
exit(PDF_PCB_PRINT)
if video_remove:
video_name = os.path.join(self.expand_filename_pcb(GS.out_dir), 'pcbnew_export_screencast.ogv')
if os.path.isfile(video_name):
os.remove(video_name)
exec_with_retry(self.add_extra_options(cmd, dir_name), PDF_PCB_PRINT)
# Rotate the paper size if needed and remove the background (or it will be over the drawings)
patch_svg_file(output, remove_bkg=True, is_portrait=self.paper_portrait)
self.remove_temporals()
self._files_to_remove = cur_files_to_remove
def plot_pads(self, la, pc, p, filelist):
id = la._id

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021-2022 Salvador E. Tropea
# Copyright (c) 2021-2022 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2021-2023 Salvador E. Tropea
# Copyright (c) 2021-2023 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
# KiCad 6/6.0.1 bug: https://gitlab.com/kicad/code/kicad/-/issues/9890
@ -14,12 +14,11 @@ Dependencies:
"""
import os
import shlex
from shutil import rmtree
import subprocess
from .misc import (RENDER_3D_ERR, PCB_MAT_COLORS, PCB_FINISH_COLORS, SOLDER_COLORS, SILK_COLORS,
KICAD_VERSION_6_0_2, MISSING_TOOL)
from .gs import GS
from .kiplot import exec_with_retry, add_extra_options, load_sch, get_board_comps_data
from .kiplot import exec_with_retry, load_sch, get_board_comps_data
from .optionable import Optionable
from .out_base_3d import Base3DOptions, Base3D
from .macros import macros, document, output_class # noqa: F401
@ -301,22 +300,9 @@ class Render3DOptions(Base3DOptions):
board_name = self.filter_components(highlight=set(self.expand_kf_components(self.highlight)))
self.undo_show_components()
cmd.extend([board_name, os.path.dirname(output)])
cmd, video_remove = add_extra_options(cmd)
# Execute it
ret = exec_with_retry(cmd)
# Remove the temporal PCB
self.remove_tmp_board(board_name)
self.remove_highlight_3D_file()
# Remove the downloaded 3D models
if self._tmp_dir:
rmtree(self._tmp_dir)
if ret:
logger.error(command+' returned %d', ret)
exit(RENDER_3D_ERR)
if video_remove:
video_name = os.path.join(self.expand_filename_pcb(GS.out_dir), 'pcbnew_3d_view_screencast.ogv')
if os.path.isfile(video_name):
os.remove(video_name)
exec_with_retry(self.add_extra_options(cmd), RENDER_3D_ERR)
self.remove_temporals()
if self.auto_crop:
_run_command([convert_command, output, '-trim', '+repage', '-trim', '+repage', output])
if self.transparent_background:

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2022 Salvador E. Tropea
# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2020-2023 Salvador E. Tropea
# Copyright (c) 2020-2023 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
# KiCad 6 bug: https://gitlab.com/kicad/code/kicad/-/issues/10075
@ -13,14 +13,11 @@ Dependencies:
"""
import os
import re
import shlex
from subprocess import check_output, STDOUT, CalledProcessError
from shutil import rmtree
from .error import KiPlotConfigurationError
from .misc import KICAD2STEP_ERR
from .gs import GS
from .out_base_3d import Base3DOptions, Base3D
from .kiplot import add_extra_options
from .kiplot import exec_with_retry
from .macros import macros, document, output_class # noqa: F401
from . import log
@ -87,30 +84,9 @@ class STEPOptions(Base3DOptions):
# The board
board_name = self.filter_components()
cmd.append(board_name)
cmd, video_remove = add_extra_options(cmd)
# Execute and inform is successful
logger.debug('Executing: '+shlex.join(cmd))
# Ensure KIPRJMOD is correct:
# KiCad sets KIPRJMOD each time we call BOARD.Save() but then Python `os.environ` becomes unsynchronized
# We don't even know the actual value and any call to Save could destroy it
os.environ['KIPRJMOD'] = os.path.dirname(board_name)
try:
cmd_output = check_output(cmd, stderr=STDOUT)
except CalledProcessError as e:
logger.error('Failed to create Step file, error %d', e.returncode)
if e.output:
logger.debug('Output from command: '+e.output.decode())
exit(KICAD2STEP_ERR)
finally:
self.remove_tmp_board(board_name)
# Remove the downloaded 3D models
if self._tmp_dir:
rmtree(self._tmp_dir)
if video_remove:
video_name = os.path.join(self.expand_filename_pcb(GS.out_dir), 'kicad2step_screencast.ogv')
if os.path.isfile(video_name):
os.remove(video_name)
logger.debug('Output from command:\n'+cmd_output.decode())
# Execute it
exec_with_retry(self.add_extra_options(cmd, os.path.dirname(output)), KICAD2STEP_ERR)
self.remove_temporals()
@output_class

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2022 Salvador E. Tropea
# Copyright (c) 2022 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2022-2023 Salvador E. Tropea
# Copyright (c) 2022-2023 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
"""
@ -13,7 +13,7 @@ import os
from .gs import GS
from .out_base_3d import Base3DOptions, Base3D
from .misc import FAILED_EXECUTE
from .kiplot import exec_with_retry, add_extra_options
from .kiplot import exec_with_retry
from .macros import macros, document, output_class # noqa: F401
from . import log
@ -75,19 +75,9 @@ class VRMLOptions(Base3DOptions):
units = self.ref_units
cmd.extend(['-x', str(x), '-y', str(x), '-u', units])
cmd.extend([board_name, os.path.dirname(name)])
cmd, video_remove = add_extra_options(cmd)
# Execute it
try:
ret = exec_with_retry(cmd)
finally:
self.remove_tmp_board(board_name)
if ret:
logger.error(command+' returned %d', ret)
exit(FAILED_EXECUTE)
if video_remove:
video_name = os.path.join(self.expand_filename_pcb(GS.out_dir), 'pcbnew_export_vrml_screencast.ogv')
if os.path.isfile(video_name):
os.remove(video_name)
exec_with_retry(self.add_extra_options(cmd), FAILED_EXECUTE)
self.remove_temporals()
@output_class

View File

@ -1,8 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2022 Salvador E. Tropea
# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2020-2023 Salvador E. Tropea
# Copyright (c) 2020-2023 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
import os
from shutil import rmtree
from .gs import GS
from .registrable import Registrable
from .optionable import Optionable
@ -28,6 +30,7 @@ class BasePreFlight(Registrable):
self._enabled = True
self._expand_id = ''
self._expand_ext = ''
self._files_to_remove = []
@staticmethod
def add_preflight(o_pre):
@ -162,3 +165,21 @@ class BasePreFlight(Registrable):
def check_tool(self, name):
""" Looks for a dependency """
return GS.check_tool_dep(self._name, name, fatal=False)
def add_extra_options(self, cmd, dir=None):
""" KiAuto extra options (debug, record, etc.) """
cmd, video_remove = GS.add_extra_options(cmd)
if video_remove:
self._files_to_remove.append(os.path.join(dir or cmd[-1], GS.get_kiauto_video_name(cmd)))
return cmd
def remove_temporals(self):
logger.debug('Removing temporal files')
for f in self._files_to_remove:
if os.path.isfile(f):
logger.debug('- File `{}`'.format(f))
os.remove(f)
elif os.path.isdir(f):
logger.debug('- Dir `{}`'.format(f))
rmtree(f)
self._files_to_remove = []

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2022 Salvador E. Tropea
# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2020-2023 Salvador E. Tropea
# Copyright (c) 2020-2023 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
"""
@ -15,7 +15,7 @@ from .macros import macros, pre_class # noqa: F401
from .error import KiPlotConfigurationError
from .gs import GS
from .optionable import Optionable
from .kiplot import exec_with_retry, load_board, add_extra_options
from .kiplot import exec_with_retry, load_board
from .misc import DRC_ERROR
from .log import get_logger
@ -61,13 +61,10 @@ class Run_DRC(BasePreFlight): # noqa: F821
cmd.append('-i')
cmd.extend([GS.pcb_file, self.expand_dirname(GS.out_dir)])
# If we are in verbose mode enable debug in the child
cmd, video_remove = add_extra_options(cmd)
cmd = self.add_extra_options(cmd)
logger.info('- Running the DRC')
ret = exec_with_retry(cmd)
if video_remove:
video_name = os.path.join(self.expand_dirname(GS.out_dir), 'pcbnew_run_drc_screencast.ogv')
if os.path.isfile(video_name):
os.remove(video_name)
self.remove_temporals()
if ret:
if ret > 127:
ret = -(256-ret)

View File

@ -15,7 +15,7 @@ from sys import exit
from .macros import macros, pre_class # noqa: F401
from .gs import GS
from .optionable import Optionable
from .kiplot import exec_with_retry, load_sch, add_extra_options
from .kiplot import exec_with_retry, load_sch
from .error import KiPlotConfigurationError
from .misc import ERC_ERROR
from .log import get_logger
@ -60,13 +60,10 @@ class Run_ERC(BasePreFlight): # noqa: F821
cmd.extend(['-f', GS.filter_file])
cmd.extend([GS.sch_file, self.expand_dirname(GS.out_dir)])
# If we are in verbose mode enable debug in the child
cmd, video_remove = add_extra_options(cmd)
cmd = self.add_extra_options(cmd)
logger.info('- Running the ERC')
ret = exec_with_retry(cmd)
if video_remove:
video_name = os.path.join(self.expand_dirname(GS.out_dir), 'run_erc_eeschema_screencast.ogv')
if os.path.isfile(video_name):
os.remove(video_name)
self.remove_temporals()
if ret:
if ret > 127:
ret = -(256-ret)

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020-2022 Salvador E. Tropea
# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial
# Copyright (c) 2020-2023 Salvador E. Tropea
# Copyright (c) 2020-2023 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
"""
@ -16,7 +16,7 @@ import xml.etree.ElementTree as ET
from .macros import macros, document, pre_class # noqa: F401
from .error import KiPlotConfigurationError
from .gs import GS
from .kiplot import exec_with_retry, add_extra_options, load_board
from .kiplot import exec_with_retry, load_board
from .misc import BOM_ERROR, NETLIST_DIFF, W_PARITY, MISSING_TOOL
from .log import get_logger
from .optionable import Optionable
@ -170,21 +170,14 @@ class Update_XML(BasePreFlight): # noqa: F821
out_dir = self.expand_dirname(GS.out_dir)
cmd = [command, 'bom_xml', GS.sch_file, out_dir]
# If we are in verbose mode enable debug in the child
cmd, video_remove = add_extra_options(cmd)
cmd = self.add_extra_options(cmd)
# While creating the XML we run a BoM plug-in that creates a useless BoM
# We remove it, unless this is already there
side_effect_file = os.path.join(out_dir, GS.sch_basename+'.csv')
remove_side_effect_file = not os.path.isfile(side_effect_file)
if not os.path.isfile(side_effect_file):
self._files_to_remove.append(side_effect_file)
logger.info('- Updating BoM in XML format')
ret = exec_with_retry(cmd)
if remove_side_effect_file and os.path.isfile(side_effect_file):
os.remove(side_effect_file)
if ret:
logger.error('Failed to update the BoM, error %d', ret)
exit(BOM_ERROR)
if video_remove:
video_name = os.path.join(self.expand_dirname(GS.out_dir), 'bom_xml_eeschema_screencast.ogv')
if os.path.isfile(video_name):
os.remove(video_name)
exec_with_retry(cmd, BOM_ERROR)
self.remove_temporals()
if self._check_pcb_parity:
self.check_pcb_parity()