Copy metadata from the given PathInfo to the given local path.
(info, target, follow_symlinks=True)
| 758 | |
| 759 | |
| 760 | def _copy_info(info, target, follow_symlinks=True): |
| 761 | """Copy metadata from the given PathInfo to the given local path.""" |
| 762 | copy_times_ns = ( |
| 763 | hasattr(info, '_access_time_ns') and |
| 764 | hasattr(info, '_mod_time_ns') and |
| 765 | (follow_symlinks or os.utime in os.supports_follow_symlinks)) |
| 766 | if copy_times_ns: |
| 767 | t0 = info._access_time_ns(follow_symlinks=follow_symlinks) |
| 768 | t1 = info._mod_time_ns(follow_symlinks=follow_symlinks) |
| 769 | os.utime(target, ns=(t0, t1), follow_symlinks=follow_symlinks) |
| 770 | |
| 771 | # We must copy extended attributes before the file is (potentially) |
| 772 | # chmod()'ed read-only, otherwise setxattr() will error with -EACCES. |
| 773 | copy_xattrs = ( |
| 774 | hasattr(info, '_xattrs') and |
| 775 | hasattr(os, 'setxattr') and |
| 776 | (follow_symlinks or os.setxattr in os.supports_follow_symlinks)) |
| 777 | if copy_xattrs: |
| 778 | xattrs = info._xattrs(follow_symlinks=follow_symlinks) |
| 779 | for attr, value in xattrs: |
| 780 | try: |
| 781 | os.setxattr(target, attr, value, follow_symlinks=follow_symlinks) |
| 782 | except OSError as e: |
| 783 | if e.errno not in (EPERM, ENOTSUP, ENODATA, EINVAL, EACCES): |
| 784 | raise |
| 785 | |
| 786 | copy_posix_permissions = ( |
| 787 | hasattr(info, '_posix_permissions') and |
| 788 | (follow_symlinks or os.chmod in os.supports_follow_symlinks)) |
| 789 | if copy_posix_permissions: |
| 790 | posix_permissions = info._posix_permissions(follow_symlinks=follow_symlinks) |
| 791 | try: |
| 792 | os.chmod(target, posix_permissions, follow_symlinks=follow_symlinks) |
| 793 | except NotImplementedError: |
| 794 | # if we got a NotImplementedError, it's because |
| 795 | # * follow_symlinks=False, |
| 796 | # * lchown() is unavailable, and |
| 797 | # * either |
| 798 | # * fchownat() is unavailable or |
| 799 | # * fchownat() doesn't implement AT_SYMLINK_NOFOLLOW. |
| 800 | # (it returned ENOSUP.) |
| 801 | # therefore we're out of options--we simply cannot chown the |
| 802 | # symlink. give up, suppress the error. |
| 803 | # (which is what shutil always did in this circumstance.) |
| 804 | pass |
| 805 | |
| 806 | copy_bsd_flags = ( |
| 807 | hasattr(info, '_bsd_flags') and |
| 808 | hasattr(os, 'chflags') and |
| 809 | (follow_symlinks or os.chflags in os.supports_follow_symlinks)) |
| 810 | if copy_bsd_flags: |
| 811 | bsd_flags = info._bsd_flags(follow_symlinks=follow_symlinks) |
| 812 | try: |
| 813 | os.chflags(target, bsd_flags, follow_symlinks=follow_symlinks) |
| 814 | except OSError as why: |
| 815 | if why.errno not in (EOPNOTSUPP, ENOTSUP): |
| 816 | raise |
| 817 |
no test coverage detected
searching dependent graphs…