Completed
Push — master ( ed35bb...dcee7e )
by Bjorn
07:54
created

dkfileutils.match()   B

Complexity

Conditions 6

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 6
dl 0
loc 14
rs 8
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 list(which(name))[0]
12
13
14
def get_path_directories():
15
    pth = os.environ['PATH']
16
    if sys.platform == 'win32' and os.environ.get("BASH"):
17
        # winbash has a bug..
18
        if pth[1] == ';':  # pragma: nocover
19
            pth = pth.replace(';', ':', 1)
20
    return pth.split(os.pathsep)
21
22
23
def is_executable(fname):
24
    return os.stat(fname)[ST_MODE] & (S_IXUSR | S_IXGRP | S_IXOTH)
25
26
27
def which(filename, interactive=False, verbose=False):
28
    exe = os.environ.get('PATHEXT', ['.cmd', '.bat', '.exe', '.com'])
29
30
    name, ext = os.path.splitext(filename)
31
    if ext and (ext in exe):  # pragma: nocover
32
        exe = []
33
34
    def match(filenames):
35
        res = set()
36
        for fname in filenames:
37
            if fname == filename:  # pragma: nocover
38
                res.add(fname)
39
                continue
40
41
            fn_name, fn_ext = os.path.splitext(fname)
42
            if name == fn_name:
43
                for suffix in exe:
44
                    if name + fn_ext == fname:
45
                        res.add(fname)
46
47
        return sorted(res)
48
49
    returnset = set()
50
    found = False
51
    for pth in get_path_directories():
52
        if not pth.strip():  # pragma: nocover
53
            continue
54
55
        if verbose:  # pragma: nocover
56
            print('checking pth..')
57
58
        try:
59
            fnames = os.listdir(pth)
60
        except:  # pragma: nocover
61
            continue
62
63
        matched = match(fnames)
64
65
        if matched:
66
            for m in matched:
67
                found_file = os.path.normcase(os.path.normpath(os.path.join(pth, m)))
68
                if found_file not in returnset:
69
                    if is_executable(found_file):
70
                        yield found_file
71
                    returnset.add(found_file)
72
            found = True
73
74
    if not found and interactive:  # pragma: nocover
75
        print("Couldn't find %r anywhere on the path.." % filename)
76
        sys.exit(1)
77
78
79
if __name__ == "__main__":  # pragma: nocover
80
    for _fname in which(sys.argv[1], interactive=True, verbose='-v' in sys.argv):
81
        print(_fname)
82
    sys.exit(0)
83