parents()   A
last analyzed

Complexity

Conditions 3

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

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