• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"""
2File sets and globbing helper for make_layout.
3"""
4
5__author__ = "Steve Dower <steve.dower@python.org>"
6__version__ = "3.8"
7
8import os
9
10
11class FileStemSet:
12    def __init__(self, *patterns):
13        self._names = set()
14        self._prefixes = []
15        self._suffixes = []
16        for p in map(os.path.normcase, patterns):
17            if p.endswith("*"):
18                self._prefixes.append(p[:-1])
19            elif p.startswith("*"):
20                self._suffixes.append(p[1:])
21            else:
22                self._names.add(p)
23
24    def _make_name(self, f):
25        return os.path.normcase(f.stem)
26
27    def __contains__(self, f):
28        bn = self._make_name(f)
29        return (
30            bn in self._names
31            or any(map(bn.startswith, self._prefixes))
32            or any(map(bn.endswith, self._suffixes))
33        )
34
35
36class FileNameSet(FileStemSet):
37    def _make_name(self, f):
38        return os.path.normcase(f.name)
39
40
41class FileSuffixSet:
42    def __init__(self, *patterns):
43        self._names = set()
44        self._prefixes = []
45        self._suffixes = []
46        for p in map(os.path.normcase, patterns):
47            if p.startswith("*."):
48                self._names.add(p[1:])
49            elif p.startswith("*"):
50                self._suffixes.append(p[1:])
51            elif p.endswith("*"):
52                self._prefixes.append(p[:-1])
53            elif p.startswith("."):
54                self._names.add(p)
55            else:
56                self._names.add("." + p)
57
58    def _make_name(self, f):
59        return os.path.normcase(f.suffix)
60
61    def __contains__(self, f):
62        bn = self._make_name(f)
63        return (
64            bn in self._names
65            or any(map(bn.startswith, self._prefixes))
66            or any(map(bn.endswith, self._suffixes))
67        )
68
69
70def _rglob(root, pattern, condition):
71    dirs = [root]
72    recurse = pattern[:3] in {"**/", "**\\"}
73    if recurse:
74        pattern = pattern[3:]
75
76    while dirs:
77        d = dirs.pop(0)
78        if recurse:
79            dirs.extend(
80                filter(
81                    condition, (type(root)(f2) for f2 in os.scandir(d) if f2.is_dir())
82                )
83            )
84        yield from (
85            (f.relative_to(root), f)
86            for f in d.glob(pattern)
87            if f.is_file() and condition(f)
88        )
89
90
91def _return_true(f):
92    return True
93
94
95def rglob(root, patterns, condition=None):
96    if isinstance(patterns, tuple):
97        for p in patterns:
98            yield from _rglob(root, p, condition or _return_true)
99    else:
100        yield from _rglob(root, patterns, condition or _return_true)
101