From d9fabe3e81b50fcd227fc14c1f32d533297cf139 Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Wed, 17 Jan 2024 15:52:06 +0100 Subject: [PATCH] mypy strict --- dotdrop/action.py | 41 ++++++++++++++++++++++++++--------------- dotdrop/logger.py | 33 ++++++++++++++++++++------------- scripts/check-syntax.sh | 12 ++++++------ 3 files changed, 52 insertions(+), 34 deletions(-) diff --git a/dotdrop/action.py b/dotdrop/action.py index 5f6079153..07f1135f7 100644 --- a/dotdrop/action.py +++ b/dotdrop/action.py @@ -8,11 +8,12 @@ import subprocess import os -from typing import List +from typing import List, Dict, TypeVar, Optional # local imports from dotdrop.dictparser import DictParser from dotdrop.exceptions import UndefinedException +from dotdrop.templategen import Templategen class Cmd(DictParser): @@ -22,7 +23,7 @@ class Cmd(DictParser): eq_ignore = ('log',) descr = 'command' - def __init__(self, key, action): + def __init__(self, key: str, action: str): """constructor @key: action key @action: action string @@ -32,7 +33,7 @@ def __init__(self, key, action): self.action = action self.silent = key.startswith('_') - def _get_action(self, templater, debug): + def _get_action(self, templater: Templategen, debug: bool) -> str: action = '' try: action = templater.generate_string(self.action) @@ -46,7 +47,7 @@ def _get_action(self, templater, debug): self.log.dbg(f' - templated \"{action}\"') return action - def _get_args(self, templater): + def _get_args(self, templater: Templategen) -> List[str]: args = [] if not self.args: return args @@ -60,7 +61,9 @@ def _get_args(self, templater): return False return args - def execute(self, templater=None, debug=False): + def execute(self, + templater: Optional[Templategen] = None, + debug: bool = False) -> bool: """execute the command in the shell""" ret = 1 action = self.action @@ -101,13 +104,16 @@ def execute(self, templater=None, debug=False): return ret == 0 @classmethod - def _adjust_yaml_keys(cls, value): + def _adjust_yaml_keys(cls, value: str) -> Dict[str, str]: return {'action': value} - def __str__(self): + def __str__(self) -> str: return f'key:{self.key} -> \"{self.action}\"' +ActionT = TypeVar('ActionT', bound='Action') + + class Action(Cmd): """An action to execute""" @@ -115,7 +121,7 @@ class Action(Cmd): post = 'post' descr = 'action' - def __init__(self, key, kind, action): + def __init__(self, key: str, kind: str, action: str): """constructor @key: action key @kind: type of action (pre or post) @@ -125,33 +131,36 @@ def __init__(self, key, kind, action): self.kind = kind self.args = [] - def copy(self, args): + def copy(self, args: List[str]): """return a copy of this object with arguments""" action = Action(self.key, self.kind, self.action) action.args = args return action @classmethod - def parse(cls, key, value): + def parse(cls, key: str, value: str) -> ActionT: """parse key value into object""" val = {} val['kind'], val['action'] = value return cls(key=key, **val) - def __str__(self): + def __str__(self) -> str: out = f'{self.key}: [{self.kind}] \"{self.action}\"' return out - def __repr__(self): + def __repr__(self) -> str: return f'action({self.__str__()})' +TransformT = TypeVar('TransformT', bound='Transform') + + class Transform(Cmd): """A transformation on a dotfile""" descr = 'transformation' - def __init__(self, key, action): + def __init__(self, key: str, action: str): """constructor @key: action key @trans: action string @@ -159,13 +168,15 @@ def __init__(self, key, action): super().__init__(key, action) self.args = [] - def copy(self, args): + def copy(self, args: List[str]) -> TransformT: """return a copy of this object with arguments""" trans = Transform(self.key, self.action) trans.args = args return trans - def transform(self, arg0, arg1, templater=None, debug=False): + def transform(self, arg0: str, arg1: str, + templater: Optional[Templategen] = None, + debug: bool = False) -> bool: """ execute transformation with {0} and {1} where {0} is the file to transform diff --git a/dotdrop/logger.py b/dotdrop/logger.py index 03f9b9134..72711329d 100644 --- a/dotdrop/logger.py +++ b/dotdrop/logger.py @@ -22,10 +22,12 @@ class Logger: EMPH = '\033[33m' BOLD = '\033[1m' - def __init__(self, debug=False): + def __init__(self, debug: bool = False): self.debug = debug - def log(self, string, end='\n', pre='', bold=False): + def log(self, string: str, + end: str = '\n', pre: str = '', + bold: bool = False) -> None: """normal log""" cstart = self._color(self.BLUE) cend = self._color(self.RESET) @@ -37,13 +39,14 @@ def log(self, string, end='\n', pre='', bold=False): fmt = f'{pre}{cstart}{string}{end}{cend}' sys.stdout.write(fmt) - def sub(self, string, end='\n'): + def sub(self, string: str, + end: str = '\n') -> None: """sub log""" cstart = self._color(self.BLUE) cend = self._color(self.RESET) sys.stdout.write(f'\t{cstart}->{cend} {string}{end}') - def emph(self, string, stdout=True): + def emph(self, string: str, stdout: bool = True) -> None: """emphasis log""" cstart = self._color(self.EMPH) cend = self._color(self.RESET) @@ -53,46 +56,50 @@ def emph(self, string, stdout=True): else: sys.stdout.write(content) - def err(self, string, end='\n'): + def err(self, string: str, end: str = '\n') -> None: """error log""" cstart = self._color(self.RED) cend = self._color(self.RESET) msg = f'{string} {end}' sys.stderr.write(f'{cstart}[ERR] {msg}{cend}') - def warn(self, string, end='\n'): + def warn(self, string: str, end: str = '\n') -> None: """warning log""" cstart = self._color(self.YELLOW) cend = self._color(self.RESET) sys.stderr.write(f'{cstart}[WARN] {string} {end}{cend}') - def dbg(self, string, force=False): + def dbg(self, string: str, force: bool = False) -> None: """debug log""" if not force and not self.debug: return frame = inspect.stack()[1] - mod = inspect.getmodule(frame[0]).__name__ + + mod = inspect.getmodule(frame[0]) + mod_name = 'module?' + if mod: + mod_name = mod.__name__ func = inspect.stack()[1][3] cstart = self._color(self.MAGENTA) cend = self._color(self.RESET) clight = self._color(self.LMAGENTA) bold = self._color(self.BOLD) - line = f'{bold}{clight}[DEBUG][{mod}.{func}]' + line = f'{bold}{clight}[DEBUG][{mod_name}.{func}]' line += f'{cend}{cstart} {string}{cend}\n' sys.stderr.write(line) - def dry(self, string, end='\n'): + def dry(self, string: str, end: str = '\n') -> None: """dry run log""" cstart = self._color(self.GREEN) cend = self._color(self.RESET) sys.stdout.write(f'{cstart}[DRY] {string} {end}{cend}') @classmethod - def raw(cls, string, end='\n'): + def raw(cls, string: str, end: str = '\n') -> None: """raw log""" sys.stdout.write(f'{string}{end}') - def ask(self, query): + def ask(self, query: str) -> bool: """ask user for confirmation""" cstart = self._color(self.BLUE) cend = self._color(self.RESET) @@ -102,7 +109,7 @@ def ask(self, query): return resp == 'y' @classmethod - def _color(cls, col): + def _color(cls, col: str) -> str: """is color supported""" if not sys.stdout.isatty(): return '' diff --git a/scripts/check-syntax.sh b/scripts/check-syntax.sh index 4aaa3f668..f2dbbc275 100755 --- a/scripts/check-syntax.sh +++ b/scripts/check-syntax.sh @@ -104,20 +104,20 @@ pylint \ --disable=R0904 \ dotdrop/ -# pytype -echo "----------------------------" -echo "checking dotdrop with pytype" -pytype dotdrop/ - # mypy echo "----------------------------" echo "checking dotdrop with mypy" -# --strict mypy \ + --strict \ --ignore-missing-imports \ --allow-redefinition \ dotdrop/ +# pytype +echo "----------------------------" +echo "checking dotdrop with pytype" +pytype dotdrop/ + # check shell scripts # SC2002: Useless cat # SC2126: Consider using grep -c instead of grep|wc -l