changeset: 99777:f6ae90450a4d parent: 99771:1118dfcbcc35 parent: 99776:224a026b4ca1 user: Guido van Rossum date: Wed Jan 06 09:53:51 2016 -0800 files: Lib/test/test_pathlib.py Misc/ACKS Misc/NEWS description: Issue #24120: Ignore PermissionError in pathlib.Path.[r]glob(). Ulrich Petri. (Merge 3.5->3.6) diff -r 1118dfcbcc35 -r f6ae90450a4d Lib/pathlib.py --- a/Lib/pathlib.py Tue Jan 05 21:27:54 2016 +0200 +++ b/Lib/pathlib.py Wed Jan 06 09:53:51 2016 -0800 @@ -499,12 +499,15 @@ _Selector.__init__(self, child_parts) 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 - 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): @@ -514,15 +517,19 @@ _Selector.__init__(self, child_parts) 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 - 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): @@ -539,19 +546,22 @@ yield p 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 - 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() # diff -r 1118dfcbcc35 -r f6ae90450a4d Lib/test/test_pathlib.py --- a/Lib/test/test_pathlib.py Tue Jan 05 21:27:54 2016 +0200 +++ b/Lib/test/test_pathlib.py Wed Jan 06 09:53:51 2016 -0800 @@ -1199,26 +1199,33 @@ # (BASE) # | - # |-- dirA/ - # |-- linkC -> "../dirB" - # |-- dirB/ - # | |-- fileB - # |-- linkD -> "../dirB" - # |-- dirC/ - # | |-- fileC - # | |-- fileD + # |-- brokenLink -> non-existing + # |-- dirA + # | `-- linkC -> ../dirB + # |-- dirB + # | |-- fileB + # | `-- linkD -> ../dirB + # |-- dirC + # | |-- dirD + # | | `-- fileD + # | `-- fileC + # |-- dirE # |-- fileA - # |-- linkA -> "fileA" - # |-- linkB -> "dirB" + # |-- linkA -> fileA + # `-- linkB -> dirB # def setUp(self): + def cleanup(): + os.chmod(join('dirE'), 0o777) + support.rmtree(BASE) + self.addCleanup(cleanup) os.mkdir(BASE) - self.addCleanup(support.rmtree, BASE) os.mkdir(join('dirA')) os.mkdir(join('dirB')) os.mkdir(join('dirC')) os.mkdir(join('dirC', 'dirD')) + os.mkdir(join('dirE')) with open(join('fileA'), 'wb') as f: f.write(b"this is file A\n") with open(join('dirB', 'fileB'), 'wb') as f: @@ -1227,6 +1234,7 @@ f.write(b"this is file C\n") with open(join('dirC', 'dirD', 'fileD'), 'wb') as f: f.write(b"this is file D\n") + os.chmod(join('dirE'), 0) if not symlink_skip_reason: # Relative symlinks os.symlink('fileA', join('linkA')) @@ -1363,7 +1371,7 @@ p = P(BASE) it = p.iterdir() paths = set(it) - expected = ['dirA', 'dirB', 'dirC', 'fileA'] + expected = ['dirA', 'dirB', 'dirC', 'dirE', 'fileA'] if not symlink_skip_reason: expected += ['linkA', 'linkB', 'brokenLink'] self.assertEqual(paths, { P(BASE, q) for q in expected }) diff -r 1118dfcbcc35 -r f6ae90450a4d Misc/ACKS --- a/Misc/ACKS Tue Jan 05 21:27:54 2016 +0200 +++ b/Misc/ACKS Wed Jan 06 09:53:51 2016 -0800 @@ -1110,6 +1110,7 @@ Tim Peters Benjamin Peterson Joe Peterson +Ulrich Petri Chris Petrilli Roumen Petrov Bjorn Pettersen diff -r 1118dfcbcc35 -r f6ae90450a4d Misc/NEWS --- a/Misc/NEWS Tue Jan 05 21:27:54 2016 +0200 +++ b/Misc/NEWS Wed Jan 06 09:53:51 2016 -0800 @@ -128,6 +128,9 @@ Library ------- +- Issue #24120: Ignore PermissionError when traversing a tree with + pathlib.Path.[r]glob(). Patch by Ulrich Petri. + - Issue #21815: Accept ] characters in the data portion of imap responses, in order to handle the flags with square brackets accepted and produced by servers such as gmail.