From c36854f250b8574a287f9077800b0f2309ada7b3 Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Tue, 14 Jul 2020 20:32:05 +0200 Subject: [PATCH] propagate undefined variable exception --- dotdrop/action.py | 15 +++++++++++++-- dotdrop/cfg_aggregator.py | 8 +++++++- dotdrop/dotdrop.py | 7 +++++-- dotdrop/exceptions.py | 5 +++++ dotdrop/installer.py | 9 +++++++-- dotdrop/templategen.py | 17 +++++++++++++---- dotdrop/updater.py | 7 ++++++- 7 files changed, 56 insertions(+), 12 deletions(-) diff --git a/dotdrop/action.py b/dotdrop/action.py index ccc7bf5..c31254e 100644 --- a/dotdrop/action.py +++ b/dotdrop/action.py @@ -11,6 +11,7 @@ import os # local imports from dotdrop.dictparser import DictParser +from dotdrop.exceptions import UndefinedException class Cmd(DictParser): @@ -32,7 +33,12 @@ class Cmd(DictParser): ret = 1 action = self.action if templater: - action = templater.generate_string(self.action) + try: + action = templater.generate_string(self.action) + except UndefinedException as e: + err = 'bad {}: {}'.format(self.descr, e) + self.log.warn(err) + return False if debug: self.log.dbg('{}:'.format(self.descr)) self.log.dbg(' - raw \"{}\"'.format(self.action)) @@ -42,7 +48,12 @@ class Cmd(DictParser): if self.args: args = self.args if templater: - args = [templater.generate_string(a) for a in args] + try: + args = [templater.generate_string(a) for a in args] + except UndefinedException as e: + err = 'bad arguments for {}: {}'.format(self.descr, e) + self.log.warn(err) + return False if debug and args: self.log.dbg('action args:') for cnt, arg in enumerate(args): diff --git a/dotdrop/cfg_aggregator.py b/dotdrop/cfg_aggregator.py index 8360ff4..958af8a 100644 --- a/dotdrop/cfg_aggregator.py +++ b/dotdrop/cfg_aggregator.py @@ -17,6 +17,7 @@ from dotdrop.profile import Profile from dotdrop.action import Action, Transform from dotdrop.logger import Logger from dotdrop.utils import strip_home +from dotdrop.exceptions import UndefinedException TILD = '~' @@ -281,7 +282,12 @@ class CfgAggregator: @src: dotfile src (in dotpath) @dst: dotfile dst (on filesystem) """ - src = self.cfgyaml.resolve_dotfile_src(src) + try: + src = self.cfgyaml.resolve_dotfile_src(src) + except UndefinedException as e: + err = 'unable to resolve {}: {}' + self.log.err(err.format(src, e)) + return None dotfiles = self.get_dotfile_by_dst(dst) for d in dotfiles: if d.src == src: diff --git a/dotdrop/dotdrop.py b/dotdrop/dotdrop.py index 417c095..efe618d 100644 --- a/dotdrop/dotdrop.py +++ b/dotdrop/dotdrop.py @@ -20,7 +20,7 @@ from dotdrop.comparator import Comparator from dotdrop.utils import get_tmpdir, remove, strip_home, \ run, uniq_list, patch_ignores, dependencies_met from dotdrop.linktypes import LinkTypes -from dotdrop.exceptions import YamlException +from dotdrop.exceptions import YamlException, UndefinedException LOG = Logger() TRANS_SUFFIX = 'trans' @@ -655,7 +655,10 @@ def main(): try: o = Options() except YamlException as e: - LOG.err('config file error: {}'.format(str(e))) + LOG.err('config error: {}'.format(str(e))) + return False + except UndefinedException as e: + LOG.err('config error: {}'.format(str(e))) return False if o.debug: diff --git a/dotdrop/exceptions.py b/dotdrop/exceptions.py index a327696..9c2df22 100644 --- a/dotdrop/exceptions.py +++ b/dotdrop/exceptions.py @@ -9,3 +9,8 @@ diverse exceptions class YamlException(Exception): """exception in CfgYaml""" pass + + +class UndefinedException(Exception): + """exception in templating""" + pass diff --git a/dotdrop/installer.py b/dotdrop/installer.py index 0cc6856..0d16049 100644 --- a/dotdrop/installer.py +++ b/dotdrop/installer.py @@ -12,6 +12,7 @@ import errno from dotdrop.logger import Logger from dotdrop.templategen import Templategen import dotdrop.utils as utils +from dotdrop.exceptions import UndefinedException class Installer: @@ -325,8 +326,12 @@ class Installer: err = 'dotfile points to itself: {}'.format(dst) return False, err saved = templater.add_tmp_vars(self._get_tmp_file_vars(src, dst)) - content = templater.generate(src) - templater.restore_vars(saved) + try: + content = templater.generate(src) + except UndefinedException as e: + return False, e.message + finally: + templater.restore_vars(saved) if noempty and utils.content_empty(content): if self.debug: self.log.dbg('ignoring empty template: {}'.format(src)) diff --git a/dotdrop/templategen.py b/dotdrop/templategen.py index 9473b6e..ff2f06b 100644 --- a/dotdrop/templategen.py +++ b/dotdrop/templategen.py @@ -9,11 +9,14 @@ import os from jinja2 import Environment, FileSystemLoader, \ ChoiceLoader, FunctionLoader, TemplateNotFound, \ StrictUndefined +from jinja2.exceptions import UndefinedError + # local imports import dotdrop.utils as utils from dotdrop.logger import Logger import dotdrop.jhelpers as jhelpers +from dotdrop.exceptions import UndefinedException BLOCK_START = '{%@@' BLOCK_END = '@@%}' @@ -79,22 +82,28 @@ class Templategen: def generate(self, src): """ render template from path - may raise a jinja2.exceptions.UndefinedError + may raise a UndefinedException in case a variable is undefined """ if not os.path.exists(src): return '' - return self._handle_file(src) + try: + return self._handle_file(src) + except UndefinedError as e: + raise UndefinedException(e.message) def generate_string(self, string): """ render template from string - may raise a jinja2.exceptions.UndefinedError + may raise a UndefinedException in case a variable is undefined """ if not string: return '' - return self.env.from_string(string).render(self.variables) + try: + return self.env.from_string(string).render(self.variables) + except UndefinedError as e: + raise UndefinedException(e.message) def add_tmp_vars(self, newvars={}): """add vars to the globals, make sure to call restore_vars""" diff --git a/dotdrop/updater.py b/dotdrop/updater.py index 67b9f6a..c5cef2f 100644 --- a/dotdrop/updater.py +++ b/dotdrop/updater.py @@ -14,6 +14,7 @@ from dotdrop.logger import Logger from dotdrop.templategen import Templategen from dotdrop.utils import patch_ignores, remove, get_unique_tmp_name, \ write_to_tmpfile, must_ignore, mirror_file_rights +from dotdrop.exceptions import UndefinedException TILD = '~' @@ -186,7 +187,11 @@ class Updater: if self.debug: self.log.dbg('{} is a template'.format(dtpath)) if self.showpatch: - self._show_patch(path, dtpath) + try: + self._show_patch(path, dtpath) + except UndefinedException as e: + msg = 'unable to show patch for {}: {}'.format(path, e) + self.log.warn(msg) return False if compare and filecmp.cmp(path, dtpath, shallow=False) and \ self._same_rights(path, dtpath):