Skip to content

Commit 9cf6cd7

Browse files
committed
gh-140774: Fix pathlib.Path.chmod not handling the Archive bit on Windows
1 parent 9c4ff8a commit 9cf6cd7

2 files changed

Lines changed: 24 additions & 1 deletion

File tree

Lib/pathlib/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1222,7 +1222,8 @@ def chmod(self, mode, *, follow_symlinks=True):
12221222
"""
12231223
Change the permissions of the path, like os.chmod().
12241224
"""
1225-
os.chmod(self, mode, follow_symlinks=follow_symlinks)
1225+
# GH-127380: Force string path to ensure Windows archive bit handling works
1226+
os.chmod(str(self), mode, follow_symlinks=follow_symlinks)
12261227

12271228
def lchmod(self, mode):
12281229
"""

Lib/test/test_pathlib/test_pathlib.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3622,6 +3622,28 @@ def test_walk_symlink_location(self):
36223622
class PosixPathTest(PathTest, PurePosixPathTest):
36233623
cls = pathlib.PosixPath
36243624

3625+
def test_chmod_archive_bit_behavior(self):
3626+
base = self.cls(self.base)
3627+
filename = base / 'test_chmod_archive.txt'
3628+
filename.touch()
3629+
self.addCleanup(filename.unlink, missing_ok=True)
3630+
3631+
# Helper to check read-only status
3632+
def is_read_only(p):
3633+
return (p.stat().st_file_attributes & stat.FILE_ATTRIBUTE_READONLY) > 0
3634+
try:
3635+
# Case 1: Archive bit CLEARED, Read-Only SET
3636+
# We use attrib command to manipulate the Archive bit directly
3637+
subprocess.run(['attrib', '-a', '+r', str(filename)], check=True, shell=True)
3638+
3639+
# This line used to fail silently (bug #140774)
3640+
filename.chmod(stat.S_IWRITE | stat.S_IREAD)
3641+
3642+
self.assertFalse(is_read_only(filename),
3643+
"chmod failed to clear Read-Only when Archive bit was cleared")
3644+
3645+
except subprocess.CalledProcessError:
3646+
self.skipTest("attrib command failed or not available")
36253647

36263648
@unittest.skipIf(os.name != 'nt', 'test requires a Windows-compatible system')
36273649
class WindowsPathTest(PathTest, PureWindowsPathTest):

0 commit comments

Comments
 (0)