(path, ignored_error=OSError)
| 561 | return abspath(path) |
| 562 | else: |
| 563 | def _readlink_deep(path, ignored_error=OSError): |
| 564 | # These error codes indicate that we should stop reading links and |
| 565 | # return the path we currently have. |
| 566 | # 1: ERROR_INVALID_FUNCTION |
| 567 | # 2: ERROR_FILE_NOT_FOUND |
| 568 | # 3: ERROR_DIRECTORY_NOT_FOUND |
| 569 | # 5: ERROR_ACCESS_DENIED |
| 570 | # 21: ERROR_NOT_READY (implies drive with no media) |
| 571 | # 32: ERROR_SHARING_VIOLATION (probably an NTFS paging file) |
| 572 | # 50: ERROR_NOT_SUPPORTED (implies no support for reparse points) |
| 573 | # 67: ERROR_BAD_NET_NAME (implies remote server unavailable) |
| 574 | # 87: ERROR_INVALID_PARAMETER |
| 575 | # 4390: ERROR_NOT_A_REPARSE_POINT |
| 576 | # 4392: ERROR_INVALID_REPARSE_DATA |
| 577 | # 4393: ERROR_REPARSE_TAG_INVALID |
| 578 | allowed_winerror = 1, 2, 3, 5, 21, 32, 50, 67, 87, 4390, 4392, 4393 |
| 579 | |
| 580 | seen = set() |
| 581 | while normcase(path) not in seen: |
| 582 | seen.add(normcase(path)) |
| 583 | try: |
| 584 | old_path = path |
| 585 | path = _nt_readlink(path) |
| 586 | # Links may be relative, so resolve them against their |
| 587 | # own location |
| 588 | if not isabs(path): |
| 589 | # If it's something other than a symlink, we don't know |
| 590 | # what it's actually going to be resolved against, so |
| 591 | # just return the old path. |
| 592 | if not islink(old_path): |
| 593 | path = old_path |
| 594 | break |
| 595 | path = normpath(join(dirname(old_path), path)) |
| 596 | except ignored_error as ex: |
| 597 | if ex.winerror in allowed_winerror: |
| 598 | break |
| 599 | raise |
| 600 | except ValueError: |
| 601 | # Stop on reparse points that are not symlinks |
| 602 | break |
| 603 | return path |
| 604 | |
| 605 | def _getfinalpathname_nonstrict(path, ignored_error=OSError): |
| 606 | # These error codes indicate that we should stop resolving the path |
no test coverage detected
searching dependent graphs…