Completed
Push — master ( 29a7b5...967611 )
by Bjorn
01:03
created

_listdir()   A

Complexity

Conditions 2

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
c 1
b 0
f 0
dl 0
loc 6
rs 9.4285
1
# -*- coding: utf-8 -*-
2
"""Print where on the path an executable is located.
3
"""
4
from __future__ import print_function
5
import sys
6
import os
7
from stat import ST_MODE, S_IXUSR, S_IXGRP, S_IXOTH
8
9
10
def get_executable(name):
11
    """Return the first executable on the path that matches `name`.
12
    """
13
    for result in which(name):
14
        return result
15
    return None
16
17
18
def get_path_directories():
19
    """Return a list of all the directories on the path.
20
    """
21
    pth = os.environ['PATH']
22
    if sys.platform == 'win32' and os.environ.get("BASH"):
23
        # winbash has a bug..
24
        if pth[1] == ';':  # pragma: nocover
25
            pth = pth.replace(';', ':', 1)
26
    return [p.strip() for p in pth.split(os.pathsep) if p.strip()]
27
28
29
def is_executable(fname):
30
    """Check if a file is executable.
31
    """
32
    return os.stat(fname)[ST_MODE] & (S_IXUSR | S_IXGRP | S_IXOTH)
33
34
35
def _noprint(*args, **kwargs):
36
    """Don't print.
37
    """
38
    pass
39
40
41
def _listdir(pth):
42
    """Non-raising listdir."""
43
    try:
44
        return os.listdir(pth)
45
    except:  # pragma: nocover
46
        pass
47
48
49
def _normalize(pth):
50
    return os.path.normcase(os.path.normpath(pth))
51
52
53
def which(filename, interactive=False, verbose=False):
54
    """Yield all executable files on path that matches `filename`.
55
    """
56
    exe = os.environ.get('PATHEXT', ['.cmd', '.bat', '.exe', '.com'])
57
    writeln = print if verbose else _noprint
58
59
    name, ext = os.path.splitext(filename)
60
    if ext and (ext in exe):  # pragma: nocover
61
        exe = []
62
63
    def match(filenames):
64
        res = set()
65
        for fname in filenames:
66
            if fname == filename:  # pragma: nocover
67
                res.add(fname)
68
                continue
69
70
            fn_name, fn_ext = os.path.splitext(fname)
71
            if name == fn_name:
72
                for _suffix in exe:  # pragma: nocover
73
                    if name + fn_ext == fname:
74
                        res.add(fname)
75
76
        return sorted(res)
77
78
    returnset = set()
79
    found = False
80
    for pth in get_path_directories():
81
        writeln('checking pth..')
82
83
        fnames = _listdir(pth)
84
        if not fnames:
85
            continue
86
87
        for m in match(fnames):
88
            found_file = _normalize(os.path.join(pth, m))
89
            if found_file not in returnset:
90
                if is_executable(found_file):
91
                    yield found_file
92
                returnset.add(found_file)
93
        found = True
94
95
    if not found and interactive:  # pragma: nocover
96
        print("Couldn't find %r anywhere on the path.." % filename)
97
        sys.exit(1)
98
99
100
if __name__ == "__main__":  # pragma: nocover
101
    for _fname in which(sys.argv[1], interactive=True, verbose='-v' in sys.argv):
102
        print(_fname)
103
    sys.exit(0)
104