summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorBarney Gale <barney.gale@gmail.com>2024-04-13 23:08:03 (GMT)
committerGitHub <noreply@github.com>2024-04-13 23:08:03 (GMT)
commita74f117dab369e6c54156c7b2256769fed0c23d0 (patch)
tree6db14d7a5be43aadca9df39cb304141f5322dcf8 /Lib
parent3095d026424f11714f0b7a828c61dc741d4e716b (diff)
downloadcpython-a74f117dab369e6c54156c7b2256769fed0c23d0.zip
cpython-a74f117dab369e6c54156c7b2256769fed0c23d0.tar.gz
cpython-a74f117dab369e6c54156c7b2256769fed0c23d0.tar.bz2
GH-115060: Speed up `pathlib.Path.glob()` by omitting initial `stat()` (#117831)
Since 6258844c, paths that might not exist can be fed into pathlib's globbing implementation, which will call `os.scandir()` / `os.lstat()` only when strictly necessary. This allows us to drop an initial `self.is_dir()` call, which saves a `stat()`. Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com>
Diffstat (limited to 'Lib')
-rw-r--r--Lib/pathlib/__init__.py4
-rw-r--r--Lib/pathlib/_abc.py4
-rw-r--r--Lib/test/test_pathlib/test_pathlib.py7
-rw-r--r--Lib/test/test_pathlib/test_pathlib_abc.py3
4 files changed, 12 insertions, 6 deletions
diff --git a/Lib/pathlib/__init__.py b/Lib/pathlib/__init__.py
index 66eb08a..a4721fb 100644
--- a/Lib/pathlib/__init__.py
+++ b/Lib/pathlib/__init__.py
@@ -607,11 +607,9 @@ class Path(_abc.PathBase, PurePath):
if raw[-1] in (self.parser.sep, self.parser.altsep):
# GH-65238: pathlib doesn't preserve trailing slash. Add it back.
parts.append('')
- if not self.is_dir():
- return iter([])
select = self._glob_selector(parts[::-1], case_sensitive, recurse_symlinks)
root = str(self)
- paths = select(root, exists=True)
+ paths = select(root)
# Normalize results
if root == '.':
diff --git a/Lib/pathlib/_abc.py b/Lib/pathlib/_abc.py
index b51ad6f..05698d5 100644
--- a/Lib/pathlib/_abc.py
+++ b/Lib/pathlib/_abc.py
@@ -705,10 +705,8 @@ class PathBase(PurePathBase):
anchor, parts = pattern._stack
if anchor:
raise NotImplementedError("Non-relative patterns are unsupported")
- if not self.is_dir():
- return iter([])
select = self._glob_selector(parts, case_sensitive, recurse_symlinks)
- return select(self, exists=True)
+ return select(self)
def rglob(self, pattern, *, case_sensitive=None, recurse_symlinks=True):
"""Recursively yield all existing files (of any kind, including
diff --git a/Lib/test/test_pathlib/test_pathlib.py b/Lib/test/test_pathlib/test_pathlib.py
index 651d666..5fd1a41 100644
--- a/Lib/test/test_pathlib/test_pathlib.py
+++ b/Lib/test/test_pathlib/test_pathlib.py
@@ -1263,6 +1263,13 @@ class PathTest(test_pathlib_abc.DummyPathTest, PurePathTest):
self.assertEqual(
set(P('.').glob('**/*/*')), {P("dirD/fileD")})
+ def test_glob_inaccessible(self):
+ P = self.cls
+ p = P(self.base, "mydir1", "mydir2")
+ p.mkdir(parents=True)
+ p.parent.chmod(0)
+ self.assertEqual(set(p.glob('*')), set())
+
def test_rglob_pathlike(self):
P = self.cls
p = P(self.base, "dirC")
diff --git a/Lib/test/test_pathlib/test_pathlib_abc.py b/Lib/test/test_pathlib/test_pathlib_abc.py
index 6656b03..aadecbc 100644
--- a/Lib/test/test_pathlib/test_pathlib_abc.py
+++ b/Lib/test/test_pathlib/test_pathlib_abc.py
@@ -8,6 +8,7 @@ import unittest
from pathlib._abc import UnsupportedOperation, ParserBase, PurePathBase, PathBase
import posixpath
+from test.support import is_wasi
from test.support.os_helper import TESTFN
@@ -1920,6 +1921,8 @@ class DummyPathTest(DummyPurePathTest):
}
self.assertEqual(given, {p / x for x in expect})
+ # See https://github.com/WebAssembly/wasi-filesystem/issues/26
+ @unittest.skipIf(is_wasi, "WASI resolution of '..' parts doesn't match POSIX")
def test_glob_dotdot(self):
# ".." is not special in globs.
P = self.cls