]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-106747: Make pathlib ABC globbing more consistent with `glob.glob()` (#115056)
authorBarney Gale <barney.gale@gmail.com>
Tue, 6 Feb 2024 02:48:18 +0000 (02:48 +0000)
committerGitHub <noreply@github.com>
Tue, 6 Feb 2024 02:48:18 +0000 (02:48 +0000)
When expanding `**` wildcards, ensure we add a trailing slash to the
topmost directory path. This matches `glob.glob()` behaviour:

    >>> glob.glob('dirA/**', recursive=True)
    ['dirA/', 'dirA/dirB', 'dirA/dirB/dirC']

This does not affect `pathlib.Path.glob()`, because trailing slashes aren't
supported in pathlib proper.

Lib/pathlib/_abc.py
Lib/test/test_pathlib/test_pathlib_abc.py

index 91f5cd6c01e9d088cf8c11c171a742c31f9d2580..e4b1201a3703c32dc5284c4631445ba75548fe7a 100644 (file)
@@ -95,7 +95,7 @@ def _select_recursive(parent_paths, dir_only, follow_symlinks):
     if follow_symlinks is None:
         follow_symlinks = False
     for parent_path in parent_paths:
-        paths = [parent_path]
+        paths = [parent_path._make_child_relpath('')]
         while paths:
             path = paths.pop()
             yield path
index 207579ccbf443b78cdec48094037c2463f754abc..1d30deca8f7a1bbe0234f779199fc2228a6decde 100644 (file)
@@ -1791,25 +1791,25 @@ class DummyPathTest(DummyPurePathTest):
         _check(p, "*/", ["dirA/", "dirB/", "dirC/", "dirE/", "linkB/"])
         _check(p, "dir*/*/..", ["dirC/dirD/..", "dirA/linkC/..", "dirB/linkD/.."])
         _check(p, "dir*/**", [
-            "dirA", "dirA/linkC", "dirA/linkC/fileB", "dirA/linkC/linkD", "dirA/linkC/linkD/fileB",
-            "dirB", "dirB/fileB", "dirB/linkD", "dirB/linkD/fileB",
-            "dirC", "dirC/fileC", "dirC/dirD",  "dirC/dirD/fileD", "dirC/novel.txt",
-            "dirE"])
+            "dirA/", "dirA/linkC", "dirA/linkC/fileB", "dirA/linkC/linkD", "dirA/linkC/linkD/fileB",
+            "dirB/", "dirB/fileB", "dirB/linkD", "dirB/linkD/fileB",
+            "dirC/", "dirC/fileC", "dirC/dirD",  "dirC/dirD/fileD", "dirC/novel.txt",
+            "dirE/"])
         _check(p, "dir*/**/", ["dirA/", "dirA/linkC/", "dirA/linkC/linkD/", "dirB/", "dirB/linkD/",
                                "dirC/", "dirC/dirD/", "dirE/"])
         _check(p, "dir*/**/..", ["dirA/..", "dirA/linkC/..", "dirB/..",
                                  "dirB/linkD/..", "dirA/linkC/linkD/..",
                                  "dirC/..", "dirC/dirD/..", "dirE/.."])
         _check(p, "dir*/*/**", [
-            "dirA/linkC", "dirA/linkC/linkD", "dirA/linkC/fileB", "dirA/linkC/linkD/fileB",
-            "dirB/linkD", "dirB/linkD/fileB",
-            "dirC/dirD", "dirC/dirD/fileD"])
+            "dirA/linkC/", "dirA/linkC/linkD", "dirA/linkC/fileB", "dirA/linkC/linkD/fileB",
+            "dirB/linkD/", "dirB/linkD/fileB",
+            "dirC/dirD/", "dirC/dirD/fileD"])
         _check(p, "dir*/*/**/", ["dirA/linkC/", "dirA/linkC/linkD/", "dirB/linkD/", "dirC/dirD/"])
         _check(p, "dir*/*/**/..", ["dirA/linkC/..", "dirA/linkC/linkD/..",
                                    "dirB/linkD/..", "dirC/dirD/.."])
         _check(p, "dir*/**/fileC", ["dirC/fileC"])
         _check(p, "dir*/*/../dirD/**/", ["dirC/dirD/../dirD/"])
