Completed
Push — master ( bff43f...8c5ef8 )
by Bjorn
51s
created

pfind()   A

Complexity

Conditions 2

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 2
c 2
b 0
f 0
dl 0
loc 17
rs 9.4285
1
#!/usr/bin/python
2
"""CLI usage: ``pfind path filename`` will find the closest ancestor directory
3
   conataining filename (used for finding syncspec.txt and config files).
4
"""
5
import os
6
import sys
7
8
9
def pfindall(path, *fnames):
10
    """Find all fnames in the closest ancestor directory.
11
       For the purposes of this function, we are our own closest ancestor.
12
       I.e. given the structure::
13
14
            .
15
            `-- a
16
                |-- b
17
                |   |-- c
18
                |   |   `-- x.txt
19
                |   `-- x.txt
20
                `-- y.txt
21
22
       the call::
23
24
           dict(pfindall('a/b/c', 'x.txt', 'y.txt'))
25
26
       will return::
27
28
           {
29
               'x.txt': 'a/b/c/x.txt',
30
               'y.txt': 'a/y.txt'
31
           }
32
33
       ``a/b/x.txt`` is not returned, since ``a/b/c/x.txt`` is the "closest"
34
       ``x.txt`` when starting from ``a/b/c`` (note: pfindall only looks
35
       "upwards", ie. towards the root).
36
    """
37
    wd = os.path.abspath(path)
38
    assert os.path.isdir(wd)
39
40
    def parents():
41
        """yield successive parent directories
42
        """
43
        parent = wd
44
        yield parent
45
        while 1:
46
            parent, dirname = os.path.split(parent)
47
            if not dirname:
48
                return
49
            yield parent
50
51
    for d in parents():
52
        curdirlist = os.listdir(d)
53
        for fname in fnames:
54
            if fname in curdirlist:
55
                yield fname, os.path.join(d, fname)
56
57
58
def pfind(path, *fnames):
59
    """Find the first fname in the closest ancestor directory.
60
       For the purposes of this function, we are our own closest ancestor, i.e.
61
       given the structure::
62
63
            /srv
64
            |-- myapp
65
            |   |-- __init__.py
66
            |   `-- myapp.py
67
            `-- setup.py
68
69
       then both ``pfind('/srv', 'setup.py')`` and
70
       ``pfind('/srv/myapp', 'setup.py')`` will return ``/srv/setup.py``
71
    """
72
    for _fname, fpath in pfindall(path, *fnames):
73
        return fpath
74
    return None
75
76
77
if __name__ == "__main__":  # pragma: nocover
78
    _path, filename = sys.argv[1], sys.argv[2]
79
    print pfind(_path, filename)
80