Commit 6c2d33a2 authored by Guido van Rossum's avatar Guido van Rossum

Issue #24120: Ignore PermissionError in pathlib.Path.[r]glob(). Ulrich Petri.

parent 114a1d63
...@@ -454,12 +454,15 @@ class _PreciseSelector(_Selector): ...@@ -454,12 +454,15 @@ class _PreciseSelector(_Selector):
_Selector.__init__(self, child_parts) _Selector.__init__(self, child_parts)
def _select_from(self, parent_path, is_dir, exists, listdir): def _select_from(self, parent_path, is_dir, exists, listdir):
if not is_dir(parent_path): try:
if not is_dir(parent_path):
return
path = parent_path._make_child_relpath(self.name)
if exists(path):
for p in self.successor._select_from(path, is_dir, exists, listdir):
yield p
except PermissionError:
return return
path = parent_path._make_child_relpath(self.name)
if exists(path):
for p in self.successor._select_from(path, is_dir, exists, listdir):
yield p
class _WildcardSelector(_Selector): class _WildcardSelector(_Selector):
...@@ -469,15 +472,19 @@ class _WildcardSelector(_Selector): ...@@ -469,15 +472,19 @@ class _WildcardSelector(_Selector):
_Selector.__init__(self, child_parts) _Selector.__init__(self, child_parts)
def _select_from(self, parent_path, is_dir, exists, listdir): def _select_from(self, parent_path, is_dir, exists, listdir):
if not is_dir(parent_path): try:
if not is_dir(parent_path):
return
cf = parent_path._flavour.casefold
for name in listdir(parent_path):
casefolded = cf(name)
if self.pat.match(casefolded):
path = parent_path._make_child_relpath(name)
for p in self.successor._select_from(path, is_dir, exists, listdir):
yield p
except PermissionError:
return return
cf = parent_path._flavour.casefold
for name in listdir(parent_path):
casefolded = cf(name)
if self.pat.match(casefolded):
path = parent_path._make_child_relpath(name)
for p in self.successor._select_from(path, is_dir, exists, listdir):
yield p
class _RecursiveWildcardSelector(_Selector): class _RecursiveWildcardSelector(_Selector):
...@@ -494,19 +501,22 @@ class _RecursiveWildcardSelector(_Selector): ...@@ -494,19 +501,22 @@ class _RecursiveWildcardSelector(_Selector):
yield p yield p
def _select_from(self, parent_path, is_dir, exists, listdir): def _select_from(self, parent_path, is_dir, exists, listdir):
if not is_dir(parent_path): try:
if not is_dir(parent_path):
return
with _cached(listdir) as listdir:
yielded = set()
try:
successor_select = self.successor._select_from
for starting_point in self._iterate_directories(parent_path, is_dir, listdir):
for p in successor_select(starting_point, is_dir, exists, listdir):
if p not in yielded:
yield p
yielded.add(p)
finally:
yielded.clear()
except PermissionError:
return return
with _cached(listdir) as listdir:
yielded = set()
try:
successor_select = self.successor._select_from
for starting_point in self._iterate_directories(parent_path, is_dir, listdir):
for p in successor_select(starting_point, is_dir, exists, listdir):
if p not in yielded:
yield p
yielded.add(p)
finally:
yielded.clear()
# #
......
...@@ -1203,26 +1203,33 @@ class _BasePathTest(object): ...@@ -1203,26 +1203,33 @@ class _BasePathTest(object):
# (BASE) # (BASE)
# | # |
# |-- dirA/ # |-- brokenLink -> non-existing
# |-- linkC -> "../dirB" # |-- dirA
# |-- dirB/ # | `-- linkC -> ../dirB
# | |-- fileB # |-- dirB
# |-- linkD -> "../dirB" # | |-- fileB
# |-- dirC/ # | `-- linkD -> ../dirB
# | |-- fileC # |-- dirC
# | |-- fileD # | |-- dirD
# | | `-- fileD
# | `-- fileC
# |-- dirE
# |-- fileA # |-- fileA
# |-- linkA -> "fileA" # |-- linkA -> fileA
# |-- linkB -> "dirB" # `-- linkB -> dirB
# #
def setUp(self): def setUp(self):
def cleanup():
os.chmod(join('dirE'), 0o777)
support.rmtree(BASE)
self.addCleanup(cleanup)
os.mkdir(BASE) os.mkdir(BASE)
self.addCleanup(support.rmtree, BASE)
os.mkdir(join('dirA')) os.mkdir(join('dirA'))
os.mkdir(join('dirB')) os.mkdir(join('dirB'))
os.mkdir(join('dirC')) os.mkdir(join('dirC'))
os.mkdir(join('dirC', 'dirD')) os.mkdir(join('dirC', 'dirD'))
os.mkdir(join('dirE'))
with open(join('fileA'), 'wb') as f: with open(join('fileA'), 'wb') as f:
f.write(b"this is file A\n") f.write(b"this is file A\n")
with open(join('dirB', 'fileB'), 'wb') as f: with open(join('dirB', 'fileB'), 'wb') as f:
...@@ -1231,6 +1238,7 @@ class _BasePathTest(object): ...@@ -1231,6 +1238,7 @@ class _BasePathTest(object):
f.write(b"this is file C\n") f.write(b"this is file C\n")
with open(join('dirC', 'dirD', 'fileD'), 'wb') as f: with open(join('dirC', 'dirD', 'fileD'), 'wb') as f:
f.write(b"this is file D\n") f.write(b"this is file D\n")
os.chmod(join('dirE'), 0)
if not symlink_skip_reason: if not symlink_skip_reason:
# Relative symlinks # Relative symlinks
os.symlink('fileA', join('linkA')) os.symlink('fileA', join('linkA'))
...@@ -1306,7 +1314,7 @@ class _BasePathTest(object): ...@@ -1306,7 +1314,7 @@ class _BasePathTest(object):
p = P(BASE) p = P(BASE)
it = p.iterdir() it = p.iterdir()
paths = set(it) paths = set(it)
expected = ['dirA', 'dirB', 'dirC', 'fileA'] expected = ['dirA', 'dirB', 'dirC', 'dirE', 'fileA']
if not symlink_skip_reason: if not symlink_skip_reason:
expected += ['linkA', 'linkB', 'brokenLink'] expected += ['linkA', 'linkB', 'brokenLink']
self.assertEqual(paths, { P(BASE, q) for q in expected }) self.assertEqual(paths, { P(BASE, q) for q in expected })
......
...@@ -1075,6 +1075,7 @@ Gabriel de Perthuis ...@@ -1075,6 +1075,7 @@ Gabriel de Perthuis
Tim Peters Tim Peters
Benjamin Peterson Benjamin Peterson
Joe Peterson Joe Peterson
Ulrich Petri
Chris Petrilli Chris Petrilli
Roumen Petrov Roumen Petrov
Bjorn Pettersen Bjorn Pettersen
......
...@@ -13,6 +13,9 @@ Core and Builtins ...@@ -13,6 +13,9 @@ Core and Builtins
Library Library
------- -------
- Issue #24120: Ignore PermissionError when traversing a tree with
pathlib.Path.[r]glob(). Patch by Ulrich Petri.
What's New in Python 3.4.4? What's New in Python 3.4.4?
=========================== ===========================
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment