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