summaryrefslogtreecommitdiffstats
path: root/Lib/pathlib
diff options
context:
space:
mode:
authorBarney Gale <barney.gale@gmail.com>2024-05-29 20:51:04 (GMT)
committerGitHub <noreply@github.com>2024-05-29 20:51:04 (GMT)
commit7ff61f51b6f75315291419269295a8ac3933397b (patch)
tree21aa4cc28d247bf4d94f4e3aaf2724ae95b9c927 /Lib/pathlib
parenta150679f90c6e3f017bd75cac3b8f727063cc4aa (diff)
downloadcpython-7ff61f51b6f75315291419269295a8ac3933397b.zip
cpython-7ff61f51b6f75315291419269295a8ac3933397b.tar.gz
cpython-7ff61f51b6f75315291419269295a8ac3933397b.tar.bz2
GH-119169: Implement `pathlib.Path.walk()` using `os.walk()` (#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()`.
Diffstat (limited to 'Lib/pathlib')
-rw-r--r--Lib/pathlib/_abc.py32
-rw-r--r--Lib/pathlib/_local.py4
2 files changed, 34 insertions, 2 deletions
diff --git a/Lib/pathlib/_abc.py b/Lib/pathlib/_abc.py
index 6b5d9fc..d7471b6 100644
--- a/Lib/pathlib/_abc.py
+++ b/Lib/pathlib/_abc.py
@@ -621,7 +621,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
diff --git a/Lib/pathlib/_local.py b/Lib/pathlib/_local.py
index 49d9f81..473fd52 100644
--- a/Lib/pathlib/_local.py
+++ b/Lib/pathlib/_local.py
@@ -672,7 +672,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:]