44 Targets ,
55 filenameof ,
66 filenamesof ,
7- cwdStack ,
7+ getcwd ,
88 error ,
99 simplerule ,
10- G
10+ G ,
1111)
12- from os .path import relpath , splitext , join , basename , isfile
12+ from os .path import relpath , splitext , join , basename , isfile , normpath
13+ from os import walk
1314from glob import iglob
1415import fnmatch
1516import subprocess
1617import shutil
18+ import re
19+ import functools
1720
1821
1922def filenamesmatchingof (xs , pattern ):
@@ -35,9 +38,61 @@ def collectattrs(*, targets, name, initial=[]):
3538 return sorted (s )
3639
3740
41+ @functools .cache
42+ def _glob_to_re (glob_str ):
43+ opts = re .compile ('([.]|[*][*]/|[*]|[?])|(.)' )
44+ out = ''
45+ for (pattern_match , literal_text ) in opts .findall (glob_str ):
46+ if pattern_match == '.' :
47+ out += '[.]'
48+ elif pattern_match == '**/' :
49+ out += '(?:.*/)?'
50+ elif pattern_match == '*' :
51+ out += '[^/]*'
52+ elif pattern_match == '?' :
53+ out += '.'
54+ elif literal_text :
55+ out += literal_text
56+ return re .compile (out )
57+
58+ def _glob_filter (paths , pattern ):
59+ r = _glob_to_re (pattern )
60+ for f in paths :
61+ if r .match (f ):
62+ yield f
63+
64+ def _glob_matches (path , pattern ):
65+ r = _glob_to_re (pattern )
66+ return r .match (path )
67+
68+ def glob (include = ["*" ], exclude = [], dir = None , relative_to = "." ):
69+ if not dir :
70+ dir = getcwd ()
71+ if dir .startswith ("./" ):
72+ dir = normpath (join (getcwd (), dir ))
73+ if relative_to .startswith ("./" ):
74+ relative_to = normpath (join (getcwd (), relative_to ))
75+
76+ def iterate ():
77+ for dirpath , dirnames , filenames in walk (
78+ dir , topdown = True , followlinks = True
79+ ):
80+ dirpath = relpath (dirpath , dir )
81+ filenames = [normpath (join (dirpath , f )) for f in filenames ]
82+ matching = set ()
83+ for p in include :
84+ matching .update (_glob_filter (filenames , p ))
85+ for p in exclude :
86+ matching = [n for n in matching if not _glob_matches (n , p )]
87+ for f in matching :
88+ yield normpath (relpath (join (dir , f ), relative_to ))
89+
90+ return list (iterate ())
91+
92+
3893def itemsof (pattern , root = None , cwd = None ):
3994 if not cwd :
40- cwd = cwdStack [ - 1 ]
95+ cwd = getcwd ()
4196 if not root :
4297 root = "."
4398
0 commit comments