Skip to content
Open
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
40 changes: 22 additions & 18 deletions dotdrop/action.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,23 @@

import subprocess
import os
from typing import Any, Dict, List, Optional, Union

# local imports
from dotdrop.dictparser import DictParser
from dotdrop.exceptions import UndefinedException

__all__ = ['Cmd', 'Action', 'Transform']


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):
"""constructor
@key: action key
@action: action string
Expand All @@ -31,8 +34,8 @@ 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: Any, debug: bool) -> Union[str, bool]:
action: Optional[str] = None
try:
action = templater.generate_string(self.action)
except UndefinedException as exc:
Expand All @@ -45,8 +48,8 @@ def _get_action(self, templater, debug):
self.log.dbg(f' - templated \"{action}\"')
return action

def _get_args(self, templater):
args = []
def _get_args(self, templater: Any) -> Union[List[str], bool]:
args: List[str] = []
if not self.args:
return args
args = self.args
Expand All @@ -59,10 +62,10 @@ def _get_args(self, templater):
return False
return args

def execute(self, templater=None, debug=False):
def execute(self, templater: Any = None, debug: bool = False) -> bool:
"""execute the command in the shell"""
ret = 1
action = self.action
action: Union[str, bool] = self.action
if templater:
action = self._get_action(templater, debug)
args = self._get_args(templater)
Expand Down Expand Up @@ -101,10 +104,10 @@ def execute(self, templater=None, debug=False):
return ret == 0

@classmethod
def _adjust_yaml_keys(cls, value):
def _adjust_yaml_keys(cls, value: Any) -> Dict[str, Any]:
return {'action': value}

def __str__(self):
def __str__(self) -> str:
return f'key:{self.key} -> \"{self.action}\"'


Expand All @@ -115,7 +118,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)
Expand All @@ -125,24 +128,24 @@ 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: Any) -> 'Action':
"""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__()})'


Expand All @@ -151,21 +154,22 @@ class Transform(Cmd):

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]) -> 'Transform':
"""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: Any = None,
debug: bool = False) -> bool:
"""
execute transformation with {0} and {1}
where {0} is the file to transform
Expand Down
35 changes: 24 additions & 11 deletions dotdrop/comparator.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,23 @@
"""

import os
from typing import List, Optional

# local imports
from dotdrop.logger import Logger
from dotdrop.ftree import FTreeDir
from dotdrop.utils import must_ignore, diff, \
get_file_perm

__all__ = ['Comparator']


class Comparator:
"""compare dotfiles helper"""
# pylint: disable=too-few-public-methods

def __init__(self, diff_cmd='', debug=False,
ignore_missing_in_dotdrop=False):
def __init__(self, diff_cmd: str = '', debug: bool = False,
ignore_missing_in_dotdrop: bool = False):
"""constructor
@diff_cmd: diff command to use
@debug: enable debug
Expand All @@ -29,7 +33,9 @@ def __init__(self, diff_cmd='', debug=False,
self.log = Logger(debug=self.debug)
self.ignore_missing_in_dotdrop = ignore_missing_in_dotdrop

def compare(self, local_path, deployed_path, ignore=None, mode=None):
def compare(self, local_path: str, deployed_path: str,
ignore: Optional[List[str]] = None,
mode: Optional[int] = None) -> str:
"""
diff local_path (dotdrop dotfile) and
deployed_path (destination file)
Expand All @@ -47,9 +53,11 @@ def compare(self, local_path, deployed_path, ignore=None, mode=None):
ignore=ignore, mode=mode,
recurse=True)

def _compare(self, local_path, deployed_path,
ignore=None, mode=None,
recurse=False):
# pylint: disable=too-many-arguments,too-many-positional-arguments
def _compare(self, local_path: str, deployed_path: str,
ignore: Optional[List[str]] = None,
mode: Optional[int] = None,
recurse: bool = False) -> str:
if not ignore:
ignore = []

Expand Down Expand Up @@ -87,7 +95,8 @@ def _compare(self, local_path, deployed_path,
ret = self._comp_mode(local_path, deployed_path, mode=mode)
return ret

def _comp_mode(self, local_path, deployed_path, mode=None):
def _comp_mode(self, local_path: str, deployed_path: str,
mode: Optional[int] = None) -> str:
"""
compare mode
If mode is None, rights will be read on local_path
Expand All @@ -105,7 +114,8 @@ def _comp_mode(self, local_path, deployed_path, mode=None):
ret += f'({deployed_mode:o}) vs {local_mode:o}\n'
return ret

def _comp_file(self, local_path, deployed_path, ignore):
def _comp_file(self, local_path: str, deployed_path: str,
ignore: List[str]) -> str:
"""compare a file"""
self.log.dbg(f'compare file {local_path} with {deployed_path}')
if (self.ignore_missing_in_dotdrop and not
Expand All @@ -116,7 +126,8 @@ def _comp_file(self, local_path, deployed_path, ignore):
return ''
return self._diff(local_path, deployed_path, header=True)

def _comp_dir(self, local_path, deployed_path, ignore):
def _comp_dir(self, local_path: str, deployed_path: str,
ignore: List[str]) -> str:
"""compare a directory"""
self.log.dbg(f'compare directory {local_path} with {deployed_path}')
if not os.path.exists(deployed_path):
Expand All @@ -135,7 +146,8 @@ def _comp_dir(self, local_path, deployed_path, ignore):

return self._compare_dirs2(local_path, deployed_path, ignore)

def _compare_dirs2(self, local_path, deployed_path, ignore):
def _compare_dirs2(self, local_path: str, deployed_path: str,
ignore: List[str]) -> str:
"""compare directories"""
self.log.dbg(f'compare dirs {local_path} and {deployed_path}')
ret = []
Expand Down Expand Up @@ -171,7 +183,8 @@ def _compare_dirs2(self, local_path, deployed_path, ignore):

return ''.join(ret)

def _diff(self, local_path, deployed_path, header=False):
def _diff(self, local_path: str, deployed_path: str,
header: bool = False) -> str:
"""diff two files"""
out = diff(modified=local_path, original=deployed_path,
diff_cmd=self.diff_cmd, debug=self.debug)
Expand Down
6 changes: 5 additions & 1 deletion dotdrop/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
default config
"""

DEFAULT_CONFIG = """config:
from typing import Final

__all__ = ['DEFAULT_CONFIG']

DEFAULT_CONFIG: Final[str] = """config:
backup: true
banner: true
create: true
Expand Down
14 changes: 11 additions & 3 deletions dotdrop/dictparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,27 @@
dictionary parser abstract class
"""

from typing import Any, Dict, List, Mapping, Type, TypeVar

from dotdrop.logger import Logger

__all__ = ['DictParser']

T = TypeVar('T', bound='DictParser')


class DictParser:
"""a dict parser"""

log = Logger()

@classmethod
def _adjust_yaml_keys(cls, value):
def _adjust_yaml_keys(cls, value: Dict[str, Any]) -> Dict[str, Any]:
"""adjust value for object 'cls'"""
return value

@classmethod
def parse(cls, key, value):
def parse(cls: Type[T], key: Any, value: Dict[str, Any]) -> T:
"""parse (key,value) and construct object 'cls'"""
tmp = value
try:
Expand All @@ -32,7 +38,9 @@ def parse(cls, key, value):
return cls(key=key, **newv)

@classmethod
def parse_dict(cls, items):
def parse_dict(
cls: Type[T],
items: Mapping[Any, Dict[str, Any]]) -> List[T]:
"""parse a dictionary and construct object 'cls'"""
if not items:
return []
Expand Down
Loading
Loading