Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

types #430

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open

types #430

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ build/
tags
env
venv
.pytype

# coverage stuff
.coverage
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ for a match with the ignore patterns.

Dotdrop is tested with the use of the [tests.sh](/tests.sh) script.

* Test for PEP8 compliance with `pylint`, `pycodestyle` and `pyflakes` (see [check-syntax.sh](/scripts/test-syntax.sh))
* Test for PEP8 compliance with linters (see [check-syntax.sh](/scripts/test-syntax.sh))
* Test the documentation and links (see [check-doc.sh](/scripts/check-doc.sh))
* Run the unittests in [tests directory](/tests) with pytest (see [check-unittest.sh](/scripts/check-unittests.sh))
* Run the blackbox bash script tests in [tests-ng directory](/tests-ng) (see [check-tests-ng.sh](/scripts/check-tests-ng.sh))
Expand Down
46 changes: 29 additions & 17 deletions dotdrop/action.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,22 @@

import subprocess
import os
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):
"""A command to execute"""

args = []
args: List[str] = []
eq_ignore = ('log',)
descr = 'command'

def __init__(self, key, action):
def __init__(self, key: str, action: str) -> None:
"""constructor
@key: action key
@action: action string
Expand All @@ -31,21 +33,21 @@ def __init__(self, key, action):
self.action = action
self.silent = key.startswith('_')

def _get_action(self, templater, debug):
action = None
def _get_action(self, templater: Templategen, debug: bool) -> str:
action = ''
try:
action = templater.generate_string(self.action)
except UndefinedException as exc:
err = f'undefined variable for {self.descr}: \"{exc}\"'
self.log.warn(err)
return False
return action
if debug:
self.log.dbg(f'{self.descr}:')
self.log.dbg(f' - raw \"{self.action}\"')
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
Expand All @@ -59,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
Expand Down Expand Up @@ -100,21 +104,24 @@ 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"""

pre = 'pre'
post = 'post'
descr = 'action'

def __init__(self, key, kind, action):
def __init__(self, key: str, kind: str, action: str) -> None:
"""constructor
@key: action key
@kind: type of action (pre or post)
Expand All @@ -124,47 +131,52 @@ def __init__(self, key, kind, action):
self.kind = kind
self.args = []

def copy(self, args):
def copy(self, args: List[str]) -> "Action":
"""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
"""
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
Expand Down
2 changes: 1 addition & 1 deletion dotdrop/cfg_yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
try:
import tomllib
except ImportError:
import tomli as tomllib
import tomli as tomllib # type: ignore
import tomli_w

# local imports
Expand Down
2 changes: 1 addition & 1 deletion dotdrop/importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ def _already_exists(self, src, dst):
return True
return False

def _ignore(self, path):
def _ignore(self, path: str):
if must_ignore([path], self.ignore, debug=self.debug):
self.log.dbg(f'ignoring import of {path}')
self.log.warn(f'{path} ignored')
Expand Down
33 changes: 20 additions & 13 deletions dotdrop/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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 ''
Expand Down
Loading
Loading