Skip to content

gh-113188: Fix shutil.copymode() on Windows #113189

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 23, 2023

Conversation

serhiy-storchaka
Copy link
Member

@serhiy-storchaka serhiy-storchaka commented Dec 15, 2023

Previously it worked differenly if dst is a symbolic link: it modified the permission bits of dst itself rather than the file it points to if follow_symlinks is true or src is not a symbolic link, and did nothing if follow_symlinks is false and src is a symbolic link.

Also document similar changes in shutil.copystat() etc.


📚 Documentation preview 📚: https://cpython-previews--113189.org.readthedocs.build/

Previously it worked differenly if dst is a symbolic link:
it modified the permission bits of dst itself rather than the file
it points to if follow_symlinks is true or src is not a symbolic link,
and did nothing if follow_symlinks is false and src is a symbolic link.

Also document similar changes in shutil.copystat() etc.
Comment on lines 112 to 116
In older Python versions :func:`!copymode` worked differenly on Windows
if *dst* is a symbolic link: it modified the permission bits of *dst*
itself rather than the file it points to if *follow_symlinks* is true
or *src* is not a symbolic link, and did not modify the permission bits
if *follow_symlinks* is false and *src* is a symbolic link.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer this to be phrased as what the function does now, probably just "copymode now behaves as intended on Windows when follow_symlinks is True", perhaps followed by "Previously, it would ..."

Unfortunately, the logic here is so complicated I can't figure out exactly what it does. I just spent 15 minutes trying to propose better wording. But that's probably a sign that it is going to confuse people.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In short, it did os.lchmod() when POSIX does os.chmod(), and did nothing when POSIX does os.lchmod().

If we are going to consider it a bug fix (even if it never worked correctly on Windows), we do not need these complicated versionchanged and What's New entries, only a NEWS entry. I'm leaning towards this solution, but want to hear an outside opinion.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But the backports will use more complicated code, because os.chmod(follow_symlinks=True) did not work.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it requires implementing chmod properly as well, then I'd say don't backport.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workaround is to resolve a symlink and calling chmod for a resolved path.

It can also be a half-solution -- only fix it for follow_symlinks=False, it is much easier.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I don't have a strong opinion then.

My main worry would be breaking someone who understands the current behaviour and has chosen not to work around it because it already does what they want.

It looks like follow_symlinks is already present on maintenance versions, so maybe it's just best to backport the chmod fix and switch the default value on Windows to reflect the current behaviour? That gives us a bigger matrix for people to specify an explicit value and get the right behaviour, and would keep the code more consistent between versions. I assume we can do different defaults on different platforms, yes?

@serhiy-storchaka serhiy-storchaka enabled auto-merge (squash) December 23, 2023 10:06
@serhiy-storchaka serhiy-storchaka merged commit 6e02d79 into python:main Dec 23, 2023
ryan-duve pushed a commit to ryan-duve/cpython that referenced this pull request Dec 26, 2023
Previously it worked differently if dst is a symbolic link:
it modified the permission bits of dst itself rather than the file
it points to if follow_symlinks is true or src is not a symbolic link,
and did nothing if follow_symlinks is false and src is a symbolic link.

Also document similar changes in shutil.copystat().
kulikjak pushed a commit to kulikjak/cpython that referenced this pull request Jan 22, 2024
Previously it worked differently if dst is a symbolic link:
it modified the permission bits of dst itself rather than the file
it points to if follow_symlinks is true or src is not a symbolic link,
and did nothing if follow_symlinks is false and src is a symbolic link.

Also document similar changes in shutil.copystat().
aisk pushed a commit to aisk/cpython that referenced this pull request Feb 11, 2024
Previously it worked differently if dst is a symbolic link:
it modified the permission bits of dst itself rather than the file
it points to if follow_symlinks is true or src is not a symbolic link,
and did nothing if follow_symlinks is false and src is a symbolic link.

Also document similar changes in shutil.copystat().
Glyphack pushed a commit to Glyphack/cpython that referenced this pull request Sep 2, 2024
Previously it worked differently if dst is a symbolic link:
it modified the permission bits of dst itself rather than the file
it points to if follow_symlinks is true or src is not a symbolic link,
and did nothing if follow_symlinks is false and src is a symbolic link.

Also document similar changes in shutil.copystat().
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants