diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2024-05-29 21:24:42 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-29 21:24:42 (GMT) |
commit | a7aa7c41ebfce5bf537c939c8dfc0605adcfabd8 (patch) | |
tree | f6f7e0f071f1e5009eff88c0776dd89cc2975c42 /Lib/pathlib | |
parent | 061abf8e4c1a0a920067aa73b0e41f40c89e340b (diff) | |
download | cpython-a7aa7c41ebfce5bf537c939c8dfc0605adcfabd8.zip cpython-a7aa7c41ebfce5bf537c939c8dfc0605adcfabd8.tar.gz cpython-a7aa7c41ebfce5bf537c939c8dfc0605adcfabd8.tar.bz2 |
[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 7ff61f51b6f75315291419269295a8ac3933397b)
Co-authored-by: Barney Gale <barney.gale@gmail.com>
Diffstat (limited to 'Lib/pathlib')
-rw-r--r-- | Lib/pathlib/_abc.py | 32 | ||||
-rw-r--r-- | Lib/pathlib/_local.py | 4 |
2 files changed, 34 insertions, 2 deletions
diff --git a/Lib/pathlib/_abc.py b/Lib/pathlib/_abc.py index 9068452..4d24146 100644 --- a/Lib/pathlib/_abc.py +++ b/Lib/pathlib/_abc.py @@ -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 diff --git a/Lib/pathlib/_local.py b/Lib/pathlib/_local.py index b1e678a..fbc8db7 100644 --- a/Lib/pathlib/_local.py +++ b/Lib/pathlib/_local.py @@ -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:] |