GH-90208: Suppress OSError exceptions from pathlib.Path.glob() (GH-104141)

`pathlib.Path.glob()` now suppresses all OSError exceptions, except
those raised from calling `is_dir()` on the top-level path.

Previously, `glob()` suppressed ENOENT, ENOTDIR, EBADF and ELOOP
errors and their Windows equivalents. PermissionError was also
suppressed unless it occurred when calling `is_dir()` on the
top-level path. However, the selector would abort prematurely
if a PermissionError was raised, and so `glob()` could return
incomplete results.
This commit is contained in:
Barney Gale 2023-05-11 01:01:39 +01:00 committed by GitHub
parent 373bca0cc5
commit 94f30c7557
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 45 deletions

View file

@ -1949,33 +1949,19 @@ class _BasePathTest(object):
P = self.cls
base = P(BASE) / 'permissions'
base.mkdir()
self.addCleanup(os_helper.rmtree, base)
file1 = base / "file1"
file1.touch()
file2 = base / "file2"
file2.touch()
for i in range(100):
link = base / f"link{i}"
if i % 2:
link.symlink_to(P(BASE, "dirE", "nonexistent"))
else:
link.symlink_to(P(BASE, "dirC"))
subdir = base / "subdir"
file3 = base / "file3"
file3.symlink_to(subdir / "other")
# Patching is needed to avoid relying on the filesystem
# to return the order of the files as the error will not
# happen if the symlink is the last item.
real_scandir = os.scandir
def my_scandir(path):
with real_scandir(path) as scandir_it:
entries = list(scandir_it)
entries.sort(key=lambda entry: entry.name)
return contextlib.nullcontext(entries)
with mock.patch("os.scandir", my_scandir):
self.assertEqual(len(set(base.glob("*"))), 3)
subdir.mkdir()
self.assertEqual(len(set(base.glob("*"))), 4)
subdir.chmod(000)
self.assertEqual(len(set(base.glob("*"))), 4)
self.assertEqual(len(set(base.glob("*"))), 100)
self.assertEqual(len(set(base.glob("*/"))), 50)
self.assertEqual(len(set(base.glob("*/fileC"))), 50)
self.assertEqual(len(set(base.glob("*/file*"))), 50)
@os_helper.skip_unless_symlink
def test_glob_long_symlink(self):