From 0af0f93a7116104676348b57cdb36698d9834c65 Mon Sep 17 00:00:00 2001 From: "Salvador E. Tropea" Date: Tue, 9 Jan 2024 08:14:05 -0300 Subject: [PATCH] [Diff/KiRi] Moved common code to a base class --- kibot/out_any_diff.py | 77 +++++++++++++++++++++++++++++++++++++++++++ kibot/out_diff.py | 57 ++------------------------------ kibot/out_kiri.py | 56 ++++--------------------------- 3 files changed, 86 insertions(+), 104 deletions(-) create mode 100644 kibot/out_any_diff.py diff --git a/kibot/out_any_diff.py b/kibot/out_any_diff.py new file mode 100644 index 00000000..d609f859 --- /dev/null +++ b/kibot/out_any_diff.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2022-2024 Salvador E. Tropea +# Copyright (c) 2022-2024 Instituto Nacional de TecnologĂ­a Industrial +# License: GPL-3.0 +# Project: KiBot (formerly KiPlot) +from tempfile import NamedTemporaryFile +from .gs import GS +from .kiplot import run_command +from .out_base import VariantOptions +from .pre_base import BasePreFlight +from .macros import macros, document, output_class # noqa: F401 +from . import log + +logger = log.get_logger() + + +class AnyDiffOptions(VariantOptions): + def __init__(self): + with document: + self.zones = 'global' + """ [global,fill,unfill,none] How to handle PCB zones. The default is *global* and means that we + fill zones if the *check_zone_fills* preflight is enabled. The *fill* option always forces + a refill, *unfill* forces a zone removal and *none* lets the zones unchanged. + Be careful with the *keep_generated* option when changing this setting """ + super().__init__() + self._expand_id = 'diff' + self._expand_ext = 'pdf' + self._kiri_mode = False + + def add_zones_ops(self, cmd): + if self.zones == 'global': + if BasePreFlight.get_option('check_zone_fills'): + cmd.extend(['--zones', 'fill']) + elif self.zones == 'fill': + cmd.extend(['--zones', 'fill']) + elif self.zones == 'unfill': + cmd.extend(['--zones', 'unfill']) + + def add_to_cache(self, name, hash): + cmd = [self.command, '--no_reader', '--only_cache', '--old_file_hash', hash, '--cache_dir', self.cache_dir] + if self._kiri_mode: + cmd.append('--kiri_mode') + self.add_zones_ops(cmd) + if self.incl_file: + cmd.extend(['--layers', self.incl_file]) + if not hasattr(self, 'only_first_sch_page') or not self.only_first_sch_page: + cmd.append('--all_pages') + if GS.debug_enabled: + cmd.insert(1, '-'+'v'*GS.debug_level) + cmd.extend([name, name]) + self.name_used_for_cache = name + run_command(cmd) + + def run_git(self, cmd, cwd=None, just_raise=False): + if cwd is None: + cwd = self.repo_dir + return run_command([self.git_command]+cmd, change_to=cwd, just_raise=just_raise) + + def git_dirty(self, file=None): + ops = ['status', '--porcelain', '-uno'] + if file is not None: + ops.append(file) + return self.run_git(ops) + + def remove_git_worktree(self, name): + logger.debug('Removing temporal checkout at '+name) + self.run_git(['worktree', 'remove', '--force', name]) + + def save_layers_incl(self, layers): + self._solved_layers = layers + logger.debug('Including layers:') + with NamedTemporaryFile(mode='w', suffix='.lst', delete=False) as f: + self.incl_file = f.name + for la in layers: + logger.debug('- {} ({})'.format(la.layer, la.id)) + f.write(str(la.id)+'\n') + return self.incl_file diff --git a/kibot/out_diff.py b/kibot/out_diff.py index 276af4b4..a2cae6f1 100644 --- a/kibot/out_diff.py +++ b/kibot/out_diff.py @@ -31,9 +31,8 @@ from .gs import GS from .kiplot import load_any_sch, run_command, config_output, get_output_dir, run_output from .layer import Layer from .misc import DIFF_TOO_BIG, FAILED_EXECUTE -from .out_base import VariantOptions -from .pre_base import BasePreFlight from .registrable import RegOutput +from .out_any_diff import AnyDiffOptions from .macros import macros, document, output_class # noqa: F401 from . import log @@ -41,7 +40,7 @@ logger = log.get_logger() STASH_MSG = 'KiBot_Changes_Entry' -class DiffOptions(VariantOptions): +class DiffOptions(AnyDiffOptions): def __init__(self): with document: self.output = GS.def_global_output @@ -109,14 +108,7 @@ class DiffOptions(VariantOptions): """ Always fail if the old/new file doesn't exist. Currently we don't fail if they are from a repo. So if you refer to a repo point where the file wasn't created KiBot will use an empty file. Enabling this option KiBot will report an error """ - self.zones = 'global' - """ [global,fill,unfill,none] How to handle PCB zones. The default is *global* and means that we - fill zones if the *check_zone_fills* preflight is enabled. The *fill* option always forces - a refill, *unfill* forces a zone removal and *none* lets the zones unchanged. - Be careful with the cache when changing this setting""" super().__init__() - self._expand_id = 'diff' - self._expand_ext = 'pdf' def config(self, parent): super().config(parent) @@ -147,28 +139,6 @@ class DiffOptions(VariantOptions): self.h.update(chunk) return self.h.hexdigest() - def add_zones_ops(self, cmd): - if self.zones == 'global': - if BasePreFlight.get_option('check_zone_fills'): - cmd.extend(['--zones', 'fill']) - elif self.zones == 'fill': - cmd.extend(['--zones', 'fill']) - elif self.zones == 'unfill': - cmd.extend(['--zones', 'unfill']) - - def add_to_cache(self, name, hash): - cmd = [self.command, '--no_reader', '--only_cache', '--old_file_hash', hash, '--cache_dir', self.cache_dir] - self.add_zones_ops(cmd) - if self.incl_file: - cmd.extend(['--layers', self.incl_file]) - if not self.only_first_sch_page: - cmd.append('--all_pages') - if GS.debug_enabled: - cmd.insert(1, '-'+'v'*GS.debug_level) - cmd.extend([name, name]) - self.name_used_for_cache = name - run_command(cmd) - def cache_pcb(self, name, force_exist): if name: if not os.path.isfile(name) and not force_exist: @@ -229,11 +199,6 @@ class DiffOptions(VariantOptions): self.git_hash = 'Current' if not name else 'FILE' return self.cache_pcb(name, force_exist) if self.pcb else self.cache_sch(name, force_exist) - def run_git(self, cmd, cwd=None, just_raise=False): - if cwd is None: - cwd = self.repo_dir - return run_command([self.git_command]+cmd, change_to=cwd, just_raise=just_raise) - def stash_pop(self, cwd=None): # We don't know if we stashed anything (push always returns 0) # So we check that the last stash contains our message @@ -355,9 +320,6 @@ class DiffOptions(VariantOptions): name += '-dirty' return '{}({})'.format(self.run_git(['rev-parse', '--short', 'HEAD'], cwd=cwd), name) - def git_dirty(self): - return self.run_git(['status', '--porcelain', '-uno']) - def cache_git_use_stash(self, name): self.stashed = False self.checkedout = False @@ -438,10 +400,6 @@ class DiffOptions(VariantOptions): self.git_hash = self.get_git_point_desc(name_ori, cwd) return hash - def remove_git_worktree(self, name): - logger.debug('Removing temporal checkout at '+name) - self.run_git(['worktree', 'remove', '--force', name]) - @staticmethod def check_output_type(out, must_be): if out.type != must_be: @@ -501,16 +459,7 @@ class DiffOptions(VariantOptions): return self.cache_output(name) def create_layers_incl(self, layers): - incl_file = None - if self.pcb and not isinstance(layers, type): - layers = Layer.solve(layers) - logger.debug('Including layers:') - with NamedTemporaryFile(mode='w', suffix='.lst', delete=False) as f: - incl_file = f.name - for la in layers: - logger.debug('- {} ({})'.format(la.layer, la.id)) - f.write(str(la.id)+'\n') - return incl_file + return self.save_layers_incl(Layer.solve(layers)) if self.pcb and not isinstance(layers, type) else None def do_compare(self, old, old_type, new, new_type, name, name_ori): dir_name = os.path.dirname(name) diff --git a/kibot/out_kiri.py b/kibot/out_kiri.py index 2c254419..fe3e3669 100644 --- a/kibot/out_kiri.py +++ b/kibot/out_kiri.py @@ -25,15 +25,14 @@ import pwd import os from shutil import copy2, rmtree from subprocess import CalledProcessError -from tempfile import mkdtemp, NamedTemporaryFile +from tempfile import mkdtemp from .error import KiPlotConfigurationError from .gs import GS from .kicad.color_theme import load_color_theme from .kiplot import load_any_sch, run_command from .layer import Layer from .misc import W_NOTHCMP -from .out_base import VariantOptions -from .pre_base import BasePreFlight +from .out_any_diff import AnyDiffOptions from .macros import macros, document, output_class # noqa: F401 from . import log @@ -54,7 +53,7 @@ def get_cur_user(): return 'Local user' -class KiRiOptions(VariantOptions): +class KiRiOptions(AnyDiffOptions): def __init__(self): with document: self.color_theme = '_builtin_classic' @@ -70,14 +69,8 @@ class KiRiOptions(VariantOptions): Note that this can be a revision-range, consult the gitrevisions manual for more information """ self.keep_generated = False """ *Avoid PCB and SCH images regeneration. Useful for incremental usage """ - self.zones = 'global' - """ [global,fill,unfill,none] How to handle PCB zones. The default is *global* and means that we - fill zones if the *check_zone_fills* preflight is enabled. The *fill* option always forces - a refill, *unfill* forces a zone removal and *none* lets the zones unchanged. - Be careful with the *keep_generated* option when changing this setting """ super().__init__() - self._expand_id = 'diff' - self._expand_ext = 'pdf' + self._kiri_mode = True def config(self, parent): super().config(parent) @@ -97,56 +90,19 @@ class KiRiOptions(VariantOptions): files.append(os.path.join(self.cache_dir, HASH_LOCAL)) return files - def add_to_cache(self, name, hash): - cmd = [self.command, '--no_reader', '--only_cache', '--old_file_hash', hash[:7], '--cache_dir', self.cache_dir, - '--kiri_mode', '--all_pages'] - if self.zones == 'global': - if BasePreFlight.get_option('check_zone_fills'): - cmd.extend(['--zones', 'fill']) - elif self.zones == 'fill': - cmd.extend(['--zones', 'fill']) - elif self.zones == 'unfill': - cmd.extend(['--zones', 'unfill']) - if self.incl_file: - cmd.extend(['--layers', self.incl_file]) - if GS.debug_enabled: - cmd.insert(1, '-'+'v'*GS.debug_level) - cmd.extend([name, name]) - self.name_used_for_cache = name - run_command(cmd) - - def run_git(self, cmd, cwd=None, just_raise=False): - if cwd is None: - cwd = self.repo_dir - return run_command([self.git_command]+cmd, change_to=cwd, just_raise=just_raise) - - def git_dirty(self, file): - return self.run_git(['status', '--porcelain', '-uno', file]) - - def remove_git_worktree(self, name): - logger.debug('Removing temporal checkout at '+name) - self.run_git(['worktree', 'remove', '--force', name]) - def create_layers_incl(self, layers): self.incl_file = None if isinstance(layers, type): self._solved_layers = None return False - layers = Layer.solve(layers) - self._solved_layers = layers - logger.debug('Including layers:') - with NamedTemporaryFile(mode='w', suffix='.lst', delete=False) as f: - self.incl_file = f.name - for la in layers: - logger.debug('- {} ({})'.format(la.layer, la.id)) - f.write(str(la.id)+'\n') + self.save_layers_incl(Layer.solve(layers)) return True def do_cache(self, name, tmp_wd, hash): name_copy = self.run_git(['ls-files', '--full-name', name]) name_copy = os.path.join(tmp_wd, name_copy) logger.debug('- Using temporal copy: '+name_copy) - self.add_to_cache(name_copy, hash) + self.add_to_cache(name_copy, hash[:7]) return name_copy def save_pcb_layers(self, hash):