@@ -1715,6 +1715,25 @@ def test_extract_all_with_target_pathlike(self):
17151715 with temp_dir () as extdir :
17161716 self ._test_extract_all_with_target (FakePath (extdir ))
17171717
1718+ @unittest .skipUnless (hasattr (os , 'chmod' ), 'requires os.chmod' )
1719+ @unittest .skipIf (sys .platform == 'win32' , 'Unix permissions only' )
1720+ def test_extract_preserves_unix_permissions (self ):
1721+ """_extract_member must apply Unix mode stored in external_attr."""
1722+ info = zipfile .ZipInfo ('secret.txt' )
1723+ info .external_attr = (stat .S_IFREG | 0o600 ) << 16
1724+ with zipfile .ZipFile (TESTFN2 , 'w' ) as zf :
1725+ zf .writestr (info , b'data' )
1726+
1727+ with temp_dir () as extdir :
1728+ with zipfile .ZipFile (TESTFN2 , 'r' ) as zf :
1729+ zf .extract ('secret.txt' , path = extdir )
1730+
1731+ extracted = os .path .join (extdir , 'secret.txt' )
1732+ actual = stat .S_IMODE (os .stat (extracted ).st_mode )
1733+ self .assertEqual (actual , 0o600 , f'expected 0o600, got 0o{ actual :03o} ' )
1734+
1735+ unlink (TESTFN2 )
1736+
17181737 def check_file (self , filename , content ):
17191738 self .assertTrue (os .path .isfile (filename ))
17201739 with open (filename , 'rb' ) as f :
0 commit comments