]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-119169: Implement `pathlib.Path.walk()` using `os.walk()` (#119573)
authorBarney Gale <barney.gale@gmail.com>
Wed, 29 May 2024 20:51:04 +0000 (21:51 +0100)
committerGitHub <noreply@github.com>
Wed, 29 May 2024 20:51:04 +0000 (20:51 +0000)
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()`.

Lib/glob.py
Lib/pathlib/_abc.py
Lib/pathlib/_local.py

index 920f79ad7e1fe5ef1abda9bf1c1306ce78cb61d7..fbb1d35aab71faa7396cbdeed0a68c3c3a76f94c 100644 (file)
@@ -519,43 +519,6 @@ class _Globber:
         elif self.lexists(path):
             yield path
 
-    @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):
     lexists = staticmethod(os.path.lexists)
index 6b5d9fc2a0c560e80e9cd2e02b6d04f076272506..d7471b6927331d3a45f2c47ac17b2a0e9499775d 100644 (file)
@@ -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
index 49d9f813c54c23bffc1816f177626b9240375d03..473fd525768b509b6dc5f59237a4258bb6d531d1 100644 (file)
@@ -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:]