|
9 | 9 | import uuid |
10 | 10 | import warnings |
11 | 11 | from enum import Enum |
| 12 | +from errno import EBADF |
| 13 | +from errno import ELOOP |
| 14 | +from errno import ENOENT |
| 15 | +from errno import ENOTDIR |
12 | 16 | from functools import partial |
13 | 17 | from os.path import expanduser |
14 | 18 | from os.path import expandvars |
|
37 | 41 |
|
38 | 42 | _AnyPurePath = TypeVar("_AnyPurePath", bound=PurePath) |
39 | 43 |
|
| 44 | +# The following function, variables and comments were |
| 45 | +# copied from cpython 3.9 Lib/pathlib.py file. |
| 46 | + |
| 47 | +# EBADF - guard against macOS `stat` throwing EBADF |
| 48 | +_IGNORED_ERRORS = (ENOENT, ENOTDIR, EBADF, ELOOP) |
| 49 | + |
| 50 | +_IGNORED_WINERRORS = ( |
| 51 | + 21, # ERROR_NOT_READY - drive exists but is not accessible |
| 52 | + 1921, # ERROR_CANT_RESOLVE_FILENAME - fix for broken symlink pointing to itself |
| 53 | +) |
| 54 | + |
| 55 | + |
| 56 | +def _ignore_error(exception): |
| 57 | + return ( |
| 58 | + getattr(exception, "errno", None) in _IGNORED_ERRORS |
| 59 | + or getattr(exception, "winerror", None) in _IGNORED_WINERRORS |
| 60 | + ) |
| 61 | + |
40 | 62 |
|
41 | 63 | def get_lock_path(path: _AnyPurePath) -> _AnyPurePath: |
42 | 64 | return path.joinpath(".lock") |
@@ -555,8 +577,20 @@ def visit( |
555 | 577 |
|
556 | 578 | Entries at each directory level are sorted. |
557 | 579 | """ |
558 | | - entries = sorted(os.scandir(path), key=lambda entry: entry.name) |
| 580 | + |
| 581 | + entries = [] |
| 582 | + for entry in os.scandir(path): |
| 583 | + try: |
| 584 | + entry.is_file() |
| 585 | + except OSError as err: |
| 586 | + if _ignore_error(err): |
| 587 | + continue |
| 588 | + entries.append(entry) |
| 589 | + |
| 590 | + entries.sort(key=lambda entry: entry.name) |
| 591 | + |
559 | 592 | yield from entries |
| 593 | + |
560 | 594 | for entry in entries: |
561 | 595 | if entry.is_dir(follow_symlinks=False) and recurse(entry): |
562 | 596 | yield from visit(entry.path, recurse) |
|
0 commit comments