Completed
Pull Request — develop (#140)
by
unknown
10:15
created

rm_error_readonly()   A

Complexity

Conditions 2

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 2
c 1
b 1
f 0
dl 0
loc 16
ccs 0
cts 0
cp 0
crap 6
rs 9.4285
1
"""Utilities to call shell programs."""
2
3 1
import os
4 1
import subprocess
5 1
import logging
6 1
import shutil
7
import stat
8 1
9 1
from . import common
10
from .exceptions import ShellError
11 1
12 1
CMD_PREFIX = "$ "
13
OUT_PREFIX = "> "
14 1
15
log = logging.getLogger(__name__)
16
17 1
18
def call(name, *args, _show=True, _ignore=False, _shell=False):
19
    """Call a program with arguments.
20
21
    :param name: name of program to call
22
    :param args: list of command-line arguments
23
    :param _show: display the call on stdout
24
    :param _ignore: ignore non-zero return codes
25
    :param _shell: force executing the program into a real shell
26
                   a Windows shell command (i.e: dir, echo) needs a real shell
27
                   but not a regular program (i.e: calc, git)
28 1
    """
29
    program = show(name, *args, stdout=_show)
30 1
31
    command = subprocess.run(
0 ignored issues
show
Bug introduced by
The Module subprocess does not seem to have a member named run.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
32
        [name, *args], universal_newlines=True,
33
        stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
34
        shell=_shell
35
    )
36 1
37 1
    for line in command.stdout.splitlines():
38
        log.debug(OUT_PREFIX + line.strip())
39 1
40 1
    if command.returncode == 0:
41
        return command.stdout.strip()
42 1
43 1
    elif _ignore:
44
        log.debug("Ignored error from call to '%s'", name)
45
46 1
    else:
47
        message = (
48
            "An external program call failed." + "\n\n"
49
            "In working directory: " + os.getcwd() + "\n\n"
50
            "The following command produced a non-zero return code:" + "\n\n" +
51
            program + "\n" +
52
            command.stdout
53 1
        )
54
        raise ShellError(message)
55
56 1
57 1
def mkdir(path):
58 1
    show('mkdir', '-p', path)
59 1
    if not os.path.exists(path):
60
        os.makedirs(path)
61
62 1
63 1
def cd(path, _show=True):
64 1
    show('cd', path, stdout=_show)
65
    os.chdir(path)
66
67 1
68 1
def ln(source, target):
69
    if os.name == 'nt':
70
        log.warning("Symlinks are not supported on Windows")
71 1
    else:
72 1
        dirpath = os.path.dirname(target)
73 1
        if not os.path.isdir(dirpath):
74 1
            mkdir(dirpath)
75
        call('ln', '-s', source, target)
76
77 1
78 1
def rm(path):
79 1
    show('rm', '-rf', path)
80 1
    if os.path.exists(path):
81 1
        if os.path.isdir(path):
82
            shutil.rmtree(
83 1
                path, 
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
84
                ignore_errors = False, 
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
Coding Style introduced by
No space allowed around keyword argument assignment
ignore_errors = False,
^
Loading history...
85
                onerror = rm_error_readonly
0 ignored issues
show
Coding Style introduced by
No space allowed around keyword argument assignment
onerror = rm_error_readonly
^
Loading history...
86 1
            )
87 1
        else:
88 1
            os.remove(path)
89 1
90
91 1
def show(name, *args, stdout=True):
92 1
    program = CMD_PREFIX + ' '.join([name, *args])
93
    if stdout:
94
        common.show(program, color='shell')
95
    else:
96
        log.debug(program)
97
    return program
98
99
100
101
def rm_error_readonly(func, path, exc_info):
0 ignored issues
show
Unused Code introduced by
The argument exc_info seems to be unused.
Loading history...
102
    """
103
    Error handler for ``shutil.rmtree``.
104
105
    If the error is due to an access error (read only file)
106
    it attempts to add write permission and then retries.
107
108
    If the error is for another reason it re-raises the error.
109
110
    Usage : ``shutil.rmtree(path, onerror=rm_error_readonly)``
111
    """
112
    if not os.access(path, os.W_OK):
113
        os.chmod(path, stat.S_IWUSR)
114
        func(path)
115
    else:
116
        raise ShellError("Can not remove " + path + " due to permission")
0 ignored issues
show
Coding Style introduced by
Final newline missing
Loading history...