@@ -1440,15 +1440,7 @@ class ZstdWriterTests(AbstractWriterTests, unittest.TestCase):
14401440
14411441def comparable_zinfo (zinfo ):
14421442 """Return a dict of public ZipInfo attributes for assertEqual comparison."""
1443- attrs = {k : getattr (zinfo , k ) for k in _ZINFO_PUBLIC_KEYS }
1444-
1445- # Since patch gh-84353, the _MASK_UTF_FILENAME (0x800) bit may be
1446- # changed when writing to the end record depending on whether filename
1447- # can be encoded with ascii or cp437. Skip checking this bit by
1448- # pretending it's always set.
1449- attrs ['flag_bits' ] |= 0x800
1450-
1451- return attrs
1443+ return {k : getattr (zinfo , k ) for k in _ZINFO_PUBLIC_KEYS }
14521444
14531445_struct_pack = struct .pack
14541446
@@ -5710,7 +5702,8 @@ def setUp(self):
57105702 with open (TESTFN , "wb" ) as tf :
57115703 tf .write (data )
57125704
5713- def _test_read (self , zipfp , expected_names , expected_content ):
5705+ def _test_read (self , zipfp , expected_names , expected_content ,
5706+ expected_comments = None , expected_efs_flags = None ):
57145707 # Check the namelist
57155708 names = zipfp .namelist ()
57165709 self .assertEqual (names , expected_names )
@@ -5720,6 +5713,17 @@ def _test_read(self, zipfp, expected_names, expected_content):
57205713 names = [zi .filename for zi in infos ]
57215714 self .assertEqual (names , expected_names )
57225715
5716+ if expected_comments is not None :
5717+ comments = [zi .comment for zi in infos ]
5718+ self .assertEqual (comments , expected_comments )
5719+
5720+ if expected_efs_flags is not None :
5721+ efs_flags = [
5722+ bool (zi .flag_bits & zipfile ._MASK_UTF_FILENAME )
5723+ for zi in infos
5724+ ]
5725+ self .assertEqual (efs_flags , expected_efs_flags )
5726+
57235727 # check getinfo
57245728 for name , content in zip (expected_names , expected_content ):
57255729 info = zipfp .getinfo (name )
@@ -5774,6 +5778,51 @@ def test_read_after_append(self):
57745778 with zipfile .ZipFile (TESTFN , "r" , metadata_encoding = 'shift_jis' ) as zipfp :
57755779 self ._test_read (zipfp , expected_names , expected_content )
57765780
5781+ def test_append_keep_efs_flag (self ):
5782+ """Files loaded from an archive should keep original EFS flags when
5783+ rewriting metadata in append mode."""
5784+ names = ['file1' , 'file2' , 'file3' , 'file4' ]
5785+ contents = [b'content1' , b'content2' , b'content3' , b'content4' ]
5786+ comments = ['\u4e00 ' .encode ('utf-8' ), b'foo' , '\u4e8c ' .encode ('shift_jis' ), b'bar' ]
5787+ efs_flags = [True , True , False , False ]
5788+
5789+ def mock_encode (self ):
5790+ if efs_flags [i ]:
5791+ zinfo .flag_bits |= zipfile ._MASK_UTF_FILENAME
5792+ return (self .filename .encode ('ascii' ), self .flag_bits )
5793+
5794+ with mock .patch ('zipfile.ZipInfo._encodeFilenameFlags' , mock_encode ), \
5795+ zipfile .ZipFile (TESTFN , "w" ) as zipfp :
5796+ for i , name in enumerate (names ):
5797+ zinfo = zipfile .ZipInfo (name )
5798+ zinfo .comment = comments [i ]
5799+ zipfp .writestr (zinfo , contents [i ])
5800+
5801+ with zipfile .ZipFile (TESTFN , "a" ) as zipfp :
5802+ # trigger archive rewriting
5803+ zipfp .comment = b'com'
5804+
5805+ with zipfile .ZipFile (TESTFN , "r" ) as zipfp :
5806+ self .assertEqual (zipfp .comment , b'com' )
5807+ self ._test_read (zipfp , names , contents , comments , efs_flags )
5808+
5809+ def test_write_enforce_efs_flag (self ):
5810+ """New files should enforce EFS flag if name or comment contains non-ASCII chars"""
5811+ names = ['\u4e00 ' , '\u4e8c ' , 'file3' , 'file4' ]
5812+ contents = [b'content1' , b'content2' , b'content3' , b'content4' ]
5813+ comments = ['\u4e00 ' .encode ('utf-8' ), b'foo' , '\u4e8c ' .encode ('utf-8' ), b'bar' ]
5814+ efs_flags = [True , True , True , False ]
5815+
5816+ with zipfile .ZipFile (TESTFN , "w" ) as zipfp :
5817+ for i , name in enumerate (names ):
5818+ zinfo = zipfile .ZipInfo (name )
5819+ zinfo .comment = comments [i ]
5820+ zipfp .writestr (zinfo , contents [i ])
5821+ self .assertEqual (zipfp .namelist (), names )
5822+
5823+ with zipfile .ZipFile (TESTFN , "r" ) as zipfp :
5824+ self ._test_read (zipfp , names , contents , comments , efs_flags )
5825+
57775826 def test_write_with_metadata_encoding (self ):
57785827 ZF = zipfile .ZipFile
57795828 for mode in ("w" , "x" , "a" ):
0 commit comments