comparison cutils/util/walk.py @ 154:c7df81fb84b7

Merge dirs and nondirs into one list that is yielded from "util.walk()"
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 06 Jan 2025 13:38:09 +0100
parents 4a0c3c9eead7
children bf74ce3c968d
comparison
equal deleted inserted replaced
153:3505406ef9f3 154:c7df81fb84b7
128 - optimized for use in :command:`treesum` 128 - optimized for use in :command:`treesum`
129 - most errors are not suppressed 129 - most errors are not suppressed
130 - the `root` is never part of the returned data 130 - the `root` is never part of the returned data
131 - the returned directory in "top" is not a string form but a list of 131 - the returned directory in "top" is not a string form but a list of
132 individual path segments 132 individual path segments
133 - all other yielded lists contain WalkDirEntry elements instead of 133 - there is only one yields list
134 strings 134
135 * contains :class:`WalkDirEntry`
136 * sorted by its fsname
137
135 - recurse into sub-directories first ("topdown=False") 138 - recurse into sub-directories first ("topdown=False")
136 - sort consistently all yielded lists by the filesystem encoding 139 - sort consistently all yielded lists by the filesystem encoding
137 140
138 .. note:: The implementation is based on Python 3.11 and needs a 141 .. note:: The implementation is based on Python 3.11 and needs a
139 functional :func:`os.scandir` or :func:`scandir.scandir` 142 functional :func:`os.scandir` or :func:`scandir.scandir`
152 if top: 155 if top:
153 path = os.path.join(root, *top) 156 path = os.path.join(root, *top)
154 else: 157 else:
155 path = root 158 path = root
156 159
157 dirs, nondirs, walk_dirs = [], [], [] 160 fsobjects, walk_dirs = [], []
158 161
159 scandir_cm = scandir(path) 162 scandir_cm = scandir(path)
160 if not hasattr(scandir_cm, "close"): 163 if not hasattr(scandir_cm, "close"):
161 scandir_cm = nullcontext(scandir_cm) 164 scandir_cm = nullcontext(scandir_cm)
162 with scandir_cm as scandir_it: 165 with scandir_cm as scandir_it:
163 while True: 166 while True:
164 try: 167 try:
165 entry = WalkDirEntry.from_direntry(next(scandir_it)) 168 entry = WalkDirEntry.from_direntry(next(scandir_it))
166 except StopIteration: 169 except StopIteration:
167 break 170 break
168 if entry.is_dir: 171 fsobjects.append(entry)
169 dirs.append(entry)
170 else:
171 nondirs.append(entry)
172 # 172 #
173 # Always bottom-up: recurse into sub-directories, but exclude 173 # Always bottom-up: recurse into sub-directories, but exclude
174 # symlinks to directories if follow_symlinks is False 174 # symlinks to directories if follow_symlinks is False
175 # 175 #
176 if entry.is_dir: 176 if entry.is_dir:
181 if walk_into: 181 if walk_into:
182 walk_dirs.append(entry) 182 walk_dirs.append(entry)
183 183
184 # Sort by low-level filesystem encoding 184 # Sort by low-level filesystem encoding
185 walk_dirs.sort(key=WalkDirEntry.sort_key) 185 walk_dirs.sort(key=WalkDirEntry.sort_key)
186 dirs.sort(key=WalkDirEntry.sort_key) 186 fsobjects.sort(key=WalkDirEntry.sort_key)
187 nondirs.sort(key=WalkDirEntry.sort_key)
188 187
189 # Recurse into sub-directories 188 # Recurse into sub-directories
190 for wd in walk_dirs: 189 for wd in walk_dirs:
191 yield from _walk(root, top + (wd.name,), follow_symlinks) 190 yield from _walk(root, top + (wd.name,), follow_symlinks)
192 # Yield after recursion if going bottom up 191 # Yield after recursion if going bottom up
193 yield top, dirs, nondirs 192 yield top, fsobjects
194 193
195 else: 194 else:
196 195
197 raise ImportError("no `scandir()' module available") 196 raise ImportError("no `scandir()' module available")