|
7 | 7 | import re |
8 | 8 | import sys |
9 | 9 | from _collections_abc import Sequence |
10 | | -from errno import EINVAL, ENOENT, ENOTDIR, EBADF |
| 10 | +from errno import EINVAL, ENOENT, ENOTDIR, EBADF, ELOOP |
11 | 11 | from operator import attrgetter |
12 | 12 | from stat import S_ISDIR, S_ISLNK, S_ISREG, S_ISSOCK, S_ISBLK, S_ISCHR, S_ISFIFO |
13 | 13 | from urllib.parse import quote_from_bytes as urlquote_from_bytes |
|
35 | 35 | # |
36 | 36 |
|
37 | 37 | # EBADF - guard against macOS `stat` throwing EBADF |
38 | | -_IGNORED_ERROS = (ENOENT, ENOTDIR, EBADF) |
| 38 | +_IGNORED_ERROS = (ENOENT, ENOTDIR, EBADF, ELOOP) |
39 | 39 |
|
40 | 40 | _IGNORED_WINERRORS = ( |
41 | 41 | 21, # ERROR_NOT_READY - drive exists but is not accessible |
| 42 | + 1921, # ERROR_CANT_RESOLVE_FILENAME - fix for broken symlink pointing to itself |
42 | 43 | ) |
43 | 44 |
|
44 | 45 | def _ignore_error(exception): |
@@ -520,7 +521,13 @@ def _select_from(self, parent_path, is_dir, exists, scandir): |
520 | 521 | cf = parent_path._flavour.casefold |
521 | 522 | entries = list(scandir(parent_path)) |
522 | 523 | for entry in entries: |
523 | | - if not self.dironly or entry.is_dir(): |
| 524 | + entry_is_dir = False |
| 525 | + try: |
| 526 | + entry_is_dir = entry.is_dir() |
| 527 | + except OSError as e: |
| 528 | + if not _ignore_error(e): |
| 529 | + raise |
| 530 | + if not self.dironly or entry_is_dir: |
524 | 531 | name = entry.name |
525 | 532 | casefolded = cf(name) |
526 | 533 | if self.pat.match(casefolded): |
|
0 commit comments