Skip to content

Conversation

dynamicy
Copy link

@dynamicy dynamicy commented Sep 18, 2025

@bedevere-app
Copy link

bedevere-app bot commented Sep 18, 2025

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

@python-cla-bot
Copy link

python-cla-bot bot commented Sep 18, 2025

All commit authors signed the Contributor License Agreement.

CLA signed

@bedevere-app
Copy link

bedevere-app bot commented Sep 18, 2025

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

@dynamicy dynamicy force-pushed the fix-pathlib-copyfile2-windows-privilege-fallback branch 2 times, most recently from 1461184 to 85637e2 Compare September 18, 2025 16:42
@dynamicy dynamicy marked this pull request as ready for review September 18, 2025 17:08
Copy link
Contributor

@barneygale barneygale left a comment

Choose a reason for hiding this comment

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

Thanks for this :-)

Comment on lines 1151 to 1160
try:
copyfile2(source_fspath, str(self))
except OSError as exc:
winerror = getattr(exc, 'winerror', None)
if (_winapi is not None and
winerror in (_winapi.ERROR_PRIVILEGE_NOT_HELD,
_winapi.ERROR_ACCESS_DENIED)):
self._copy_from_file_fallback(source, preserve_metadata)
return
raise
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
try:
copyfile2(source_fspath, str(self))
except OSError as exc:
winerror = getattr(exc, 'winerror', None)
if (_winapi is not None and
winerror in (_winapi.ERROR_PRIVILEGE_NOT_HELD,
_winapi.ERROR_ACCESS_DENIED)):
self._copy_from_file_fallback(source, preserve_metadata)
return
raise
try:
copyfile2(source_fspath, str(self))
except OSError as exc:
# Use fallback on ERROR_ACCESS_DENIED
# or ERROR_PRIVILEGE_NOT_HELD
if exc.winerror not in (5, 1314):
raise
else:
return

This code is Windows-specific because of the if copyfile2: line above, so we can access exc.winerror directly I think.

We usually hard-code Windows error numbers rather than using _winapi in pathlib - I'm not sure if that's wise but I guess let's be consistent.

Copy link
Author

Choose a reason for hiding this comment

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

Thanks—good call. I switched to exc.winerror and check for 5/1314. If we hit either, we fall back to _copy_from_file_fallback; otherwise we re-raise. I also added a tiny comment mapping those to ERROR_ACCESS_DENIED and ERROR_PRIVILEGE_NOT_HELD. Still under the if copyfile2: guard, so Windows-only. Happy to tweak wording or style if you prefer.

@dynamicy dynamicy force-pushed the fix-pathlib-copyfile2-windows-privilege-fallback branch from 5ec9c09 to f5866e7 Compare September 19, 2025 13:55
@dynamicy dynamicy requested a review from barneygale September 19, 2025 15:17
@dynamicy dynamicy force-pushed the fix-pathlib-copyfile2-windows-privilege-fallback branch from f5866e7 to 9d80882 Compare September 19, 2025 16:56
Comment on lines 28 to 31
try:
import _winapi
except ImportError:
_winapi = None
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
try:
import _winapi
except ImportError:
_winapi = None

This is unused now

Copy link
Author

Choose a reason for hiding this comment

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

Removing unused imports.

try:
copyfile2(source_path, str(self))
except OSError as exc:
if hasattr(exc, "winerror") and exc.winerror in (5, 1314):
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
if hasattr(exc, "winerror") and exc.winerror in (5, 1314):
if exc.winerror in (5, 1314):

IIUC winerror is guaranteed to exist for any OSError raised from CopyFile2().

Copy link
Author

Choose a reason for hiding this comment

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

Good catch! You're absolutely right. Since we're specifically catching OSError from copyfile2(), the winerror attribute is indeed guaranteed to exist, making the hasattr() check redundant.

The simplified condition if exc.winerror in (5, 1314): is cleaner and more direct. Thanks for the improvement - it makes the code more concise while maintaining the same functionality.

@@ -0,0 +1 @@
Fix ``pathlib.Path.copy()`` failing on Windows when copying files that require elevated privileges (e.g., hidden or system files) by adding a fallback mechanism when ``copyfile2`` encounters privilege-related errors.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Fix ``pathlib.Path.copy()`` failing on Windows when copying files that require elevated privileges (e.g., hidden or system files) by adding a fallback mechanism when ``copyfile2`` encounters privilege-related errors.
Fix :meth:`pathlib.Path.copy` failing on Windows when copying files that require elevated privileges (e.g., hidden or system files) by adding a fallback mechanism when ``CopyFile2()`` encounters privilege-related errors.

Copy link
Author

Choose a reason for hiding this comment

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

Updated the commit message to be more precise. Thanks for keeping the details accurate!

@dynamicy dynamicy force-pushed the fix-pathlib-copyfile2-windows-privilege-fallback branch from bbd3417 to 762f4c7 Compare September 20, 2025 20:23
@dynamicy dynamicy requested a review from barneygale September 20, 2025 20:58
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