Skip to content

Commit b64cd9f

Browse files
barneygaleestyxx
authored andcommitted
pythonGH-119169: Implement pathlib.Path.walk() using os.walk() (python#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()`.
1 parent 459d4f3 commit b64cd9f

File tree

3 files changed

+34
-39
lines changed

3 files changed

+34
-39
lines changed

Lib/glob.py

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -519,43 +519,6 @@ def select_exists(self, path, exists=False):
519519
elif self.lexists(path):
520520
yield path
521521

522-
@classmethod
523-
def walk(cls, root, top_down, on_error, follow_symlinks):
524-
"""Walk the directory tree from the given root, similar to os.walk().
525-
"""
526-
paths = [root]
527-
while paths:
528-
path = paths.pop()
529-
if isinstance(path, tuple):
530-
yield path
531-
continue
532-
try:
533-
with cls.scandir(path) as scandir_it:
534-
dirnames = []
535-
filenames = []
536-
if not top_down:
537-
paths.append((path, dirnames, filenames))
538-
for entry in scandir_it:
539-
name = entry.name
540-
try:
541-
if entry.is_dir(follow_symlinks=follow_symlinks):
542-
if not top_down:
543-
paths.append(cls.parse_entry(entry))
544-
dirnames.append(name)
545-
else:
546-
filenames.append(name)
547-
except OSError:
548-
filenames.append(name)
549-
except OSError as error:
550-
if on_error is not None:
551-
on_error(error)
552-
else:
553-
if top_down:
554-
yield path, dirnames, filenames
555-
if dirnames:
556-
prefix = cls.add_slash(path)
557-
paths += [cls.concat_path(prefix, d) for d in reversed(dirnames)]
558-
559522

560523
class _StringGlobber(_Globber):
561524
lexists = staticmethod(os.path.lexists)

Lib/pathlib/_abc.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,37 @@ def rglob(self, pattern, *, case_sensitive=None, recurse_symlinks=True):
621621

622622
def walk(self, top_down=True, on_error=None, follow_symlinks=False):
623623
"""Walk the directory tree from this directory, similar to os.walk()."""
624-
return self._globber.walk(self, top_down, on_error, follow_symlinks)
624+
paths = [self]
625+
while paths:
626+
path = paths.pop()
627+
if isinstance(path, tuple):
628+
yield path
629+
continue
630+
dirnames = []
631+
filenames = []
632+
if not top_down:
633+
paths.append((path, dirnames, filenames))
634+
try:
635+
for child in path.iterdir():
636+
try:
637+
if child.is_dir(follow_symlinks=follow_symlinks):
638+
if not top_down:
639+
paths.append(child)
640+
dirnames.append(child.name)
641+
else:
642+
filenames.append(child.name)
643+
except OSError:
644+
filenames.append(child.name)
645+
except OSError as error:
646+
if on_error is not None:
647+
on_error(error)
648+
if not top_down:
649+
while not isinstance(paths.pop(), tuple):
650+
pass
651+
continue
652+
if top_down:
653+
yield path, dirnames, filenames
654+
paths += [path.joinpath(d) for d in reversed(dirnames)]
625655

626656
def absolute(self):
627657
"""Return an absolute version of this path

Lib/pathlib/_local.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,9 @@ def walk(self, top_down=True, on_error=None, follow_symlinks=False):
672672
"""Walk the directory tree from this directory, similar to os.walk()."""
673673
sys.audit("pathlib.Path.walk", self, on_error, follow_symlinks)
674674
root_dir = str(self)
675-
results = self._globber.walk(root_dir, top_down, on_error, follow_symlinks)
675+
if not follow_symlinks:
676+
follow_symlinks = os._walk_symlinks_as_files
677+
results = os.walk(root_dir, top_down, on_error, follow_symlinks)
676678
for path_str, dirnames, filenames in results:
677679
if root_dir == '.':
678680
path_str = path_str[2:]

0 commit comments

Comments
 (0)