Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 43 additions & 48 deletions Lib/pathlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,21 @@ def __init__(self, child_parts, flavour):
self.successor = _TerminatingSelector()
self.dironly = False

def _skip_entry(self, entry):
if self.dironly:
try:
return not entry.is_dir()
except PermissionError:
# "entry.is_dir()" can raise PermissionError
# in some cases (see bpo-38894), which is not
# among the errors ignored by _ignore_error().
return True
except OSError as e:
if not _ignore_error(e):
raise
return True
return False

def select_from(self, parent_path):
"""Iterate over all child paths of `parent_path` matched by this
selector. This can contain parent_path itself."""
Expand All @@ -527,13 +542,13 @@ def __init__(self, name, child_parts, flavour):
_Selector.__init__(self, child_parts, flavour)

def _select_from(self, parent_path, is_dir, exists, scandir):
path = parent_path._make_child_relpath(self.name)
try:
path = parent_path._make_child_relpath(self.name)
if (is_dir if self.dironly else exists)(path):
for p in self.successor._select_from(path, is_dir, exists, scandir):
yield p
if not (is_dir if self.dironly else exists)(path):
return
except PermissionError:
return
yield from self.successor._select_from(path, is_dir, exists, scandir)


class _WildcardSelector(_Selector):
Expand All @@ -546,25 +561,15 @@ def _select_from(self, parent_path, is_dir, exists, scandir):
try:
with scandir(parent_path) as scandir_it:
entries = list(scandir_it)
for entry in entries:
if self.dironly:
try:
# "entry.is_dir()" can raise PermissionError
# in some cases (see bpo-38894), which is not
# among the errors ignored by _ignore_error()
if not entry.is_dir():
continue
except OSError as e:
if not _ignore_error(e):
raise
continue
name = entry.name
if self.match(name):
path = parent_path._make_child_relpath(name)
for p in self.successor._select_from(path, is_dir, exists, scandir):
yield p
except PermissionError:
return
for entry in entries:
if self._skip_entry(entry):
continue
name = entry.name
if self.match(name):
path = parent_path._make_child_relpath(name)
yield from self.successor._select_from(path, is_dir, exists, scandir)


class _RecursiveWildcardSelector(_Selector):
Expand All @@ -577,34 +582,26 @@ def _iterate_directories(self, parent_path, is_dir, scandir):
try:
with scandir(parent_path) as scandir_it:
entries = list(scandir_it)
for entry in entries:
entry_is_dir = False
try:
entry_is_dir = entry.is_dir()
except OSError as e:
if not _ignore_error(e):
raise
if entry_is_dir and not entry.is_symlink():
path = parent_path._make_child_relpath(entry.name)
for p in self._iterate_directories(path, is_dir, scandir):
yield p
except PermissionError:
return
for entry in entries:
if self._skip_entry(entry):
continue
if not entry.is_symlink():
path = parent_path._make_child_relpath(entry.name)
yield from self._iterate_directories(path, is_dir, scandir)

def _select_from(self, parent_path, is_dir, exists, scandir):
yielded = set()
try:
yielded = set()
try:
successor_select = self.successor._select_from
for starting_point in self._iterate_directories(parent_path, is_dir, scandir):
for p in successor_select(starting_point, is_dir, exists, scandir):
if p not in yielded:
yield p
yielded.add(p)
finally:
yielded.clear()
except PermissionError:
return
successor_select = self.successor._select_from
for starting_point in self._iterate_directories(parent_path, is_dir, scandir):
for p in successor_select(starting_point, is_dir, exists, scandir):
if p not in yielded:
yield p
yielded.add(p)
finally:
yielded.clear()


#
Expand Down Expand Up @@ -1163,8 +1160,7 @@ def glob(self, pattern):
if drv or root:
raise NotImplementedError("Non-relative patterns are unsupported")
selector = _make_selector(tuple(pattern_parts), self._flavour)
for p in selector.select_from(self):
yield p
yield from selector.select_from(self)

def rglob(self, pattern):
"""Recursively yield all existing files (of any kind, including
Expand All @@ -1176,8 +1172,7 @@ def rglob(self, pattern):
if drv or root:
raise NotImplementedError("Non-relative patterns are unsupported")
selector = _make_selector(("**",) + tuple(pattern_parts), self._flavour)
for p in selector.select_from(self):
yield p
yield from selector.select_from(self)

def absolute(self):
"""Return an absolute version of this path. This function works
Expand Down