mirror of https://github.com/python/cpython
[3.13] GH-119169: Implement `pathlib.Path.walk()` using `os.walk()` (GH-119573) (#119750)
GH-119169: Implement `pathlib.Path.walk()` using `os.walk()` (GH-119573)
For silly reasons, pathlib's generic implementation of `walk()` currently
resides in `glob._Globber`. This commit moves it into
`pathlib._abc.PathBase.walk()` where it really belongs, and makes
`pathlib.Path.walk()` call `os.walk()`.
(cherry picked from commit 7ff61f51b6
)
Co-authored-by: Barney Gale <barney.gale@gmail.com>
This commit is contained in:
parent
061abf8e4c
commit
a7aa7c41eb
37
Lib/glob.py
37
Lib/glob.py
|
@ -523,43 +523,6 @@ class _Globber:
|
|||
except OSError:
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def walk(cls, root, top_down, on_error, follow_symlinks):
|
||||
"""Walk the directory tree from the given root, similar to os.walk().
|
||||
"""
|
||||
paths = [root]
|
||||
while paths:
|
||||
path = paths.pop()
|
||||
if isinstance(path, tuple):
|
||||
yield path
|
||||
continue
|
||||
try:
|
||||
with cls.scandir(path) as scandir_it:
|
||||
dirnames = []
|
||||
filenames = []
|
||||
if not top_down:
|
||||
paths.append((path, dirnames, filenames))
|
||||
for entry in scandir_it:
|
||||
name = entry.name
|
||||
try:
|
||||
if entry.is_dir(follow_symlinks=follow_symlinks):
|
||||
if not top_down:
|
||||
paths.append(cls.parse_entry(entry))
|
||||
dirnames.append(name)
|
||||
else:
|
||||
filenames.append(name)
|
||||
except OSError:
|
||||
filenames.append(name)
|
||||
except OSError as error:
|
||||
if on_error is not None:
|
||||
on_error(error)
|
||||
else:
|
||||
if top_down:
|
||||
yield path, dirnames, filenames
|
||||
if dirnames:
|
||||
prefix = cls.add_slash(path)
|
||||
paths += [cls.concat_path(prefix, d) for d in reversed(dirnames)]
|
||||
|
||||
|
||||
class _StringGlobber(_Globber):
|
||||
lstat = staticmethod(os.lstat)
|
||||
|
|
|
@ -696,7 +696,37 @@ class PathBase(PurePathBase):
|
|||
|
||||
def walk(self, top_down=True, on_error=None, follow_symlinks=False):
|
||||
"""Walk the directory tree from this directory, similar to os.walk()."""
|
||||
return self._globber.walk(self, top_down, on_error, follow_symlinks)
|
||||
paths = [self]
|
||||
while paths:
|
||||
path = paths.pop()
|
||||
if isinstance(path, tuple):
|
||||
yield path
|
||||
continue
|
||||
dirnames = []
|
||||
filenames = []
|
||||
if not top_down:
|
||||
paths.append((path, dirnames, filenames))
|
||||
try:
|
||||
for child in path.iterdir():
|
||||
try:
|
||||
if child.is_dir(follow_symlinks=follow_symlinks):
|
||||
if not top_down:
|
||||
paths.append(child)
|
||||
dirnames.append(child.name)
|
||||
else:
|
||||
filenames.append(child.name)
|
||||
except OSError:
|
||||
filenames.append(child.name)
|
||||
except OSError as error:
|
||||
if on_error is not None:
|
||||
on_error(error)
|
||||
if not top_down:
|
||||
while not isinstance(paths.pop(), tuple):
|
||||
pass
|
||||
continue
|
||||
if top_down:
|
||||
yield path, dirnames, filenames
|
||||
paths += [path.joinpath(d) for d in reversed(dirnames)]
|
||||
|
||||
def absolute(self):
|
||||
"""Return an absolute version of this path
|
||||
|
|
|
@ -623,7 +623,9 @@ class Path(PathBase, PurePath):
|
|||
"""Walk the directory tree from this directory, similar to os.walk()."""
|
||||
sys.audit("pathlib.Path.walk", self, on_error, follow_symlinks)
|
||||
root_dir = str(self)
|
||||
results = self._globber.walk(root_dir, top_down, on_error, follow_symlinks)
|
||||
if not follow_symlinks:
|
||||
follow_symlinks = os._walk_symlinks_as_files
|
||||
results = os.walk(root_dir, top_down, on_error, follow_symlinks)
|
||||
for path_str, dirnames, filenames in results:
|
||||
if root_dir == '.':
|
||||
path_str = path_str[2:]
|
||||
|
|
Loading…
Reference in New Issue