-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdoitcmd.py
122 lines (93 loc) · 3.57 KB
/
doitcmd.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
"""
Helpers for creating tasks that exectue shell commands.
"""
__version__ = (0, 1, 0)
from doit.tools import Interactive
class BaseCommand(object):
"""Base class to create tasks that execute a shell command.
It provides:
- conversion of a param dict to a command options string
- handle/control wheather the command should be as `sudo`
- handle/control wheather the command is going to be execute interactively
:var str cmd_template: python str template for command
eg. `install {opts} {source} {dest}`
:var dict base_options: default command options
:var bool sudo: If `True` prepend `sudo` to command
:var bool Interactive: If `True` use `doit.tools.Interactive` on action.
Usage: see `doitsys.copy.Copy`
"""
cmd_template = None
base_options = {}
sudo = False
interactive = False
def __init__(self, sudo=None, interactive=None, options=None):
if sudo is not None:
self.sudo = sudo
if interactive is not None:
self.interactive = interactive
self.options = {}
self.options.update(self.base_options)
if options:
self.options.update(options)
@staticmethod
def opt_str(*opt_list):
"""command line option formatter
:param list-dict opt_list: list of dict with command options
:return string: formatted options for a command line
If the value of an option is `True`, option is added wihtout a value.
If opt name lenght is just one characher use only one dash.
"""
options = {}
for opt_dict in opt_list:
options.update(opt_dict)
# format options as strings
parts = []
for name, val in sorted(options.items()):
if val is False or val is None:
continue
dashes = '-' if len(name) == 1 else '--'
opt_val = ' {}'.format(val) if val is not True else ''
parts.append(dashes + name + opt_val)
return ' '.join(parts)
def action(self, cmd_str):
"""Modify action adding sudo / Interactive.
:param str cmd_str: command string
:return: An action for a doit task (might be a plain string)
"""
if self.sudo:
cmd_str = 'sudo ' + cmd_str
if self.interactive:
return Interactive(cmd_str)
else:
return cmd_str
def __call__(self): # pragma: no cover
"""return a task dictionary (to be implement on sub-class)"""
raise NotImplementedError()
def cmd(cmd_str, sudo=None, **task_params):
"""short-cut to return a task that executes a simple command
:param str cmd_str: the command to be executed
:param bool sudo: execute to command as `sudo`
:param dict task_params: extra doit task params (file_dep, task_dep...)
:return dict: doit task metadata
"""
_cmd = BaseCommand(sudo=sudo)
task = {
'name': cmd_str,
'actions': [_cmd.action(cmd_str)],
}
task.update(task_params)
return task
def interactive(cmd_str, sudo=None, **task_params):
"""short-cut to return a task that executes a simple command interactively
:param str cmd_str: the command to be executed
:param bool sudo: execute to command as `sudo`
:param dict task_params: extra doit task params (file_dep, task_dep...)
:return dict: doit task metadata
"""
_cmd = BaseCommand(sudo=sudo, interactive=True)
task = {
'name': cmd_str,
'actions': [_cmd.action(cmd_str)],
}
task.update(task_params)
return task