1 """
2 File sets and globbing helper for make_layout.
3 """
4
5 __author__ = "Steve Dower <steve.dower@python.org>"
6 __version__ = "3.8"
7
8 import os
9
10
11 class ESC[4;38;5;81mFileStemSet:
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
36 class ESC[4;38;5;81mFileNameSet(ESC[4;38;5;149mFileStemSet):
37 def _make_name(self, f):
38 return os.path.normcase(f.name)
39
40
41 class ESC[4;38;5;81mFileSuffixSet:
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
70 def _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
91 def _return_true(f):
92 return True
93
94
95 def rglob(root, patterns, condition=None):
96 if not os.path.isdir(root):
97 return
98 if isinstance(patterns, tuple):
99 for p in patterns:
100 yield from _rglob(root, p, condition or _return_true)
101 else:
102 yield from _rglob(root, patterns, condition or _return_true)