-        _check(p, "*/dirD/**", ["dirC/dirD", "dirC/dirD/fileD"])
+        _check(p, "*/dirD/**", ["dirC/dirD/", "dirC/dirD/fileD"])
         _check(p, "*/dirD/**/", ["dirC/dirD/"])
 
     @needs_symlinks
@@ -1827,19 +1827,19 @@ class DummyPathTest(DummyPurePathTest):
         _check(p, "*/", ["dirA/", "dirB/", "dirC/", "dirE/"])
         _check(p, "dir*/*/..", ["dirC/dirD/.."])
         _check(p, "dir*/**", [
-            "dirA", "dirA/linkC",
-            "dirB", "dirB/fileB", "dirB/linkD",
-            "dirC", "dirC/fileC", "dirC/dirD", "dirC/dirD/fileD", "dirC/novel.txt",
-            "dirE"])
+            "dirA/", "dirA/linkC",
+            "dirB/", "dirB/fileB", "dirB/linkD",
+            "dirC/", "dirC/fileC", "dirC/dirD", "dirC/dirD/fileD", "dirC/novel.txt",
+            "dirE/"])
         _check(p, "dir*/**/", ["dirA/", "dirB/", "dirC/", "dirC/dirD/", "dirE/"])
         _check(p, "dir*/**/..", ["dirA/..", "dirB/..", "dirC/..", "dirC/dirD/..", "dirE/.."])
-        _check(p, "dir*/*/**", ["dirC/dirD", "dirC/dirD/fileD"])
+        _check(p, "dir*/*/**", ["dirC/dirD/", "dirC/dirD/fileD"])
         _check(p, "dir*/*/**/", ["dirC/dirD/"])
         _check(p, "dir*/*/**/..", ["dirC/dirD/.."])
         _check(p, "dir*/**/fileC", ["dirC/fileC"])
-        _check(p, "dir*/*/../dirD/**", ["dirC/dirD/../dirD", "dirC/dirD/../dirD/fileD"])
+        _check(p, "dir*/*/../dirD/**", ["dirC/dirD/../dirD/", "dirC/dirD/../dirD/fileD"])
         _check(p, "dir*/*/../dirD/**/", ["dirC/dirD/../dirD/"])
-        _check(p, "*/dirD/**", ["dirC/dirD", "dirC/dirD/fileD"])
+        _check(p, "*/dirD/**", ["dirC/dirD/", "dirC/dirD/fileD"])
         _check(p, "*/dirD/**/", ["dirC/dirD/"])
 
     def test_rglob_common(self):
@@ -1876,13 +1876,13 @@ class DummyPathTest(DummyPurePathTest):
                               "dirC/dirD", "dirC/dirD/fileD"])
         _check(p.rglob("file*"), ["dirC/fileC", "dirC/dirD/fileD"])
         _check(p.rglob("**/file*"), ["dirC/fileC", "dirC/dirD/fileD"])
-        _check(p.rglob("dir*/**"), ["dirC/dirD", "dirC/dirD/fileD"])
+        _check(p.rglob("dir*/**"), ["dirC/dirD/", "dirC/dirD/fileD"])
         _check(p.rglob("dir*/**/"), ["dirC/dirD/"])
         _check(p.rglob("*/*"), ["dirC/dirD/fileD"])
         _check(p.rglob("*/"), ["dirC/dirD/"])
         _check(p.rglob(""), ["dirC/", "dirC/dirD/"])
         _check(p.rglob("**"), [
-            "dirC", "dirC/fileC", "dirC/dirD", "dirC/dirD/fileD", "dirC/novel.txt"])
+            "dirC/", "dirC/fileC", "dirC/dirD", "dirC/dirD/fileD", "dirC/novel.txt"])
         _check(p.rglob("**/"), ["dirC/", "dirC/dirD/"])
         # gh-91616, a re module regression
         _check(p.rglob("*.txt"), ["dirC/novel.txt"])