diff --git a/dotdrop/__init__.py b/dotdrop/__init__.py index e267a8d..78ebeca 100644 --- a/dotdrop/__init__.py +++ b/dotdrop/__init__.py @@ -4,10 +4,11 @@ Copyright (c) 2017, deadc0de6 """ import sys +import dotdrop.dotdrop def main(): - import dotdrop.dotdrop + """entry point""" if dotdrop.dotdrop.main(): sys.exit(0) sys.exit(1) diff --git a/dotdrop/action.py b/dotdrop/action.py index 57f9978..41dd413 100644 --- a/dotdrop/action.py +++ b/dotdrop/action.py @@ -15,6 +15,9 @@ from dotdrop.exceptions import UndefinedException class Cmd(DictParser): + """A command to execute""" + + args = [] eq_ignore = ('log',) descr = 'command' @@ -28,46 +31,58 @@ class Cmd(DictParser): self.action = action self.silent = key.startswith('_') + def _get_action(self, templater, debug): + action = None + try: + action = templater.generate_string(self.action) + except UndefinedException as exc: + err = 'undefined variable for {}: \"{}\"'.format(self.descr, exc) + self.log.warn(err) + return False + if debug: + self.log.dbg('{}:'.format(self.descr)) + self.log.dbg(' - raw \"{}\"'.format(self.action)) + self.log.dbg(' - templated \"{}\"'.format(action)) + return action + + def _get_args(self, templater): + args = [] + if not self.args: + return args + args = self.args + if templater: + try: + args = [templater.generate_string(a) for a in args] + except UndefinedException as exc: + err = 'undefined arguments for {}: {}' + self.log.warn(err.format(self.descr, exc)) + return False + return args + def execute(self, templater=None, debug=False): """execute the command in the shell""" ret = 1 action = self.action if templater: - try: - action = templater.generate_string(self.action) - except UndefinedException as e: - err = 'undefined variable for {}: \"{}\"'.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)) - self.log.dbg(' - templated \"{}\"'.format(action)) + action = self._get_action(templater, debug) cmd = action - args = [] - if self.args: - args = self.args - if templater: - try: - args = [templater.generate_string(a) for a in args] - except UndefinedException as e: - err = 'undefined arguments for {}: {}' - self.log.warn(err.format(self.descr, e)) - return False + args = self._get_args(templater) if debug and args: self.log.dbg('action args:') for cnt, arg in enumerate(args): self.log.dbg('\targs[{}]: {}'.format(cnt, arg)) try: cmd = action.format(*args) - except IndexError as e: + except IndexError as exc: err = 'index error for {}: \"{}\"'.format(self.descr, action) err += ' with \"{}\"'.format(args) - err += ': {}'.format(e) + err += ': {}'.format(exc) self.log.warn(err) return False - except KeyError as e: - err = 'key error for {}: \"{}\": {}'.format(self.descr, action, e) + except KeyError as exc: + err = 'key error for {}: \"{}\": {}'.format(self.descr, + action, + exc) err += ' with \"{}\"'.format(args) self.log.warn(err) return False @@ -96,6 +111,7 @@ class Cmd(DictParser): class Action(Cmd): + """An action to execute""" pre = 'pre' post = 'post' @@ -107,7 +123,7 @@ class Action(Cmd): @kind: type of action (pre or post) @action: action string """ - super(Action, self).__init__(key, action) + super().__init__(key, action) self.kind = kind self.args = [] @@ -120,9 +136,9 @@ class Action(Cmd): @classmethod def parse(cls, key, value): """parse key value into object""" - v = {} - v['kind'], v['action'] = value - return cls(key=key, **v) + val = {} + val['kind'], val['action'] = value + return cls(key=key, **val) def __str__(self): out = '{}: [{}] \"{}\"' @@ -133,6 +149,8 @@ class Action(Cmd): class Transform(Cmd): + """A transformation on a dotfile""" + descr = 'transformation' def __init__(self, key, action): @@ -140,7 +158,7 @@ class Transform(Cmd): @key: action key @trans: action string """ - super(Transform, self).__init__(key, action) + super().__init__(key, action) self.args = [] def copy(self, args): diff --git a/dotdrop/cfg_aggregator.py b/dotdrop/cfg_aggregator.py index 3853386..1614416 100644 --- a/dotdrop/cfg_aggregator.py +++ b/dotdrop/cfg_aggregator.py @@ -24,6 +24,7 @@ TILD = '~' class CfgAggregator: + """The config aggregator class""" file_prefix = 'f' dir_prefix = 'd' @@ -106,10 +107,10 @@ class CfgAggregator: """ dotfiles = [] dst = self._norm_path(dst) - for d in self.dotfiles: - left = self._norm_path(d.dst) + for dotfile in self.dotfiles: + left = self._norm_path(dotfile.dst) if left == dst: - dotfiles.append(d) + dotfiles.append(dotfile) return dotfiles def get_dotfile_by_src_dst(self, src, dst): @@ -120,14 +121,14 @@ class CfgAggregator: """ try: src = self.cfgyaml.resolve_dotfile_src(src) - except UndefinedException as e: + except UndefinedException as exc: err = 'unable to resolve {}: {}' - self.log.err(err.format(src, e)) + self.log.err(err.format(src, exc)) return None dotfiles = self.get_dotfile_by_dst(dst) - for d in dotfiles: - if d.src == src: - return d + for dotfile in dotfiles: + if dotfile.src == src: + return dotfile return None def save(self): @@ -162,10 +163,10 @@ class CfgAggregator: def get_profiles_by_dotfile_key(self, key): """return all profiles having this dotfile""" res = [] - for p in self.profiles: - keys = [d.key for d in p.dotfiles] + for profile in self.profiles: + keys = [dotfile.key for dotfile in profile.dotfiles] if key in keys: - res.append(p) + res.append(profile) return res def get_dotfiles(self): @@ -282,27 +283,27 @@ class CfgAggregator: return if self.debug: self.log.dbg('patching {} ...'.format(keys)) - for c in containers: + for container in containers: objects = [] - okeys = getattr(c, keys) + okeys = getattr(container, keys) if not okeys: continue if not islist: okeys = [okeys] - for k in okeys: - o = get_by_key(k) - if not o: - err = '{} does not contain'.format(c) - err += ' a {} entry named {}'.format(keys, k) + for key in okeys: + obj = get_by_key(key) + if not obj: + err = '{} does not contain'.format(container) + err += ' a {} entry named {}'.format(keys, key) self.log.err(err) raise Exception(err) - objects.append(o) + objects.append(obj) if not islist: objects = objects[0] # if self.debug: # er = 'patching {}.{} with {}' # self.log.dbg(er.format(c, keys, objects)) - setattr(c, keys, objects) + setattr(container, keys, objects) ######################################################## # dotfile key @@ -341,8 +342,8 @@ class CfgAggregator: dirs.reverse() prefix = self.dir_prefix if os.path.isdir(path) else self.file_prefix entries = [] - for d in dirs: - entries.insert(0, d) + for dri in dirs: + entries.insert(0, dri) key = self.key_sep.join([prefix] + entries) if key not in keys: return key @@ -384,12 +385,12 @@ class CfgAggregator: def _split_path_for_key(self, path): """return a list of path elements, excluded home path""" - p = strip_home(path) + path = strip_home(path) dirs = [] while True: - p, f = os.path.split(p) - dirs.append(f) - if not p or not f: + path, file = os.path.split(path) + dirs.append(file) + if not path or not file: break dirs.reverse() # remove empty entries @@ -453,13 +454,13 @@ class CfgAggregator: if not self.debug: return self.log.dbg('{}:'.format(title)) - for e in elems: - self.log.dbg('\t- {}'.format(e)) + for elem in elems: + self.log.dbg('\t- {}'.format(elem)) def _debug_dict(self, title, elems): """pretty print dict""" if not self.debug: return self.log.dbg('{}:'.format(title)) - for k, v in elems.items(): - self.log.dbg('\t- \"{}\": {}'.format(k, v)) + for k, val in elems.items(): + self.log.dbg('\t- \"{}\": {}'.format(k, val))